mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 23:05:42 +00:00
Merge inbound to central, a=merge
This commit is contained in:
commit
98d8b5b1e9
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
9
dom/base/crashtests/1157995.html
Normal file
9
dom/base/crashtests/1157995.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
// This should not leak.
|
||||
var a = navigator;
|
||||
navigator.mediaDevices._ = null;
|
||||
</script>
|
||||
</body>
|
@ -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
174
dom/cache/DBSchema.cpp
vendored
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
185
dom/manifest/ManifestImageObjectProcessor.jsm
Normal file
185
dom/manifest/ManifestImageObjectProcessor.jsm
Normal 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
|
@ -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
|
||||
|
34
dom/manifest/manifestValueExtractor.js
Normal file
34
dom/manifest/manifestValueExtractor.js
Normal 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;
|
||||
}
|
@ -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']
|
||||
|
@ -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]
|
||||
|
@ -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>
|
@ -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';
|
@ -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';
|
@ -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';
|
@ -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
|
||||
**/
|
||||
|
29
dom/manifest/test/test_ManifestProcessor_splash_screens.html
Normal file
29
dom/manifest/test/test_ManifestProcessor_splash_screens.html
Normal 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>
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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.");
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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']
|
||||
|
@ -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]
|
@ -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();
|
||||
}
|
5
dom/promise/tests/unit/xpcshell.ini
Normal file
5
dom/promise/tests/unit/xpcshell.ini
Normal file
@ -0,0 +1,5 @@
|
||||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
|
||||
[test_monitor_uncaught.js]
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
||||
|
57
gfx/tests/gtest/TestGfxWidgets.cpp
Normal file
57
gfx/tests/gtest/TestGfxWidgets.cpp
Normal 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"));
|
||||
}
|
||||
|
@ -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
78
image/ImageCacheKey.cpp
Normal 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
55
image/ImageCacheKey.h
Normal 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
|
@ -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
|
||||
|
@ -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--) {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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())
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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'"
|
||||
]
|
||||
};
|
||||
|
@ -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]",
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -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: "",
|
||||
},
|
||||
{
|
||||
|
@ -313,7 +313,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestLongerTimeout(4);
|
||||
SimpleTest.requestLongerTimeout(5);
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [["layout.css.variables.enabled", true]] },
|
||||
runTest);
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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]
|
||||
|
133
toolkit/content/tests/chrome/test_menulist_paging.xul
Normal file
133
toolkit/content/tests/chrome/test_menulist_paging.xul
Normal 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>
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user