Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2015-05-20 18:16:22 -07:00
commit 98d8b5b1e9
90 changed files with 1651 additions and 908 deletions

View File

@ -5,7 +5,6 @@ no_sccache=1
ac_add_options --enable-valgrind
ac_add_options --disable-jemalloc
ac_add_options --enable-optimize="-g -O -freorder-blocks"
ac_add_options --disable-install-strip
# Include the override mozconfig again (even though the above includes it)

View File

@ -5,7 +5,6 @@ no_sccache=1
ac_add_options --enable-valgrind
ac_add_options --disable-jemalloc
ac_add_options --enable-optimize="-g -O -freorder-blocks"
ac_add_options --disable-install-strip
# Include the override mozconfig again (even though the above includes it)

View File

@ -201,6 +201,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioChannelManager)
#endif
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCameraManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessagesManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeviceStorageStores)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager)
@ -307,6 +308,7 @@ Navigator::Invalidate()
#endif
mCameraManager = nullptr;
mMediaDevices = nullptr;
if (mMessagesManager) {
mMessagesManager = nullptr;

View File

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<body>
<script>
// This should not leak.
var a = navigator;
navigator.mediaDevices._ = null;
</script>
</body>

View File

@ -202,3 +202,4 @@ load xhr_empty_datauri.html
load xhr_html_nullresponse.html
load structured_clone_container_throws.html
load 1154598.xhtml
load 1157995.html

174
dom/cache/DBSchema.cpp vendored
View File

@ -181,7 +181,7 @@ static void AppendListParamsToQuery(nsACString& aQuery,
static nsresult BindListParamsToQuery(mozIStorageStatement* aState,
const nsTArray<EntryId>& aEntryIdList,
uint32_t aPos, int32_t aLen);
static nsresult BindId(mozIStorageStatement* aState, uint32_t aPos,
static nsresult BindId(mozIStorageStatement* aState, const nsACString& aName,
const nsID* aId);
static nsresult ExtractId(mozIStorageStatement* aState, uint32_t aPos,
nsID* aIdOut);
@ -412,11 +412,11 @@ DeleteCacheId(mozIStorageConnection* aConn, CacheId aCacheId,
// Delete the remainder of the cache using cascade semantics.
nsCOMPtr<mozIStorageStatement> state;
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"DELETE FROM caches WHERE id=?1;"
"DELETE FROM caches WHERE id=:id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64Parameter(0, aCacheId);
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->Execute();
@ -438,11 +438,11 @@ IsCacheOrphaned(mozIStorageConnection* aConn, CacheId aCacheId,
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT COUNT(*) FROM storage WHERE cache_id=?1;"
"SELECT COUNT(*) FROM storage WHERE cache_id=:cache_id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64Parameter(0, aCacheId);
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
@ -646,11 +646,11 @@ StorageMatch(mozIStorageConnection* aConn,
nsCOMPtr<mozIStorageStatement> state;
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT cache_id FROM storage WHERE namespace=?1 ORDER BY rowid;"
"SELECT cache_id FROM storage WHERE namespace=:namespace ORDER BY rowid;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aNamespace);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("namespace"), aNamespace);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsAutoTArray<CacheId, 32> cacheIdList;
@ -693,14 +693,15 @@ StorageGetCacheId(mozIStorageConnection* aConn, Namespace aNamespace,
// Use IS for matching the key since an EmptryString() key maps to NULL.
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT cache_id FROM storage WHERE namespace=?1 AND key IS ?2 ORDER BY rowid;"
"SELECT cache_id FROM storage WHERE namespace=:namespace AND key IS :key "
"ORDER BY rowid;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aNamespace);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("namespace"), aNamespace);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindStringAsBlobParameter(1, aKey);
rv = state->BindStringAsBlobByName(NS_LITERAL_CSTRING("key"), aKey);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
@ -727,17 +728,18 @@ StoragePutCache(mozIStorageConnection* aConn, Namespace aNamespace,
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"INSERT INTO storage (namespace, key, cache_id) VALUES(?1, ?2, ?3);"
"INSERT INTO storage (namespace, key, cache_id) "
"VALUES (:namespace, :key, :cache_id);"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aNamespace);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("namespace"), aNamespace);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindStringAsBlobParameter(1, aKey);
rv = state->BindStringAsBlobByName(NS_LITERAL_CSTRING("key"), aKey);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64Parameter(2, aCacheId);
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->Execute();
@ -756,14 +758,14 @@ StorageForgetCache(mozIStorageConnection* aConn, Namespace aNamespace,
// Use IS for matching the key since an EmptryString() key maps to NULL.
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"DELETE FROM storage WHERE namespace=?1 AND key IS ?2;"
"DELETE FROM storage WHERE namespace=:namespace AND key IS :key;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aNamespace);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("namespace"), aNamespace);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindStringAsBlobParameter(1, aKey);
rv = state->BindStringAsBlobByName(NS_LITERAL_CSTRING("key"), aKey);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->Execute();
@ -781,11 +783,11 @@ StorageGetKeys(mozIStorageConnection* aConn, Namespace aNamespace,
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT key FROM storage WHERE namespace=?1 ORDER BY rowid;"
"SELECT key FROM storage WHERE namespace=:namespace ORDER BY rowid;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aNamespace);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("namespace"), aNamespace);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
@ -811,11 +813,11 @@ QueryAll(mozIStorageConnection* aConn, CacheId aCacheId,
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT id FROM entries WHERE cache_id=?1 ORDER BY id;"
"SELECT id FROM entries WHERE cache_id=:cache_id ORDER BY id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64Parameter(0, aCacheId);
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
@ -851,7 +853,7 @@ QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
"FROM entries "
"LEFT OUTER JOIN response_headers ON entries.id=response_headers.entry_id "
"AND response_headers.name='vary' "
"WHERE entries.cache_id=?1 "
"WHERE entries.cache_id=:cache_id "
"AND entries."
);
@ -864,16 +866,16 @@ QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
query.AppendLiteral("request_url");
}
query.AppendLiteral("=?2 GROUP BY entries.id ORDER BY entries.id;");
query.AppendLiteral("=:url GROUP BY entries.id ORDER BY entries.id;");
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(query, getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64Parameter(0, aCacheId);
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindStringParameter(1, urlToMatch);
rv = state->BindStringByName(NS_LITERAL_CSTRING("url"), urlToMatch);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
@ -919,11 +921,11 @@ MatchByVaryHeader(mozIStorageConnection* aConn,
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT value FROM response_headers "
"WHERE name='vary' AND entry_id=?1;"
"WHERE name='vary' AND entry_id=:entry_id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, entryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("entry_id"), entryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsAutoTArray<nsCString, 8> varyValues;
@ -943,11 +945,11 @@ MatchByVaryHeader(mozIStorageConnection* aConn,
state->Reset();
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT name, value FROM request_headers "
"WHERE entry_id=?1;"
"WHERE entry_id=:entry_id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, entryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("entry_id"), entryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsRefPtr<InternalHeaders> cachedHeaders =
@ -1138,71 +1140,101 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
"response_body_id, "
"response_security_info, "
"cache_id "
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19)"
") VALUES ("
":request_method, "
":request_url, "
":request_url_no_query, "
":request_referrer, "
":request_headers_guard, "
":request_mode, "
":request_credentials, "
":request_contentpolicytype, "
":request_context, "
":request_cache, "
":request_body_id, "
":response_type, "
":response_url, "
":response_status, "
":response_status_text, "
":response_headers_guard, "
":response_body_id, "
":response_security_info, "
":cache_id "
");"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindUTF8StringParameter(0, aRequest.method());
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("request_method"),
aRequest.method());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindStringParameter(1, aRequest.url());
rv = state->BindStringByName(NS_LITERAL_CSTRING("request_url"),
aRequest.url());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindStringParameter(2, aRequest.urlWithoutQuery());
rv = state->BindStringByName(NS_LITERAL_CSTRING("request_url_no_query"),
aRequest.urlWithoutQuery());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindStringParameter(3, aRequest.referrer());
rv = state->BindStringByName(NS_LITERAL_CSTRING("request_referrer"),
aRequest.referrer());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(4,
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("request_headers_guard"),
static_cast<int32_t>(aRequest.headersGuard()));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(5, static_cast<int32_t>(aRequest.mode()));
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("request_mode"),
static_cast<int32_t>(aRequest.mode()));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(6,
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("request_credentials"),
static_cast<int32_t>(aRequest.credentials()));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(7,
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("request_contentpolicytype"),
static_cast<int32_t>(aRequest.contentPolicyType()));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(8,
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("request_context"),
static_cast<int32_t>(aRequest.context()));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(9,
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("request_cache"),
static_cast<int32_t>(aRequest.requestCache()));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = BindId(state, 10, aRequestBodyId);
rv = BindId(state, NS_LITERAL_CSTRING("request_body_id"), aRequestBodyId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(11, static_cast<int32_t>(aResponse.type()));
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("response_type"),
static_cast<int32_t>(aResponse.type()));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindStringParameter(12, aResponse.url());
rv = state->BindStringByName(NS_LITERAL_CSTRING("response_url"),
aResponse.url());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(13, aResponse.status());
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("response_status"),
aResponse.status());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindUTF8StringParameter(14, aResponse.statusText());
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("response_status_text"),
aResponse.statusText());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(15,
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("response_headers_guard"),
static_cast<int32_t>(aResponse.headersGuard()));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = BindId(state, 16, aResponseBodyId);
rv = BindId(state, NS_LITERAL_CSTRING("response_body_id"), aResponseBodyId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindUTF8StringAsBlobParameter(17, aResponse.securityInfo());
rv = state->BindUTF8StringAsBlobByName(NS_LITERAL_CSTRING("response_security_info"),
aResponse.securityInfo());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64Parameter(18, aCacheId);
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->Execute();
@ -1226,19 +1258,21 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
"name, "
"value, "
"entry_id "
") VALUES (?1, ?2, ?3)"
") VALUES (:name, :value, :entry_id)"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
const nsTArray<HeadersEntry>& requestHeaders = aRequest.headers();
for (uint32_t i = 0; i < requestHeaders.Length(); ++i) {
rv = state->BindUTF8StringParameter(0, requestHeaders[i].name());
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("name"),
requestHeaders[i].name());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindUTF8StringParameter(1, requestHeaders[i].value());
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("value"),
requestHeaders[i].value());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(2, entryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("entry_id"), entryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->Execute();
@ -1250,19 +1284,21 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
"name, "
"value, "
"entry_id "
") VALUES (?1, ?2, ?3)"
") VALUES (:name, :value, :entry_id)"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
const nsTArray<HeadersEntry>& responseHeaders = aResponse.headers();
for (uint32_t i = 0; i < responseHeaders.Length(); ++i) {
rv = state->BindUTF8StringParameter(0, responseHeaders[i].name());
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("name"),
responseHeaders[i].name());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindUTF8StringParameter(1, responseHeaders[i].value());
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("value"),
responseHeaders[i].value());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(2, entryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("entry_id"), entryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->Execute();
@ -1291,11 +1327,11 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
"response_body_id, "
"response_security_info "
"FROM entries "
"WHERE id=?1;"
"WHERE id=:id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aEntryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("id"), aEntryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
@ -1342,11 +1378,11 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
"name, "
"value "
"FROM response_headers "
"WHERE entry_id=?1;"
"WHERE entry_id=:entry_id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aEntryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("entry_id"), aEntryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
@ -1387,11 +1423,11 @@ ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
"request_cache, "
"request_body_id "
"FROM entries "
"WHERE id=?1;"
"WHERE id=:id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aEntryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("id"), aEntryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
@ -1460,11 +1496,11 @@ ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
"name, "
"value "
"FROM request_headers "
"WHERE entry_id=?1;"
"WHERE entry_id=:entry_id;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32Parameter(0, aEntryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("entry_id"), aEntryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
@ -1506,28 +1542,28 @@ BindListParamsToQuery(mozIStorageStatement* aState,
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT((aPos + aLen) <= aEntryIdList.Length());
for (int32_t i = aPos; i < aLen; ++i) {
nsresult rv = aState->BindInt32Parameter(i, aEntryIdList[i]);
nsresult rv = aState->BindInt32ByIndex(i, aEntryIdList[i]);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
nsresult
BindId(mozIStorageStatement* aState, uint32_t aPos, const nsID* aId)
BindId(mozIStorageStatement* aState, const nsACString& aName, const nsID* aId)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aState);
nsresult rv;
if (!aId) {
rv = aState->BindNullParameter(aPos);
rv = aState->BindNullByName(aName);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
return rv;
}
char idBuf[NSID_LENGTH];
aId->ToProvidedString(idBuf);
rv = aState->BindUTF8StringParameter(aPos, nsAutoCString(idBuf));
rv = aState->BindUTF8StringByName(aName, nsAutoCString(idBuf));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
return rv;

View File

@ -465,15 +465,7 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices)
return NS_OK;
}
// Kick off the geo device, if it isn't already running
nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
nsresult rv = gs->StartDevice(GetPrincipal());
if (NS_FAILED(rv)) {
// Location provider error
NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
return NS_OK;
}
bool canUseCache = false;
CachedPositionAndAccuracy lastPosition = gs->GetCachedPosition();
@ -497,6 +489,15 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices)
// getCurrentPosition requests serviced by the cache
// will now be owned by the RequestSendLocationEvent
Update(lastPosition.position);
} else {
// Kick off the geo device, if it isn't already running
nsresult rv = gs->StartDevice(GetPrincipal());
if (NS_FAILED(rv)) {
// Location provider error
NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
return NS_OK;
}
}
if (mIsWatchPositionRequest || !canUseCache) {
@ -957,7 +958,9 @@ nsGeolocationService::Observe(nsISupports* aSubject,
NS_IMETHODIMP
nsGeolocationService::Update(nsIDOMGeoPosition *aSomewhere)
{
SetCachedPosition(aSomewhere);
if (aSomewhere) {
SetCachedPosition(aSomewhere);
}
for (uint32_t i = 0; i< mGeolocators.Length(); i++) {
mGeolocators[i]->Update(aSomewhere);

View File

@ -193,7 +193,9 @@ let FormAssistant = {
addEventListener("focus", this, true, false);
addEventListener("blur", this, true, false);
addEventListener("resize", this, true, false);
addEventListener("submit", this, true, false);
// We should not blur the fucus if the submit event is cancelled,
// therefore we are binding our event listener in the bubbling phase here.
addEventListener("submit", this, false, false);
addEventListener("pagehide", this, true, false);
addEventListener("beforeunload", this, true, false);
addEventListener("input", this, true, false);
@ -399,7 +401,7 @@ let FormAssistant = {
}
// fall through
case "submit":
if (this.focusedElement) {
if (this.focusedElement && !evt.defaultPrevented) {
this.focusedElement.blur();
}
break;

View File

@ -64,56 +64,6 @@ SetUpSandboxEnvironment()
return;
}
}
#if defined(NIGHTLY_BUILD)
static void
CleanUpOldSandboxEnvironment()
{
// Temporary code to clean up the old low integrity temp directories.
// The removal of this is tracked by bug 1165818.
nsCOMPtr<nsIFile> lowIntegrityMozilla;
nsresult rv = NS_GetSpecialDirectory(NS_WIN_LOCAL_APPDATA_LOW_DIR,
getter_AddRefs(lowIntegrityMozilla));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
rv = lowIntegrityMozilla->Append(NS_LITERAL_STRING(MOZ_USER_DIR));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsISimpleEnumerator> iter;
rv = lowIntegrityMozilla->GetDirectoryEntries(getter_AddRefs(iter));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
bool more;
nsCOMPtr<nsISupports> elem;
while (NS_SUCCEEDED(iter->HasMoreElements(&more)) && more) {
rv = iter->GetNext(getter_AddRefs(elem));
if (NS_FAILED(rv)) {
break;
}
nsCOMPtr<nsIFile> file = do_QueryInterface(elem);
if (!file) {
continue;
}
nsAutoString leafName;
rv = file->GetLeafName(leafName);
if (NS_FAILED(rv)) {
continue;
}
if (leafName.Find(NS_LITERAL_STRING("MozTemp-{")) == 0) {
file->Remove(/* aRecursive */ true);
}
}
}
#endif
#endif
void
@ -138,12 +88,11 @@ ContentProcess::Init()
return true;
}
// Note: CleanUp() never gets called in non-debug builds because we exit early
// in ContentChild::ActorDestroy().
void
ContentProcess::CleanUp()
{
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX) && defined(NIGHTLY_BUILD)
CleanUpOldSandboxEnvironment();
#endif
mXREEmbed.Stop();
}

View File

@ -14,9 +14,9 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s || toolkit == 'androi
[test_cpow_cookies.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet'
[test_NuwaProcessCreation.html]
skip-if = toolkit != 'gonk'
skip-if = true # bug 1166923
[test_NuwaProcessDeadlock.html]
skip-if = toolkit != 'gonk'
skip-if = true # bug 1166923
[test_child_docshell.html]
skip-if = toolkit == 'cocoa' # disabled due to hangs, see changeset 6852e7c47edf
[test_CrashService_crash.html]

View File

@ -0,0 +1,185 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* ManifestImageObjectProcessor
* Implementation of Image Object processing algorithms from:
* http://www.w3.org/2008/webapps/manifest/#image-object-and-its-members
*
* This is intended to be used in conjunction with ManifestProcessor.jsm
*
* Creates an object to process Image Objects as defined by the
* W3C specification. This is used to process things like the
* icon member and the splash_screen member.
*
* Usage:
*
* .process(aManifest, aBaseURL, aMemberName, console);
*
*/
/*exported EXPORTED_SYMBOLS */
/*globals extractValue, Components*/
'use strict';
this.EXPORTED_SYMBOLS = ['ManifestImageObjectProcessor']; // jshint ignore:line
const imports = {};
const {
utils: Cu,
classes: Cc,
interfaces: Ci
} = Components;
const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1']
.getService(Ci.mozIJSSubScriptLoader);
scriptLoader.loadSubScript(
'resource://gre/modules/manifestValueExtractor.js',
this); // jshint ignore:line
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.importGlobalProperties(['URL']);
imports.netutil = Cc['@mozilla.org/network/util;1']
.getService(Ci.nsINetUtil);
imports.DOMUtils = Cc['@mozilla.org/inspector/dom-utils;1']
.getService(Ci.inIDOMUtils);
function ManifestImageObjectProcessor() {}
// Static getters
Object.defineProperties(ManifestImageObjectProcessor, {
'decimals': {
get: function() {
return /^\d+$/;
}
},
'anyRegEx': {
get: function() {
return new RegExp('any', 'i');
}
}
});
ManifestImageObjectProcessor.process = function(
aManifest, aBaseURL, aMemberName, console
) {
const spec = {
objectName: 'manifest',
object: aManifest,
property: aMemberName,
expectedType: 'array',
trim: false
};
const images = [];
const value = extractValue(spec, console);
if (Array.isArray(value)) {
// Filter out images whose "src" is not useful.
value.filter(item => !!processSrcMember(item, aBaseURL))
.map(toImageObject)
.forEach(image => images.push(image));
}
return images;
function toImageObject(aImageSpec) {
return {
'src': processSrcMember(aImageSpec, aBaseURL),
'type': processTypeMember(aImageSpec),
'sizes': processSizesMember(aImageSpec),
'density': processDensityMember(aImageSpec),
'background_color': processBackgroundColorMember(aImageSpec)
};
}
function processTypeMember(aImage) {
const charset = {};
const hadCharset = {};
const spec = {
objectName: 'image',
object: aImage,
property: 'type',
expectedType: 'string',
trim: true
};
let value = extractValue(spec, console);
if (value) {
value = imports.netutil.parseContentType(value, charset, hadCharset);
}
return value || undefined;
}
function processDensityMember(aImage) {
const value = parseFloat(aImage.density);
const validNum = Number.isNaN(value) || value === +Infinity || value <=
0;
return (validNum) ? 1.0 : value;
}
function processSrcMember(aImage, aBaseURL) {
const spec = {
objectName: 'image',
object: aImage,
property: 'src',
expectedType: 'string',
trim: false
};
const value = extractValue(spec, console);
let url;
if (value && value.length) {
try {
url = new URL(value, aBaseURL).href;
} catch (e) {}
}
return url;
}
function processSizesMember(aImage) {
const sizes = new Set();
const spec = {
objectName: 'image',
object: aImage,
property: 'sizes',
expectedType: 'string',
trim: true
};
const value = extractValue(spec, console);
if (value) {
// Split on whitespace and filter out invalid values.
value.split(/\s+/)
.filter(isValidSizeValue)
.forEach(size => sizes.add(size));
}
return sizes;
// Implementation of HTML's link@size attribute checker.
function isValidSizeValue(aSize) {
const size = aSize.toLowerCase();
if (ManifestImageObjectProcessor.anyRegEx.test(aSize)) {
return true;
}
if (!size.includes('x') || size.indexOf('x') !== size.lastIndexOf('x')) {
return false;
}
// Split left of x for width, after x for height.
const widthAndHeight = size.split('x');
const w = widthAndHeight.shift();
const h = widthAndHeight.join('x');
const validStarts = !w.startsWith('0') && !h.startsWith('0');
const validDecimals = ManifestImageObjectProcessor.decimals.test(w + h);
return (validStarts && validDecimals);
}
}
function processBackgroundColorMember(aImage) {
const spec = {
objectName: 'image',
object: aImage,
property: 'background_color',
expectedType: 'string',
trim: true
};
const value = extractValue(spec, console);
let color;
if (imports.DOMUtils.isValidCSSColor(value)) {
color = value;
} else {
const msg = `background_color: ${value} is not a valid CSS color.`;
console.warn(msg);
}
return color;
}
};
this.ManifestImageObjectProcessor = ManifestImageObjectProcessor; // jshint ignore:line

View File

@ -1,7 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
/*
* ManifestProcessor
* Implementation of processing algorithms from:
* http://www.w3.org/2008/webapps/manifest/
@ -12,54 +12,38 @@
*
* .process({jsonText,manifestURL,docURL});
*
* Depends on ManifestImageObjectProcessor to process things like
* icons and splash_screens.
*
* TODO: The constructor should accept the UA's supported orientations.
* TODO: The constructor should accept the UA's supported display modes.
* TODO: hook up developer tools to console. (1086997).
*/
/*exported EXPORTED_SYMBOLS */
/*JSLint options in comment below: */
/*globals Components, XPCOMUtils*/
/*globals Components, XPCOMUtils, extractValue*/
'use strict';
this.EXPORTED_SYMBOLS = ['ManifestProcessor'];
this.EXPORTED_SYMBOLS = ['ManifestProcessor']; // jshint ignore:line
const imports = {};
const {
utils: Cu,
classes: Cc,
interfaces: Ci
} = Components;
const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1']
.getService(Ci.mozIJSSubScriptLoader);
//Add extractValue() helper to this context.
scriptLoader.loadSubScript(
'resource://gre/modules/manifestValueExtractor.js',
this); // jshint ignore:line
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.importGlobalProperties(['URL']);
XPCOMUtils.defineLazyModuleGetter(imports, 'Services',
'resource://gre/modules/Services.jsm');
imports.netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil);
// Helper function extracts values from manifest members
// and reports conformance violations.
function extractValue({
objectName,
object,
property,
expectedType,
trim
}, console) {
const value = object[property];
const isArray = Array.isArray(value);
// We need to special-case "array", as it's not a JS primitive.
const type = (isArray) ? 'array' : typeof value;
if (type !== expectedType) {
if (type !== 'undefined') {
let msg = `Expected the ${objectName}'s ${property} `;
msg += `member to a be a ${expectedType}.`;
console.log(msg);
}
return undefined;
}
// Trim string and returned undefined if the empty string.
const shouldTrim = expectedType === 'string' && value && trim;
if (shouldTrim) {
return value.trim() || undefined;
}
return value;
}
XPCOMUtils.defineLazyModuleGetter(imports, 'ManifestImageObjectProcessor',
'resource://gre/modules/ManifestImageObjectProcessor.jsm');
imports.netutil = Cc['@mozilla.org/network/util;1']
.getService(Ci.nsINetUtil);
const displayModes = new Set(['fullscreen', 'standalone', 'minimal-ui',
'browser'
]);
@ -93,13 +77,12 @@ Object.defineProperties(ManifestProcessor, {
});
ManifestProcessor.prototype = {
// process method: processes json text into a clean manifest
// process method: processes JSON text into a clean manifest
// that conforms with the W3C specification. Takes an object
// expecting the following dictionary items:
// * jsonText: the JSON string to be processd.
// * manifestURL: the URL of the manifest, to resolve URLs.
// * docURL: the URL of the owner doc, for security checks.
// * aJsonText: the JSON string to be processed.
// * aManifestURL: the URL of the manifest, to resolve URLs.
// * aDocURL: the URL of the owner doc, for security checks.
process({
jsonText: aJsonText,
manifestURL: aManifestURL,
@ -120,15 +103,20 @@ ManifestProcessor.prototype = {
rawManifest = {};
}
const processedManifest = {
start_url: processStartURLMember(rawManifest, manifestURL, docURL),
display: processDisplayMember(rawManifest),
orientation: processOrientationMember(rawManifest),
name: processNameMember(rawManifest),
icons: IconsProcessor.process(rawManifest, manifestURL, console),
short_name: processShortNameMember(rawManifest),
'start_url': processStartURLMember(rawManifest, manifestURL, docURL),
'display': processDisplayMember(rawManifest),
'orientation': processOrientationMember(rawManifest),
'name': processNameMember(rawManifest),
'icons': imports.ManifestImageObjectProcessor.process(
rawManifest, manifestURL, 'icons', console
),
'splash_screens': imports.ManifestImageObjectProcessor.process(
rawManifest, manifestURL, 'splash_screens', console
),
'short_name': processShortNameMember(rawManifest),
};
processedManifest.scope = processScopeMember(rawManifest, manifestURL,
docURL, new URL(processedManifest.start_url));
docURL, new URL(processedManifest['start_url'])); // jshint ignore:line
return processedManifest;
@ -251,126 +239,4 @@ ManifestProcessor.prototype = {
}
}
};
this.ManifestProcessor = ManifestProcessor;
function IconsProcessor() {}
// Static getters
Object.defineProperties(IconsProcessor, {
'onlyDecimals': {
get: function() {
return /^\d+$/;
}
},
'anyRegEx': {
get: function() {
return new RegExp('any', 'i');
}
}
});
IconsProcessor.process = function(aManifest, aBaseURL, console) {
const spec = {
objectName: 'manifest',
object: aManifest,
property: 'icons',
expectedType: 'array',
trim: false
};
const icons = [];
const value = extractValue(spec, console);
if (Array.isArray(value)) {
// Filter out icons whose "src" is not useful.
value.filter(item => !!processSrcMember(item, aBaseURL))
.map(toIconObject)
.forEach(icon => icons.push(icon));
}
return icons;
function toIconObject(aIconData) {
return {
src: processSrcMember(aIconData, aBaseURL),
type: processTypeMember(aIconData),
sizes: processSizesMember(aIconData),
density: processDensityMember(aIconData)
};
}
function processTypeMember(aIcon) {
const charset = {};
const hadCharset = {};
const spec = {
objectName: 'icon',
object: aIcon,
property: 'type',
expectedType: 'string',
trim: true
};
let value = extractValue(spec, console);
if (value) {
value = imports.netutil.parseContentType(value, charset, hadCharset);
}
return value || undefined;
}
function processDensityMember(aIcon) {
const value = parseFloat(aIcon.density);
const validNum = Number.isNaN(value) || value === +Infinity || value <=
0;
return (validNum) ? 1.0 : value;
}
function processSrcMember(aIcon, aBaseURL) {
const spec = {
objectName: 'icon',
object: aIcon,
property: 'src',
expectedType: 'string',
trim: false
};
const value = extractValue(spec, console);
let url;
if (value && value.length) {
try {
url = new URL(value, aBaseURL).href;
} catch (e) {}
}
return url;
}
function processSizesMember(aIcon) {
const sizes = new Set(),
spec = {
objectName: 'icon',
object: aIcon,
property: 'sizes',
expectedType: 'string',
trim: true
},
value = extractValue(spec, console);
if (value) {
// Split on whitespace and filter out invalid values.
value.split(/\s+/)
.filter(isValidSizeValue)
.forEach(size => sizes.add(size));
}
return sizes;
// Implementation of HTML's link@size attribute checker.
function isValidSizeValue(aSize) {
const size = aSize.toLowerCase();
if (IconsProcessor.anyRegEx.test(aSize)) {
return true;
}
if (!size.includes('x') || size.indexOf('x') !== size.lastIndexOf('x')) {
return false;
}
// Split left of x for width, after x for height.
const widthAndHeight = size.split('x');
const w = widthAndHeight.shift();
const h = widthAndHeight.join('x');
const validStarts = !w.startsWith('0') && !h.startsWith('0');
const validDecimals = IconsProcessor.onlyDecimals.test(w + h);
return (validStarts && validDecimals);
}
}
};
this.ManifestProcessor = ManifestProcessor; // jshint ignore:line

View File

@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Helper function extracts values from manifest members
* and reports conformance violations.
*/
function extractValue({
objectName,
object,
property,
expectedType,
trim
}, console) {
const value = object[property];
const isArray = Array.isArray(value);
// We need to special-case "array", as it's not a JS primitive.
const type = (isArray) ? 'array' : typeof value;
if (type !== expectedType) {
if (type !== 'undefined') {
let msg = `Expected the ${objectName}'s ${property} `;
msg += `member to be a ${expectedType}.`;
console.log(msg);
}
return undefined;
}
// Trim string and returned undefined if the empty string.
const shouldTrim = expectedType === 'string' && value && trim;
if (shouldTrim) {
return value.trim() || undefined;
}
return value;
}

View File

@ -5,9 +5,11 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXTRA_JS_MODULES += [
'ManifestImageObjectProcessor.jsm',
'ManifestObtainer.jsm',
'ManifestProcessor.jsm',
'manifestValueExtractor.js'
]
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View File

@ -4,14 +4,16 @@ support-files =
resource.sjs
manifestLoader.html
[test_IconsProcessor_density.html]
[test_IconsProcessor_sizes.html]
[test_IconsProcessor_src.html]
[test_IconsProcessor_type.html]
[test_ImageObjectProcessor_background_color.html]
[test_ImageObjectProcessor_density.html]
[test_ImageObjectProcessor_sizes.html]
[test_ImageObjectProcessor_src.html]
[test_ImageObjectProcessor_type.html]
[test_ManifestProcessor_display.html]
[test_ManifestProcessor_icons.html]
[test_ManifestProcessor_JSON.html]
[test_ManifestProcessor_name_and_short_name.html]
[test_ManifestProcessor_orientation.html]
[test_ManifestProcessor_start_url.html]
[test_ManifestProcessor_scope.html]
[test_ManifestProcessor_scope.html]
[test_ManifestProcessor_splash_screens.html]

View File

@ -0,0 +1,84 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1162808
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1162808</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script src="common.js"></script>
<script type="application/javascript">
/**
* Image object's type member
* https://w3c.github.io/manifest/#type-member
*
* Checks that invalid and valid colors are processed correctly.
**/
/*globals data, processor, is*/
'use strict';
var testIcon = {
icons: [{
src: 'test',
'background_color': undefined
}]
};
// Test invalid colors.
var invalidColors = [
'marooon',
'f000000',
'#ff00000',
'rgb(255 0 0)',
'rgb(100, 0%, 0%)',
'rgb(255,0)',
'rgb(300 0 0)',
'rbg(255,-10,0)',
'rgb(110, 0%, 0%)',
'(255,0,0) }',
'rgba(255)',
' rgb(100%,0%,0%) }',
'hsl 120, 100%, 50%',
'hsla{120, 100%, 50%, 1}'
];
invalidColors.forEach((invalidColor) => {
var expected = `Treat invalid color (${invalidColor}) as undefined.`;
testIcon.icons[0].background_color = invalidColor;
data.jsonText = JSON.stringify(testIcon);
var result = processor.process(data);
is(result.icons[0].background_color, undefined, expected);
});
// Test valid colors.
var validColors = [
'maroon',
'#f00',
'#ff0000',
'rgb(255,0,0)',
'rgb(100%, 0%, 0%)',
'rgb(255,0,0)',
'rgb(300,0,0)',
'rgb(255,-10,0)',
'rgb(110%, 0%, 0%)',
'rgb(255,0,0)',
'rgba(255,0,0,1)',
'rgb(100%,0%,0%)',
'rgba(100%,0%,0%,1)',
'rgba(0,0,255,0.5)',
'rgba(100%, 50%, 0%, 0.1)',
'hsl(120, 100%, 50%)',
'hsla(120, 100%, 50%, 1)'
];
validColors.forEach((color) => {
var expected = `Treat valid CSS color (${color}) as valid input.`;
testIcon.icons[0].background_color = color;
data.jsonText = JSON.stringify(testIcon);
var result = processor.process(data);
is(result.icons[0].background_color, color, expected);
});
</script>
</head>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1162808">Mozilla Bug 1162808</a>

View File

@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1079453
<script src="common.js"></script>
<script>
/**
* icon member's density member
* Image object density member
* https://w3c.github.io/manifest/#density-member
**/
'use strict';

View File

@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1079453
<script src="common.js"></script>
<script>
/**
* icon member's sizes property
* Image object's sizes member
* https://w3c.github.io/manifest/#sizes-member
**/
'use strict';

View File

@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1079453
<script src="common.js"></script>
<script>
/**
* icon member's src member
* Image object's src member
* https://w3c.github.io/manifest/#src-member
**/
'use strict';

View File

@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1079453
<script src="common.js"></script>
<script>
/**
* icon member's type property
* Image object's type property
* https://w3c.github.io/manifest/#type-member
**/

View File

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1162808
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1162808</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script src="common.js"></script>
<script>
/**
* Manifest splash_screens member
* http://www.w3.org/TR/appmanifest/#splash_screens-member
**/
'use strict';
typeTests.forEach((type) => {
var expected = `Expect non-array splash_screens to be empty: ${typeof type}.`;
data.jsonText = JSON.stringify({
splash_screens: type
});
var result = processor.process(data);
is(result.splash_screens.length, 0, expected);
});
</script>
</head>

View File

@ -47,9 +47,10 @@ MediaStreamPlayback.prototype = {
startMedia : function(isResume) {
var canPlayThroughFired = false;
// If we're initially running this media, check that the time is zero
// If we're playing this media element for the first time,
// check that the time is zero.
if (!isResume) {
is(this.mediaStream.currentTime, 0,
is(this.mediaElement.currentTime, 0,
"Before starting the media element, currentTime = 0");
}

View File

@ -14,13 +14,13 @@ skip-if = toolkit == "gonk"
[test_tcpsocket_enabled_with_perm.html]
skip-if = toolkit == "gonk" || e10s
[test_networkstats_alarms.html]
skip-if = true # Bug 958689
skip-if = toolkit != "gonk"
[test_networkstats_basics.html]
skip-if = true # Bug 958689, bug 858005
skip-if = toolkit != "gonk"
[test_networkstats_disabled.html]
skip-if = toolkit != "gonk"
[test_networkstats_enabled_no_perm.html]
skip-if = true # Bug 958689
skip-if = toolkit != "gonk"
[test_networkstats_enabled_perm.html]
skip-if = toolkit != "gonk"
[test_udpsocket.html]

View File

@ -149,7 +149,6 @@ var steps = [
},
function () {
ok(true, "all done!\n");
SpecialPowers.removePermission("networkstats-manage", document);
SimpleTest.finish();
return;
}
@ -170,21 +169,23 @@ function next() {
SimpleTest.waitForExplicitFinish();
SpecialPowers.addPermission("networkstats-manage", true, document);
SpecialPowers.pushPrefEnv({'set': [["dom.mozNetworkStats.enabled", true]]},
function() {
ok(SpecialPowers.hasPermission("networkstats-manage", document),
"Has permission 'networkstats-manage'.");
SpecialPowers.pushPermissions([{ 'type': 'networkstats-manage', 'allow': 1, 'context': window.document }],
function() {
ok(SpecialPowers.hasPermission("networkstats-manage", document),
"Has permission 'networkstats-manage'.");
ok(SpecialPowers.getBoolPref("dom.mozNetworkStats.enabled"),
"Preference 'dom.mozNetworkStats.enabled' is true.");
ok(SpecialPowers.getBoolPref("dom.mozNetworkStats.enabled"),
"Preference 'dom.mozNetworkStats.enabled' is true.");
ok('mozNetworkStats' in navigator, "navigator.mozNetworkStats should exist");
ok('mozNetworkStats' in navigator, "navigator.mozNetworkStats should exist");
ok(navigator.mozNetworkStats instanceof SpecialPowers.Ci.nsIDOMMozNetworkStatsManager,
"navigator.mozNetworkStats should be a nsIDOMMozNetworkStatsManager object");
ok(navigator.mozNetworkStats instanceof SpecialPowers.Ci.nsIDOMMozNetworkStatsManager,
"navigator.mozNetworkStats should be a nsIDOMMozNetworkStatsManager object");
test();
test();
});
});
</script>

View File

@ -301,7 +301,6 @@ var steps = [
},
function () {
ok(true, "all done!\n");
SpecialPowers.removePermission("networkstats-manage", document);
SimpleTest.finish();
return;
}
@ -322,21 +321,23 @@ function next() {
SimpleTest.waitForExplicitFinish();
SpecialPowers.addPermission("networkstats-manage", true, document);
SpecialPowers.pushPrefEnv({'set': [["dom.mozNetworkStats.enabled", true]]},
function() {
ok(SpecialPowers.hasPermission("networkstats-manage", document),
"Has permission 'networkstats-manage'.");
SpecialPowers.pushPermissions([{ 'type': 'networkstats-manage', 'allow': 1, 'context': window.document }],
function() {
ok(SpecialPowers.hasPermission("networkstats-manage", document),
"Has permission 'networkstats-manage'.");
ok(SpecialPowers.getBoolPref("dom.mozNetworkStats.enabled"),
"Preference 'dom.mozNetworkStats.enabled' is true.");
ok(SpecialPowers.getBoolPref("dom.mozNetworkStats.enabled"),
"Preference 'dom.mozNetworkStats.enabled' is true.");
ok('mozNetworkStats' in navigator, "navigator.mozNetworkStats should exist");
ok('mozNetworkStats' in navigator, "navigator.mozNetworkStats should exist");
ok(navigator.mozNetworkStats instanceof SpecialPowers.Ci.nsIDOMMozNetworkStatsManager,
"navigator.mozNetworkStats should be a nsIDOMMozNetworkStatsManager object");
ok(navigator.mozNetworkStats instanceof SpecialPowers.Ci.nsIDOMMozNetworkStatsManager,
"navigator.mozNetworkStats should be a nsIDOMMozNetworkStatsManager object");
test();
test();
});
});
</script>

View File

@ -15,10 +15,12 @@
// Test to ensure NetworkStats is enabled but mozNetworkStats.getAvailableNetworks
// does not work in content because mozNetworkStats is null when no permission.
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [['dom.mozNetworkStats.enabled', true]]}, runTest);
function runTest() {
SpecialPowers.removePermission("networkstats-manage", document);
SpecialPowers.pushPrefEnv({"set": [['dom.mozNetworkStats.enabled', true]]},
function() {
SpecialPowers.pushPermissions([{ 'type': 'networkstats-manage', 'allow': 0, 'context': window.document }], runTest);
});
function runTest() {
ok(SpecialPowers.getBoolPref("dom.mozNetworkStats.enabled"),
"Preference 'dom.mozNetworkStats.enabled' is true.");

View File

@ -16,23 +16,25 @@
SimpleTest.waitForExplicitFinish();
// Test to ensure NetworkStats is not accessible when it is disabled
SpecialPowers.addPermission("networkstats-manage", true, document);
// Test to ensure NetworkStats is not accessible when it is disabled.
SpecialPowers.pushPrefEnv({'set': [["dom.mozNetworkStats.enabled", true]]},
function(){
ok(SpecialPowers.hasPermission("networkstats-manage", document),
"Has permission 'networkstats-manage'.");
function() {
SpecialPowers.pushPermissions([{ 'type': 'networkstats-manage', 'allow': 1, 'context': window.document }],
function() {
ok(SpecialPowers.getBoolPref("dom.mozNetworkStats.enabled"),
"Preference 'dom.mozNetworkStats.enabled' is true.");
ok(SpecialPowers.hasPermission("networkstats-manage", document),
"Has permission 'networkstats-manage'.");
ok('mozNetworkStats' in navigator, "navigator.mozNetworkStats should exist");
ok(SpecialPowers.getBoolPref("dom.mozNetworkStats.enabled"),
"Preference 'dom.mozNetworkStats.enabled' is true.");
ok(navigator.mozNetworkStats instanceof SpecialPowers.Ci.nsIDOMMozNetworkStatsManager,
"navigator.mozNetworkStats should be a nsIDOMMozNetworkStatsManager object");
ok('mozNetworkStats' in navigator, "navigator.mozNetworkStats should exist");
SpecialPowers.removePermission("networkstats-manage", document);
SimpleTest.finish();
ok(navigator.mozNetworkStats instanceof SpecialPowers.Ci.nsIDOMMozNetworkStatsManager,
"navigator.mozNetworkStats should be a nsIDOMMozNetworkStatsManager object");
SimpleTest.finish();
});
});
</script>

View File

@ -35,4 +35,5 @@ FINAL_LIBRARY = 'xul'
MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
BROWSER_CHROME_MANIFESTS += ['tests/browser.ini']
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']

View File

@ -1,7 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[DEFAULT]
[browser_monitorUncaught.js]

View File

@ -4,6 +4,8 @@
"use strict";
const { utils: Cu } = Components;
Cu.import("resource://gre/modules/Timer.jsm", this);
add_task(function* test_globals() {
@ -18,7 +20,7 @@ add_task(function* test_promiseID() {
let promise = [p1, p2, p3];
let identifiers = promise.map(PromiseDebugging.getPromiseID);
info("Identifiers: " + JSON.stringify(identifiers));
do_print("Identifiers: " + JSON.stringify(identifiers));
let idSet = new Set(identifiers);
Assert.equal(idSet.size, identifiers.length,
"PromiseDebugging.getPromiseID returns a distinct id per promise");
@ -42,7 +44,7 @@ add_task(function* test_observe_uncaught() {
};
CallbackResults.prototype = {
observe: function(promise) {
info(this.name + " observing Promise " + names.get(promise));
do_print(this.name + " observing Promise " + names.get(promise));
Assert.equal(PromiseDebugging.getState(promise).state, "rejected",
this.name + " observed a rejected Promise");
if (!this.expected.has(promise)) {
@ -62,8 +64,8 @@ add_task(function* test_observe_uncaught() {
if (this.expected.size == 0) {
this.resolve();
} else {
info(this.name + " is still waiting for " + this.expected.size + " observations:");
info(JSON.stringify([names.get(x) for (x of this.expected.values())]));
do_print(this.name + " is still waiting for " + this.expected.size + " observations:");
do_print(JSON.stringify([names.get(x) for (x of this.expected.values())]));
}
},
};
@ -117,7 +119,7 @@ add_task(function* test_observe_uncaught() {
// Reject a promise now, consume it later.
let p = Promise.reject("Reject now, consume later");
setTimeout(() => p.then(null, () => {
info("Consumed promise");
do_print("Consumed promise");
}), 200);
yield {
promise: p,
@ -190,7 +192,7 @@ add_task(function* test_observe_uncaught() {
let samples = [];
for (let s of makeSamples()) {
samples.push(s);
info("Promise '" + s.name + "' has id " + PromiseDebugging.getPromiseID(s.promise));
do_print("Promise '" + s.name + "' has id " + PromiseDebugging.getPromiseID(s.promise));
}
PromiseDebugging.addUncaughtRejectionObserver(observer);
@ -205,17 +207,17 @@ add_task(function* test_observe_uncaught() {
}
}
info("Test setup, waiting for callbacks.");
do_print("Test setup, waiting for callbacks.");
yield onLeftUncaught.blocker;
info("All calls to onLeftUncaught are complete.");
do_print("All calls to onLeftUncaught are complete.");
if (onConsumed.expected.size != 0) {
info("onConsumed is still waiting for the following Promise:");
info(JSON.stringify([names.get(x) for (x of onConsumed.expected.values())]));
do_print("onConsumed is still waiting for the following Promise:");
do_print(JSON.stringify([names.get(x) for (x of onConsumed.expected.values())]));
yield onConsumed.blocker;
}
info("All calls to onConsumed are complete.");
do_print("All calls to onConsumed are complete.");
let removed = PromiseDebugging.removeUncaughtRejectionObserver(observer);
Assert.ok(removed, "removeUncaughtRejectionObserver succeeded");
removed = PromiseDebugging.removeUncaughtRejectionObserver(observer);
@ -246,21 +248,23 @@ add_task(function* test_uninstall_observer() {
},
};
info("Adding an observer.");
do_print("Adding an observer.");
let deactivate = new Observer();
Promise.reject("I am an uncaught rejection.");
yield deactivate.blocker;
Assert.ok(true, "The observer has observed an uncaught Promise.");
deactivate.active = false;
info("Removing the observer, it should not observe any further uncaught Promise.");
do_print("Removing the observer, it should not observe any further uncaught Promise.");
info("Rejecting a Promise and waiting a little to give a chance to observers.");
do_print("Rejecting a Promise and waiting a little to give a chance to observers.");
let wait = new Observer();
Promise.reject("I am another uncaught rejection.");
yield wait.blocker;
yield new Promise(resolve => setTimeout(resolve, 100));
// Normally, `deactivate` should not be notified of the uncaught rejection.
wait.active = false;
});
function run_test() {
run_next_test();
}

View File

@ -0,0 +1,5 @@
[DEFAULT]
head =
tail =
[test_monitor_uncaught.js]

View File

@ -53,9 +53,6 @@ NS_IMPL_RELEASE_INHERITED(ServiceWorkerRegistrationBase, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistrationBase)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistrationBase,
DOMEventTargetHelper, mCCDummy);
ServiceWorkerRegistrationBase::ServiceWorkerRegistrationBase(nsPIDOMWindow* aWindow,
const nsAString& aScope)
: DOMEventTargetHelper(aWindow)

View File

@ -66,8 +66,6 @@ class ServiceWorkerRegistrationBase : public DOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerRegistrationBase,
DOMEventTargetHelper)
IMPL_EVENT_HANDLER(updatefound)
@ -91,8 +89,6 @@ protected:
{ }
const nsString mScope;
private:
nsCOMPtr<nsISupports> mCCDummy;
};
class ServiceWorkerRegistrationMainThread final : public ServiceWorkerRegistrationBase,
@ -120,10 +116,10 @@ public:
already_AddRefed<workers::ServiceWorker>
GetWaiting() override;
already_AddRefed<workers::ServiceWorker>
GetActive() override;
already_AddRefed<PushManager>
GetPushManager(ErrorResult& aRv);

View File

@ -969,7 +969,8 @@ GLBlitHelper::BlitFramebufferToTexture(GLuint srcFB, GLuint destTex,
GLenum destTarget,
bool internalFBs)
{
MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB));
// On the Android 4.3 emulator, IsFramebuffer may return false incorrectly.
MOZ_ASSERT_IF(mGL->Renderer() != GLRenderer::AndroidEmulator, !srcFB || mGL->fIsFramebuffer(srcFB));
MOZ_ASSERT(mGL->fIsTexture(destTex));
if (mGL->IsSupported(GLFeature::framebuffer_blit)) {

View File

@ -417,7 +417,7 @@ LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
// Draw a translation delay warning overlay
int width;
int border;
if ((now - mWarnTime).ToMilliseconds() < kVisualWarningDuration) {
if (!mWarnTime.IsNull() && (now - mWarnTime).ToMilliseconds() < kVisualWarningDuration) {
EffectChain effects;
// Black blorder

View File

@ -14,6 +14,10 @@
#include "gfx2DGlue.h"
#include "SharedSurfaceGralloc.h"
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
#include <ui/Fence.h>
#endif
namespace mozilla {
namespace layers {

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "GfxDriverInfo.h"
#include "nsVersionComparator.h"
using namespace mozilla::widget;
TEST(GfxWidgets, Split) {
char aStr[8], bStr[8], cStr[8], dStr[8];
ASSERT_TRUE(SplitDriverVersion("33.4.3.22", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 33 && atoi(bStr) == 4 && atoi(cStr) == 3 && atoi(dStr) == 22);
ASSERT_TRUE(SplitDriverVersion("28.74.0.0", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 28 && atoi(bStr) == 74 && atoi(cStr) == 0 && atoi(dStr) == 0);
ASSERT_TRUE(SplitDriverVersion("132.0.0.0", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 132 && atoi(bStr) == 0 && atoi(cStr) == 0 && atoi(dStr) == 0);
ASSERT_TRUE(SplitDriverVersion("2.3.0.0", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 2 && atoi(bStr) == 3 && atoi(cStr) == 0 && atoi(dStr) == 0);
ASSERT_TRUE(SplitDriverVersion("25.4.0.8", aStr, bStr, cStr, dStr));
ASSERT_TRUE(atoi(aStr) == 25 && atoi(bStr) == 4 && atoi(cStr) == 0 && atoi(dStr) == 8);
}
TEST(GfxWidgets, Versioning) {
ASSERT_TRUE(mozilla::Version("0") < mozilla::Version("41.0a1"));
ASSERT_TRUE(mozilla::Version("39.0.5b7") < mozilla::Version("41.0a1"));
ASSERT_TRUE(mozilla::Version("18.0.5b7") < mozilla::Version("18.2"));
ASSERT_TRUE(mozilla::Version("30.0.5b7") < mozilla::Version("41.0b9"));
ASSERT_TRUE(mozilla::Version("100") > mozilla::Version("43.0a1"));
ASSERT_FALSE(mozilla::Version("42.0") < mozilla::Version("42.0"));
ASSERT_TRUE(mozilla::Version("42.0b2") < mozilla::Version("42.0"));
ASSERT_TRUE(mozilla::Version("42.0b2") < mozilla::Version("42"));
ASSERT_TRUE(mozilla::Version("42.0b2") < mozilla::Version("43.0a1"));
ASSERT_TRUE(mozilla::Version("42") < mozilla::Version("43.0a1"));
ASSERT_TRUE(mozilla::Version("42.0") < mozilla::Version("43.0a1"));
ASSERT_TRUE(mozilla::Version("42.0.5") < mozilla::Version("43.0a1"));
ASSERT_TRUE(mozilla::Version("42.1") < mozilla::Version("43.0a1"));
ASSERT_TRUE(mozilla::Version("42.0a1") < mozilla::Version("42"));
ASSERT_TRUE(mozilla::Version("42.0a1") < mozilla::Version("42.0.5"));
ASSERT_TRUE(mozilla::Version("42.0b7") < mozilla::Version("42.0.5"));
ASSERT_TRUE(mozilla::Version("") == mozilla::Version("0"));
// Note these two; one would expect for 42.0b1 and 42b1 to compare the
// same, but they do not. If this ever changes, we want to know, so
// leave the test here to fail.
ASSERT_TRUE(mozilla::Version("42.0a1") < mozilla::Version("42.0b2"));
ASSERT_FALSE(mozilla::Version("42.0a1") < mozilla::Version("42b2"));
}

View File

@ -13,6 +13,7 @@ UNIFIED_SOURCES += [
'TestColorNames.cpp',
'TestCompositor.cpp',
'TestGfxPrefs.cpp',
'TestGfxWidgets.cpp',
'TestLayers.cpp',
'TestRegion.cpp',
'TestSkipChars.cpp',

78
image/ImageCacheKey.cpp Normal file
View File

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ImageCacheKey.h"
#include "mozilla/Move.h"
#include "File.h"
#include "ImageURL.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsString.h"
namespace mozilla {
using namespace dom;
namespace image {
ImageCacheKey::ImageCacheKey(nsIURI* aURI)
: mURI(new ImageURL(aURI))
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mURI);
bool isChrome;
mIsChrome = NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome;
mHash = ComputeHash(mURI);
}
ImageCacheKey::ImageCacheKey(ImageURL* aURI)
: mURI(aURI)
{
MOZ_ASSERT(mURI);
bool isChrome;
mIsChrome = NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome;
mHash = ComputeHash(mURI);
}
ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
: mURI(aOther.mURI)
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
{ }
ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
: mURI(Move(aOther.mURI))
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
{ }
bool
ImageCacheKey::operator==(const ImageCacheKey& aOther) const
{
return *mURI == *aOther.mURI;
}
const char*
ImageCacheKey::Spec() const
{
return mURI->Spec();
}
/* static */ uint32_t
ImageCacheKey::ComputeHash(ImageURL* aURI)
{
// Since we frequently call Hash() several times in a row on the same
// ImageCacheKey, as an optimization we compute our hash once and store it.
nsAutoCString spec;
aURI->GetSpec(spec);
return HashString(spec);
}
} // namespace image
} // namespace mozilla

55
image/ImageCacheKey.h Normal file
View File

@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* ImageCacheKey is the key type for the image cache (see imgLoader.h).
*/
#ifndef mozilla_image_src_ImageCacheKey_h
#define mozilla_image_src_ImageCacheKey_h
class nsIURI;
namespace mozilla {
namespace image {
class ImageURL;
/**
* An ImageLib cache entry key.
*
* We key the cache on the initial URI (before any redirects), with some
* canonicalization applied. See ComputeHash() for the details.
*/
class ImageCacheKey final
{
public:
explicit ImageCacheKey(nsIURI* aURI);
explicit ImageCacheKey(ImageURL* aURI);
ImageCacheKey(const ImageCacheKey& aOther);
ImageCacheKey(ImageCacheKey&& aOther);
bool operator==(const ImageCacheKey& aOther) const;
uint32_t Hash() const { return mHash; }
/// A weak pointer to the URI spec for this cache entry. For logging only.
const char* Spec() const;
/// Is this cache entry for a chrome image?
bool IsChrome() const { return mIsChrome; }
private:
static uint32_t ComputeHash(ImageURL* aURI);
nsRefPtr<ImageURL> mURI;
uint32_t mHash;
bool mIsChrome;
};
} // namespace image
} // namespace mozilla
#endif // mozilla_image_src_ImageCacheKey_h

View File

@ -44,6 +44,9 @@ public:
return NS_OK;
}
/// A weak pointer to the URI spec for this ImageURL. For logging only.
const char* Spec() const { return mSpec.get(); }
nsresult GetScheme(nsACString& result)
{
result = mScheme;
@ -74,6 +77,13 @@ public:
return newURI.forget();
}
bool operator==(const ImageURL& aOther) const
{
// Note that we don't need to consider mScheme and mRef, because they're
// already represented in mSpec.
return mSpec == aOther.mSpec;
}
private:
// Since this is a basic storage class, no duplication of spec parsing is
// included in the functionality. Instead, the class depends upon the

View File

@ -549,9 +549,10 @@ nsProgressNotificationProxy::GetInterface(const nsIID& iid,
static void
NewRequestAndEntry(bool aForcePrincipalCheckForCacheEntry, imgLoader* aLoader,
const ImageCacheKey& aKey,
imgRequest** aRequest, imgCacheEntry** aEntry)
{
nsRefPtr<imgRequest> request = new imgRequest(aLoader);
nsRefPtr<imgRequest> request = new imgRequest(aLoader, aKey);
nsRefPtr<imgCacheEntry> entry =
new imgCacheEntry(aLoader, request, aForcePrincipalCheckForCacheEntry);
aLoader->AddToUncachedImages(request);
@ -894,18 +895,12 @@ void
imgCacheEntry::SetHasNoProxies(bool hasNoProxies)
{
if (PR_LOG_TEST(GetImgLog(), PR_LOG_DEBUG)) {
nsRefPtr<ImageURL> uri;
mRequest->GetURI(getter_AddRefs(uri));
nsAutoCString spec;
if (uri) {
uri->GetSpec(spec);
}
if (hasNoProxies) {
LOG_FUNC_WITH_PARAM(GetImgLog(), "imgCacheEntry::SetHasNoProxies true",
"uri", spec.get());
"uri", mRequest->CacheKey().Spec());
} else {
LOG_FUNC_WITH_PARAM(GetImgLog(), "imgCacheEntry::SetHasNoProxies false",
"uri", spec.get());
"uri", mRequest->CacheKey().Spec());
}
}
@ -1078,15 +1073,11 @@ imgCacheExpirationTracker::NotifyExpired(imgCacheEntry* entry)
nsRefPtr<imgCacheEntry> kungFuDeathGrip(entry);
if (PR_LOG_TEST(GetImgLog(), PR_LOG_DEBUG)) {
nsRefPtr<imgRequest> req(entry->GetRequest());
nsRefPtr<imgRequest> req = entry->GetRequest();
if (req) {
nsRefPtr<ImageURL> uri;
req->GetURI(getter_AddRefs(uri));
nsAutoCString spec;
uri->GetSpec(spec);
LOG_FUNC_WITH_PARAM(GetImgLog(),
"imgCacheExpirationTracker::NotifyExpired",
"entry", spec.get());
"entry", req->CacheKey().Spec());
}
}
@ -1100,60 +1091,6 @@ imgCacheExpirationTracker::NotifyExpired(imgCacheEntry* entry)
}
///////////////////////////////////////////////////////////////////////////////
// ImageCacheKey
///////////////////////////////////////////////////////////////////////////////
ImageCacheKey::ImageCacheKey(nsIURI* aURI)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aURI);
bool isChrome;
mIsChrome = NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome;
aURI->GetSpec(mSpec);
mHash = ComputeHash(mSpec);
}
ImageCacheKey::ImageCacheKey(ImageURL* aURI)
{
MOZ_ASSERT(aURI);
bool isChrome;
mIsChrome = NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome;
aURI->GetSpec(mSpec);
mHash = ComputeHash(mSpec);
}
ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
: mSpec(aOther.mSpec)
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
{ }
ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
: mSpec(Move(aOther.mSpec))
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
{ }
bool
ImageCacheKey::operator==(const ImageCacheKey& aOther) const
{
return mSpec == aOther.mSpec;
}
/* static */ uint32_t
ImageCacheKey::ComputeHash(const nsACString& aSpec)
{
// Since we frequently call Hash() several times in a row on the same
// ImageCacheKey, as an optimization we compute our hash once and store it.
return HashString(aSpec);
}
///////////////////////////////////////////////////////////////////////////////
// imgLoader
///////////////////////////////////////////////////////////////////////////////
@ -1513,15 +1450,9 @@ imgLoader::PutIntoCache(const ImageCacheKey& aKey, imgCacheEntry* entry)
bool
imgLoader::SetHasNoProxies(imgRequest* aRequest, imgCacheEntry* aEntry)
{
if (PR_LOG_TEST(GetImgLog(), PR_LOG_DEBUG)) {
nsRefPtr<ImageURL> uri;
aRequest->GetURI(getter_AddRefs(uri));
nsAutoCString spec;
uri->GetSpec(spec);
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(),
"imgLoader::SetHasNoProxies", "uri", spec.get());
}
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(),
"imgLoader::SetHasNoProxies", "uri",
aRequest->CacheKey().Spec());
aEntry->SetHasNoProxies(true);
@ -1552,10 +1483,7 @@ imgLoader::SetHasProxies(imgRequest* aRequest)
{
VerifyCacheSizes();
nsRefPtr<ImageURL> uri;
aRequest->GetURI(getter_AddRefs(uri));
ImageCacheKey key(uri);
const ImageCacheKey& key = aRequest->CacheKey();
imgCacheTable& cache = GetCache(key);
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(),
@ -1606,15 +1534,11 @@ imgLoader::CheckCacheLimits(imgCacheTable& cache, imgCacheQueue& queue)
NS_ASSERTION(entry, "imgLoader::CheckCacheLimits -- NULL entry pointer");
if (PR_LOG_TEST(GetImgLog(), PR_LOG_DEBUG)) {
nsRefPtr<imgRequest> req(entry->GetRequest());
nsRefPtr<imgRequest> req = entry->GetRequest();
if (req) {
nsRefPtr<ImageURL> uri;
req->GetURI(getter_AddRefs(uri));
nsAutoCString spec;
uri->GetSpec(spec);
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(),
"imgLoader::CheckCacheLimits",
"entry", spec.get());
"entry", req->CacheKey().Spec());
}
}
@ -1932,36 +1856,30 @@ imgLoader::RemoveFromCache(imgCacheEntry* entry)
nsRefPtr<imgRequest> request = entry->GetRequest();
if (request) {
nsRefPtr<ImageURL> uri;
if (NS_SUCCEEDED(request->GetURI(getter_AddRefs(uri))) && uri) {
ImageCacheKey key(uri);
const ImageCacheKey& key = request->CacheKey();
imgCacheTable& cache = GetCache(key);
imgCacheQueue& queue = GetCacheQueue(key);
imgCacheTable& cache = GetCache(key);
imgCacheQueue& queue = GetCacheQueue(key);
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(),
"imgLoader::RemoveFromCache", "entry's uri",
key.Spec());
#ifdef DEBUG
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(),
"imgLoader::RemoveFromCache", "entry's uri",
key.Spec());
#endif
cache.Remove(key);
cache.Remove(key);
if (entry->HasNoProxies()) {
LOG_STATIC_FUNC(GetImgLog(),
"imgLoader::RemoveFromCache removing from tracker");
if (mCacheTracker) {
mCacheTracker->RemoveObject(entry);
}
queue.Remove(entry);
if (entry->HasNoProxies()) {
LOG_STATIC_FUNC(GetImgLog(),
"imgLoader::RemoveFromCache removing from tracker");
if (mCacheTracker) {
mCacheTracker->RemoveObject(entry);
}
entry->SetEvicted(true);
request->SetIsInCache(false);
AddToUncachedImages(request);
return true;
queue.Remove(entry);
}
entry->SetEvicted(true);
request->SetIsInCache(false);
AddToUncachedImages(request);
return true;
}
return false;
@ -2243,7 +2161,8 @@ imgLoader::LoadImage(nsIURI* aURI,
MOZ_ASSERT(NS_UsePrivateBrowsing(newChannel) == mRespectPrivacy);
NewRequestAndEntry(forcePrincipalCheck, this, getter_AddRefs(request),
NewRequestAndEntry(forcePrincipalCheck, this, key,
getter_AddRefs(request),
getter_AddRefs(entry));
PR_LOG(GetImgLog(), PR_LOG_DEBUG,
@ -2494,16 +2413,24 @@ imgLoader::LoadImageWithChannel(nsIChannel* channel,
requestFlags, _retval);
static_cast<imgRequestProxy*>(*_retval)->NotifyListener();
} else {
// Default to doing a principal check because we don't know who
// started that load and whether their principal ended up being
// inherited on the channel.
NewRequestAndEntry(true, this, getter_AddRefs(request),
getter_AddRefs(entry));
// We use originalURI here to fulfil the imgIRequest contract on GetURI.
nsCOMPtr<nsIURI> originalURI;
channel->GetOriginalURI(getter_AddRefs(originalURI));
// XXX(seth): We should be able to just use |key| here, except that |key| is
// constructed above with the *current URI* and not the *original URI*. I'm
// pretty sure this is a bug, and it's preventing us from ever getting a
// cache hit in LoadImageWithChannel when redirects are involved.
ImageCacheKey originalURIKey(originalURI);
// Default to doing a principal check because we don't know who
// started that load and whether their principal ended up being
// inherited on the channel.
NewRequestAndEntry(/* aForcePrincipalCheckForCacheEntry = */ true,
this, originalURIKey,
getter_AddRefs(request),
getter_AddRefs(entry));
// No principal specified here, because we're not passed one.
// In LoadImageWithChannel, the redirects that may have been
// assoicated with this load would have gone through necko.
@ -2521,7 +2448,7 @@ imgLoader::LoadImageWithChannel(nsIChannel* channel,
pl.forget(listener);
// Try to add the new request into the cache.
PutIntoCache(ImageCacheKey(originalURI), entry);
PutIntoCache(originalURIKey, entry);
rv = CreateNewProxyForRequest(request, loadGroup, aObserver,
requestFlags, _retval);
@ -2773,6 +2700,7 @@ imgCacheValidator::imgCacheValidator(nsProgressNotificationProxy* progress,
mHadInsecureRedirect(false)
{
NewRequestAndEntry(forcePrincipalCheckForCacheEntry, loader,
mRequest->CacheKey(),
getter_AddRefs(mNewRequest),
getter_AddRefs(mNewEntry));
}
@ -2901,7 +2829,7 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
// Try to add the new request into the cache. Note that the entry must be in
// the cache before the proxies' ownership changes, because adding a proxy
// changes the caching behaviour for imgRequests.
mImgLoader->PutIntoCache(ImageCacheKey(originalURI), mNewEntry);
mImgLoader->PutIntoCache(mNewRequest->CacheKey(), mNewEntry);
uint32_t count = mProxies.Count();
for (int32_t i = count-1; i>=0; i--) {

View File

@ -17,6 +17,7 @@
#include "nsRefPtrHashtable.h"
#include "nsExpirationTracker.h"
#include "nsAutoPtr.h"
#include "ImageCacheKey.h"
#include "imgRequest.h"
#include "nsIProgressEventSink.h"
#include "nsIChannel.h"
@ -214,38 +215,6 @@ enum class AcceptedMimeTypes : uint8_t {
IMAGES_AND_DOCUMENTS,
};
/**
* An ImageLib cache entry key.
*
* We key the cache on the initial URI (before any redirects), with some
* canonicalization applied. See ComputeHash() for the details.
*/
class ImageCacheKey final
{
public:
explicit ImageCacheKey(nsIURI* aURI);
explicit ImageCacheKey(mozilla::image::ImageURL* aURI);
ImageCacheKey(const ImageCacheKey& aOther);
ImageCacheKey(ImageCacheKey&& aOther);
bool operator==(const ImageCacheKey& aOther) const;
uint32_t Hash() const { return mHash; }
/// A weak pointer to the URI spec for this cache entry. For logging only.
const char* Spec() const { return mSpec.get(); }
/// Is this cache entry for a chrome image?
bool IsChrome() const { return mIsChrome; }
private:
static uint32_t ComputeHash(const nsACString& aSpec);
nsCString mSpec;
uint32_t mHash;
bool mIsChrome;
};
class imgLoader final : public imgILoader,
public nsIContentSniffer,
public imgICache,
@ -255,6 +224,7 @@ class imgLoader final : public imgILoader,
virtual ~imgLoader();
public:
typedef mozilla::image::ImageCacheKey ImageCacheKey;
typedef mozilla::image::ImageURL ImageURL;
typedef nsRefPtrHashtable<nsGenericHashKey<ImageCacheKey>,
imgCacheEntry> imgCacheTable;

View File

@ -60,8 +60,10 @@ NS_IMPL_ISUPPORTS(imgRequest,
nsIInterfaceRequestor,
nsIAsyncVerifyRedirectCallback)
imgRequest::imgRequest(imgLoader* aLoader)
imgRequest::imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey)
: mLoader(aLoader)
, mCacheKey(aCacheKey)
, mLoadId(nullptr)
, mValidator(nullptr)
, mInnerWindowId(0)
, mCORSMode(imgIRequest::CORS_NONE)

View File

@ -21,6 +21,7 @@
#include "nsIAsyncVerifyRedirectCallback.h"
#include "mozilla/Mutex.h"
#include "mozilla/net/ReferrerPolicy.h"
#include "ImageCacheKey.h"
class imgCacheValidator;
class imgLoader;
@ -49,12 +50,13 @@ class imgRequest final : public nsIStreamListener,
public nsIAsyncVerifyRedirectCallback
{
typedef mozilla::image::Image Image;
typedef mozilla::image::ImageCacheKey ImageCacheKey;
typedef mozilla::image::ImageURL ImageURL;
typedef mozilla::image::ProgressTracker ProgressTracker;
typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
public:
explicit imgRequest(imgLoader* aLoader);
imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISTREAMLISTENER
@ -143,6 +145,9 @@ public:
// Get the current principal of the image. No AddRefing.
inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); }
/// Get the ImageCacheKey associated with this request.
const ImageCacheKey& CacheKey() const { return mCacheKey; }
// Resize the cache entry to 0 if it exists
void ResetCacheEntry();
@ -246,6 +251,9 @@ private:
/* we hold on to this to this so long as we have observers */
nsRefPtr<imgCacheEntry> mCacheEntry;
/// The key under which this imgRequest is stored in the image cache.
ImageCacheKey mCacheKey;
void* mLoadId;
imgCacheValidator* mValidator;

View File

@ -34,6 +34,7 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'imglib2'
EXPORTS += [
'ImageCacheKey.h',
'ImageLogging.h',
'ImageOps.h',
'ImageRegion.h',
@ -53,6 +54,7 @@ UNIFIED_SOURCES += [
'FrameAnimator.cpp',
'FrozenImage.cpp',
'Image.cpp',
'ImageCacheKey.cpp',
'ImageFactory.cpp',
'ImageMetadata.cpp',
'ImageOps.cpp',

View File

@ -21,7 +21,12 @@ ParseContext<ParseHandler>::init(TokenStream& ts)
if (!frontend::GenerateBlockId(ts, this, this->bodyid))
return false;
return decls_.init() && lexdeps.ensureMap(sc->context);
if (!decls_.init() || !lexdeps.ensureMap(sc->context)) {
ReportOutOfMemory(sc->context);
return false;
}
return true;
}
template <typename ParseHandler>

View File

@ -1123,6 +1123,7 @@ inline uintptr_t
ArenaHeader::address() const
{
uintptr_t addr = reinterpret_cast<uintptr_t>(this);
MOZ_ASSERT(addr);
MOZ_ASSERT(!(addr & ArenaMask));
MOZ_ASSERT(Chunk::withinArenasRange(addr));
return addr;
@ -1186,7 +1187,8 @@ ArenaHeader::setNextDelayedMarking(ArenaHeader* aheader)
MOZ_ASSERT(!(uintptr_t(aheader) & ArenaMask));
MOZ_ASSERT(!auxNextLink && !hasDelayedMarking);
hasDelayedMarking = 1;
auxNextLink = aheader->arenaAddress() >> ArenaShift;
if (aheader)
auxNextLink = aheader->arenaAddress() >> ArenaShift;
}
inline void
@ -1209,7 +1211,8 @@ ArenaHeader::setNextAllocDuringSweep(ArenaHeader* aheader)
{
MOZ_ASSERT(!auxNextLink && !allocatedDuringIncremental);
allocatedDuringIncremental = 1;
auxNextLink = aheader->arenaAddress() >> ArenaShift;
if (aheader)
auxNextLink = aheader->arenaAddress() >> ArenaShift;
}
inline void

View File

@ -1948,8 +1948,10 @@ js::TenuringTracer::traceObjectSlots(NativeObject* nobj, uint32_t start, uint32_
HeapSlot* dynStart;
HeapSlot* dynEnd;
nobj->getSlotRange(start, length, &fixedStart, &fixedEnd, &dynStart, &dynEnd);
traceSlots(fixedStart->unsafeGet(), fixedEnd->unsafeGet());
traceSlots(dynStart->unsafeGet(), dynEnd->unsafeGet());
if (fixedStart)
traceSlots(fixedStart->unsafeGet(), fixedEnd->unsafeGet());
if (dynStart)
traceSlots(dynStart->unsafeGet(), dynEnd->unsafeGet());
}
void

View File

@ -397,9 +397,9 @@ js::TenuringTracer::~TenuringTracer()
runtime()->setNeedsIncrementalBarrier(savedRuntimeNeedBarrier);
}
#define TIME_START(name) int64_t timstampStart_##name = enableProfiling_ ? PRMJ_Now() : 0
#define TIME_END(name) int64_t timstampEnd_##name = enableProfiling_ ? PRMJ_Now() : 0
#define TIME_TOTAL(name) (timstampEnd_##name - timstampStart_##name)
#define TIME_START(name) int64_t timestampStart_##name = enableProfiling_ ? PRMJ_Now() : 0
#define TIME_END(name) int64_t timestampEnd_##name = enableProfiling_ ? PRMJ_Now() : 0
#define TIME_TOTAL(name) (timestampEnd_##name - timestampStart_##name)
void
js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList* pretenureGroups)
@ -427,7 +427,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
TraceMinorGCStart();
TIME_START(total);
int64_t timestampStart_total = PRMJ_Now();
AutoTraceSession session(rt, MinorCollecting);
AutoStopVerifyingBarriers av(rt, false);
@ -554,11 +554,14 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
if (rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes())
disable();
TIME_END(total);
int64_t totalTime = PRMJ_Now() - timestampStart_total;
rt->addTelemetry(JS_TELEMETRY_GC_MINOR_US, totalTime);
rt->addTelemetry(JS_TELEMETRY_GC_MINOR_REASON, reason);
if (totalTime > 1000)
rt->addTelemetry(JS_TELEMETRY_GC_MINOR_REASON_LONG, reason);
TraceMinorGCEnd();
int64_t totalTime = TIME_TOTAL(total);
if (enableProfiling_ && totalTime >= profileThreshold_) {
static bool printedHeader = false;
if (!printedHeader) {

View File

@ -397,7 +397,7 @@ struct AllPhaseIterator {
size_t activeSlot;
mozilla::Vector<Phase>::Range descendants;
explicit AllPhaseIterator(int64_t (*table)[PHASE_LIMIT])
explicit AllPhaseIterator(Statistics::PhaseTimeTable table)
: current(0)
, baseLevel(0)
, activeSlot(PHASE_DAG_NONE)
@ -444,7 +444,7 @@ struct AllPhaseIterator {
};
static void
FormatPhaseTimes(StatisticsSerializer& ss, const char* name, int64_t (*times)[PHASE_LIMIT])
FormatPhaseTimes(StatisticsSerializer& ss, const char* name, Statistics::PhaseTimeTable times)
{
ss.beginObject(name);
@ -585,8 +585,55 @@ Join(const FragmentVector& fragments) {
return UniqueChars(joined);
}
static int64_t
SumChildTimes(size_t phaseSlot, Phase phase, Statistics::PhaseTimeTable phaseTimes)
{
// Sum the contributions from single-parented children.
int64_t total = 0;
for (unsigned i = 0; i < PHASE_LIMIT; i++) {
if (phases[i].parent == phase)
total += phaseTimes[phaseSlot][i];
}
// Sum the contributions from multi-parented children.
size_t dagSlot = phaseExtra[phase].dagSlot;
if (dagSlot != PHASE_DAG_NONE) {
for (size_t i = 0; i < mozilla::ArrayLength(dagChildEdges); i++) {
if (dagChildEdges[i].parent == phase) {
Phase child = dagChildEdges[i].child;
total += phaseTimes[dagSlot][child];
}
}
}
return total;
}
UniqueChars
Statistics::formatDescription()
Statistics::formatDetailedMessage()
{
FragmentVector fragments;
if (!fragments.append(formatDetailedDescription()))
return UniqueChars(nullptr);
if (slices.length() > 1) {
for (unsigned i = 0; i < slices.length(); i++) {
if (!fragments.append(formatDetailedSliceDescription(i, slices[i])))
return UniqueChars(nullptr);
if (!fragments.append(formatDetailedPhaseTimes(slices[i].phaseTimes)))
return UniqueChars(nullptr);
}
}
if (!fragments.append(formatDetailedTotals()))
return UniqueChars(nullptr);
if (!fragments.append(formatDetailedPhaseTimes(phaseTimes)))
return UniqueChars(nullptr);
return Join(fragments);
}
UniqueChars
Statistics::formatDetailedDescription()
{
const double bytesPerMiB = 1024 * 1024;
@ -632,7 +679,7 @@ Statistics::formatDescription()
}
UniqueChars
Statistics::formatSliceDescription(unsigned i, const SliceData& slice)
Statistics::formatDetailedSliceDescription(unsigned i, const SliceData& slice)
{
char budgetDescription[200];
slice.budget.describe(budgetDescription, sizeof(budgetDescription) - 1);
@ -656,48 +703,7 @@ Statistics::formatSliceDescription(unsigned i, const SliceData& slice)
}
UniqueChars
Statistics::formatTotals()
{
int64_t total, longest;
gcDuration(&total, &longest);
const char* format =
"\
---- Totals ----\n\
Total Time: %.3fms\n\
Max Pause: %.3fms\n\
";
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
JS_snprintf(buffer, sizeof(buffer), format, t(total), t(longest));
return make_string_copy(buffer);
}
static int64_t
SumChildTimes(size_t phaseSlot, Phase phase, int64_t (*phaseTimes)[PHASE_LIMIT])
{
// Sum the contributions from single-parented children.
int64_t total = 0;
for (unsigned i = 0; i < PHASE_LIMIT; i++) {
if (phases[i].parent == phase)
total += phaseTimes[phaseSlot][i];
}
// Sum the contributions from multi-parented children.
size_t dagSlot = phaseExtra[phase].dagSlot;
if (dagSlot != PHASE_DAG_NONE) {
for (size_t i = 0; i < mozilla::ArrayLength(dagChildEdges); i++) {
if (dagChildEdges[i].parent == phase) {
Phase child = dagChildEdges[i].child;
total += phaseTimes[dagSlot][child];
}
}
}
return total;
}
UniqueChars
Statistics::formatPhaseTimes(int64_t (*phaseTimes)[PHASE_LIMIT])
Statistics::formatDetailedPhaseTimes(PhaseTimeTable phaseTimes)
{
static const char* LevelToIndent[] = { "", " ", " ", " " };
static const int64_t MaxUnaccountedChildTimeUS = 50;
@ -732,27 +738,21 @@ Statistics::formatPhaseTimes(int64_t (*phaseTimes)[PHASE_LIMIT])
}
UniqueChars
Statistics::formatDetailedMessage()
Statistics::formatDetailedTotals()
{
FragmentVector fragments;
int64_t total, longest;
gcDuration(&total, &longest);
if (!fragments.append(formatDescription()))
return UniqueChars(nullptr);
if (slices.length() > 1) {
for (unsigned i = 0; i < slices.length(); i++) {
if (!fragments.append(formatSliceDescription(i, slices[i])))
return UniqueChars(nullptr);
if (!fragments.append(formatPhaseTimes(slices[i].phaseTimes)))
return UniqueChars(nullptr);
}
}
if (!fragments.append(formatTotals()))
return UniqueChars(nullptr);
if (!fragments.append(formatPhaseTimes(phaseTimes)))
return UniqueChars(nullptr);
return Join(fragments);
const char* format =
"\
---- Totals ----\n\
Total Time: %.3fms\n\
Max Pause: %.3fms\n\
";
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
JS_snprintf(buffer, sizeof(buffer), format, t(total), t(longest));
return make_string_copy(buffer);
}
char16_t*
@ -775,7 +775,6 @@ Statistics::Statistics(JSRuntime* rt)
: runtime(rt),
startupTime(PRMJ_Now()),
fp(nullptr),
fullFormat(false),
gcDepth(0),
nonincrementalReason_(nullptr),
timedGCStart(0),
@ -840,36 +839,30 @@ Statistics::Statistics(JSRuntime* rt)
}
char* env = getenv("MOZ_GCTIMER");
if (!env || strcmp(env, "none") == 0) {
fp = nullptr;
return;
}
if (strcmp(env, "stdout") == 0) {
fullFormat = false;
fp = stdout;
} else if (strcmp(env, "stderr") == 0) {
fullFormat = false;
fp = stderr;
} else {
fullFormat = true;
fp = fopen(env, "a");
MOZ_ASSERT(fp);
if (env) {
if (strcmp(env, "none") == 0) {
fp = nullptr;
} else if (strcmp(env, "stdout") == 0) {
fp = stdout;
} else if (strcmp(env, "stderr") == 0) {
fp = stderr;
} else {
fp = fopen(env, "a");
if (!fp)
MOZ_CRASH("Failed to open MOZ_GCTIMER log file.");
}
}
}
Statistics::~Statistics()
{
if (fp) {
if (fullFormat) {
StatisticsSerializer ss(StatisticsSerializer::AsText);
FormatPhaseTimes(ss, "", phaseTotals);
char* msg = ss.finishCString();
if (msg) {
fprintf(fp, "TOTALS\n%s\n\n-------\n", msg);
js_free(msg);
}
StatisticsSerializer ss(StatisticsSerializer::AsText);
FormatPhaseTimes(ss, "", phaseTotals);
char* msg = ss.finishCString();
if (msg) {
fprintf(fp, "TOTALS\n%s\n\n-------\n", msg);
js_free(msg);
}
if (fp != stdout && fp != stderr)
@ -900,7 +893,7 @@ Statistics::getMaxGCPauseSinceClear()
}
static int64_t
SumPhase(Phase phase, int64_t (*times)[PHASE_LIMIT])
SumPhase(Phase phase, Statistics::PhaseTimeTable times)
{
int64_t sum = 0;
for (size_t i = 0; i < Statistics::MAX_MULTIPARENT_PHASES + 1; i++)
@ -912,26 +905,11 @@ void
Statistics::printStats()
{
if (aborted) {
if (fullFormat)
fprintf(fp, "OOM during GC statistics collection. The report is unavailable for this GC.\n");
fflush(fp);
return;
}
if (fullFormat) {
fprintf(fp, "OOM during GC statistics collection. The report is unavailable for this GC.\n");
} else {
UniqueChars msg = formatDetailedMessage();
if (msg)
fprintf(fp, "GC(T+%.3fs) %s\n", t(slices[0].start - startupTime) / 1000.0, msg.get());
} else {
int64_t total, longest;
gcDuration(&total, &longest);
int64_t markTotal = SumPhase(PHASE_MARK, phaseTimes);
fprintf(fp, "%f %f %f\n",
t(total),
t(markTotal),
t(phaseTimes[PHASE_DAG_NONE][PHASE_SWEEP]));
MOZ_ASSERT(phaseExtra[PHASE_SWEEP].dagSlot == PHASE_DAG_NONE);
}
fflush(fp);
}

View File

@ -232,13 +232,16 @@ struct Statistics
SliceRange sliceRange() const { return slices.all(); }
size_t slicesLength() const { return slices.length(); }
/* Create a convenient typedef for referring tables of phase times. */
typedef int64_t (*PhaseTimeTable)[PHASE_LIMIT];
private:
JSRuntime* runtime;
int64_t startupTime;
/* File pointer used for MOZ_GCTIMER output. */
FILE* fp;
bool fullFormat;
/*
* GCs can't really nest, but a second GC can be triggered from within the
@ -311,10 +314,10 @@ struct Statistics
void printStats();
bool formatData(StatisticsSerializer& ss, uint64_t timestamp);
UniqueChars formatDescription();
UniqueChars formatSliceDescription(unsigned i, const SliceData& slice);
UniqueChars formatTotals();
UniqueChars formatPhaseTimes(int64_t (*phaseTimes)[PHASE_LIMIT]);
UniqueChars formatDetailedDescription();
UniqueChars formatDetailedSliceDescription(unsigned i, const SliceData& slice);
UniqueChars formatDetailedPhaseTimes(PhaseTimeTable phaseTimes);
UniqueChars formatDetailedTotals();
double computeMMU(int64_t resolution);
};

View File

@ -107,8 +107,10 @@ BaselineCompiler::compile()
if (!emitOutOfLinePostBarrierSlot())
return Method_Error;
if (masm.oom())
if (masm.oom()) {
ReportOutOfMemory(cx);
return Method_Error;
}
Linker linker(masm);
AutoFlushICache afc("Baseline");
@ -170,8 +172,10 @@ BaselineCompiler::compile()
previousOffset = entry.nativeOffset;
}
if (pcEntries.oom())
if (pcEntries.oom()) {
ReportOutOfMemory(cx);
return Method_Error;
}
prologueOffset_.fixup(&masm);
epilogueOffset_.fixup(&masm);
@ -282,6 +286,7 @@ BaselineCompiler::compile()
JitcodeGlobalTable* globalTable = cx->runtime()->jitRuntime()->getJitcodeGlobalTable();
if (!globalTable->addEntry(entry, cx->runtime())) {
entry.destroy();
ReportOutOfMemory(cx);
return Method_Error;
}
@ -936,8 +941,10 @@ BaselineCompiler::emitBody()
bool addIndexEntry = (pc == script->code() || lastOpUnreachable || emittedOps > 100);
if (addIndexEntry)
emittedOps = 0;
if (!addPCMappingEntry(addIndexEntry))
if (!addPCMappingEntry(addIndexEntry)) {
ReportOutOfMemory(cx);
return Method_Error;
}
// Emit traps for breakpoints and step mode.
if (compileDebugInstrumentation_ && !emitDebugTrap())

View File

@ -228,14 +228,19 @@ jit::BaselineCompile(JSContext* cx, JSScript* script, bool forceDebugInstrumenta
LifoAlloc alloc(TempAllocator::PreferredLifoChunkSize);
TempAllocator* temp = alloc.new_<TempAllocator>(&alloc);
if (!temp)
if (!temp) {
ReportOutOfMemory(cx);
return Method_Error;
}
JitContext jctx(cx, temp);
BaselineCompiler compiler(cx, *temp, script);
if (!compiler.init())
if (!compiler.init()) {
ReportOutOfMemory(cx);
return Method_Error;
}
if (forceDebugInstrumentation)
compiler.setCompileDebugInstrumentation();

View File

@ -264,7 +264,7 @@ class RepatchIonCache::RepatchStubAppender : public IonCache::StubAttacher
public:
explicit RepatchStubAppender(RepatchIonCache& cache)
: StubAttacher(cache.rejoinLabel()),
: StubAttacher(cache.rejoinLabel_),
cache_(cache)
{
}
@ -302,6 +302,9 @@ RepatchIonCache::emitInitialJump(MacroAssembler& masm, AddCacheState& addState)
{
initialJump_ = masm.jumpWithPatch(&addState.repatchEntry);
lastJump_ = initialJump_;
Label label;
masm.bind(&label);
rejoinLabel_ = CodeOffsetLabel(label.offset());
}
void
@ -316,6 +319,7 @@ RepatchIonCache::updateBaseAddress(JitCode* code, MacroAssembler& masm)
IonCache::updateBaseAddress(code, masm);
initialJump_.repoint(code, &masm);
lastJump_.repoint(code, &masm);
rejoinLabel_.repoint(code, &masm);
}
class DispatchIonCache::DispatchStubPrepender : public IonCache::StubAttacher

View File

@ -354,26 +354,7 @@ class RepatchIonCache : public IonCache
CodeLocationJump initialJump_;
CodeLocationJump lastJump_;
// Offset from the initial jump to the rejoin label.
#ifdef JS_CODEGEN_ARM
static const size_t REJOIN_LABEL_OFFSET = 4;
#elif defined(JS_CODEGEN_MIPS)
// The size of jump created by MacroAssemblerMIPSCompat::jumpWithPatch.
static const size_t REJOIN_LABEL_OFFSET = 4 * sizeof(void*);
#else
static const size_t REJOIN_LABEL_OFFSET = 0;
#endif
CodeLocationLabel rejoinLabel() const {
uint8_t* ptr = initialJump_.raw();
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
uint32_t i = 0;
while (i < REJOIN_LABEL_OFFSET)
ptr = Assembler::NextInstruction(ptr, &i);
#endif
return CodeLocationLabel(ptr);
}
CodeLocationLabel rejoinLabel_;
public:
RepatchIonCache()
@ -395,7 +376,7 @@ class RepatchIonCache : public IonCache
void updateBaseAddress(JitCode* code, MacroAssembler& masm) override;
virtual void* rejoinAddress() override {
return rejoinLabel().raw();
return rejoinLabel_.raw();
}
};

View File

@ -373,13 +373,10 @@ class JitFrameLayout : public CommonFrameLayout
return offsetof(JitFrameLayout, numActualArgs_);
}
static size_t offsetOfThis() {
JitFrameLayout* base = nullptr;
return reinterpret_cast<size_t>(&base->argv()[0]);
return sizeof(JitFrameLayout);
}
static size_t offsetOfActualArgs() {
JitFrameLayout* base = nullptr;
// +1 to skip |this|.
return reinterpret_cast<size_t>(&base->argv()[1]);
return offsetOfThis() + sizeof(Value);
}
static size_t offsetOfActualArg(size_t arg) {
return offsetOfActualArgs() + arg * sizeof(Value);

View File

@ -888,6 +888,20 @@ template void
MacroAssembler::loadUnboxedProperty(BaseIndex address, JSValueType type,
TypedOrValueRegister output);
static void
StoreUnboxedFailure(MacroAssembler& masm, Label* failure)
{
// Storing a value to an unboxed property is a fallible operation and
// the caller must provide a failure label if a particular unboxed store
// might fail. Sometimes, however, a store that cannot succeed (such as
// storing a string to an int32 property) will be marked as infallible.
// This can only happen if the code involved is unreachable.
if (failure)
masm.jump(failure);
else
masm.assumeUnreachable("Incompatible write to unboxed property");
}
template <typename T>
void
MacroAssembler::storeUnboxedProperty(T address, JSValueType type,
@ -899,12 +913,12 @@ MacroAssembler::storeUnboxedProperty(T address, JSValueType type,
if (value.value().isBoolean())
store8(Imm32(value.value().toBoolean()), address);
else
jump(failure);
StoreUnboxedFailure(*this, failure);
} else if (value.reg().hasTyped()) {
if (value.reg().type() == MIRType_Boolean)
store8(value.reg().typedReg().gpr(), address);
else
jump(failure);
StoreUnboxedFailure(*this, failure);
} else {
if (failure)
branchTestBoolean(Assembler::NotEqual, value.reg().valueReg(), failure);
@ -917,12 +931,12 @@ MacroAssembler::storeUnboxedProperty(T address, JSValueType type,
if (value.value().isInt32())
store32(Imm32(value.value().toInt32()), address);
else
jump(failure);
StoreUnboxedFailure(*this, failure);
} else if (value.reg().hasTyped()) {
if (value.reg().type() == MIRType_Int32)
store32(value.reg().typedReg().gpr(), address);
else
jump(failure);
StoreUnboxedFailure(*this, failure);
} else {
if (failure)
branchTestInt32(Assembler::NotEqual, value.reg().valueReg(), failure);
@ -936,7 +950,7 @@ MacroAssembler::storeUnboxedProperty(T address, JSValueType type,
loadConstantDouble(value.value().toNumber(), ScratchDoubleReg);
storeDouble(ScratchDoubleReg, address);
} else {
jump(failure);
StoreUnboxedFailure(*this, failure);
}
} else if (value.reg().hasTyped()) {
if (value.reg().type() == MIRType_Int32) {
@ -945,7 +959,7 @@ MacroAssembler::storeUnboxedProperty(T address, JSValueType type,
} else if (value.reg().type() == MIRType_Double) {
storeDouble(value.reg().typedReg().fpu(), address);
} else {
jump(failure);
StoreUnboxedFailure(*this, failure);
}
} else {
ValueOperand reg = value.reg().valueReg();
@ -967,13 +981,13 @@ MacroAssembler::storeUnboxedProperty(T address, JSValueType type,
if (value.value().isObjectOrNull())
storePtr(ImmGCPtr(value.value().toObjectOrNull()), address);
else
jump(failure);
StoreUnboxedFailure(*this, failure);
} else if (value.reg().hasTyped()) {
MOZ_ASSERT(value.reg().type() != MIRType_Null);
if (value.reg().type() == MIRType_Object)
storePtr(value.reg().typedReg().gpr(), address);
else
jump(failure);
StoreUnboxedFailure(*this, failure);
} else {
if (failure) {
Label ok;
@ -990,12 +1004,12 @@ MacroAssembler::storeUnboxedProperty(T address, JSValueType type,
if (value.value().isString())
storePtr(ImmGCPtr(value.value().toString()), address);
else
jump(failure);
StoreUnboxedFailure(*this, failure);
} else if (value.reg().hasTyped()) {
if (value.reg().type() == MIRType_String)
storePtr(value.reg().typedReg().gpr(), address);
else
jump(failure);
StoreUnboxedFailure(*this, failure);
} else {
if (failure)
branchTestString(Assembler::NotEqual, value.reg().valueReg(), failure);

View File

@ -81,8 +81,10 @@ class BaselineCompilerShared
return nullptr;
// Create the entry and add it to the vector.
if (!icEntries_.append(ICEntry(script->pcToOffset(pc), kind)))
if (!icEntries_.append(ICEntry(script->pcToOffset(pc), kind))) {
ReportOutOfMemory(cx);
return nullptr;
}
ICEntry& vecEntry = icEntries_.back();
// Set the first stub for the IC entry to the fallback stub

View File

@ -116,6 +116,9 @@ enum {
JS_TELEMETRY_GC_NON_INCREMENTAL,
JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS,
JS_TELEMETRY_GC_MINOR_REASON,
JS_TELEMETRY_GC_MINOR_REASON_LONG,
JS_TELEMETRY_GC_MINOR_US,
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT,
JS_TELEMETRY_ADDON_EXCEPTIONS
};

View File

@ -530,9 +530,9 @@ BytecodeParser::addJump(uint32_t offset, uint32_t* currentOffset,
Bytecode*& code = codeArray_[offset];
if (!code) {
code = alloc().new_<Bytecode>();
if (!code)
return false;
if (!code->captureOffsetStack(alloc(), offsetStack, stackDepth)) {
if (!code ||
!code->captureOffsetStack(alloc(), offsetStack, stackDepth))
{
reportOOM();
return false;
}

View File

@ -3158,6 +3158,15 @@ AccumulateTelemetryCallback(int id, uint32_t sample, const char* key)
case JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS:
Telemetry::Accumulate(Telemetry::GC_SCC_SWEEP_MAX_PAUSE_MS, sample);
break;
case JS_TELEMETRY_GC_MINOR_REASON:
Telemetry::Accumulate(Telemetry::GC_MINOR_REASON, sample);
break;
case JS_TELEMETRY_GC_MINOR_REASON_LONG:
Telemetry::Accumulate(Telemetry::GC_MINOR_REASON_LONG, sample);
break;
case JS_TELEMETRY_GC_MINOR_US:
Telemetry::Accumulate(Telemetry::GC_MINOR_US, sample);
break;
case JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT:
Telemetry::Accumulate(Telemetry::JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, sample);
break;

View File

@ -46,13 +46,13 @@ span {
.test3 {
grid-template-areas:'. a .';
grid-template-columns: (a-start) 20px 20px (a-start-start) 20px (a-start-end);
grid-template-columns: [a-start] 20px 20px [a-start-start] 20px [a-start-end];
}
.test3 span { grid-column: a-start / 8; }
.test4, .test5 {
grid-template-areas:'. . . a';
grid-template-columns: 20px (a-start) 20px (a-start) 20px (a-end) 20px ;
grid-template-columns: 20px [a-start] 20px [a-start] 20px [a-end] 20px ;
}
.test4 span { grid-column: a-start 2 / 8; }
.test5 span { grid-column: a / 8; }

View File

@ -24,7 +24,7 @@ span {
.grid {
display: grid;
grid-template-columns: (A) 20px (A) 20px;
grid-template-columns: [A] 20px [A] 20px;
grid-template-rows: 20px 20px;
grid-auto-columns: 20px;
}

View File

@ -14,7 +14,7 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
.grid {
display: grid;
grid-template-columns: 20px 20px (A) 20px;
grid-template-columns: 20px 20px [A] 20px;
grid-template-rows: 20px;
grid-auto-columns: 20px;
grid-auto-rows: 20px;

View File

@ -1040,10 +1040,10 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
} else if (unit == eCSSUnit_List || unit == eCSSUnit_ListDep) {
// Non-empty <line-names>
aValue.Append('(');
aValue.Append('[');
rowsItem->mValue.AppendToString(eCSSProperty_grid_template_rows,
aValue, aSerialization);
aValue.Append(')');
aValue.Append(']');
} else {
nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[row++], aValue);

View File

@ -839,7 +839,7 @@ protected:
// to indicate that we parsed the empty list,
// or set it to a eCSSUnit_List of eCSSUnit_Ident.
//
// To parse an optional <line-names> (ie. if not finding an open paren
// To parse an optional <line-names> (ie. if not finding an open bracket
// is considered the same as an empty list),
// treat CSSParseResult::NotFound the same as CSSParseResult::Ok.
//
@ -8005,10 +8005,10 @@ CSSParserImpl::ParseGridAutoFlow()
CSSParseResult
CSSParserImpl::ParseGridLineNames(nsCSSValue& aValue)
{
if (!ExpectSymbol('(', true)) {
if (!ExpectSymbol('[', true)) {
return CSSParseResult::NotFound;
}
if (!GetToken(true) || mToken.IsSymbol(')')) {
if (!GetToken(true) || mToken.IsSymbol(']')) {
return CSSParseResult::Ok;
}
// 'return' so far leaves aValue untouched, to represent an empty list.
@ -8035,10 +8035,10 @@ CSSParserImpl::ParseGridLineNames(nsCSSValue& aValue)
if (!(eCSSToken_Ident == mToken.mType &&
ParseCustomIdent(item->mValue, mToken.mIdent))) {
UngetToken();
SkipUntil(')');
SkipUntil(']');
return CSSParseResult::Error;
}
if (!GetToken(true) || mToken.IsSymbol(')')) {
if (!GetToken(true) || mToken.IsSymbol(']')) {
return CSSParseResult::Ok;
}
item->mNext = new nsCSSValueList;

View File

@ -1944,7 +1944,7 @@ AppendGridTemplateToString(const nsCSSValueList* val,
} else if (unit == eCSSUnit_Null) {
// Empty or omitted <line-names>.
if (isSubgrid) {
aResult.AppendLiteral("()");
aResult.AppendLiteral("[]");
} else {
// Serializes to nothing.
addSpaceSeparator = false; // Avoid a double space.
@ -1952,10 +1952,10 @@ AppendGridTemplateToString(const nsCSSValueList* val,
} else if (unit == eCSSUnit_List || unit == eCSSUnit_ListDep) {
// Non-empty <line-names>
aResult.Append('(');
aResult.Append('[');
AppendValueListToString(val->mValue.GetListValue(), aProperty,
aResult, aSerialization);
aResult.Append(')');
aResult.Append(']');
} else {
// <track-size>

View File

@ -2272,7 +2272,7 @@ nsComputedDOMStyle::GetGridLineNames(const nsTArray<nsString>& aLineNames)
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
nsAutoString lineNamesString;
uint32_t i_end = aLineNames.Length();
lineNamesString.Assign('(');
lineNamesString.Assign('[');
if (i_end > 0) {
for (uint32_t i = 0;;) {
nsStyleUtil::AppendEscapedCSSIdent(aLineNames[i], lineNamesString);
@ -2282,7 +2282,7 @@ nsComputedDOMStyle::GetGridLineNames(const nsTArray<nsString>& aLineNames)
lineNamesString.Append(' ');
}
}
lineNamesString.Append(')');
lineNamesString.Append(']');
val->SetString(lineNamesString);
return val;
}

View File

@ -5790,32 +5790,32 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
"auto",
"40px",
"2.5fr",
"(normal) 40px () auto ( ) 12%",
"(foo) 40px min-content ( bar ) calc(20px + 10%) max-content",
"[normal] 40px [] auto [ ] 12%",
"[foo] 40px min-content [ bar ] calc(20px + 10%) max-content",
"40px min-content calc(20px + 10%) max-content",
"minmax(min-content, auto)",
"minmax(auto, max-content)",
"m\\69nmax(20px, 4Fr)",
"40px MinMax(min-content, calc(20px + 10%)) max-content",
"40px 2em",
"() 40px (-foo) 2em (bar baz This\ is\ one\ ident)",
// TODO bug 978478: "(a) repeat(3, (b) 20px (c) 40px (d)) (e)",
"[] 40px [-foo] 2em [bar baz This\ is\ one\ ident]",
// TODO bug 978478: "[a] repeat(3, [b] 20px [c] 40px [d]) [e]",
"repeat(1, 20px)",
"repeat(1, (a) 20px)",
"(a) Repeat(4, (a) 20px () auto (b c)) (d)",
"(a) 2.5fr Repeat(4, (a) 20px () auto (b c)) (d)",
"(a) 2.5fr (z) Repeat(4, (a) 20px () auto (b c)) (d)",
"(a) 2.5fr (z) Repeat(4, (a) 20px () auto) (d)",
"(a) 2.5fr (z) Repeat(4, 20px (b c) auto (b c)) (d)",
"(a) 2.5fr (z) Repeat(4, 20px auto) (d)",
"repeat(1, [a] 20px)",
"[a] Repeat(4, [a] 20px [] auto [b c]) [d]",
"[a] 2.5fr Repeat(4, [a] 20px [] auto [b c]) [d]",
"[a] 2.5fr [z] Repeat(4, [a] 20px [] auto [b c]) [d]",
"[a] 2.5fr [z] Repeat(4, [a] 20px [] auto) [d]",
"[a] 2.5fr [z] Repeat(4, 20px [b c] auto [b c]) [d]",
"[a] 2.5fr [z] Repeat(4, 20px auto) [d]",
// See https://bugzilla.mozilla.org/show_bug.cgi?id=981300
"(none auto subgrid min-content max-content foo) 40px",
"[none auto subgrid min-content max-content foo] 40px",
"subgrid",
"subgrid () (foo bar)",
"subgrid repeat(1, ())",
"subgrid Repeat(4, (a) (b c) () (d))",
"subgrid [] [foo bar]",
"subgrid repeat(1, [])",
"subgrid Repeat(4, [a] [b c] [] [d])",
],
invalid_values: [
"",
@ -5833,7 +5833,7 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
"(5th) 40px",
"(foo() bar) 40px",
"(foo)) 40px",
"[foo] 40px",
"(foo) 40px",
"(foo) (bar) 40px",
"40px (foo) (bar)",
"minmax()",
@ -5917,32 +5917,32 @@ if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
"subgrid",
// <'grid-template-columns'> / <'grid-template-rows'>
"40px / 100px",
"(foo) 40px (bar) / (baz) 100px (fizz)",
"[foo] 40px [bar] / [baz] 100px [fizz]",
" none/100px",
"40px/none",
"subgrid/40px 20px",
"subgrid (foo) () (bar baz) / 40px 20px",
"subgrid [foo] [] [bar baz] / 40px 20px",
"40px 20px/subgrid",
"40px 20px/subgrid (foo) () repeat(3, (a) (b)) (bar baz)",
"40px 20px/subgrid [foo] [] repeat(3, [a] [b]) [bar baz]",
"subgrid/subgrid",
"subgrid (foo) () (bar baz)/subgrid (foo) () (bar baz)",
"subgrid [foo] [] [bar baz]/subgrid [foo] [] [bar baz]",
// [ <track-list> / ]? [ <line-names>? <string> <track-size>? <line-names>? ]+
"'fizz'",
"(bar) 'fizz'",
"(foo) 40px / 'fizz'",
"(foo) 40px / (bar) 'fizz'",
"(foo) 40px / 'fizz' 100px",
"(foo) 40px / (bar) 'fizz' 100px",
"(foo) 40px / (bar) 'fizz' 100px (buzz)",
"(foo) 40px / (bar) 'fizz' 100px (buzz) \n (a) '.' 200px (b)",
"[bar] 'fizz'",
"[foo] 40px / 'fizz'",
"[foo] 40px / [bar] 'fizz'",
"[foo] 40px / 'fizz' 100px",
"[foo] 40px / [bar] 'fizz' 100px",
"[foo] 40px / [bar] 'fizz' 100px [buzz]",
"[foo] 40px / [bar] 'fizz' 100px [buzz] \n [a] '.' 200px [b]",
],
invalid_values: [
"subgrid ()",
"subgrid () / 'fizz'",
"subgrid []",
"subgrid [] / 'fizz'",
"subgrid / 'fizz'",
"(foo) (bar) 40px / 100px",
"40px / (fizz) (buzz) 100px",
"40px / (fizz) (buzz) 'foo'",
"[foo] [bar] 40px / 100px",
"40px / [fizz] [buzz] 100px",
"40px / [fizz] [buzz] 'foo'",
"none / 'foo'"
]
};

View File

@ -34,9 +34,9 @@ var grid_template_test_cases = [
gridTemplateRows: "100px",
},
{
specified: "(foo) 40px (bar) / (baz) 100px (fizz)",
gridTemplateColumns: "(foo) 40px (bar)",
gridTemplateRows: "(baz) 100px (fizz)",
specified: "[foo] 40px [bar] / [baz] 100px [fizz]",
gridTemplateColumns: "[foo] 40px [bar]",
gridTemplateRows: "[baz] 100px [fizz]",
},
{
specified: " none/100px",
@ -54,54 +54,54 @@ var grid_template_test_cases = [
gridTemplateRows: "20px",
},
{
specified: "40px/(a)repeat(1, 20px)",
specified: "40px/[a]repeat(1, 20px)",
gridTemplateColumns: "40px",
gridTemplateRows: "(a) 20px",
gridTemplateRows: "[a] 20px",
},
{
specified: "40px/repeat(1, (a) 20px)",
specified: "40px/repeat(1, [a] 20px)",
gridTemplateColumns: "40px",
gridTemplateRows: "(a) 20px",
gridTemplateRows: "[a] 20px",
},
{
specified: "40px/(a)repeat(2, (b)20px)",
specified: "40px/[a]repeat(2, [b]20px)",
gridTemplateColumns: "40px",
gridTemplateRows: "(a b) 20px (b) 20px",
gridTemplateRows: "[a b] 20px [b] 20px",
},
{
specified: "40px/(a)repeat(2, 20px)",
specified: "40px/[a]repeat(2, 20px)",
gridTemplateColumns: "40px",
gridTemplateRows: "(a) 20px 20px",
gridTemplateRows: "[a] 20px 20px",
},
{
specified: "40px/repeat(2, (a) 20px)",
specified: "40px/repeat(2, [a] 20px)",
gridTemplateColumns: "40px",
gridTemplateRows: "(a) 20px (a) 20px",
gridTemplateRows: "[a] 20px [a] 20px",
},
{
specified: "40px/(a)repeat(2, (b)20px)",
specified: "40px/[a]repeat(2, [b]20px)",
gridTemplateColumns: "40px",
gridTemplateRows: "(a b) 20px (b) 20px",
gridTemplateRows: "[a b] 20px [b] 20px",
},
{
specified: "40px/repeat(2, 20px(a))",
specified: "40px/repeat(2, 20px[a])",
gridTemplateColumns: "40px",
gridTemplateRows: "20px (a) 20px (a)",
gridTemplateRows: "20px [a] 20px [a]",
},
{
specified: "40px/repeat(2, 20px(a)) (b)",
specified: "40px/repeat(2, 20px[a]) [b]",
gridTemplateColumns: "40px",
gridTemplateRows: "20px (a) 20px (a b)",
gridTemplateRows: "20px [a] 20px [a b]",
},
{
specified: "40px/repeat(2, (a) 20px(b)) (c)",
specified: "40px/repeat(2, [a] 20px[b]) [c]",
gridTemplateColumns: "40px",
gridTemplateRows: "(a) 20px (b a) 20px (b c)",
gridTemplateRows: "[a] 20px [b a] 20px [b c]",
},
{
specified: "40px/(a) repeat(3, (b c) 20px (d) 100px (e f)) (g)",
specified: "40px/[a] repeat(3, [b c] 20px [d] 100px [e f]) [g]",
gridTemplateColumns: "40px",
gridTemplateRows: "(a b c) 20px (d) 100px (e f b c) 20px (d) 100px (e f b c) 20px (d) 100px (e f g)",
gridTemplateRows: "[a b c] 20px [d] 100px [e f b c] 20px [d] 100px [e f b c] 20px [d] 100px [e f g]",
},
{
specified: "'fizz'",
@ -109,33 +109,33 @@ var grid_template_test_cases = [
gridTemplateRows: "auto",
},
{
specified: "(bar) 'fizz'",
specified: "[bar] 'fizz'",
gridTemplateAreas: "\"fizz\"",
gridTemplateRows: "(bar) auto",
gridTemplateRows: "[bar] auto",
},
{
specified: "(foo) 40px / 'fizz'",
specified: "[foo] 40px / 'fizz'",
gridTemplateAreas: "\"fizz\"",
gridTemplateColumns: "(foo) 40px",
gridTemplateColumns: "[foo] 40px",
gridTemplateRows: "auto",
},
{
specified: "(foo) 40px / (bar) 'fizz'",
specified: "[foo] 40px / [bar] 'fizz'",
gridTemplateAreas: "\"fizz\"",
gridTemplateColumns: "(foo) 40px",
gridTemplateRows: "(bar) auto",
gridTemplateColumns: "[foo] 40px",
gridTemplateRows: "[bar] auto",
},
{
specified: "(foo) 40px / 'fizz' 100px",
specified: "[foo] 40px / 'fizz' 100px",
gridTemplateAreas: "\"fizz\"",
gridTemplateColumns: "(foo) 40px",
gridTemplateColumns: "[foo] 40px",
gridTemplateRows: "100px",
},
{
specified: "(foo) 40px / (bar) 'fizz' 100px (buzz) \n (a) '.' 200px (b)",
specified: "[foo] 40px / [bar] 'fizz' 100px [buzz] \n [a] '.' 200px [b]",
gridTemplateAreas: "\"fizz\" \".\"",
gridTemplateColumns: "(foo) 40px",
gridTemplateRows: "(bar) 100px (buzz a) 200px (b)",
gridTemplateColumns: "[foo] 40px",
gridTemplateRows: "[bar] 100px [buzz a] 200px [b]",
},
{
specified: "subgrid",
@ -148,28 +148,28 @@ var grid_template_test_cases = [
gridTemplateRows: "subgrid",
},
{
specified: "subgrid / subgrid (foo)",
specified: "subgrid / subgrid [foo]",
gridTemplateColumns: "subgrid",
gridTemplateRows: "subgrid (foo)",
gridTemplateRows: "subgrid [foo]",
},
{
specified: "subgrid / subgrid (foo) repeat(3, () (a b) (c))",
specified: "subgrid / subgrid [foo] repeat(3, [] [a b] [c])",
gridTemplateColumns: "subgrid",
gridTemplateRows: "subgrid (foo) () (a b) (c) () (a b) (c) () (a b) (c)",
gridTemplateRows: "subgrid [foo] [] [a b] [c] [] [a b] [c] [] [a b] [c]",
},
{
// https://bugzilla.mozilla.org/show_bug.cgi?id=978478#c1
// The number of repetitions is clamped to
// #define GRID_TEMPLATE_MAX_REPETITIONS 10000
specified: "subgrid / subgrid (foo) repeat(999999999, (a))",
specified: "subgrid / subgrid [foo] repeat(999999999, [a])",
gridTemplateColumns: "subgrid",
// Array(n + 1).join(s) is a hack for the non-standard s.repeat(n)
gridTemplateRows: "subgrid (foo)" + Array(10000 + 1).join(" (a)"),
gridTemplateRows: "subgrid [foo]" + Array(10000 + 1).join(" [a]"),
},
{
specified: "subgrid () (foo)/ subgrid (bar",
gridTemplateColumns: "subgrid () (foo)",
gridTemplateRows: "subgrid (bar)",
specified: "subgrid [] [foo]/ subgrid [bar",
gridTemplateColumns: "subgrid [] [foo]",
gridTemplateRows: "subgrid [bar]",
},
];

View File

@ -38,9 +38,9 @@ var grid_template_test_cases = [
shorthand: "40px / subgrid",
},
{
gridTemplateColumns: "(foo) 40px (bar)",
gridTemplateRows: "(baz) 100px (fizz)",
shorthand: "(foo) 40px (bar) / (baz) 100px (fizz)",
gridTemplateColumns: "[foo] 40px [bar]",
gridTemplateRows: "[baz] 100px [fizz]",
shorthand: "[foo] 40px [bar] / [baz] 100px [fizz]",
},
{
gridTemplateAreas: "\"a\"",
@ -49,8 +49,8 @@ var grid_template_test_cases = [
},
{
gridTemplateAreas: "\"a\"",
gridTemplateRows: "(foo) 20px (bar)",
shorthand: "(foo) \"a\" 20px (bar)",
gridTemplateRows: "[foo] 20px [bar]",
shorthand: "[foo] \"a\" 20px [bar]",
},
// Combinations of longhands that make the shorthand non-serializable:
{
@ -70,7 +70,7 @@ var grid_template_test_cases = [
},
{
gridTemplateAreas: "\"a\"",
gridTemplateRows: "subgrid (foo)",
gridTemplateRows: "subgrid [foo]",
shorthand: "",
},
{

View File

@ -313,7 +313,7 @@ function runTest() {
}
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(4);
SimpleTest.requestLongerTimeout(5);
SpecialPowers.pushPrefEnv({ set: [["layout.css.variables.enabled", true]] },
runTest);

View File

@ -1635,6 +1635,87 @@ void nsMenuPopupFrame::EnsureMenuItemIsVisible(nsMenuFrame* aMenuItem)
}
}
void nsMenuPopupFrame::ChangeByPage(bool aIsUp)
{
nsIFrame* parentMenu = GetParent();
if (parentMenu) {
// Only scroll by page within menulists.
nsCOMPtr<nsIDOMXULMenuListElement> menulist = do_QueryInterface(parentMenu->GetContent());
if (!menulist) {
return;
}
}
nsMenuFrame* newMenu = nullptr;
nsIFrame* currentMenu = mCurrentMenu;
if (!currentMenu) {
// If there is no current menu item, get the first item. When moving up,
// just use this as the newMenu and leave currentMenu null so that no
// check for a later element is performed. When moving down, set currentMenu
// so that we look for one page down from the first item.
newMenu = nsXULPopupManager::GetNextMenuItem(this, nullptr, true);
if (!aIsUp) {
currentMenu = newMenu;
}
}
if (currentMenu) {
nscoord scrollHeight = mRect.height;
nsIScrollableFrame *scrollframe = GetScrollFrame(this);
if (scrollframe) {
scrollHeight = scrollframe->GetScrollPortRect().height;
}
// Get the position of the current item and add or subtract one popup's
// height to or from it.
nscoord targetPosition = aIsUp ? currentMenu->GetRect().YMost() - scrollHeight :
currentMenu->GetRect().y + scrollHeight;
// Indicates that the last visible child was a valid menuitem.
bool lastWasValid = false;
// Look for the next child which is just past the target position. This child
// will need to be selected.
while (currentMenu) {
// Only consider menu frames.
nsMenuFrame* menuFrame = do_QueryFrame(currentMenu);
if (menuFrame &&
nsXULPopupManager::IsValidMenuItem(PresContext(), menuFrame->GetContent(), true)) {
// If the right position was found, break out. Otherwise, look for another item.
if ((!aIsUp && currentMenu->GetRect().YMost() > targetPosition) ||
(aIsUp && currentMenu->GetRect().y < targetPosition)) {
// If the last visible child was not a valid menuitem or was disabled,
// use this as the menu to select, skipping over any non-valid items at
// the edge of the page.
if (!lastWasValid) {
newMenu = menuFrame;
}
break;
}
// Assign this item to newMenu. This item will be selected in case we
// don't find any more.
lastWasValid = true;
newMenu = menuFrame;
}
else {
lastWasValid = false;
}
currentMenu = aIsUp ? currentMenu->GetPrevSibling() :
currentMenu->GetNextSibling();
}
}
// Select the new menuitem.
if (newMenu) {
ChangeMenuItem(newMenu, false);
}
}
NS_IMETHODIMP nsMenuPopupFrame::SetCurrentMenuItem(nsMenuFrame* aMenuItem)
{
if (mCurrentMenu == aMenuItem)

View File

@ -326,6 +326,8 @@ public:
void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame);
void ChangeByPage(bool aIsUp);
// Move the popup to the screen coordinate (aLeft, aTop) in CSS pixels.
// If aUpdateAttrs is true, and the popup already has left or top attributes,
// then those attributes are updated to the new location.

View File

@ -2172,6 +2172,13 @@ nsXULPopupManager::HandleKeyboardEventWithKeyCode(
HandleKeyboardNavigation(keyCode);
break;
case nsIDOMKeyEvent::DOM_VK_PAGE_DOWN:
case nsIDOMKeyEvent::DOM_VK_PAGE_UP:
if (aTopVisibleMenuItem) {
aTopVisibleMenuItem->Frame()->ChangeByPage(keyCode == nsIDOMKeyEvent::DOM_VK_PAGE_UP);
}
break;
case nsIDOMKeyEvent::DOM_VK_ESCAPE:
// Pressing Escape hides one level of menus only. If no menu is open,
// check if a menubar is active and inform it that a menu closed. Even

View File

@ -1307,6 +1307,8 @@ JsepSessionImpl::SetLocalDescription(JsepSdpType type, const std::string& sdp)
{
mLastError.clear();
MOZ_MTLOG(ML_DEBUG, "SetLocalDescription type=" << type << "\nSDP=\n"
<< sdp);
switch (mState) {
case kJsepStateStable:
if (type != kJsepSdpOffer) {

View File

@ -301,12 +301,15 @@ void AudioSendAndReceive::GenerateAndReadSamples()
FILE* inFile = fopen( iFile.c_str(), "wb+");
if(!inFile) {
cerr << "Input File Creation Failed " << endl;
free(inbuf);
return;
}
FILE* outFile = fopen( oFile.c_str(), "wb+");
if(!outFile) {
cerr << "Output File Creation Failed " << endl;
free(inbuf);
fclose(inFile);
return;
}
@ -323,6 +326,8 @@ void AudioSendAndReceive::GenerateAndReadSamples()
{
if(!memcpy(audioInput.get(), inbuf, sampleLengthInBytes))
{
free(inbuf);
fclose(outFile);
return;
}
@ -350,6 +355,7 @@ void AudioSendAndReceive::GenerateAndReadSamples()
}while(numSamplesReadFromInput < SAMPLES);
FinishWaveHeader(outFile);
free(inbuf);
fclose(outFile);
}

View File

@ -407,10 +407,17 @@ NS_IMPL_ADDREF(nsProtocolProxyService)
NS_IMPL_RELEASE(nsProtocolProxyService)
NS_IMPL_CLASSINFO(nsProtocolProxyService, nullptr, nsIClassInfo::SINGLETON,
NS_PROTOCOLPROXYSERVICE_CID)
NS_IMPL_QUERY_INTERFACE_CI(nsProtocolProxyService,
nsIProtocolProxyService,
nsIProtocolProxyService2,
nsIObserver)
// NS_IMPL_QUERY_INTERFACE_CI with the nsProtocolProxyService QI change
NS_INTERFACE_MAP_BEGIN(nsProtocolProxyService)
NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyService)
NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyService2)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
if ( aIID.Equals(NS_GET_IID(nsProtocolProxyService)) ) foundInterface = static_cast<nsIProtocolProxyService2*>(this); else
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIProtocolProxyService)
NS_IMPL_QUERY_CLASSINFO(nsProtocolProxyService)
NS_INTERFACE_MAP_END
NS_IMPL_CI_INTERFACE_GETTER(nsProtocolProxyService,
nsIProtocolProxyService,
nsIProtocolProxyService2)

View File

@ -4822,6 +4822,8 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
return rv;
}
// On error BeginConnect() should call AsyncAbort() before exiting until
// ContineBeginConnect after that it should not call it.
nsresult
nsHttpChannel::BeginConnect()
{
@ -4845,12 +4847,17 @@ nsHttpChannel::BeginConnect()
mURI->GetUsername(mUsername);
if (NS_SUCCEEDED(rv))
rv = mURI->GetAsciiSpec(mSpec);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
AsyncAbort(rv);
return rv;
}
// Reject the URL if it doesn't specify a host
if (host.IsEmpty())
return NS_ERROR_MALFORMED_URI;
if (host.IsEmpty()) {
rv = NS_ERROR_MALFORMED_URI;
AsyncAbort(rv);
return rv;
}
LOG(("host=%s port=%d\n", host.get(), port));
LOG(("uri=%s\n", mSpec.get()));
@ -4923,8 +4930,10 @@ nsHttpChannel::BeginConnect()
&rv);
if (NS_SUCCEEDED(rv))
rv = mAuthProvider->Init(this);
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
AsyncAbort(rv);
return rv;
}
// check to see if authorization headers should be included
mAuthProvider->AddAuthorizationHeaders();
@ -4935,7 +4944,11 @@ nsHttpChannel::BeginConnect()
// Check to see if we should redirect this channel elsewhere by
// nsIHttpChannel.redirectTo API request
if (mAPIRedirectToURI) {
return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
rv = AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
if (NS_FAILED(rv)) {
AsyncAbort(rv);
}
return rv;
}
// Check to see if this principal exists on local blocklists.
nsRefPtr<nsChannelClassifier> channelClassifier = new nsChannelClassifier();
@ -5028,6 +5041,8 @@ nsHttpChannel::BeginConnect()
mCaps &= ~NS_HTTP_ALLOW_PIPELINING;
}
if (!(mLoadFlags & LOAD_CLASSIFY_URI)) {
// On error ContinueBeginConnect() will call AsyncAbort so do not do it
// here
return ContinueBeginConnect();
}
// mLocalBlocklist is true only if tracking protection is enabled and the
@ -5038,6 +5053,8 @@ nsHttpChannel::BeginConnect()
if (mCanceled || !mLocalBlocklist) {
rv = ContinueBeginConnect();
if (NS_FAILED(rv)) {
// On error ContinueBeginConnect() will call AsyncAbort so do not do
// it here
return rv;
}
callContinueBeginConnect = false;
@ -5161,21 +5178,15 @@ nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIChannel *channel,
LOG(("nsHttpChannel::OnProxyAvailable [this=%p] "
"Handler no longer active.\n", this));
rv = NS_ERROR_NOT_AVAILABLE;
AsyncAbort(rv);
}
else {
// On error BeginConnect() will call AsyncAbort.
rv = BeginConnect();
}
if (NS_FAILED(rv)) {
Cancel(rv);
// Calling OnStart/OnStop synchronously here would mean doing it before
// returning from AsyncOpen which is a contract violation. Do it async.
nsRefPtr<nsRunnableMethod<HttpBaseChannel> > event =
NS_NewRunnableMethod(this, &nsHttpChannel::DoNotifyListener);
rv = NS_DispatchToCurrentThread(event);
if (NS_FAILED(rv)) {
NS_WARNING("Failed To Dispatch DoNotifyListener");
}
}
return rv;
}

View File

@ -1,53 +1,54 @@
var ScriptableUnicodeConverter =
"use strict";
let ScriptableUnicodeConverter =
Components.Constructor("@mozilla.org/intl/scriptableunicodeconverter",
"nsIScriptableUnicodeConverter");
function getHMAC(data, key, alg)
{
var converter = new ScriptableUnicodeConverter();
converter.charset = 'utf8';
var dataarray = converter.convertToByteArray(data);
var keyObject = Components.classes["@mozilla.org/security/keyobjectfactory;1"]
.getService(Components.interfaces.nsIKeyObjectFactory)
.keyFromString(Components.interfaces.nsIKeyObject.HMAC, key);
var cryptoHMAC = Components.classes["@mozilla.org/security/hmac;1"]
.createInstance(Components.interfaces.nsICryptoHMAC);
"nsIScriptableUnicodeConverter");
function getHMAC(data, key, alg) {
let converter = new ScriptableUnicodeConverter();
converter.charset = "utf8";
let dataArray = converter.convertToByteArray(data);
let keyObject = Cc["@mozilla.org/security/keyobjectfactory;1"]
.getService(Ci.nsIKeyObjectFactory)
.keyFromString(Ci.nsIKeyObject.HMAC, key);
let cryptoHMAC = Cc["@mozilla.org/security/hmac;1"]
.createInstance(Ci.nsICryptoHMAC);
cryptoHMAC.init(alg, keyObject);
cryptoHMAC.update(dataarray, dataarray.length);
var digest1 = cryptoHMAC.finish(false);
cryptoHMAC.update(dataArray, dataArray.length);
let digest1 = cryptoHMAC.finish(false);
cryptoHMAC.reset();
cryptoHMAC.update(dataarray, dataarray.length);
var digest2 = cryptoHMAC.finish(false);
do_check_eq(digest1, digest2);
cryptoHMAC.update(dataArray, dataArray.length);
let digest2 = cryptoHMAC.finish(false);
equal(digest1, digest2,
"Initial digest and digest after calling reset() should match");
return digest1;
}
function testHMAC(alg) {
const key1 = 'MyKey_ABCDEFGHIJKLMN';
const key2 = 'MyKey_01234567890123';
const dataA = "Secret message";
const dataB = "Secres message";
var diegest1a = getHMAC(key1, dataA, alg);
var diegest2 = getHMAC(key2, dataA, alg);
var diegest1b = getHMAC(key1, dataA, alg);
do_check_eq(diegest1a, diegest1b);
do_check_neq(diegest1a, diegest2);
var diegest1 = getHMAC(key1, dataA, alg);
diegest2 = getHMAC(key1, dataB, alg);
do_check_neq(diegest1, diegest2);
return diegest1;
let digest1a = getHMAC(key1, dataA, alg);
let digest2 = getHMAC(key2, dataA, alg);
let digest1b = getHMAC(key1, dataA, alg);
equal(digest1a, digest1b,
"The digests for the same key, data and algorithm should match");
notEqual(digest1a, digest2, "The digests for different keys should not match");
let digest1 = getHMAC(key1, dataA, alg);
digest2 = getHMAC(key1, dataB, alg);
notEqual(digest1, digest2, "The digests for different data should not match");
}
function hexdigest(data) {
@ -56,35 +57,32 @@ function hexdigest(data) {
function testVectors() {
// These are test vectors taken from RFC 4231, section 4.3. (Test Case 2)
const keyTestVector = "Jefe";
const dataTestVector = "what do ya want for nothing?";
var diegest;
/*
Bug 356713
diegest = hexdigest(getHMAC(dataTestVector, keyTestVector,
Components.interfaces.nsICryptoHMAC.SHA224));
do_check_eq(diegest, "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44");
*/
let digest = hexdigest(getHMAC(dataTestVector, keyTestVector,
Ci.nsICryptoHMAC.SHA256));
equal(digest,
"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
"Actual and expected SHA-256 digests should match");
diegest = hexdigest(getHMAC(dataTestVector, keyTestVector,
Components.interfaces.nsICryptoHMAC.SHA256));
do_check_eq(diegest, "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
digest = hexdigest(getHMAC(dataTestVector, keyTestVector,
Ci.nsICryptoHMAC.SHA384));
equal(digest,
"af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649",
"Actual and expected SHA-384 digests should match");
diegest = hexdigest(getHMAC(dataTestVector, keyTestVector,
Components.interfaces.nsICryptoHMAC.SHA384));
do_check_eq(diegest, "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649");
diegest = hexdigest(getHMAC(dataTestVector, keyTestVector,
Components.interfaces.nsICryptoHMAC.SHA512));
do_check_eq(diegest, "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737");
digest = hexdigest(getHMAC(dataTestVector, keyTestVector,
Ci.nsICryptoHMAC.SHA512));
equal(digest,
"164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
"Actual and expected SHA-512 digests should match");
}
function run_test() {
testVectors();
testHMAC(Components.interfaces.nsICryptoHMAC.SHA1);
testHMAC(Components.interfaces.nsICryptoHMAC.SHA512);
testHMAC(Components.interfaces.nsICryptoHMAC.MD5);
testHMAC(Ci.nsICryptoHMAC.SHA1);
testHMAC(Ci.nsICryptoHMAC.SHA512);
testHMAC(Ci.nsICryptoHMAC.MD5);
}

View File

@ -134,7 +134,7 @@ FrameManager.prototype = {
frameMessageManager.sendAsyncMessage("aliveCheck", {});
} catch (e) {
if (e.result == Components.results.NS_ERROR_NOT_INITIALIZED) {
remoteFrames.splice(i, 1);
remoteFrames.splice(i--, 1);
continue;
}
}

View File

@ -331,6 +331,25 @@
"n_buckets": 50,
"description": "Time spent sweeping slowest compartment SCC (ms)"
},
"GC_MINOR_REASON": {
"expires_in_version": "never",
"kind": "enumerated",
"n_values": "JS::gcreason::NUM_TELEMETRY_REASONS",
"description": "Reason (enum value) for initiating a minor GC"
},
"GC_MINOR_REASON_LONG": {
"expires_in_version": "never",
"kind": "enumerated",
"n_values": "JS::gcreason::NUM_TELEMETRY_REASONS",
"description": "Reason (enum value) that caused a long (>1ms) minor GC"
},
"GC_MINOR_US": {
"expires_in_version": "never",
"kind": "exponential",
"high": "1000000",
"n_buckets": 100,
"description": "Time spent running JS minor GC (us)"
},
"GEOLOCATION_ACCURACY_EXPONENTIAL": {
"expires_in_version": "default",
"kind": "exponential",

View File

@ -116,6 +116,7 @@ skip-if = buildapp == 'mulet'
skip-if = buildapp == 'mulet'
[test_menulist_keynav.xul]
[test_menulist_null_value.xul]
[test_menulist_paging.xul]
[test_mousecapture.xul]
skip-if = buildapp == 'mulet'
[test_mousescroll.xul]

View File

@ -0,0 +1,133 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Menulist Tests"
onload="setTimeout(startTest, 0);"
onpopupshown="menulistShown()" onpopuphidden="runTest()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<menulist id="menulist1">
<menupopup id="menulist-popup1">
<menuitem label="One"/>
<menuitem label="Two"/>
<menuitem label="Three"/>
<menuitem label="Four"/>
<menuitem label="Five"/>
<menuitem label="Six"/>
<menuitem label="Seven"/>
<menuitem label="Eight"/>
<menuitem label="Nine"/>
<menuitem label="Ten"/>
</menupopup>
</menulist>
<menulist id="menulist2">
<menupopup id="menulist-popup2">
<menuitem label="One" disabled="true"/>
<menuitem label="Two" selected="true"/>
<menuitem label="Three"/>
<menuitem label="Four"/>
<menuitem label="Five"/>
<menuitem label="Six"/>
<menuitem label="Seven"/>
<menuitem label="Eight"/>
<menuitem label="Nine"/>
<menuitem label="Ten" disabled="true"/>
</menupopup>
</menulist>
<menulist id="menulist3">
<menupopup id="menulist-popup3">
<label value="One"/>
<menuitem label="Two" selected="true"/>
<menuitem label="Three"/>
<menuitem label="Four"/>
<menuitem label="Five" disabled="true"/>
<menuitem label="Six" disabled="true"/>
<menuitem label="Seven"/>
<menuitem label="Eight"/>
<menuitem label="Nine"/>
<label value="Ten"/>
</menupopup>
</menulist>
<script class="testbody" type="application/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
let test;
// Windows allows disabled items to be selected.
let isWindows = navigator.platform.indexOf("Win") >= 0;
let tests = [
{ list: "menulist1", initial: 0, downs: [3, 6, 9, 9],
ups: [6, 3, 0, 0] },
{ list: "menulist2", initial: 1, downs: [4, 7, isWindows ? 9 : 8, isWindows ? 9 : 8],
ups: [isWindows ? 6 : 5, isWindows ? 3 : 2, isWindows ? 0 : 1] },
{ list: "menulist3", initial: 1, downs: [isWindows ? 4 : 6, isWindows ? 7 : 8, 8],
ups: [isWindows ? 5 : 3, isWindows ? 2 : 1, 1] }
];
function startTest()
{
let popup = document.getElementById("menulist-popup1");
let menupopupHeight = popup.getBoundingClientRect().height;
let menuitemHeight = popup.firstChild.getBoundingClientRect().height;
// First, set the height of each popup to the height of four menuitems plus
// any padding and border on the menupopup.
let height = menuitemHeight * 4 + (menupopupHeight - menuitemHeight * 10);
popup.height = height;
document.getElementById("menulist-popup2").height = height;
document.getElementById("menulist-popup3").height = height;
runTest();
}
function runTest()
{
if (!tests.length) {
SimpleTest.finish();
return;
}
test = tests.shift();
document.getElementById(test.list).open = true;
}
function menulistShown()
{
let menulist = document.getElementById(test.list);
is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.initial).label, test.list + " initial selection");
for (let i = 0; i < test.downs.length; i++) {
sendKey("PAGE_DOWN");
is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.downs[i]).label, test.list + " page down " + i);
}
for (let i = 0; i < test.ups.length; i++) {
sendKey("PAGE_UP");
is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.ups[i]).label, test.list + " page up " + i);
}
menulist.open = false;
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display">
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</window>

View File

@ -694,6 +694,47 @@ CleanUpSandboxEnvironment()
// Get and remove the low integrity Mozilla temp directory.
// This function already warns if the deletion fails.
unused << GetAndCleanLowIntegrityTemp(tempDirSuffix);
#if defined(NIGHTLY_BUILD)
// Temporary code to clean up the old low integrity temp directories.
// The removal of this is tracked by bug 1165818.
nsCOMPtr<nsIFile> lowIntegrityMozilla;
nsresult rv = NS_GetSpecialDirectory(NS_WIN_LOW_INTEGRITY_TEMP_BASE,
getter_AddRefs(lowIntegrityMozilla));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsISimpleEnumerator> iter;
rv = lowIntegrityMozilla->GetDirectoryEntries(getter_AddRefs(iter));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
bool more;
nsCOMPtr<nsISupports> elem;
while (NS_SUCCEEDED(iter->HasMoreElements(&more)) && more) {
rv = iter->GetNext(getter_AddRefs(elem));
if (NS_FAILED(rv)) {
break;
}
nsCOMPtr<nsIFile> file = do_QueryInterface(elem);
if (!file) {
continue;
}
nsAutoString leafName;
rv = file->GetLeafName(leafName);
if (NS_FAILED(rv)) {
continue;
}
if (leafName.Find(NS_LITERAL_STRING("MozTemp-{")) == 0) {
file->Remove(/* aRecursive */ true);
}
}
#endif
}
#endif

View File

@ -16,6 +16,7 @@
#include "nsAutoPtr.h"
#include "nsString.h"
#include "nsUnicharUtils.h"
#include "nsVersionComparator.h"
#include "mozilla/Services.h"
#include "mozilla/Observer.h"
#include "nsIObserver.h"
@ -26,6 +27,7 @@
#include "nsIDOMNodeList.h"
#include "nsTArray.h"
#include "nsXULAppAPI.h"
#include "nsIXULAppInfo.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/gfx/2D.h"
@ -144,6 +146,9 @@ GetPrefNameForFeature(int32_t aFeature)
case nsIGfxInfo::FEATURE_STAGEFRIGHT:
name = BLACKLIST_PREF_BRANCH "stagefright";
break;
case nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION:
name = BLACKLIST_PREF_BRANCH "webrtc.hw.acceleration";
break;
default:
break;
};
@ -217,6 +222,29 @@ BlacklistNodeToTextValue(nsIDOMNode *aBlacklistNode, nsAString& aValue)
return true;
}
// <foo attr=Hello/> finds "Hello" if the aAttrName is "attr".
static bool
BlacklistAttrToTextValue(nsIDOMNode *aBlacklistNode,
const nsAString& aAttrName,
nsAString& aValue)
{
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aBlacklistNode);
if (!element) {
return false;
}
nsAutoString value;
if (NS_FAILED(element->GetAttribute(aAttrName, value))) {
return false;
}
value.Trim(" \t\r\n");
aValue = value;
return true;
}
static OperatingSystem
BlacklistOSToOperatingSystem(const nsAString& os)
{
@ -307,6 +335,8 @@ BlacklistFeatureToGfxFeature(const nsAString& aFeature)
return nsIGfxInfo::FEATURE_WEBGL_MSAA;
else if (aFeature.EqualsLiteral("STAGEFRIGHT"))
return nsIGfxInfo::FEATURE_STAGEFRIGHT;
else if (aFeature.EqualsLiteral("WEBRTC_HW_ACCELERATION"))
return nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION;
return 0;
}
@ -408,6 +438,42 @@ BlacklistEntryToDriverInfo(nsIDOMNode* aBlacklistEntry,
nsCOMPtr<nsIDOMNode> dataNode;
nsAutoString dataValue;
// If we get an application version to be zero, something is not working
// and we are not going to bother checking the blocklist versions.
// See TestGfxWidgets.cpp for how version comparison works.
// <versionRange minVersion="42.0a1" maxVersion="45.0"></versionRange>
static mozilla::Version zeroV("0");
static mozilla::Version appV(GfxInfoBase::GetApplicationVersion().get());
if (appV <= zeroV) {
gfxCriticalErrorOnce(gfxCriticalError::DefaultOptions(false)) << "Invalid application version " << GfxInfoBase::GetApplicationVersion().get();
} else if (BlacklistNodeGetChildByName(element,
NS_LITERAL_STRING("versionRange"),
getter_AddRefs(dataNode))) {
if (BlacklistAttrToTextValue(dataNode,
NS_LITERAL_STRING("minVersion"),
dataValue)) {
mozilla::Version minV(NS_ConvertUTF16toUTF8(dataValue).get());
if (minV > zeroV && appV < minV) {
// The version of the application is less than the minimal version
// this blocklist entry applies to, so we can just ignore it by
// returning false and letting the caller deal with it.
return false;
}
}
if (BlacklistAttrToTextValue(dataNode,
NS_LITERAL_STRING("maxVersion"),
dataValue)) {
mozilla::Version maxV(NS_ConvertUTF16toUTF8(dataValue).get());
if (maxV > zeroV && appV > maxV) {
// The version of the application is more than the maximal version
// this blocklist entry applies to, so we can just ignore it by
// returning false and letting the caller deal with it.
return false;
}
}
}
// <os>WINNT 6.0</os>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("os"),
getter_AddRefs(dataNode))) {
@ -532,9 +598,9 @@ BlacklistEntriesToDriverInfo(nsIDOMHTMLCollection* aBlacklistEntries,
GfxDriverInfo di;
if (BlacklistEntryToDriverInfo(blacklistEntry, di)) {
aDriverInfo[i] = di;
// Prevent di falling out of scope from destroying the devices.
di.mDeleteDevices = false;
}
// Prevent di falling out of scope from destroying the devices.
di.mDeleteDevices = false;
}
}
}
@ -613,6 +679,21 @@ GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
uint32_t i = 0;
for (; i < info.Length(); i++) {
// Do the operating system check first, no point in getting the driver
// info if we won't need to use it. Note we also catch and skips the
// application version mismatches that would leave operating system
// set to unknown.
if (info[i].mOperatingSystem == DRIVER_OS_UNKNOWN ||
(info[i].mOperatingSystem != DRIVER_OS_ALL &&
info[i].mOperatingSystem != os))
{
continue;
}
if (info[i].mOperatingSystemVersion && info[i].mOperatingSystemVersion != OperatingSystemVersion()) {
continue;
}
// XXX: it would be better not to do this everytime round the loop
nsAutoString adapterVendorID;
nsAutoString adapterDeviceID;
@ -638,17 +719,6 @@ GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
ParseDriverVersion(adapterDriverVersionString, &driverVersion);
#endif
if (info[i].mOperatingSystem != DRIVER_OS_ALL &&
info[i].mOperatingSystem != os)
{
continue;
}
if (info[i].mOperatingSystemVersion && info[i].mOperatingSystemVersion != OperatingSystemVersion()) {
continue;
}
if (!info[i].mAdapterVendor.Equals(GfxDriverInfo::GetDeviceVendor(VendorAll), nsCaseInsensitiveStringComparator()) &&
!info[i].mAdapterVendor.Equals(adapterVendorID, nsCaseInsensitiveStringComparator())) {
continue;
@ -870,6 +940,7 @@ GfxInfoBase::EvaluateDownloadedBlacklist(nsTArray<GfxDriverInfo>& aDriverInfo)
nsIGfxInfo::FEATURE_WEBGL_ANGLE,
nsIGfxInfo::FEATURE_WEBGL_MSAA,
nsIGfxInfo::FEATURE_STAGEFRIGHT,
nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION,
0
};
@ -927,8 +998,8 @@ GfxInfoBase::LogFailure(const nsACString &failure)
/* void getFailures (out unsigned long failureCount, [optional, array, size_is (failureCount)] out long indices, [array, size_is (failureCount), retval] out string failures); */
/* XPConnect method of returning arrays is very ugly. Would not recommend. */
NS_IMETHODIMP GfxInfoBase::GetFailures(uint32_t* failureCount,
int32_t** indices,
char ***failures)
int32_t** indices,
char ***failures)
{
MutexAutoLock lock(mMutex);
@ -979,7 +1050,7 @@ NS_IMETHODIMP GfxInfoBase::GetFailures(uint32_t* failureCount,
if (!(*failures)[i]) {
/* <sarcasm> I'm too afraid to use an inline function... </sarcasm> */
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, (*failures));
*failureCount = i;
*failureCount = i;
return NS_ERROR_OUT_OF_MEMORY;
}
}
@ -1019,6 +1090,24 @@ nsresult GfxInfoBase::GetInfo(JSContext* aCx, JS::MutableHandle<JS::Value> aResu
return NS_OK;
}
const nsCString&
GfxInfoBase::GetApplicationVersion()
{
static nsAutoCString version;
static bool versionInitialized = false;
if (!versionInitialized) {
// If we fail to get the version, we will not try again.
versionInitialized = true;
// Get the version from xpcom/system/nsIXULAppInfo.idl
nsCOMPtr<nsIXULAppInfo> app = do_GetService("@mozilla.org/xre/app-info;1");
if (app) {
app->GetVersion(version);
}
}
return version;
}
void
GfxInfoBase::AddCollector(GfxInfoCollectorBase* collector)
{

View File

@ -82,6 +82,9 @@ public:
virtual nsString Manufacturer() { return EmptyString(); }
virtual uint32_t OperatingSystemVersion() { return 0; }
// Convenience to get the application version
static const nsCString& GetApplicationVersion();
protected:
virtual ~GfxInfoBase();

View File

@ -207,13 +207,15 @@ public:
HasMoreElements(bool* aRetvalue) override
{
MOZ_ASSERT(aRetvalue);
*aRetvalue = mFiles.Length() >= mIndex;
*aRetvalue = mIndex < mFiles.Length();
return NS_OK;
}
NS_IMETHOD
GetNext(nsISupports** aSupports) override
{
NS_ENSURE_TRUE(mIndex < mFiles.Length(), NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMBlob> blob = mFiles[mIndex++].get();
blob.forget(aSupports);
return NS_OK;

View File

@ -825,6 +825,10 @@ static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
// If you are looking for NS_IMPL_CYCLE_COLLECTION_INHERITED_0(_class, _base)
// you should instead not declare any cycle collected stuff in _class, so it
// will just inherit the CC declarations from _base.
#define NS_IMPL_CYCLE_COLLECTION_INHERITED(_class, _base, ...) \
NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base) \