mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1236786 - [WebGL2] pass getVertexAttrib in gl-object-get-calls.html, r=jgilbert (60a2c91a38)
- Bug 1233046 - Fix OES_texture_float on OSX. - r=jrmuizel (4bc0059f5f)
- Bug 1233557 - Allow RGB8 to be renderable again for web-compat. - r=jrmuizel (4c13bfd8e8)
- Bug 1233549. Disallow ES3 compressed texture formats. r=jgilbert (1073033161)
- Bug 1241702 - Allow unsized DEPTH_STENCIL for RBs in WebGL 2. - r=kamidphish (87d17d2cf9)
- Bug 1239126. Handle gl_InstanceID attribute with no location. r=jgilbert (4894997e98)
- Bug 1236782 - [WebGL2] pass getProgramParameter in gl-object-get-calls.html; r=jgilbert (2136fcce48)
- Bug 1232462. Only ask for a higher version of GLSL when using WebGL2. r=jgilbert (0317be4eb4)
- Bug 1242330 - "Four extensions were promoted to core in WebGL 2 and should no longer be available as extensions." r=jgilbert r=jmuizelaar (6df020b8d4)
- Bug 1233626 - Default MaxDrawingBuffers to 1 unless ext/webgl2. - r=jrmuizel (a7580d661c)
- Bug 1231657. Don't allow linking different versions shaders. r=jgilbert (e610f98066)
- Bug 1241777 - TexCompareFunc should be stored in ascending order. r=jgilbert (b6151a0076)
- Bug 1228885 - Implement WebGLTexture::MemoryUsage. - r=kamidphish (ea06815414)
- Bug 1239259 - Fix WebGL2 generateMipmap checking. r=jgilbert (39f587c421)
- Bug 1242347 - Allow unsized internal format when generate mipmap. r=jgilbert (b203a8898c)
- Bug 1232502. Use the correct internalFormat when calling CopyTexImage2D. r=jgilbert (eeaef3215e)
- Bug 1243663 - Max uniform and attribute location lengths in WebGL2 should be 1024. r=jgilbert (c4ec6de507)
- Bug 1239488 - Add int/uint to vertex attrib data type. r=jgilbert (11b4968025)
- Bug 1184242 - Remove aTabParent != sActiveTabParent warning from IMEStateManager::SetInputContextForChildProcess. r=masayuki (0fcda10e15)
- Bug 1178652 - Send NOTIFY_IME_OF_COMPOSITION_UPDATE to parent process correctly. r=masayuki (bce28e2c91)
- Bug 1107782 - Only accept certain mouse, gamepad events as user-active. r=smaug (00542c80b9)
- Bug 1247850 - Shrink NameTableKey in nsStaticCaseInsensitiveNameTable. r=froydnj,erahm. (ce3cb3edfb)
- Bug 1247359 - micro-optimize the common case of String{Begins,End}With; r=erahm (333e042b31)
- Bug 1239125. Add operator!=(char_type*) to nsTSubstring. r=froydnj (0cc047a9a1)
- Bug 1213862 - Align nsString whitespace handling with web specs; r=froydnj (db5b11ca52)
- Bug 1141884 - Trigger compositor smooth scrolling to snap points when APZ is enabled. r=mstange,kip (593af59f2a)
- Bug 1244582: Add back in a null check that was accidentally removed. r=smaug (76bff1b01f)
- Bug 1234176 - Introduce and use the WriteSysFile() helper function. r=dhylands (22a46fbe8b)
- missing bit of Bug 1198124 - Enable -Wshadow (f84535a7a2)
- Bug 1249171 - Simplify nsCOMArray::SizeOfExcludingThis(). r=erahm. (57efdce1c6)
- Bug 1156416 - Validate camera parameters supplied by the application. r=mikeh (f8b4b84ccf)
- Bug 1186808 - Replace nsBaseHashtable::EnumerateRead() calls in dom/camera/ with iterators. r=mikeh. (7b1db5f6a1)
- Bug 1158378 - Fix how a failed set configuration call would try to shutdown the camera after release. (9d5e323bca)
- Bug 1171374 - Permit software video codecs with the emulated camera. r=sotaro (c1ae26ea0d)
- Bug 1234458 P1 Allow the CacheChild to be "locked" into memory so it will delay destruction. r=ehsan a=ritu (9e46185779)
- Bug 1234458 P2 Lock the CacheChild actor while Cache DOM methods are running. r=ehsan a=ritu (038342a6e2)
- Bug 1244764 P1 Make Cache .add()/.addAll() fail if a Response.ok() is false. r=ehsan (ae26ca9ef1)
- Bug 1172562 - Clear QuotaManager storage when uninstalling an app. Test. r=bkelly (b07311a3b7)
- Bug 1172629 - Use the caches global property from an iframe loaded after setting the pref in order to make the tests pass with the pref disabled; r=bkelly a=RyanVM (e7c05d8b79)
- Bug 1244764 P2 Make dom/cache mochitests pass with new add()/addAll() behavior. r=ehsan (e1f667c1b4)
- Bug 1244764 P3 Make service worker tests pass with new Cache add()/addAll() behavior. r=ehsan (1518ae5225)
- Bug 1003860 - Simplify storage setup tasks in storage inspector tests. r=mratcliffe (249a8bdb2b)
- Bug 1003860 - Service worker cache for storage actor. r=mratcliffe (5c3d1ecd0c)
- Bug 1244764 P5 Fix devtools test to work with new Cache add()/addAll() behavior. r=ehsan (bf85405de8)
- Bug 1232901 - Use channel.asyncOpen2 within dom/browser-element/BrowserElementParent.js (r=sicking,aus) (2a228ed551)
- Bug 1180330 - http auth prompt shown when opening browser if prompt canceled/dismissed earlier. r=fabrice (ba3666f4bd)
- Bug 1234118 - Delete code for supporting 'do-command' and 'copypaste-docommand'. r=mtseng, r=smaug (b1b575d3c5)
- Bug 1238883 - [TV Browser] It shows "The page cannot be displayed" when user browse some webpages. r=roc (e6d7739dd6)
- Bug 1238440 - FileReader should throw an error when the blob changed size when reading, r=khuey (b006adba10)
- Bug 1230422 - FileReader should handle nested ReadAs*() calls. r=khuey (5a3ff84a31)
- Bug 1225202, part 3 - Create files in test_fileapi_slice.html using SpecialPowers.createFiles. r=baku (1137975548)
- Bug 1241171 - FormData should not force 'blob' as filename, r=smaug (748055f751)
- Bug 1246375 - Restore the previous spec version of FormData, r=smaug (3586af2b88)
- Bug 1237183 - Modify implementation of reading preference. r=seanlin (a132bc7246)
- Bug 801545 - Remove DocumentType.internalSubset, r=bz (ea30c9b5ee)
- Bug 1226440 - Expose a method to get a node's immediate dominator; r=bz,sfink (f77ae44037)
- Bug 825318 - Implement adoptDownload for mozDownloadManager, r=aus, r=sicking (e98cb05210)
- Bug 1237370 - Always log the reason for remote AppRep lookup failures. r=gcp (2c804e68fc)
- Bug 1167493 - Application Reputation: disable remote lookup of zip files on Mac/Linux, r=gcp (517459e064)
- Bug 1195519 - Use channel->ascynOpen2 toolkit/components/downloads/ApplicationReputation.cpp (r=sicking) (2856e5213a)
- Bug 1237856 - Add prefs to honor/ignore Application Reputation verdicts. r=gcp (54ee06264f)
- Bug 1243643 - Deprecate unsafe CPOW usage in contentAreaUtils' saveImage. r=jld (6ae790f1ef)
- Bug 1229224: Add an eslint plugin for importing all browser.js globals for browser-chrome tests. r=miker (9df52a7f3b)
- Bug 1245916: Add additional browser window scripts to eslint globals. r=felipe (92d316ca5e)
- Bug 1246244 - Allow non-CPOW documents to pass through saveImageURL properly. r=jaws,Margaret (c8d4ca241d)
- some missing bits after world fix (c0439eebb0)
- add some missing stuff (ddbd47dc03)
- bissing bit of 1229519 (4e255c3dae)
- Bug 1199662 - Crash ping environment block is broken when any string field contains a quotation mark. Unescape INI fields properly using the library that already exists for the purpose. r=ted (874a999edc)
- Bug 1216150 - Turn on the experimental Intl.DateTimeFormat.prototype.formatToParts in b2g certified apps. r=fabrice (40eeb1a4d4)
- Bug 1216150 - Mini-bustage fix for something I think I unintentionally qref'd into the final patch. r=bustage in a CLOSED TREE (36d9b21a67)
- Bug 1141311 - Add async mode support to GonkNativeWindow on Lollipop Gonk r=pchang (39d9d56326)
- Bug 1146671 - Ensure camera not already released when performing operations. r=dhylands (71b59caa1f)
- Bug 1248737. Improve documentation for WorkerRunnable and associated classes. r=khuey (4ff57790c5)
- Bug 1235629 - Remove dead code in WorkerFeature.h, r=smaug (75a51fcf03)
- Bug 1212333 - WorkerDebuggerManager should live on the main thread;r=khuey (11fdfbbae6)
- Bug 1226443 P3 Re-enable service worker update wpt tests. r=ehsan (605dac5f9e)
- Bug 1226443 P4 Cleanup ServiceWorkerScriptCache objects when initialization fails. r=ehsan (43de3429a2)
- Bug 1234127: Change |BluetoothAdapter.pairingReqs| as a nullable object; r=btian, r=mrbkap (45d2038f6a)
- Bug 1188487 - BrowserElement webidl changes for muting and setting volume. r=ehsan (21bea70a07)
- Bug 1238210 - Correct the Promise return types on two Clients methods; r=baku (fa41b25df0)
- Bug 1246784 - Expose Console to the WorkerDebuggerGlobalScope - part 2, r=khuey (0da9ce8ff6)
- Bug 1228702. Don't expose the 'location' property of Exception/DOMException on workers. r=bholley (0fe86ea586)
- Bug 1223825 - Change Directory.path to include the directory's name. r=baku (0cdae4c2f0)
- Bug 1238225 - Mark ExtendableMessageEvent.ports as SameObject; r=baku (45b9a9746f)
- Bug 1236933 - Return null from FetchEvent.clientId for non-subresource network requests; r=bkelly (4a9c4b40cb)
- Bug 1238213 - Make FetchEvent.request non-nullable; r=baku (751082c8ba)
- Bug 1193125 - Avoid corrupting image data in test_fetch_event.html. r=bkelly (9f6bff232f)
- Bug 1201664 - Avoid using Request's constructor when creating FetchEvent.request; r=bkelly (7a3401e345)
- Bug 1175944 - Packaged app's (app://) JS files are not loaded and do not trigger "onfetch" handler. r=jdm (62df139153)
- Bug 1233644 - use pattern matching when listening clear-origin-data. r=baku (ea2594f50e)
- Bug 1237363 - Part 1: Unregister all service workers registered in mochitests at the end of the test; r=jdm (5be97e5bb0)
- Bug 1237363 - Part 2: Fail mochitests which register a service worker without unregistering it; r=jdm (c4160ffd5f)
- Bug 1237363 - Part 3: Add a test for a mochitest finishing without unregistering its service worker; r=jdm (911d37291b)
- Bug 1174078 - Calling "fetch" inside Service Worker's "onfetch" handler in b2g causes "onfetch" again that leads to an infinite loop. Test. r=nsm (208451f346)
- Bug 1197379 - Remove support for intercepting app:// URIs using service workers; r=jdm (3cbdd725f1)
- Bug 1179399 - Part 1: Relax the ShouldIntercept checks when overriding JAR channel info; r=jdm (850bb2bdb8)
- Bug 1238213 follow-up: Mark the FetchEventInit dictionary argument to FetchEvent's constructor optional too; r=bzbarsky (356cbe6db7)
- Bug 1232732 - modify NS_WARNING in MOZ_WIN_MEM_TRY_CATCH; r=aklotz (e2be4d6919)
- Bug 1247658 - Expose a method to JS for find the shortest retaining paths of some nodes in a heap snapshot; r=bz r=jimb (2c82198808)
- Bug 1188115: Expose IDBCursorWithValue in workers. r=baku (e1c40aeb6e)
- Bug 1162680 - Notify Keyboard.jsm to send blur event when the message manager is closed first. r=timdream (53727ab300)
- Bug 1192986 Also mark Cache/CacheStorage as release interfaces on workers. r=ehsan a=bustage (25cf83c154)
- Bug 1159742. Get rid of the pref annotation from test_interfaces, since it basically corresponds to disabling the test. r=jst (c229e3f881)
- Bug 1203160 - Part 2: Fix the interfaces tests to allow SW interfaces for non-release Fennec; r=baku (072840db1f)
- Bug 1197700 - Correct mistakes in InputMethod.webidl. r=kanru, r=janjongboom, sr=smaug (4edb6f201f)
- Bug 1206970 - Stop expecting AnimationPlaybackEvent to be exposed on release branches, where it's disabled by pref, r=smaug (30ae2b13db)
- Bug 1177276 - Pref on canvas.captureStream by default. r=smaug,mt (0cfe0f72f2)
- Bug 1215147 - Enable VR API's on FF for Android by default. r=snorp, r=vlad, r=bz (5ff3725318)
- Bug 1218482 - Enable WebVR By Default,r=bz (f26111ed82)
- Bug 1159755. Stop forcing the media.eme.apiVisible preference to be true in our test harness. r=cpearce (09f7887917)
- Bug 1149312 - Obtain test coverage for the file-backed case of MediaRecorder. r=roc (bd2e7e40f0)
- Bug 1154559 - Remove flaky timeouts from manifest.js and register SimpleTest.registerCleanupFunction() to report unfinished tests. r=cpearce. (eb68db0fb2)
- Bug 1154564 - Add the ability to notify timeouts to MediaTestManager and remove flaky timeouts from test_playback.html. r=cpearce. (c89b4e58d9)
- Bug 1135170 - Fix up racey test_seek-1.html. rpending=mattwoodrow (b3a7d0dcd6)
- Bug 902686 - Change manifest.js to use SpecialPowers.pushPrefEnv. r=edwin (636b0edc1a)
- Bug 1183502 - give androidVersion a correct value in manifest.js. r=sotaro. (933e9ea712)
- Bug 1235588 - add null check to SimpleTest. r=bechen. (958ede68de)
- misspatch (c8922447ff)
- Bug 1151740 - pass the callback object as-is to SpecialPowers.exactGC(). r=edwin (99ca873bce)
- Bug 1197682 - InputMethodManager#setSupportsSwitchingTypes, r=janjongboom, sr=smaug (e7eb54e491)
- Bug 1201407 - Add input-manage-only events for InputMethod API. r=janjongboom, sr=smaug (776d064bd1)
- Bug 1234459 - Expose full text in the input box to InputMethod API, r=masayuki, sr=smaug (4fa0554356)
- Bug 1198163 - Workaround Mochitest app and assign frame proper permissions, r=kanru (c3bcf8ecc1)
- Bug 990250 - Fold nsIStyleSheet into CSSStyleSheet. r=dbaron (23579cb300)
This commit is contained in:
+17
-25
@@ -414,14 +414,12 @@ nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindow* aWindow)
|
||||
nsCOMPtr<nsIPresShell> shell = document->GetShell();
|
||||
if (shell) {
|
||||
// Reload only the chrome URL agent style sheets.
|
||||
nsCOMArray<nsIStyleSheet> agentSheets;
|
||||
nsTArray<RefPtr<CSSStyleSheet>> agentSheets;
|
||||
rv = shell->GetAgentStyleSheets(agentSheets);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMArray<nsIStyleSheet> newAgentSheets;
|
||||
for (int32_t l = 0; l < agentSheets.Count(); ++l) {
|
||||
nsIStyleSheet *sheet = agentSheets[l];
|
||||
|
||||
nsTArray<RefPtr<CSSStyleSheet>> newAgentSheets;
|
||||
for (CSSStyleSheet* sheet : agentSheets) {
|
||||
nsIURI* uri = sheet->GetSheetURI();
|
||||
|
||||
if (IsChromeURI(uri)) {
|
||||
@@ -431,12 +429,12 @@ nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindow* aWindow)
|
||||
getter_AddRefs(newSheet));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (newSheet) {
|
||||
rv = newAgentSheets.AppendObject(newSheet) ? NS_OK : NS_ERROR_FAILURE;
|
||||
rv = newAgentSheets.AppendElement(newSheet) ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
else { // Just use the same sheet.
|
||||
rv = newAgentSheets.AppendObject(sheet) ? NS_OK : NS_ERROR_FAILURE;
|
||||
rv = newAgentSheets.AppendElement(sheet) ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
@@ -445,27 +443,22 @@ nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindow* aWindow)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Build an array of nsIURIs of style sheets we need to load.
|
||||
nsCOMArray<nsIStyleSheet> oldSheets;
|
||||
nsCOMArray<nsIStyleSheet> newSheets;
|
||||
|
||||
int32_t count = document->GetNumberOfStyleSheets();
|
||||
|
||||
// Iterate over the style sheets.
|
||||
int32_t i;
|
||||
for (i = 0; i < count; i++) {
|
||||
// Get the style sheet
|
||||
nsIStyleSheet *styleSheet = document->GetStyleSheetAt(i);
|
||||
// Build an array of style sheets we need to reload.
|
||||
nsTArray<RefPtr<CSSStyleSheet>> oldSheets(count);
|
||||
nsTArray<RefPtr<CSSStyleSheet>> newSheets(count);
|
||||
|
||||
if (!oldSheets.AppendObject(styleSheet)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
// Iterate over the style sheets.
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
// Get the style sheet
|
||||
CSSStyleSheet* styleSheet = document->GetStyleSheetAt(i);
|
||||
oldSheets.AppendElement(styleSheet);
|
||||
}
|
||||
|
||||
// Iterate over our old sheets and kick off a sync load of the new
|
||||
// sheet if and only if it's a chrome URL.
|
||||
for (i = 0; i < count; i++) {
|
||||
RefPtr<CSSStyleSheet> sheet = do_QueryObject(oldSheets[i]);
|
||||
for (CSSStyleSheet* sheet : oldSheets) {
|
||||
nsIURI* uri = sheet ? sheet->GetOriginalURI() : nullptr;
|
||||
|
||||
if (uri && IsChromeURI(uri)) {
|
||||
@@ -475,11 +468,10 @@ nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindow* aWindow)
|
||||
// only works by sheer dumb luck.
|
||||
document->LoadChromeSheetSync(uri, false, getter_AddRefs(newSheet));
|
||||
// Even if it's null, we put in in there.
|
||||
newSheets.AppendObject(newSheet);
|
||||
}
|
||||
else {
|
||||
newSheets.AppendElement(newSheet);
|
||||
} else {
|
||||
// Just use the same sheet.
|
||||
newSheets.AppendObject(sheet);
|
||||
newSheets.AppendElement(sheet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-2
@@ -13,6 +13,7 @@
|
||||
#include "nsIStreamTransportService.h"
|
||||
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
@@ -315,11 +316,17 @@ FileReader::DoReadData(uint64_t aCount)
|
||||
NS_ASSERTION(bytesRead == aCount, "failed to read data");
|
||||
}
|
||||
else {
|
||||
CheckedInt<uint64_t> size = mDataLen;
|
||||
size += aCount;
|
||||
|
||||
//Update memory buffer to reflect the contents of the file
|
||||
if (mDataLen + aCount > UINT32_MAX) {
|
||||
// PR_Realloc doesn't support over 4GB memory size even if 64-bit OS
|
||||
if (!size.isValid() ||
|
||||
// PR_Realloc doesn't support over 4GB memory size even if 64-bit OS
|
||||
size.value() > UINT32_MAX ||
|
||||
size.value() > mTotal) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (mDataFormat != FILE_AS_ARRAYBUFFER) {
|
||||
mFileData = (char *) moz_realloc(mFileData, mDataLen + aCount);
|
||||
NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
|
||||
@@ -347,6 +354,14 @@ FileReader::ReadFileContent(Blob& aBlob,
|
||||
Abort(error);
|
||||
error.SuppressException();
|
||||
|
||||
if (mReadyState == LOADING) {
|
||||
// A nested ReadAsSomething() as been called during one of the events
|
||||
// dispatched by Abort(). We have to terminate this operation in order to
|
||||
// continue the nested one.
|
||||
aRv.Throw(NS_ERROR_ABORT);
|
||||
return;
|
||||
}
|
||||
|
||||
mError = nullptr;
|
||||
SetDOMStringToNull(mResult);
|
||||
mTransferred = 0;
|
||||
|
||||
+41
-30
@@ -23,16 +23,17 @@ FormData::FormData(nsISupports* aOwner)
|
||||
|
||||
namespace {
|
||||
|
||||
already_AddRefed<Blob>
|
||||
GetBlobForFormDataStorage(Blob& aBlob, const Optional<nsAString>& aFilename,
|
||||
ErrorResult& aRv)
|
||||
already_AddRefed<File>
|
||||
GetOrCreateFileCalledBlob(Blob& aBlob, ErrorResult& aRv)
|
||||
{
|
||||
if (!aFilename.WasPassed()) {
|
||||
RefPtr<Blob> blob = &aBlob;
|
||||
return blob.forget();
|
||||
// If this is file, we can just use it
|
||||
RefPtr<File> file = aBlob.ToFile();
|
||||
if (file) {
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
RefPtr<File> file = aBlob.ToFile(aFilename.Value(), aRv);
|
||||
// Forcing 'blob' as filename
|
||||
file = aBlob.ToFile(NS_LITERAL_STRING("blob"), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -40,6 +41,23 @@ GetBlobForFormDataStorage(Blob& aBlob, const Optional<nsAString>& aFilename,
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<File>
|
||||
GetBlobForFormDataStorage(Blob& aBlob, const Optional<nsAString>& aFilename,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Forcing a filename
|
||||
if (aFilename.WasPassed()) {
|
||||
RefPtr<File> file = aBlob.ToFile(aFilename.Value(), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
return GetOrCreateFileCalledBlob(aBlob, aRv);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -102,12 +120,12 @@ FormData::Append(const nsAString& aName, Blob& aBlob,
|
||||
const Optional<nsAString>& aFilename,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<Blob> blob = GetBlobForFormDataStorage(aBlob, aFilename, aRv);
|
||||
RefPtr<File> file = GetBlobForFormDataStorage(aBlob, aFilename, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddNameBlobPair(aName, blob);
|
||||
AddNameBlobPair(aName, file);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -165,8 +183,14 @@ FormData::AddNameBlobPair(const nsAString& aName, Blob* aBlob)
|
||||
{
|
||||
MOZ_ASSERT(aBlob);
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<File> file = GetOrCreateFileCalledBlob(*aBlob, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
FormDataTuple* data = mFormData.AppendElement();
|
||||
SetNameBlobPair(data, aName, aBlob);
|
||||
SetNameFilePair(data, aName, file);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -199,12 +223,12 @@ FormData::Set(const nsAString& aName, Blob& aBlob,
|
||||
{
|
||||
FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName);
|
||||
if (tuple) {
|
||||
RefPtr<Blob> blob = GetBlobForFormDataStorage(aBlob, aFilename, aRv);
|
||||
RefPtr<File> file = GetBlobForFormDataStorage(aBlob, aFilename, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetNameBlobPair(tuple, aName, blob);
|
||||
SetNameFilePair(tuple, aName, file);
|
||||
} else {
|
||||
Append(aName, aBlob, aFilename, aRv);
|
||||
}
|
||||
@@ -253,15 +277,15 @@ FormData::SetNameValuePair(FormDataTuple* aData,
|
||||
}
|
||||
|
||||
void
|
||||
FormData::SetNameBlobPair(FormDataTuple* aData,
|
||||
FormData::SetNameFilePair(FormDataTuple* aData,
|
||||
const nsAString& aName,
|
||||
Blob* aBlob)
|
||||
File* aFile)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
MOZ_ASSERT(aBlob);
|
||||
MOZ_ASSERT(aFile);
|
||||
|
||||
aData->name = aName;
|
||||
aData->value.SetAsBlob() = aBlob;
|
||||
aData->value.SetAsBlob() = aFile;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -343,20 +367,7 @@ FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
||||
|
||||
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
|
||||
if (mFormData[i].value.IsBlob()) {
|
||||
RefPtr<File> file = mFormData[i].value.GetAsBlob()->ToFile();
|
||||
if (file) {
|
||||
fs.AddNameBlobPair(mFormData[i].name, file);
|
||||
continue;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
file =
|
||||
mFormData[i].value.GetAsBlob()->ToFile(NS_LITERAL_STRING("blob"), rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
fs.AddNameBlobPair(mFormData[i].name, file);
|
||||
fs.AddNameBlobPair(mFormData[i].name, mFormData[i].value.GetAsBlob());
|
||||
} else if (mFormData[i].value.IsUSVString()) {
|
||||
fs.AddNameValuePair(mFormData[i].name,
|
||||
mFormData[i].value.GetAsUSVString());
|
||||
|
||||
+2
-2
@@ -47,9 +47,9 @@ private:
|
||||
const nsAString& aName,
|
||||
const nsAString& aValue);
|
||||
|
||||
void SetNameBlobPair(FormDataTuple* aData,
|
||||
void SetNameFilePair(FormDataTuple* aData,
|
||||
const nsAString& aName,
|
||||
Blob* aBlob);
|
||||
File* aFile);
|
||||
|
||||
public:
|
||||
explicit FormData(nsISupports* aOwner = nullptr);
|
||||
|
||||
@@ -2121,17 +2121,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Suspend(JSContext* aCx) override
|
||||
{
|
||||
{
|
||||
MutexAutoLock lock(mWebSocketImpl->mMutex);
|
||||
mWebSocketImpl->mWorkerShuttingDown = true;
|
||||
}
|
||||
|
||||
mWebSocketImpl->CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
WebSocketImpl* mWebSocketImpl;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var a = new FileReader();
|
||||
|
||||
function f() {
|
||||
a.removeEventListener("loadend", f);
|
||||
g();
|
||||
}
|
||||
|
||||
function g() {
|
||||
a.readAsBinaryString(new Blob());
|
||||
}
|
||||
|
||||
a.addEventListener("loadend", f);
|
||||
|
||||
try {
|
||||
g();
|
||||
g();
|
||||
} catch(e) {}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -204,3 +204,4 @@ load structured_clone_container_throws.html
|
||||
HTTP(..) load xhr_abortinprogress.html
|
||||
load xhr_empty_datauri.html
|
||||
load xhr_html_nullresponse.html
|
||||
load 1230422.html
|
||||
|
||||
@@ -99,7 +99,6 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsIContentIterator.h"
|
||||
#include "nsIDOMStyleSheet.h"
|
||||
#include "nsIStyleSheet.h"
|
||||
#include "nsIStyleSheetService.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "nsCSSPseudoElements.h" // for CSSPseudoElementType
|
||||
@@ -3381,7 +3380,7 @@ nsDOMWindowUtils::AddSheet(nsIDOMStyleSheet *aSheet, uint32_t aSheetType)
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
|
||||
nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
|
||||
nsCOMPtr<nsIStyleSheet> sheet = do_QueryInterface(aSheet);
|
||||
RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
|
||||
NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
|
||||
if (sheet->GetOwningDocument()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
+89
-137
@@ -716,15 +716,6 @@ nsDOMStyleSheetList::Length()
|
||||
// been added or removed.
|
||||
if (-1 == mLength) {
|
||||
mLength = mDocument->GetNumberOfStyleSheets();
|
||||
|
||||
#ifdef DEBUG
|
||||
int32_t i;
|
||||
for (i = 0; i < mLength; i++) {
|
||||
nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(i);
|
||||
nsCOMPtr<nsIDOMStyleSheet> domss(do_QueryInterface(sheet));
|
||||
NS_ASSERTION(domss, "All \"normal\" sheets implement nsIDOMStyleSheet");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return mLength;
|
||||
}
|
||||
@@ -738,7 +729,7 @@ nsDOMStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
||||
}
|
||||
|
||||
aFound = true;
|
||||
nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(aIndex);
|
||||
CSSStyleSheet* sheet = mDocument->GetStyleSheetAt(aIndex);
|
||||
NS_ASSERTION(sheet, "Must have a sheet");
|
||||
|
||||
return static_cast<CSSStyleSheet*>(sheet);
|
||||
@@ -751,26 +742,20 @@ nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode)
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMStyleSheetList::StyleSheetAdded(nsIStyleSheet* aStyleSheet,
|
||||
nsDOMStyleSheetList::StyleSheetAdded(CSSStyleSheet* aStyleSheet,
|
||||
bool aDocumentSheet)
|
||||
{
|
||||
if (aDocumentSheet && -1 != mLength) {
|
||||
nsCOMPtr<nsIDOMStyleSheet> domss(do_QueryInterface(aStyleSheet));
|
||||
if (domss) {
|
||||
mLength++;
|
||||
}
|
||||
mLength++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMStyleSheetList::StyleSheetRemoved(nsIStyleSheet* aStyleSheet,
|
||||
nsDOMStyleSheetList::StyleSheetRemoved(CSSStyleSheet* aStyleSheet,
|
||||
bool aDocumentSheet)
|
||||
{
|
||||
if (aDocumentSheet && -1 != mLength) {
|
||||
nsCOMPtr<nsIDOMStyleSheet> domss(do_QueryInterface(aStyleSheet));
|
||||
if (domss) {
|
||||
mLength--;
|
||||
}
|
||||
mLength--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1333,7 +1318,7 @@ nsDOMStyleSheetSetList::EnsureFresh()
|
||||
int32_t count = mDocument->GetNumberOfStyleSheets();
|
||||
nsAutoString title;
|
||||
for (int32_t index = 0; index < count; index++) {
|
||||
nsIStyleSheet* sheet = mDocument->GetStyleSheetAt(index);
|
||||
CSSStyleSheet* sheet = mDocument->GetStyleSheetAt(index);
|
||||
NS_ASSERTION(sheet, "Null sheet in sheet list!");
|
||||
sheet->GetTitle(title);
|
||||
if (!title.IsEmpty() && !mNames.Contains(title) && !Add(title)) {
|
||||
@@ -1607,9 +1592,7 @@ nsDocument::~nsDocument()
|
||||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
int32_t indx; // must be signed
|
||||
uint32_t count = mChildren.ChildCount();
|
||||
for (indx = int32_t(count) - 1; indx >= 0; --indx) {
|
||||
for (uint32_t indx = mChildren.ChildCount(); indx-- != 0; ) {
|
||||
mChildren.ChildAt(indx)->UnbindFromTree();
|
||||
mChildren.RemoveChildAt(indx);
|
||||
}
|
||||
@@ -1617,9 +1600,8 @@ nsDocument::~nsDocument()
|
||||
mCachedRootElement = nullptr;
|
||||
|
||||
// Let the stylesheets know we're going away
|
||||
indx = mStyleSheets.Count();
|
||||
while (--indx >= 0) {
|
||||
mStyleSheets[indx]->SetOwningDocument(nullptr);
|
||||
for (CSSStyleSheet* sheet : mStyleSheets) {
|
||||
sheet->SetOwningDocument(nullptr);
|
||||
}
|
||||
if (mAttrStyleSheet) {
|
||||
mAttrStyleSheet->SetOwningDocument(nullptr);
|
||||
@@ -2297,9 +2279,7 @@ void
|
||||
nsDocument::RemoveDocStyleSheetsFromStyleSets()
|
||||
{
|
||||
// The stylesheets should forget us
|
||||
int32_t indx = mStyleSheets.Count();
|
||||
while (--indx >= 0) {
|
||||
nsIStyleSheet* sheet = mStyleSheets[indx];
|
||||
for (CSSStyleSheet* sheet : Reversed(mStyleSheets)) {
|
||||
sheet->SetOwningDocument(nullptr);
|
||||
|
||||
if (sheet->IsApplicable()) {
|
||||
@@ -2313,12 +2293,12 @@ nsDocument::RemoveDocStyleSheetsFromStyleSets()
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RemoveStyleSheetsFromStyleSets(nsCOMArray<nsIStyleSheet>& aSheets, SheetType aType)
|
||||
nsDocument::RemoveStyleSheetsFromStyleSets(
|
||||
nsTArray<RefPtr<CSSStyleSheet>>& aSheets,
|
||||
SheetType aType)
|
||||
{
|
||||
// The stylesheets should forget us
|
||||
int32_t indx = aSheets.Count();
|
||||
while (--indx >= 0) {
|
||||
nsIStyleSheet* sheet = aSheets[indx];
|
||||
for (CSSStyleSheet* sheet : Reversed(aSheets)) {
|
||||
sheet->SetOwningDocument(nullptr);
|
||||
|
||||
if (sheet->IsApplicable()) {
|
||||
@@ -2327,10 +2307,8 @@ nsDocument::RemoveStyleSheetsFromStyleSets(nsCOMArray<nsIStyleSheet>& aSheets, S
|
||||
shell->StyleSet()->RemoveStyleSheet(aType, sheet);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Tell observers?
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2385,21 +2363,13 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
AppendAuthorSheet(nsIStyleSheet *aSheet, void *aData)
|
||||
{
|
||||
nsStyleSet *styleSet = static_cast<nsStyleSet*>(aData);
|
||||
styleSet->AppendStyleSheet(SheetType::Doc, aSheet);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
AppendSheetsToStyleSet(nsStyleSet* aStyleSet,
|
||||
const nsCOMArray<nsIStyleSheet>& aSheets,
|
||||
const nsTArray<RefPtr<CSSStyleSheet>>& aSheets,
|
||||
SheetType aType)
|
||||
{
|
||||
for (int32_t i = aSheets.Count() - 1; i >= 0; --i) {
|
||||
aStyleSet->AppendStyleSheet(aType, aSheets[i]);
|
||||
for (CSSStyleSheet* sheet : Reversed(aSheets)) {
|
||||
aStyleSet->AppendStyleSheet(aType, sheet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2411,9 +2381,7 @@ nsDocument::FillStyleSet(nsStyleSet* aStyleSet)
|
||||
NS_PRECONDITION(aStyleSet->SheetCount(SheetType::Doc) == 0,
|
||||
"Style set already has document sheets?");
|
||||
|
||||
int32_t i;
|
||||
for (i = mStyleSheets.Count() - 1; i >= 0; --i) {
|
||||
nsIStyleSheet* sheet = mStyleSheets[i];
|
||||
for (CSSStyleSheet* sheet : Reversed(mStyleSheets)) {
|
||||
if (sheet->IsApplicable()) {
|
||||
aStyleSet->AddDocStyleSheet(sheet, this);
|
||||
}
|
||||
@@ -2421,13 +2389,13 @@ nsDocument::FillStyleSet(nsStyleSet* aStyleSet)
|
||||
|
||||
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
|
||||
if (sheetService) {
|
||||
sheetService->AuthorStyleSheets()->EnumerateForwards(AppendAuthorSheet,
|
||||
aStyleSet);
|
||||
for (CSSStyleSheet* sheet : *sheetService->AuthorStyleSheets()) {
|
||||
aStyleSet->AppendStyleSheet(SheetType::Doc, sheet);
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate backwards to maintain order
|
||||
for (i = mOnDemandBuiltInUASheets.Count() - 1; i >= 0; --i) {
|
||||
nsIStyleSheet* sheet = mOnDemandBuiltInUASheets[i];
|
||||
for (CSSStyleSheet* sheet : Reversed(mOnDemandBuiltInUASheets)) {
|
||||
if (sheet->IsApplicable()) {
|
||||
aStyleSet->PrependStyleSheet(SheetType::Agent, sheet);
|
||||
}
|
||||
@@ -4082,8 +4050,7 @@ nsDocument::RemoveChildAt(uint32_t aIndex, bool aNotify)
|
||||
void
|
||||
nsDocument::EnsureOnDemandBuiltInUASheet(CSSStyleSheet* aSheet)
|
||||
{
|
||||
// Contains() takes nsISupport*, so annoyingly we have to cast here
|
||||
if (mOnDemandBuiltInUASheets.Contains(static_cast<nsIStyleSheet*>(aSheet))) {
|
||||
if (mOnDemandBuiltInUASheets.Contains(aSheet)) {
|
||||
return;
|
||||
}
|
||||
BeginUpdate(UPDATE_STYLE);
|
||||
@@ -4094,8 +4061,7 @@ nsDocument::EnsureOnDemandBuiltInUASheet(CSSStyleSheet* aSheet)
|
||||
void
|
||||
nsDocument::AddOnDemandBuiltInUASheet(CSSStyleSheet* aSheet)
|
||||
{
|
||||
// Contains() takes nsISupport*, so annoyingly we have to cast here
|
||||
MOZ_ASSERT(!mOnDemandBuiltInUASheets.Contains(static_cast<nsIStyleSheet*>(aSheet)));
|
||||
MOZ_ASSERT(!mOnDemandBuiltInUASheets.Contains(aSheet));
|
||||
|
||||
// Prepend here so that we store the sheets in mOnDemandBuiltInUASheets in
|
||||
// the same order that they should end up in the style set.
|
||||
@@ -4119,24 +4085,23 @@ nsDocument::AddOnDemandBuiltInUASheet(CSSStyleSheet* aSheet)
|
||||
int32_t
|
||||
nsDocument::GetNumberOfStyleSheets() const
|
||||
{
|
||||
return mStyleSheets.Count();
|
||||
return mStyleSheets.Length();
|
||||
}
|
||||
|
||||
nsIStyleSheet*
|
||||
CSSStyleSheet*
|
||||
nsDocument::GetStyleSheetAt(int32_t aIndex) const
|
||||
{
|
||||
NS_ENSURE_TRUE(0 <= aIndex && aIndex < mStyleSheets.Count(), nullptr);
|
||||
return mStyleSheets[aIndex];
|
||||
return mStyleSheets.SafeElementAt(aIndex, nullptr);
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsDocument::GetIndexOfStyleSheet(nsIStyleSheet* aSheet) const
|
||||
nsDocument::GetIndexOfStyleSheet(CSSStyleSheet* aSheet) const
|
||||
{
|
||||
return mStyleSheets.IndexOf(aSheet);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::AddStyleSheetToStyleSets(nsIStyleSheet* aSheet)
|
||||
nsDocument::AddStyleSheetToStyleSets(CSSStyleSheet* aSheet)
|
||||
{
|
||||
nsCOMPtr<nsIPresShell> shell = GetShell();
|
||||
if (shell) {
|
||||
@@ -4146,15 +4111,10 @@ nsDocument::AddStyleSheetToStyleSets(nsIStyleSheet* aSheet)
|
||||
|
||||
#define DO_STYLESHEET_NOTIFICATION(className, type, memberName, argName) \
|
||||
do { \
|
||||
RefPtr<CSSStyleSheet> cssSheet = do_QueryObject(aSheet); \
|
||||
if (!cssSheet) { \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
className##Init init; \
|
||||
init.mBubbles = true; \
|
||||
init.mCancelable = true; \
|
||||
init.mStylesheet = cssSheet; \
|
||||
init.mStylesheet = aSheet; \
|
||||
init.memberName = argName; \
|
||||
\
|
||||
RefPtr<className> event = \
|
||||
@@ -4168,7 +4128,7 @@ nsDocument::AddStyleSheetToStyleSets(nsIStyleSheet* aSheet)
|
||||
} while (0);
|
||||
|
||||
void
|
||||
nsDocument::NotifyStyleSheetAdded(nsIStyleSheet* aSheet, bool aDocumentSheet)
|
||||
nsDocument::NotifyStyleSheetAdded(CSSStyleSheet* aSheet, bool aDocumentSheet)
|
||||
{
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (aSheet, aDocumentSheet));
|
||||
|
||||
@@ -4181,7 +4141,7 @@ nsDocument::NotifyStyleSheetAdded(nsIStyleSheet* aSheet, bool aDocumentSheet)
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::NotifyStyleSheetRemoved(nsIStyleSheet* aSheet, bool aDocumentSheet)
|
||||
nsDocument::NotifyStyleSheetRemoved(CSSStyleSheet* aSheet, bool aDocumentSheet)
|
||||
{
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetRemoved, (aSheet, aDocumentSheet));
|
||||
|
||||
@@ -4194,10 +4154,10 @@ nsDocument::NotifyStyleSheetRemoved(nsIStyleSheet* aSheet, bool aDocumentSheet)
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::AddStyleSheet(nsIStyleSheet* aSheet)
|
||||
nsDocument::AddStyleSheet(CSSStyleSheet* aSheet)
|
||||
{
|
||||
NS_PRECONDITION(aSheet, "null arg");
|
||||
mStyleSheets.AppendObject(aSheet);
|
||||
mStyleSheets.AppendElement(aSheet);
|
||||
aSheet->SetOwningDocument(this);
|
||||
|
||||
if (aSheet->IsApplicable()) {
|
||||
@@ -4208,7 +4168,7 @@ nsDocument::AddStyleSheet(nsIStyleSheet* aSheet)
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RemoveStyleSheetFromStyleSets(nsIStyleSheet* aSheet)
|
||||
nsDocument::RemoveStyleSheetFromStyleSets(CSSStyleSheet* aSheet)
|
||||
{
|
||||
nsCOMPtr<nsIPresShell> shell = GetShell();
|
||||
if (shell) {
|
||||
@@ -4217,12 +4177,12 @@ nsDocument::RemoveStyleSheetFromStyleSets(nsIStyleSheet* aSheet)
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RemoveStyleSheet(nsIStyleSheet* aSheet)
|
||||
nsDocument::RemoveStyleSheet(CSSStyleSheet* aSheet)
|
||||
{
|
||||
NS_PRECONDITION(aSheet, "null arg");
|
||||
nsCOMPtr<nsIStyleSheet> sheet = aSheet; // hold ref so it won't die too soon
|
||||
RefPtr<CSSStyleSheet> sheet = aSheet; // hold ref so it won't die too soon
|
||||
|
||||
if (!mStyleSheets.RemoveObject(aSheet)) {
|
||||
if (!mStyleSheets.RemoveElement(aSheet)) {
|
||||
NS_ASSERTION(mInUnlinkOrDeletion, "stylesheet not found");
|
||||
return;
|
||||
}
|
||||
@@ -4239,17 +4199,17 @@ nsDocument::RemoveStyleSheet(nsIStyleSheet* aSheet)
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::UpdateStyleSheets(nsCOMArray<nsIStyleSheet>& aOldSheets,
|
||||
nsCOMArray<nsIStyleSheet>& aNewSheets)
|
||||
nsDocument::UpdateStyleSheets(nsTArray<RefPtr<CSSStyleSheet>>& aOldSheets,
|
||||
nsTArray<RefPtr<CSSStyleSheet>>& aNewSheets)
|
||||
{
|
||||
BeginUpdate(UPDATE_STYLE);
|
||||
|
||||
// XXX Need to set the sheet on the ownernode, if any
|
||||
NS_PRECONDITION(aOldSheets.Count() == aNewSheets.Count(),
|
||||
NS_PRECONDITION(aOldSheets.Length() == aNewSheets.Length(),
|
||||
"The lists must be the same length!");
|
||||
int32_t count = aOldSheets.Count();
|
||||
int32_t count = aOldSheets.Length();
|
||||
|
||||
nsCOMPtr<nsIStyleSheet> oldSheet;
|
||||
RefPtr<CSSStyleSheet> oldSheet;
|
||||
int32_t i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
oldSheet = aOldSheets[i];
|
||||
@@ -4260,9 +4220,9 @@ nsDocument::UpdateStyleSheets(nsCOMArray<nsIStyleSheet>& aOldSheets,
|
||||
RemoveStyleSheet(oldSheet); // This does the right notifications
|
||||
|
||||
// Now put the new one in its place. If it's null, just ignore it.
|
||||
nsIStyleSheet* newSheet = aNewSheets[i];
|
||||
CSSStyleSheet* newSheet = aNewSheets[i];
|
||||
if (newSheet) {
|
||||
mStyleSheets.InsertObjectAt(newSheet, oldIndex);
|
||||
mStyleSheets.InsertElementAt(oldIndex, newSheet);
|
||||
newSheet->SetOwningDocument(this);
|
||||
if (newSheet->IsApplicable()) {
|
||||
AddStyleSheetToStyleSets(newSheet);
|
||||
@@ -4276,10 +4236,11 @@ nsDocument::UpdateStyleSheets(nsCOMArray<nsIStyleSheet>& aOldSheets,
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::InsertStyleSheetAt(nsIStyleSheet* aSheet, int32_t aIndex)
|
||||
nsDocument::InsertStyleSheetAt(CSSStyleSheet* aSheet, int32_t aIndex)
|
||||
{
|
||||
NS_PRECONDITION(aSheet, "null ptr");
|
||||
mStyleSheets.InsertObjectAt(aSheet, aIndex);
|
||||
|
||||
mStyleSheets.InsertElementAt(aIndex, aSheet);
|
||||
|
||||
aSheet->SetOwningDocument(this);
|
||||
|
||||
@@ -4292,13 +4253,13 @@ nsDocument::InsertStyleSheetAt(nsIStyleSheet* aSheet, int32_t aIndex)
|
||||
|
||||
|
||||
void
|
||||
nsDocument::SetStyleSheetApplicableState(nsIStyleSheet* aSheet,
|
||||
nsDocument::SetStyleSheetApplicableState(CSSStyleSheet* aSheet,
|
||||
bool aApplicable)
|
||||
{
|
||||
NS_PRECONDITION(aSheet, "null arg");
|
||||
|
||||
// If we're actually in the document style sheet list
|
||||
if (-1 != mStyleSheets.IndexOf(aSheet)) {
|
||||
if (mStyleSheets.IndexOf(aSheet) != mStyleSheets.NoIndex) {
|
||||
if (aApplicable) {
|
||||
AddStyleSheetToStyleSets(aSheet);
|
||||
} else {
|
||||
@@ -4358,9 +4319,9 @@ ConvertAdditionalSheetType(nsIDocument::additionalSheetType aType)
|
||||
}
|
||||
|
||||
static int32_t
|
||||
FindSheet(const nsCOMArray<nsIStyleSheet>& aSheets, nsIURI* aSheetURI)
|
||||
FindSheet(const nsTArray<RefPtr<CSSStyleSheet>>& aSheets, nsIURI* aSheetURI)
|
||||
{
|
||||
for (int32_t i = aSheets.Count() - 1; i >= 0; i-- ) {
|
||||
for (int32_t i = aSheets.Length() - 1; i >= 0; i-- ) {
|
||||
bool bEqual;
|
||||
nsIURI* uri = aSheets[i]->GetSheetURI();
|
||||
|
||||
@@ -4414,7 +4375,7 @@ nsDocument::LoadAdditionalStyleSheet(additionalSheetType aType,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::AddAdditionalStyleSheet(additionalSheetType aType, nsIStyleSheet* aSheet)
|
||||
nsDocument::AddAdditionalStyleSheet(additionalSheetType aType, CSSStyleSheet* aSheet)
|
||||
{
|
||||
if (mAdditionalSheets[aType].Contains(aSheet))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
@@ -4422,7 +4383,7 @@ nsDocument::AddAdditionalStyleSheet(additionalSheetType aType, nsIStyleSheet* aS
|
||||
if (!aSheet->IsApplicable())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mAdditionalSheets[aType].AppendObject(aSheet);
|
||||
mAdditionalSheets[aType].AppendElement(aSheet);
|
||||
|
||||
BeginUpdate(UPDATE_STYLE);
|
||||
nsCOMPtr<nsIPresShell> shell = GetShell();
|
||||
@@ -4443,12 +4404,12 @@ nsDocument::RemoveAdditionalStyleSheet(additionalSheetType aType, nsIURI* aSheet
|
||||
{
|
||||
MOZ_ASSERT(aSheetURI);
|
||||
|
||||
nsCOMArray<nsIStyleSheet>& sheets = mAdditionalSheets[aType];
|
||||
nsTArray<RefPtr<CSSStyleSheet>>& sheets = mAdditionalSheets[aType];
|
||||
|
||||
int32_t i = FindSheet(mAdditionalSheets[aType], aSheetURI);
|
||||
if (i >= 0) {
|
||||
nsCOMPtr<nsIStyleSheet> sheetRef = sheets[i];
|
||||
sheets.RemoveObjectAt(i);
|
||||
RefPtr<CSSStyleSheet> sheetRef = sheets[i];
|
||||
sheets.RemoveElementAt(i);
|
||||
|
||||
BeginUpdate(UPDATE_STYLE);
|
||||
if (!mIsGoingAway) {
|
||||
@@ -4469,10 +4430,10 @@ nsDocument::RemoveAdditionalStyleSheet(additionalSheetType aType, nsIURI* aSheet
|
||||
}
|
||||
}
|
||||
|
||||
nsIStyleSheet*
|
||||
CSSStyleSheet*
|
||||
nsDocument::FirstAdditionalAuthorSheet()
|
||||
{
|
||||
return mAdditionalSheets[eAuthorSheet].SafeObjectAt(0);
|
||||
return mAdditionalSheets[eAuthorSheet].SafeElementAt(0, nullptr);
|
||||
}
|
||||
|
||||
nsIGlobalObject*
|
||||
@@ -5212,7 +5173,7 @@ nsDocument::DocumentStatesChanged(EventStates aStateMask)
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::StyleRuleChanged(nsIStyleSheet* aSheet,
|
||||
nsDocument::StyleRuleChanged(CSSStyleSheet* aSheet,
|
||||
css::Rule* aStyleRule)
|
||||
{
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleChanged, (aSheet));
|
||||
@@ -5226,7 +5187,7 @@ nsDocument::StyleRuleChanged(nsIStyleSheet* aSheet,
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::StyleRuleAdded(nsIStyleSheet* aSheet,
|
||||
nsDocument::StyleRuleAdded(CSSStyleSheet* aSheet,
|
||||
css::Rule* aStyleRule)
|
||||
{
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleAdded, (aSheet));
|
||||
@@ -5241,7 +5202,7 @@ nsDocument::StyleRuleAdded(nsIStyleSheet* aSheet,
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::StyleRuleRemoved(nsIStyleSheet* aSheet,
|
||||
nsDocument::StyleRuleRemoved(CSSStyleSheet* aSheet,
|
||||
css::Rule* aStyleRule)
|
||||
{
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleRemoved, (aSheet));
|
||||
@@ -6482,13 +6443,11 @@ nsIDocument::GetSelectedStyleSheetSet(nsAString& aSheetSet)
|
||||
int32_t count = GetNumberOfStyleSheets();
|
||||
nsAutoString title;
|
||||
for (int32_t index = 0; index < count; index++) {
|
||||
nsIStyleSheet* sheet = GetStyleSheetAt(index);
|
||||
CSSStyleSheet* sheet = GetStyleSheetAt(index);
|
||||
NS_ASSERTION(sheet, "Null sheet in sheet list!");
|
||||
|
||||
nsCOMPtr<nsIDOMStyleSheet> domSheet = do_QueryInterface(sheet);
|
||||
NS_ASSERTION(domSheet, "Sheet must QI to nsIDOMStyleSheet");
|
||||
bool disabled;
|
||||
domSheet->GetDisabled(&disabled);
|
||||
sheet->GetDisabled(&disabled);
|
||||
if (disabled) {
|
||||
// Disabled sheets don't affect the currently selected set
|
||||
continue;
|
||||
@@ -6598,7 +6557,7 @@ nsDocument::EnableStyleSheetsForSetInternal(const nsAString& aSheetSet,
|
||||
int32_t count = GetNumberOfStyleSheets();
|
||||
nsAutoString title;
|
||||
for (int32_t index = 0; index < count; index++) {
|
||||
nsIStyleSheet* sheet = GetStyleSheetAt(index);
|
||||
CSSStyleSheet* sheet = GetStyleSheetAt(index);
|
||||
NS_ASSERTION(sheet, "Null sheet in sheet list!");
|
||||
sheet->GetTitle(title);
|
||||
if (!title.IsEmpty()) {
|
||||
@@ -10205,7 +10164,7 @@ nsIDocument::CreateStaticClone(nsIDocShell* aCloneContainer)
|
||||
|
||||
int32_t sheetsCount = GetNumberOfStyleSheets();
|
||||
for (int32_t i = 0; i < sheetsCount; ++i) {
|
||||
RefPtr<CSSStyleSheet> sheet = do_QueryObject(GetStyleSheetAt(i));
|
||||
RefPtr<CSSStyleSheet> sheet = GetStyleSheetAt(i);
|
||||
if (sheet) {
|
||||
if (sheet->IsApplicable()) {
|
||||
RefPtr<CSSStyleSheet> clonedSheet =
|
||||
@@ -10218,11 +10177,8 @@ nsIDocument::CreateStaticClone(nsIDocShell* aCloneContainer)
|
||||
}
|
||||
}
|
||||
|
||||
sheetsCount = thisAsDoc->mOnDemandBuiltInUASheets.Count();
|
||||
// Iterate backwards to maintain order
|
||||
for (int32_t i = sheetsCount - 1; i >= 0; --i) {
|
||||
RefPtr<CSSStyleSheet> sheet =
|
||||
do_QueryObject(thisAsDoc->mOnDemandBuiltInUASheets[i]);
|
||||
for (CSSStyleSheet* sheet : Reversed(thisAsDoc->mOnDemandBuiltInUASheets)) {
|
||||
if (sheet) {
|
||||
if (sheet->IsApplicable()) {
|
||||
RefPtr<CSSStyleSheet> clonedSheet =
|
||||
@@ -12360,7 +12316,7 @@ nsDocument::OnAppThemeChanged()
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < GetNumberOfStyleSheets(); i++) {
|
||||
RefPtr<CSSStyleSheet> sheet = do_QueryObject(GetStyleSheetAt(i));
|
||||
RefPtr<CSSStyleSheet> sheet = GetStyleSheetAt(i);
|
||||
if (!sheet) {
|
||||
continue;
|
||||
}
|
||||
@@ -12727,15 +12683,19 @@ nsIDocument::DocAddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfStyleSheetsElementIncludingThis(nsIStyleSheet* aStyleSheet,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aData)
|
||||
SizeOfOwnedSheetArrayExcludingThis(const nsTArray<RefPtr<CSSStyleSheet>>& aSheets,
|
||||
MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
if (!aStyleSheet->GetOwningDocument()) {
|
||||
// Avoid over-reporting shared sheets.
|
||||
return 0;
|
||||
size_t n = 0;
|
||||
n += aSheets.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (CSSStyleSheet* sheet : aSheets) {
|
||||
if (!sheet->GetOwningDocument()) {
|
||||
// Avoid over-reporting shared sheets.
|
||||
continue;
|
||||
}
|
||||
n += sheet->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
return aStyleSheet->SizeOfIncludingThis(aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -12786,26 +12746,18 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
||||
}
|
||||
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
mStyleSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
SizeOfOwnedSheetArrayExcludingThis(mStyleSheets,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
// Note that we do not own the sheets pointed to by mOnDemandBuiltInUASheets
|
||||
// (the nsLayoutStyleSheetCache singleton does) so pass nullptr as the
|
||||
// aSizeOfElementIncludingThis callback argument.
|
||||
// (the nsLayoutStyleSheetCache singleton does).
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
mOnDemandBuiltInUASheets.SizeOfExcludingThis(nullptr,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
mAdditionalSheets[eAgentSheet].
|
||||
SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
mAdditionalSheets[eUserSheet].
|
||||
SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
mAdditionalSheets[eAuthorSheet].
|
||||
SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
mOnDemandBuiltInUASheets.ShallowSizeOfExcludingThis(
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
for (auto& sheetArray : mAdditionalSheets) {
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
SizeOfOwnedSheetArrayExcludingThis(sheetArray,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
}
|
||||
// Lumping in the loader with the style-sheets size is not ideal,
|
||||
// but most of the things in there are in fact stylesheets, so it
|
||||
// doesn't seem worthwhile to separate it out.
|
||||
|
||||
+30
-24
@@ -775,24 +775,29 @@ public:
|
||||
* These are ordered, highest priority last
|
||||
*/
|
||||
virtual int32_t GetNumberOfStyleSheets() const override;
|
||||
virtual nsIStyleSheet* GetStyleSheetAt(int32_t aIndex) const override;
|
||||
virtual int32_t GetIndexOfStyleSheet(nsIStyleSheet* aSheet) const override;
|
||||
virtual void AddStyleSheet(nsIStyleSheet* aSheet) override;
|
||||
virtual void RemoveStyleSheet(nsIStyleSheet* aSheet) override;
|
||||
virtual mozilla::CSSStyleSheet* GetStyleSheetAt(int32_t aIndex) const override;
|
||||
virtual int32_t GetIndexOfStyleSheet(mozilla::CSSStyleSheet* aSheet) const override;
|
||||
virtual void AddStyleSheet(mozilla::CSSStyleSheet* aSheet) override;
|
||||
virtual void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet) override;
|
||||
|
||||
virtual void UpdateStyleSheets(nsCOMArray<nsIStyleSheet>& aOldSheets,
|
||||
nsCOMArray<nsIStyleSheet>& aNewSheets) override;
|
||||
virtual void AddStyleSheetToStyleSets(nsIStyleSheet* aSheet);
|
||||
virtual void RemoveStyleSheetFromStyleSets(nsIStyleSheet* aSheet);
|
||||
virtual void UpdateStyleSheets(
|
||||
nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aOldSheets,
|
||||
nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aNewSheets) override;
|
||||
virtual void AddStyleSheetToStyleSets(mozilla::CSSStyleSheet* aSheet);
|
||||
virtual void RemoveStyleSheetFromStyleSets(mozilla::CSSStyleSheet* aSheet);
|
||||
|
||||
virtual void InsertStyleSheetAt(nsIStyleSheet* aSheet, int32_t aIndex) override;
|
||||
virtual void SetStyleSheetApplicableState(nsIStyleSheet* aSheet,
|
||||
virtual void InsertStyleSheetAt(mozilla::CSSStyleSheet* aSheet,
|
||||
int32_t aIndex) override;
|
||||
virtual void SetStyleSheetApplicableState(mozilla::CSSStyleSheet* aSheet,
|
||||
bool aApplicable) override;
|
||||
|
||||
virtual nsresult LoadAdditionalStyleSheet(additionalSheetType aType, nsIURI* aSheetURI) override;
|
||||
virtual nsresult AddAdditionalStyleSheet(additionalSheetType aType, nsIStyleSheet* aSheet) override;
|
||||
virtual void RemoveAdditionalStyleSheet(additionalSheetType aType, nsIURI* sheetURI) override;
|
||||
virtual nsIStyleSheet* FirstAdditionalAuthorSheet() override;
|
||||
virtual nsresult LoadAdditionalStyleSheet(additionalSheetType aType,
|
||||
nsIURI* aSheetURI) override;
|
||||
virtual nsresult AddAdditionalStyleSheet(additionalSheetType aType,
|
||||
mozilla::CSSStyleSheet* aSheet) override;
|
||||
virtual void RemoveAdditionalStyleSheet(additionalSheetType aType,
|
||||
nsIURI* sheetURI) override;
|
||||
virtual mozilla::CSSStyleSheet* FirstAdditionalAuthorSheet() override;
|
||||
|
||||
virtual nsIChannel* GetChannel() const override {
|
||||
return mChannel;
|
||||
@@ -852,11 +857,11 @@ public:
|
||||
virtual void DocumentStatesChanged(
|
||||
mozilla::EventStates aStateMask) override;
|
||||
|
||||
virtual void StyleRuleChanged(nsIStyleSheet* aStyleSheet,
|
||||
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aStyleRule) override;
|
||||
virtual void StyleRuleAdded(nsIStyleSheet* aStyleSheet,
|
||||
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aStyleRule) override;
|
||||
virtual void StyleRuleRemoved(nsIStyleSheet* aStyleSheet,
|
||||
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aStyleRule) override;
|
||||
|
||||
virtual void FlushPendingNotifications(mozFlushType aType) override;
|
||||
@@ -1483,8 +1488,9 @@ protected:
|
||||
nsStyleSet* aStyleSet);
|
||||
|
||||
void RemoveDocStyleSheetsFromStyleSets();
|
||||
void RemoveStyleSheetsFromStyleSets(nsCOMArray<nsIStyleSheet>& aSheets,
|
||||
mozilla::SheetType aType);
|
||||
void RemoveStyleSheetsFromStyleSets(
|
||||
nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aSheets,
|
||||
mozilla::SheetType aType);
|
||||
void ResetStylesheetsToURI(nsIURI* aURI);
|
||||
void FillStyleSet(nsStyleSet* aStyleSet);
|
||||
|
||||
@@ -1532,9 +1538,9 @@ protected:
|
||||
// EndLoad() has already happened.
|
||||
nsWeakPtr mWeakSink;
|
||||
|
||||
nsCOMArray<nsIStyleSheet> mStyleSheets;
|
||||
nsCOMArray<nsIStyleSheet> mOnDemandBuiltInUASheets;
|
||||
nsCOMArray<nsIStyleSheet> mAdditionalSheets[AdditionalSheetTypeCount];
|
||||
nsTArray<RefPtr<mozilla::CSSStyleSheet>> mStyleSheets;
|
||||
nsTArray<RefPtr<mozilla::CSSStyleSheet>> mOnDemandBuiltInUASheets;
|
||||
nsTArray<RefPtr<mozilla::CSSStyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
|
||||
|
||||
// Array of observers
|
||||
nsTObserverArray<nsIDocumentObserver*> mObservers;
|
||||
@@ -1713,8 +1719,8 @@ private:
|
||||
friend class nsUnblockOnloadEvent;
|
||||
// Recomputes the visibility state but doesn't set the new value.
|
||||
mozilla::dom::VisibilityState GetVisibilityState() const;
|
||||
void NotifyStyleSheetAdded(nsIStyleSheet* aSheet, bool aDocumentSheet);
|
||||
void NotifyStyleSheetRemoved(nsIStyleSheet* aSheet, bool aDocumentSheet);
|
||||
void NotifyStyleSheetAdded(mozilla::CSSStyleSheet* aSheet, bool aDocumentSheet);
|
||||
void NotifyStyleSheetRemoved(mozilla::CSSStyleSheet* aSheet, bool aDocumentSheet);
|
||||
|
||||
void PostUnblockOnloadEvent();
|
||||
void DoUnblockOnload();
|
||||
|
||||
+20
-16
@@ -73,7 +73,6 @@ class nsIRequest;
|
||||
class nsIRunnable;
|
||||
class nsIStreamListener;
|
||||
class nsIStructuredCloneContainer;
|
||||
class nsIStyleSheet;
|
||||
class nsIURI;
|
||||
class nsIVariant;
|
||||
class nsLocation;
|
||||
@@ -946,7 +945,7 @@ public:
|
||||
* @return the stylesheet at aIndex. Null if aIndex is out of range.
|
||||
* @throws no exceptions
|
||||
*/
|
||||
virtual nsIStyleSheet* GetStyleSheetAt(int32_t aIndex) const = 0;
|
||||
virtual mozilla::CSSStyleSheet* GetStyleSheetAt(int32_t aIndex) const = 0;
|
||||
|
||||
/**
|
||||
* Insert a sheet at a particular spot in the stylesheet list (zero-based)
|
||||
@@ -955,7 +954,8 @@ public:
|
||||
* adjusted for the "special" sheets.
|
||||
* @throws no exceptions
|
||||
*/
|
||||
virtual void InsertStyleSheetAt(nsIStyleSheet* aSheet, int32_t aIndex) = 0;
|
||||
virtual void InsertStyleSheetAt(mozilla::CSSStyleSheet* aSheet,
|
||||
int32_t aIndex) = 0;
|
||||
|
||||
/**
|
||||
* Get the index of a particular stylesheet. This will _always_
|
||||
@@ -963,7 +963,7 @@ public:
|
||||
* @param aSheet the sheet to get the index of
|
||||
* @return aIndex the index of the sheet in the full list
|
||||
*/
|
||||
virtual int32_t GetIndexOfStyleSheet(nsIStyleSheet* aSheet) const = 0;
|
||||
virtual int32_t GetIndexOfStyleSheet(mozilla::CSSStyleSheet* aSheet) const = 0;
|
||||
|
||||
/**
|
||||
* Replace the stylesheets in aOldSheets with the stylesheets in
|
||||
@@ -973,24 +973,25 @@ public:
|
||||
* may be null; if so the corresponding sheets in the first list
|
||||
* will simply be removed.
|
||||
*/
|
||||
virtual void UpdateStyleSheets(nsCOMArray<nsIStyleSheet>& aOldSheets,
|
||||
nsCOMArray<nsIStyleSheet>& aNewSheets) = 0;
|
||||
virtual void UpdateStyleSheets(
|
||||
nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aOldSheets,
|
||||
nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aNewSheets) = 0;
|
||||
|
||||
/**
|
||||
* Add a stylesheet to the document
|
||||
*/
|
||||
virtual void AddStyleSheet(nsIStyleSheet* aSheet) = 0;
|
||||
virtual void AddStyleSheet(mozilla::CSSStyleSheet* aSheet) = 0;
|
||||
|
||||
/**
|
||||
* Remove a stylesheet from the document
|
||||
*/
|
||||
virtual void RemoveStyleSheet(nsIStyleSheet* aSheet) = 0;
|
||||
virtual void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet) = 0;
|
||||
|
||||
/**
|
||||
* Notify the document that the applicable state of the sheet changed
|
||||
* and that observers should be notified and style sets updated
|
||||
*/
|
||||
virtual void SetStyleSheetApplicableState(nsIStyleSheet* aSheet,
|
||||
virtual void SetStyleSheetApplicableState(mozilla::CSSStyleSheet* aSheet,
|
||||
bool aApplicable) = 0;
|
||||
|
||||
enum additionalSheetType {
|
||||
@@ -1000,10 +1001,13 @@ public:
|
||||
AdditionalSheetTypeCount
|
||||
};
|
||||
|
||||
virtual nsresult LoadAdditionalStyleSheet(additionalSheetType aType, nsIURI* aSheetURI) = 0;
|
||||
virtual nsresult AddAdditionalStyleSheet(additionalSheetType aType, nsIStyleSheet* aSheet) = 0;
|
||||
virtual void RemoveAdditionalStyleSheet(additionalSheetType aType, nsIURI* sheetURI) = 0;
|
||||
virtual nsIStyleSheet* FirstAdditionalAuthorSheet() = 0;
|
||||
virtual nsresult LoadAdditionalStyleSheet(additionalSheetType aType,
|
||||
nsIURI* aSheetURI) = 0;
|
||||
virtual nsresult AddAdditionalStyleSheet(additionalSheetType aType,
|
||||
mozilla::CSSStyleSheet* aSheet) = 0;
|
||||
virtual void RemoveAdditionalStyleSheet(additionalSheetType aType,
|
||||
nsIURI* sheetURI) = 0;
|
||||
virtual mozilla::CSSStyleSheet* FirstAdditionalAuthorSheet() = 0;
|
||||
|
||||
/**
|
||||
* Get this document's CSSLoader. This is guaranteed to not return null.
|
||||
@@ -1306,11 +1310,11 @@ public:
|
||||
|
||||
// Observation hooks for style data to propagate notifications
|
||||
// to document observers
|
||||
virtual void StyleRuleChanged(nsIStyleSheet* aStyleSheet,
|
||||
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aStyleRule) = 0;
|
||||
virtual void StyleRuleAdded(nsIStyleSheet* aStyleSheet,
|
||||
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aStyleRule) = 0;
|
||||
virtual void StyleRuleRemoved(nsIStyleSheet* aStyleSheet,
|
||||
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aStyleRule) = 0;
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
#include "nsIMutationObserver.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIStyleSheet;
|
||||
class nsIDocument;
|
||||
|
||||
namespace mozilla {
|
||||
class CSSStyleSheet;
|
||||
namespace css {
|
||||
class Rule;
|
||||
} // namespace css
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
* @param aDocumentSheet True if sheet is in document's style sheet list,
|
||||
* false if sheet is not (i.e., UA or user sheet)
|
||||
*/
|
||||
virtual void StyleSheetAdded(nsIStyleSheet* aStyleSheet,
|
||||
virtual void StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
bool aDocumentSheet) = 0;
|
||||
|
||||
/**
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
* @param aDocumentSheet True if sheet is in document's style sheet list,
|
||||
* false if sheet is not (i.e., UA or user sheet)
|
||||
*/
|
||||
virtual void StyleSheetRemoved(nsIStyleSheet* aStyleSheet,
|
||||
virtual void StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
bool aDocumentSheet) = 0;
|
||||
|
||||
/**
|
||||
@@ -125,7 +125,7 @@ public:
|
||||
*
|
||||
* @param aStyleSheet the StyleSheet that has changed state
|
||||
*/
|
||||
virtual void StyleSheetApplicableStateChanged(nsIStyleSheet* aStyleSheet) = 0;
|
||||
virtual void StyleSheetApplicableStateChanged(mozilla::CSSStyleSheet* aStyleSheet) = 0;
|
||||
|
||||
/**
|
||||
* A StyleRule has just been modified within a style sheet.
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
*
|
||||
* @param aStyleSheet the StyleSheet that contians the rule
|
||||
*/
|
||||
virtual void StyleRuleChanged(nsIStyleSheet* aStyleSheet) = 0;
|
||||
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet) = 0;
|
||||
|
||||
/**
|
||||
* A StyleRule has just been added to a style sheet.
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
*
|
||||
* @param aStyleSheet the StyleSheet that has been modified
|
||||
*/
|
||||
virtual void StyleRuleAdded(nsIStyleSheet* aStyleSheet) = 0;
|
||||
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet) = 0;
|
||||
|
||||
/**
|
||||
* A StyleRule has just been removed from a style sheet.
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
*
|
||||
* @param aStyleSheet the StyleSheet that has been modified
|
||||
*/
|
||||
virtual void StyleRuleRemoved(nsIStyleSheet* aStyleSheet) = 0;
|
||||
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
||||
@@ -186,24 +186,25 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
||||
mozilla::EventStates aStateMask) override;
|
||||
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED \
|
||||
virtual void StyleSheetAdded(nsIStyleSheet* aStyleSheet, \
|
||||
virtual void StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet, \
|
||||
bool aDocumentSheet) override;
|
||||
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED \
|
||||
virtual void StyleSheetRemoved(nsIStyleSheet* aStyleSheet, \
|
||||
virtual void StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet, \
|
||||
bool aDocumentSheet) override;
|
||||
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETAPPLICABLESTATECHANGED \
|
||||
virtual void StyleSheetApplicableStateChanged(nsIStyleSheet* aStyleSheet) override;
|
||||
virtual void StyleSheetApplicableStateChanged( \
|
||||
mozilla::CSSStyleSheet* aStyleSheet) override;
|
||||
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED \
|
||||
virtual void StyleRuleChanged(nsIStyleSheet* aStyleSheet) override;
|
||||
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet) override;
|
||||
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED \
|
||||
virtual void StyleRuleAdded(nsIStyleSheet* aStyleSheet) override;
|
||||
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet) override;
|
||||
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEREMOVED \
|
||||
virtual void StyleRuleRemoved(nsIStyleSheet* aStyleSheet) override;
|
||||
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet) override;
|
||||
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER \
|
||||
NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE \
|
||||
@@ -261,29 +262,29 @@ NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class)
|
||||
|
||||
#define NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(_class) \
|
||||
void \
|
||||
_class::StyleSheetAdded(nsIStyleSheet* aStyleSheet, \
|
||||
_class::StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet, \
|
||||
bool aDocumentSheet) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::StyleSheetRemoved(nsIStyleSheet* aStyleSheet, \
|
||||
_class::StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet, \
|
||||
bool aDocumentSheet) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::StyleSheetApplicableStateChanged(nsIStyleSheet* aStyleSheet) \
|
||||
_class::StyleSheetApplicableStateChanged(mozilla::CSSStyleSheet* aStyleSheet) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::StyleRuleChanged(nsIStyleSheet* aStyleSheet) \
|
||||
_class::StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::StyleRuleAdded(nsIStyleSheet* aStyleSheet) \
|
||||
_class::StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::StyleRuleRemoved(nsIStyleSheet* aStyleSheet) \
|
||||
_class::StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet) \
|
||||
{ \
|
||||
}
|
||||
|
||||
|
||||
@@ -285,17 +285,6 @@ UpdateIsElementInStyleScopeFlagOnSubtree(Element* aElement)
|
||||
}
|
||||
}
|
||||
|
||||
static Element*
|
||||
GetScopeElement(nsIStyleSheet* aSheet)
|
||||
{
|
||||
RefPtr<CSSStyleSheet> cssStyleSheet = do_QueryObject(aSheet);
|
||||
if (!cssStyleSheet) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return cssStyleSheet->GetScopeElement();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
ShadowRoot* aOldShadowRoot,
|
||||
@@ -327,7 +316,8 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Element* oldScopeElement = GetScopeElement(mStyleSheet);
|
||||
Element* oldScopeElement =
|
||||
mStyleSheet ? mStyleSheet->GetScopeElement() : nullptr;
|
||||
|
||||
if (mStyleSheet && (aOldDocument || aOldShadowRoot)) {
|
||||
MOZ_ASSERT(!(aOldDocument && aOldShadowRoot),
|
||||
|
||||
@@ -26,3 +26,5 @@ skip-if = true # Intermittent failures - bug 987493. Restore the skip-if above o
|
||||
[browser_bug1058164.js]
|
||||
skip-if = e10s # We need bug 918634 to land before this can be tested with e10s.
|
||||
[browser_use_counters.js]
|
||||
[browser_bug1238440.js]
|
||||
skip-if = e10s
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
Components.utils.import("resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
const PAGE = "data:text/html,<html><body><input type=\"file\"/></body></html>";
|
||||
|
||||
function writeFile(file, text) {
|
||||
return new Promise((resolve) => {
|
||||
let converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
let ostream = FileUtils.openSafeFileOutputStream(file);
|
||||
let istream = converter.convertToInputStream(text);
|
||||
NetUtil.asyncCopy(istream, ostream, function(status) {
|
||||
if (!Components.isSuccessCode(status)) throw 'fail';
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function runFileReader(input, status) {
|
||||
return new Promise((resolve) => {
|
||||
let fr = new FileReader();
|
||||
fr.onload = function() {
|
||||
ok(status, "FileReader called onload");
|
||||
resolve();
|
||||
}
|
||||
|
||||
fr.onerror = function(e) {
|
||||
e.preventDefault();
|
||||
ok(!status, "FileReader called onerror");
|
||||
resolve();
|
||||
}
|
||||
|
||||
fr.readAsArrayBuffer(input);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function() {
|
||||
info("Creating a temporary file...");
|
||||
let file = FileUtils.getFile("TmpD", ["bug1238440.txt"]);
|
||||
yield writeFile(file, "hello world");
|
||||
|
||||
info("Opening a tab...");
|
||||
let tab = gBrowser.addTab(PAGE);
|
||||
gBrowser.selectedTab = tab;
|
||||
let browser = tab.linkedBrowser;
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
|
||||
info("Populating the form...");
|
||||
let doc = browser.contentDocument;
|
||||
let input = doc.querySelector('input');
|
||||
input.value = file.path;
|
||||
|
||||
info("Running the FileReader...");
|
||||
yield runFileReader(input.files[0], true);
|
||||
|
||||
info("Writing the temporary file again...");
|
||||
yield writeFile(file, "hello world-----------------------------");
|
||||
|
||||
info("Running the FileReader again...");
|
||||
yield runFileReader(input.files[0], false);
|
||||
|
||||
info("Closing the tab...");
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
|
||||
ok(true, "we didn't crash.");
|
||||
});
|
||||
@@ -127,23 +127,6 @@ function testHasRun() {
|
||||
}
|
||||
}
|
||||
|
||||
function createFileWithData(fileData) {
|
||||
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"].getService(SpecialPowers.Ci.nsIProperties);
|
||||
var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
testFile.append("fileAPItestfile2-" + fileNum);
|
||||
fileNum++;
|
||||
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].createInstance(SpecialPowers.Ci.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
outStream.close();
|
||||
|
||||
var fileList = document.getElementById('fileList');
|
||||
SpecialPowers.wrap(fileList).value = testFile.path;
|
||||
|
||||
return fileList.files[0];
|
||||
}
|
||||
|
||||
function gc() {
|
||||
window.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIDOMWindowUtils)
|
||||
|
||||
@@ -513,7 +513,6 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||
[test_bug433533.html]
|
||||
[test_bug433662.html]
|
||||
[test_bug435425.html]
|
||||
[test_bug438519.html]
|
||||
[test_bug444030.xhtml]
|
||||
[test_bug444322.html]
|
||||
[test_bug444722.html]
|
||||
@@ -732,7 +731,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183
|
||||
[test_encodeToStringWithMaxLength.html]
|
||||
[test_fileapi.html]
|
||||
[test_fileapi_slice.html]
|
||||
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' || e10s #bug 775227
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 775227
|
||||
[test_getElementById.html]
|
||||
[test_html_colors_quirks.html]
|
||||
[test_html_colors_standards.html]
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=438519
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 438519</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="doTest()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=438519">Mozilla Bug 438519</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display:none">
|
||||
|
||||
<iframe id="empty" src="data:text/xml,<!DOCTYPE HTML []><html></html>"></iframe>
|
||||
<iframe id="missing" src="data:text/xml,<!DOCTYPE HTML><html></html>"></iframe>
|
||||
<iframe id="entity" src="data:text/xml,<!DOCTYPE HTML [ <!ENTITY foo 'foo'> ]><html></html>"></iframe>
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 218236 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function doTest() {
|
||||
function checkInternalSubset(id, expected) {
|
||||
var e = document.getElementById(id);
|
||||
is(e.contentDocument.doctype.internalSubset, expected, "checking '" + id + "'");
|
||||
}
|
||||
|
||||
checkInternalSubset("empty", "");
|
||||
checkInternalSubset("missing", null);
|
||||
checkInternalSubset("entity", " <!ENTITY foo 'foo'> ");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -24,7 +24,6 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
is(doc.doctype.name, "html");
|
||||
is(doc.doctype.publicId, "");
|
||||
is(doc.doctype.systemId, "");
|
||||
is(doc.doctype.internalSubset, null, "internalSubset should be null!");
|
||||
isElement(doc.documentElement, "html");
|
||||
isElement(doc.documentElement.firstChild, "head");
|
||||
if (title !== undefined) {
|
||||
@@ -38,8 +37,7 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
}
|
||||
isElement(doc.documentElement.lastChild, "body");
|
||||
is(doc.documentElement.lastChild.childNodes.length, 0);
|
||||
((!title || title.indexOf("\f") === -1) ? is : todo_is)
|
||||
(doc.title, normalizedtitle);
|
||||
is(doc.title, normalizedtitle);
|
||||
doc.body.innerHTML = "foo";
|
||||
is(doc.body.innerHTML, "foo", "innerHTML should work in HTML data documents!");
|
||||
}
|
||||
|
||||
@@ -54,31 +54,6 @@ cx.fill();
|
||||
cx.closePath();
|
||||
|
||||
|
||||
var fileData =
|
||||
atob(cx.canvas.toDataURL("image/png").substring("data:text/png;base64,".length + 1));
|
||||
var memFile = cx.canvas.mozGetAsFile("image/png");
|
||||
var fileFile = createFileWithData(fileData);
|
||||
var size = fileData.length;
|
||||
|
||||
// This might fail if we dramatically improve the png encoder. If that happens
|
||||
// please increase the complexity or size of the image generated above to ensure
|
||||
// that we're testing with files that are large enough.
|
||||
ok(size > 65536, "test data sufficiently large");
|
||||
|
||||
|
||||
// Test that basic properties work
|
||||
testSlice(memFile, size, "image/png", fileData, "memFile");
|
||||
testSlice(fileFile, size, "", fileData, "fileFile");
|
||||
|
||||
|
||||
// Try loading directly from slice into an image
|
||||
var testBinaryData = "";
|
||||
for (var i = 0; i < 256; i++) {
|
||||
testBinaryData += String.fromCharCode(i);
|
||||
}
|
||||
while (testBinaryData.length < 20000) {
|
||||
testBinaryData += testBinaryData;
|
||||
}
|
||||
function imageLoadHandler(event) {
|
||||
var origcanvas = $("canvas");
|
||||
var testcanvas = $("testcanvas");
|
||||
@@ -100,37 +75,93 @@ function imageLoadHandler(event) {
|
||||
testHasRun();
|
||||
}
|
||||
|
||||
// image in the middle
|
||||
var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData);
|
||||
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
var fileData =
|
||||
atob(cx.canvas.toDataURL("image/png").substring("data:text/png;base64,".length + 1));
|
||||
var size = fileData.length;
|
||||
var testBinaryData = "";
|
||||
|
||||
// image at start
|
||||
var imgfile = createFileWithData(fileData + testBinaryData);
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(0, size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
// This might fail if we dramatically improve the png encoder. If that happens
|
||||
// please increase the complexity or size of the image generated above to ensure
|
||||
// that we're testing with files that are large enough.
|
||||
ok(size > 65536, "test data sufficiently large");
|
||||
|
||||
// image at end
|
||||
var imgfile = createFileWithData(testBinaryData + fileData);
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
SpecialPowers.createFiles([{name: "basicTestFile", data: fileData}],
|
||||
basicTest);
|
||||
|
||||
function basicTest(files) {
|
||||
var fileFile = files[0];
|
||||
|
||||
// Test that basic properties work
|
||||
var memFile = cx.canvas.mozGetAsFile("image/png");
|
||||
testSlice(memFile, size, "image/png", fileData, "memFile");
|
||||
testSlice(fileFile, size, "", fileData, "fileFile");
|
||||
|
||||
// Try loading directly from slice into an image
|
||||
for (var i = 0; i < 256; i++) {
|
||||
testBinaryData += String.fromCharCode(i);
|
||||
}
|
||||
while (testBinaryData.length < 20000) {
|
||||
testBinaryData += testBinaryData;
|
||||
}
|
||||
|
||||
// image in the middle
|
||||
SpecialPowers.createFiles([{name: "middleTestFile",
|
||||
data: testBinaryData + fileData + testBinaryData}],
|
||||
imageMiddleTest);
|
||||
}
|
||||
|
||||
function imageMiddleTest(files) {
|
||||
var imgfile = files[0];
|
||||
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
|
||||
// image at start
|
||||
SpecialPowers.createFiles([{name: "startTestFile",
|
||||
data: fileData + testBinaryData}],
|
||||
imageStartTest);
|
||||
}
|
||||
|
||||
function imageStartTest(files) {
|
||||
var imgfile = files[0];
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(0, size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
|
||||
// image at end
|
||||
SpecialPowers.createFiles([{name: "endTestFile",
|
||||
data: testBinaryData + fileData}],
|
||||
imageEndTest);
|
||||
}
|
||||
|
||||
function imageEndTest(files) {
|
||||
var imgfile = files[0];
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
|
||||
// image past end
|
||||
SpecialPowers.createFiles([{name: "pastEndTestFile",
|
||||
data: testBinaryData + fileData}],
|
||||
imagePastEndTest);
|
||||
}
|
||||
|
||||
function imagePastEndTest(files) {
|
||||
var imgfile = files[0];
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size + 1000));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
}
|
||||
|
||||
// image past end
|
||||
var imgfile = createFileWithData(testBinaryData + fileData);
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size + 1000));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
</script>
|
||||
</pre>
|
||||
</body> </html>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -89,3 +89,4 @@ MSG_DEF(MSG_IS_NOT_PROMISE, 1, JSEXN_TYPEERR, "{0} is not a Promise")
|
||||
MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
|
||||
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
|
||||
MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")
|
||||
MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 3, JSEXN_TYPEERR, "Cache got {0} response with bad status {1} while trying to add request {2}")
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
return mDiscoverable;
|
||||
}
|
||||
|
||||
BluetoothPairingListener* PairingReqs() const
|
||||
BluetoothPairingListener* GetPairingReqs() const
|
||||
{
|
||||
return mPairingReqs;
|
||||
}
|
||||
|
||||
@@ -75,15 +75,6 @@ const OBSERVED_EVENTS = [
|
||||
'will-launch-app'
|
||||
];
|
||||
|
||||
const COMMAND_MAP = {
|
||||
'cut': 'cmd_cut',
|
||||
'copy': 'cmd_copyAndCollapseToEnd',
|
||||
'copyImage': 'cmd_copyImage',
|
||||
'copyLink': 'cmd_copyLink',
|
||||
'paste': 'cmd_paste',
|
||||
'selectall': 'cmd_selectAll'
|
||||
};
|
||||
|
||||
/**
|
||||
* The BrowserElementChild implements one half of <iframe mozbrowser>.
|
||||
* (The other half is, unsurprisingly, BrowserElementParent.)
|
||||
@@ -269,7 +260,6 @@ BrowserElementChild.prototype = {
|
||||
"activate-next-paint-listener": this._activateNextPaintListener.bind(this),
|
||||
"set-input-method-active": this._recvSetInputMethodActive.bind(this),
|
||||
"deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this),
|
||||
"do-command": this._recvDoCommand,
|
||||
"find-all": this._recvFindAll.bind(this),
|
||||
"find-next": this._recvFindNext.bind(this),
|
||||
"clear-match": this._recvClearMatch.bind(this),
|
||||
@@ -419,15 +409,6 @@ BrowserElementChild.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_isCommandEnabled: function(cmd) {
|
||||
let command = COMMAND_MAP[cmd];
|
||||
if (!command) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return docShell.isCommandEnabled(command);
|
||||
},
|
||||
|
||||
/**
|
||||
* Spin in a nested event loop until we receive a unblock-modal-prompt message for
|
||||
* this window.
|
||||
@@ -1187,14 +1168,16 @@ BrowserElementChild.prototype = {
|
||||
_recvFireCtxCallback: function(data) {
|
||||
debug("Received fireCtxCallback message: (" + data.json.menuitem + ")");
|
||||
|
||||
let doCommandIfEnabled = (command) => {
|
||||
if (docShell.isCommandEnabled(command)) {
|
||||
docShell.doCommand(command);
|
||||
}
|
||||
};
|
||||
|
||||
if (data.json.menuitem == 'copy-image') {
|
||||
// Set command
|
||||
data.json.command = 'copyImage';
|
||||
this._recvDoCommand(data);
|
||||
doCommandIfEnabled('cmd_copyImage');
|
||||
} else if (data.json.menuitem == 'copy-link') {
|
||||
// Set command
|
||||
data.json.command = 'copyLink';
|
||||
this._recvDoCommand(data);
|
||||
doCommandIfEnabled('cmd_copyLink');
|
||||
} else if (data.json.menuitem in this._ctxHandlers) {
|
||||
this._ctxHandlers[data.json.menuitem].click();
|
||||
this._ctxHandlers = {};
|
||||
@@ -1378,12 +1361,6 @@ BrowserElementChild.prototype = {
|
||||
docShell.contentViewer.fullZoom = data.json.zoom;
|
||||
},
|
||||
|
||||
_recvDoCommand: function(data) {
|
||||
if (this._isCommandEnabled(data.json.command)) {
|
||||
docShell.doCommand(COMMAND_MAP[data.json.command]);
|
||||
}
|
||||
},
|
||||
|
||||
_recvGetAudioChannelVolume: function(data) {
|
||||
debug("Received getAudioChannelVolume message: (" + data.json.id + ")");
|
||||
|
||||
@@ -1871,6 +1848,7 @@ BrowserElementChild.prototype = {
|
||||
case Cr.NS_BINDING_ABORTED :
|
||||
// Ignoring NS_BINDING_ABORTED, which is set when loading page is
|
||||
// stopped.
|
||||
case Cr.NS_ERROR_PARSED_DATA_CACHED:
|
||||
return;
|
||||
|
||||
// TODO See nsDocShell::DisplayLoadError to see what extra
|
||||
|
||||
@@ -30,7 +30,7 @@ var CopyPasteAssistent = {
|
||||
switch (e.data.msg_name) {
|
||||
case 'copypaste-do-command':
|
||||
if (this._isCommandEnabled(e.data.command)) {
|
||||
docShell.doCommand(COMMAND_MAP[e.data.command]);
|
||||
docShell.doCommand(this.COMMAND_MAP[e.data.command]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ var Cr = Components.results;
|
||||
*/
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||
|
||||
@@ -262,7 +263,6 @@ function BrowserElementParent() {
|
||||
|
||||
Services.obs.addObserver(this, 'ask-children-to-exit-fullscreen', /* ownsWeak = */ true);
|
||||
Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
|
||||
Services.obs.addObserver(this, 'copypaste-docommand', /* ownsWeak = */ true);
|
||||
Services.obs.addObserver(this, 'ask-children-to-execute-copypaste-command', /* ownsWeak = */ true);
|
||||
Services.obs.addObserver(this, 'back-docommand', /* ownsWeak = */ true);
|
||||
|
||||
@@ -470,6 +470,7 @@ BrowserElementParent.prototype = {
|
||||
/* username and password */
|
||||
let detail = {
|
||||
host: authDetail.host,
|
||||
path: authDetail.path,
|
||||
realm: authDetail.realm,
|
||||
isProxy: authDetail.isProxy
|
||||
};
|
||||
@@ -1008,36 +1009,17 @@ BrowserElementParent.prototype = {
|
||||
Ci.nsIRequestObserver])
|
||||
};
|
||||
|
||||
// If we have a URI we'll use it to get the triggering principal to use,
|
||||
// if not available a null principal is acceptable.
|
||||
let referrer = null;
|
||||
let principal = null;
|
||||
if (_options.referrer) {
|
||||
// newURI can throw on malformed URIs.
|
||||
try {
|
||||
referrer = Services.io.newURI(_options.referrer, null, null);
|
||||
}
|
||||
catch(e) {
|
||||
debug('Malformed referrer -- ' + e);
|
||||
}
|
||||
let referrer = Services.io.newURI(_options.referrer, null, null);
|
||||
let principal =
|
||||
Services.scriptSecurityManager.createCodebasePrincipal(
|
||||
referrer, this._frameLoader.loadContext.originAttributes);
|
||||
|
||||
// This simply returns null if there is no principal available
|
||||
// for the requested uri. This is an acceptable fallback when
|
||||
// calling newChannelFromURI2.
|
||||
principal =
|
||||
Services.scriptSecurityManager.createCodebasePrincipal(
|
||||
referrer, this._frameLoader.loadContext.originAttributes);
|
||||
}
|
||||
|
||||
debug('Using principal? ' + !!principal);
|
||||
|
||||
let channel =
|
||||
Services.io.newChannelFromURI2(url,
|
||||
null, // No document.
|
||||
principal, // Loading principal
|
||||
principal, // Triggering principal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let channel = NetUtil.newChannel({
|
||||
uri: url,
|
||||
loadingPrincipal: principal,
|
||||
securityFlags: SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS,
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
|
||||
});
|
||||
|
||||
// XXX We would set private browsing information prior to calling this.
|
||||
channel.notificationCallbacks = interfaceRequestor;
|
||||
@@ -1062,7 +1044,7 @@ BrowserElementParent.prototype = {
|
||||
}
|
||||
|
||||
// Set-up complete, let's get things started.
|
||||
channel.asyncOpen(new DownloadListener(), null);
|
||||
channel.asyncOpen2(new DownloadListener());
|
||||
|
||||
return req;
|
||||
},
|
||||
@@ -1292,11 +1274,6 @@ BrowserElementParent.prototype = {
|
||||
this._sendAsyncMsg('exit-fullscreen');
|
||||
}
|
||||
break;
|
||||
case 'copypaste-docommand':
|
||||
if (this._isAlive() && this._frameElement.isEqualNode(subject.wrappedJSObject)) {
|
||||
this._sendAsyncMsg('do-command', { command: data });
|
||||
}
|
||||
break;
|
||||
case 'ask-children-to-execute-copypaste-command':
|
||||
if (this._isAlive() && this._frameElement == subject.wrappedJSObject) {
|
||||
this._sendAsyncMsg('copypaste-do-command', { command: data });
|
||||
|
||||
@@ -381,6 +381,7 @@ BrowserElementAuthPrompt.prototype = {
|
||||
let [hostname, httpRealm] = this._getAuthTarget(channel, authInfo);
|
||||
return {
|
||||
host: hostname,
|
||||
path: channel.URI.path,
|
||||
realm: httpRealm,
|
||||
username: authInfo.username,
|
||||
isProxy: !!(authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY),
|
||||
|
||||
@@ -49,6 +49,9 @@ function testHttpAuthCancel(e) {
|
||||
|
||||
is(e.detail.realm, 'http_realm', 'expected realm matches');
|
||||
is(e.detail.host, 'http://test', 'expected host matches');
|
||||
is(e.detail.path,
|
||||
'/tests/dom/browser-element/mochitest/file_http_401_response.sjs',
|
||||
'expected path matches');
|
||||
e.preventDefault();
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
@@ -71,6 +74,9 @@ function testHttpAuth(e) {
|
||||
|
||||
is(e.detail.realm, 'http_realm', 'expected realm matches');
|
||||
is(e.detail.host, 'http://test', 'expected host matches');
|
||||
is(e.detail.path,
|
||||
'/tests/dom/browser-element/mochitest/file_http_401_response.sjs',
|
||||
'expected path matches');
|
||||
is(e.detail.isProxy, false, 'expected isProxy is false');
|
||||
e.preventDefault();
|
||||
|
||||
@@ -98,6 +104,9 @@ function testProxyAuth(e) {
|
||||
|
||||
is(e.detail.realm, 'http_realm', 'expected realm matches');
|
||||
is(e.detail.host, mozproxy, 'expected host matches');
|
||||
is(e.detail.path,
|
||||
'/tests/dom/browser-element/mochitest/file_http_407_response.sjs',
|
||||
'expected path matches');
|
||||
is(e.detail.isProxy, true, 'expected isProxy is true');
|
||||
e.preventDefault();
|
||||
|
||||
|
||||
@@ -86,8 +86,14 @@ function runTest() {
|
||||
}
|
||||
|
||||
function doCommand(cmd) {
|
||||
Services.obs.notifyObservers({wrappedJSObject: SpecialPowers.unwrap(iframeInner)},
|
||||
'copypaste-docommand', cmd);
|
||||
var COMMAND_MAP = {
|
||||
'cut': 'cmd_cut',
|
||||
'copy': 'cmd_copyAndCollapseToEnd',
|
||||
'paste': 'cmd_paste',
|
||||
'selectall': 'cmd_selectAll'
|
||||
};
|
||||
var script = 'data:,docShell.doCommand("' + COMMAND_MAP[cmd] + '");';
|
||||
mm.loadFrameScript(script, false);
|
||||
}
|
||||
|
||||
function dispatchTest(e) {
|
||||
|
||||
@@ -9,6 +9,27 @@ SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
// We'll need to get the appId from the current document,
|
||||
// it's either SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID when
|
||||
// we are not running inside an app (e.g. Firefox Desktop),
|
||||
// or the appId of Mochitest app when we are running inside that app
|
||||
// (e.g. Emulator).
|
||||
var currentAppId = SpecialPowers.wrap(document).nodePrincipal.appId;
|
||||
var inApp =
|
||||
currentAppId !== SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID;
|
||||
// We will also need the manifest URL and set it on iframes.
|
||||
var currentAppManifestURL;
|
||||
|
||||
if (inApp) {
|
||||
let appsService = SpecialPowers.Cc["@mozilla.org/AppsService;1"]
|
||||
.getService(SpecialPowers.Ci.nsIAppsService);
|
||||
|
||||
currentAppManifestURL = appsService.getManifestURLByLocalId(currentAppId);
|
||||
};
|
||||
|
||||
info('appId=' + currentAppId);
|
||||
info('manifestURL=' + currentAppManifestURL);
|
||||
|
||||
function setup() {
|
||||
let appInfo = SpecialPowers.Cc['@mozilla.org/xre/app-info;1']
|
||||
.getService(SpecialPowers.Ci.nsIXULAppInfo);
|
||||
@@ -27,110 +48,134 @@ function tearDown() {
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
let path = location.pathname;
|
||||
let imeUrl = location.protocol + '//' + location.host +
|
||||
path.substring(0, path.lastIndexOf('/')) +
|
||||
'/file_inputmethod.html';
|
||||
SpecialPowers.pushPermissions([{
|
||||
type: 'input',
|
||||
allow: true,
|
||||
context: {
|
||||
url: imeUrl,
|
||||
originAttributes: {inBrowser: true}
|
||||
}
|
||||
}], SimpleTest.waitForFocus.bind(SimpleTest, createFrames));
|
||||
createFrames();
|
||||
}
|
||||
|
||||
var gFrames = [];
|
||||
var gInputMethodFrames = [];
|
||||
var gInputFrame;
|
||||
|
||||
function createFrames() {
|
||||
// Create two input method iframes.
|
||||
let loadendCount = 0;
|
||||
let countLoadend = function() {
|
||||
if (this === gInputFrame) {
|
||||
// The frame script running in the frame where the input is hosted.
|
||||
let appFrameScript = function appFrameScript() {
|
||||
let input = content.document.body.firstElementChild;
|
||||
input.oninput = function() {
|
||||
sendAsyncMessage('test:InputMethod:oninput', {
|
||||
from: 'input',
|
||||
value: this.value
|
||||
});
|
||||
};
|
||||
|
||||
input.onblur = function() {
|
||||
// "Expected" lost of focus since the test is finished.
|
||||
if (input.value === '#0#1hello') {
|
||||
return;
|
||||
}
|
||||
|
||||
sendAsyncMessage('test:InputMethod:oninput', {
|
||||
from: 'input',
|
||||
error: true,
|
||||
value: 'Unexpected lost of focus on the input frame!'
|
||||
});
|
||||
};
|
||||
|
||||
input.focus();
|
||||
}
|
||||
|
||||
// Inject frame script to receive input.
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(gInputFrame);
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||||
mm.addMessageListener("test:InputMethod:oninput", next);
|
||||
} else {
|
||||
ok(this.setInputMethodActive, 'Can access setInputMethodActive.');
|
||||
|
||||
// The frame script running in the input method frames.
|
||||
|
||||
let appFrameScript = function appFrameScript() {
|
||||
content.addEventListener("message", function(evt) {
|
||||
sendAsyncMessage('test:InputMethod:imFrameMessage', {
|
||||
from: 'im',
|
||||
value: evt.data
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Inject frame script to receive message.
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(this);
|
||||
mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false);
|
||||
mm.addMessageListener("test:InputMethod:imFrameMessage", next);
|
||||
}
|
||||
|
||||
loadendCount++;
|
||||
if (loadendCount === 3) {
|
||||
startTest();
|
||||
setPermissions();
|
||||
}
|
||||
};
|
||||
|
||||
// Create an input field to receive string from input method iframes.
|
||||
gInputFrame = document.createElement('iframe');
|
||||
gInputFrame.setAttribute('mozbrowser', 'true');
|
||||
gInputFrame.src =
|
||||
'data:text/html,<input autofocus value="hello" />' +
|
||||
'<p>This is targetted mozbrowser frame.</p>';
|
||||
document.body.appendChild(gInputFrame);
|
||||
gInputFrame.addEventListener('mozbrowserloadend', countLoadend);
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
let frame = gInputMethodFrames[i] = document.createElement('iframe');
|
||||
frame.setAttribute('mozbrowser', 'true');
|
||||
if (currentAppManifestURL) {
|
||||
frame.setAttribute('mozapp', currentAppManifestURL);
|
||||
}
|
||||
};
|
||||
frame.src = 'file_empty.html#' + i;
|
||||
document.body.appendChild(frame);
|
||||
frame.addEventListener('mozbrowserloadend', countLoadend);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an input field to receive string from input method iframes.
|
||||
gInputFrame = document.createElement('iframe');
|
||||
gInputFrame.setAttribute('mozbrowser', 'true');
|
||||
gInputFrame.src =
|
||||
'data:text/html,<input autofocus value="hello" />' +
|
||||
'<p>This is targetted mozbrowser frame.</p>';
|
||||
document.body.appendChild(gInputFrame);
|
||||
gInputFrame.addEventListener('mozbrowserloadend', countLoadend);
|
||||
function setPermissions() {
|
||||
let permissions = [{
|
||||
type: 'input',
|
||||
allow: true,
|
||||
context: {
|
||||
url: SimpleTest.getTestFileURL('/file_empty.html'),
|
||||
originAttributes: {
|
||||
appId: currentAppId,
|
||||
inBrowser: true
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
let frame = gFrames[i] = document.createElement('iframe');
|
||||
gFrames[i].setAttribute('mozbrowser', 'true');
|
||||
// When the input method iframe is activated, it will send the URL
|
||||
// hash to current focused element. We set different hash to each
|
||||
// iframe so that iframes can be differentiated by their hash.
|
||||
frame.src = 'file_inputmethod.html#' + i;
|
||||
document.body.appendChild(frame);
|
||||
frame.addEventListener('mozbrowserloadend', countLoadend);
|
||||
if (inApp) {
|
||||
// The current document would also need to be given access for IPC to
|
||||
// recognize our permission (why)?
|
||||
permissions.push({
|
||||
type: 'input', allow: true, context: document });
|
||||
}
|
||||
|
||||
SpecialPowers.pushPermissions(permissions,
|
||||
SimpleTest.waitForFocus.bind(SimpleTest, startTest));
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
// Set focus to the input field and wait for input methods' inputting.
|
||||
SpecialPowers.DOMWindowUtils.focus(gInputFrame);
|
||||
function startTest() {
|
||||
// The frame script running in the frame where the input is hosted.
|
||||
let appFrameScript = function appFrameScript() {
|
||||
let input = content.document.body.firstElementChild;
|
||||
input.oninput = function() {
|
||||
sendAsyncMessage('test:InputMethod:oninput', {
|
||||
from: 'input',
|
||||
value: this.value
|
||||
});
|
||||
};
|
||||
|
||||
let req0 = gFrames[0].setInputMethodActive(true);
|
||||
input.onblur = function() {
|
||||
// "Expected" lost of focus since the test is finished.
|
||||
if (input.value === '#0#1hello') {
|
||||
return;
|
||||
}
|
||||
|
||||
sendAsyncMessage('test:InputMethod:oninput', {
|
||||
from: 'input',
|
||||
error: true,
|
||||
value: 'Unexpected lost of focus on the input frame!'
|
||||
});
|
||||
};
|
||||
|
||||
input.focus();
|
||||
};
|
||||
|
||||
// Inject frame script to receive input.
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(gInputFrame);
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||||
mm.addMessageListener("test:InputMethod:oninput", next);
|
||||
|
||||
gInputMethodFrames.forEach((frame) => {
|
||||
ok(frame.setInputMethodActive, 'Can access setInputMethodActive.');
|
||||
|
||||
// The frame script running in the input method frames.
|
||||
let appFrameScript = function appFrameScript() {
|
||||
let im = content.navigator.mozInputMethod;
|
||||
im.oninputcontextchange = function() {
|
||||
let ctx = im.inputcontext;
|
||||
// Report back to parent frame on status of ctx gotten.
|
||||
// (A setTimeout() here to ensure this always happens after
|
||||
// DOMRequest succeed.)
|
||||
content.setTimeout(() => {
|
||||
sendAsyncMessage('test:InputMethod:imFrameMessage', {
|
||||
from: 'im',
|
||||
value: content.location.hash + !!ctx
|
||||
});
|
||||
});
|
||||
|
||||
// If there is a context, send out the hash.
|
||||
if (ctx) {
|
||||
ctx.replaceSurroundingText(content.location.hash);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Inject frame script to receive message.
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(frame);
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||||
mm.addMessageListener("test:InputMethod:imFrameMessage", next);
|
||||
});
|
||||
|
||||
// Set focus to the input field and wait for input methods' inputting.
|
||||
SpecialPowers.DOMWindowUtils.focus(gInputFrame);
|
||||
|
||||
let req0 = gInputMethodFrames[0].setInputMethodActive(true);
|
||||
req0.onsuccess = function() {
|
||||
ok(true, 'setInputMethodActive succeeded (0).');
|
||||
};
|
||||
@@ -203,14 +248,14 @@ function next(msg) {
|
||||
|
||||
gCount++;
|
||||
|
||||
let req0 = gFrames[0].setInputMethodActive(false);
|
||||
let req0 = gInputMethodFrames[0].setInputMethodActive(false);
|
||||
req0.onsuccess = function() {
|
||||
ok(true, 'setInputMethodActive succeeded (0).');
|
||||
};
|
||||
req0.onerror = function() {
|
||||
ok(false, 'setInputMethodActive failed (0): ' + this.error.name);
|
||||
};
|
||||
let req1 = gFrames[1].setInputMethodActive(true);
|
||||
let req1 = gInputMethodFrames[1].setInputMethodActive(true);
|
||||
req1.onsuccess = function() {
|
||||
ok(true, 'setInputMethodActive succeeded (1).');
|
||||
};
|
||||
@@ -259,7 +304,7 @@ function next(msg) {
|
||||
|
||||
// Receive the second input from the second iframe.
|
||||
// Deactive the second iframe.
|
||||
let req3 = gFrames[1].setInputMethodActive(false);
|
||||
let req3 = gInputMethodFrames[1].setInputMethodActive(false);
|
||||
req3.onsuccess = function() {
|
||||
ok(true, 'setInputMethodActive(false) succeeded (2).');
|
||||
};
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var im = navigator.mozInputMethod;
|
||||
if (im) {
|
||||
im.oninputcontextchange = function() {
|
||||
var ctx = im.inputcontext;
|
||||
// Report back to parent frame on status of ctx gotten.
|
||||
window.postMessage(window.location.hash + !!ctx, '*');
|
||||
// If there is a context, send out the hash.
|
||||
if (ctx) {
|
||||
ctx.replaceSurroundingText(location.hash);
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<p>This frame represents the input method frame.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -75,8 +75,10 @@ skip-if = (toolkit == 'gonk') # Disabled on emulator. See bug 1144015 comment 8
|
||||
[test_browserElement_oop_PrivateBrowsing.html]
|
||||
[test_browserElement_oop_PromptCheck.html]
|
||||
[test_browserElement_oop_PromptConfirm.html]
|
||||
# Disabled on B2G Emulator because permission cannot be asserted in content process,
|
||||
# need to fix either bug 1094055 or bug 1020135.
|
||||
[test_browserElement_oop_Proxy.html]
|
||||
skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
|
||||
skip-if = (toolkit == 'gonk')
|
||||
[test_browserElement_oop_PurgeHistory.html]
|
||||
[test_browserElement_oop_Reload.html]
|
||||
[test_browserElement_oop_ReloadPostRequest.html]
|
||||
@@ -86,7 +88,7 @@ skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
|
||||
skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) #TIMED_OUT, bug 766586
|
||||
[test_browserElement_oop_SendEvent.html]
|
||||
[test_browserElement_oop_SetInputMethodActive.html]
|
||||
skip-if = (os == "android") || (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
|
||||
skip-if = (os == "android")
|
||||
[test_browserElement_oop_SetVisible.html]
|
||||
[test_browserElement_oop_SetVisibleFrames.html]
|
||||
[test_browserElement_oop_SetVisibleFrames2.html]
|
||||
|
||||
@@ -129,12 +129,10 @@ support-files =
|
||||
file_focus.html
|
||||
file_http_401_response.sjs
|
||||
file_http_407_response.sjs
|
||||
file_inputmethod.html
|
||||
file_microdata.html
|
||||
file_microdata_bad_itemref.html
|
||||
file_microdata_itemref.html
|
||||
file_microformats.html
|
||||
file_inputmethod.html
|
||||
file_post_request.html
|
||||
file_wyciwyg.html
|
||||
file_audio.html
|
||||
@@ -212,8 +210,10 @@ skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_inproc_PrivateBrowsing.html]
|
||||
[test_browserElement_inproc_PromptCheck.html]
|
||||
[test_browserElement_inproc_PromptConfirm.html]
|
||||
# Disabled on B2G Emulator because permission cannot be asserted in content process,
|
||||
# need to fix either bug 1094055 or bug 1020135.
|
||||
[test_browserElement_inproc_Proxy.html]
|
||||
skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
|
||||
skip-if = (toolkit == 'gonk')
|
||||
[test_browserElement_inproc_PurgeHistory.html]
|
||||
[test_browserElement_inproc_ReloadPostRequest.html]
|
||||
[test_browserElement_inproc_RemoveBrowserElement.html]
|
||||
@@ -223,7 +223,7 @@ skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) # android(TIMED_
|
||||
[test_browserElement_inproc_SendEvent.html]
|
||||
# The setInputMethodActive() tests will timed out on Android
|
||||
[test_browserElement_inproc_SetInputMethodActive.html]
|
||||
skip-if = (os == "android") || (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
|
||||
skip-if = (os == "android")
|
||||
[test_browserElement_inproc_SetVisible.html]
|
||||
[test_browserElement_inproc_SetVisibleFrames.html]
|
||||
[test_browserElement_inproc_SetVisibleFrames2.html]
|
||||
|
||||
Vendored
+38
@@ -158,6 +158,26 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not allow the convenience methods .add()/.addAll() to store failed
|
||||
// responses. A consequence of this is that these methods cannot be
|
||||
// used to store opaque or opaqueredirect responses since they always
|
||||
// expose a 0 status value.
|
||||
if (!response->Ok()) {
|
||||
uint32_t t = static_cast<uint32_t>(response->Type());
|
||||
NS_ConvertASCIItoUTF16 type(ResponseTypeValues::strings[t].value,
|
||||
ResponseTypeValues::strings[t].length);
|
||||
nsAutoString status;
|
||||
status.AppendInt(response->Status());
|
||||
nsAutoString url;
|
||||
mRequestList[i]->GetUrl(url);
|
||||
ErrorResult rv;
|
||||
rv.ThrowTypeError<MSG_CACHE_ADD_FAILED_RESPONSE>(type, status, url);
|
||||
|
||||
// TODO: abort the fetch requests we have running (bug 1157434)
|
||||
mPromise->MaybeReject(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
responseList.AppendElement(Move(response));
|
||||
}
|
||||
|
||||
@@ -234,6 +254,8 @@ Cache::Match(const RequestOrUSVString& aRequest,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CacheChild::AutoLock actorLock(mActor);
|
||||
|
||||
RefPtr<InternalRequest> ir = ToInternalRequest(aRequest, IgnoreBody, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
@@ -261,6 +283,8 @@ Cache::MatchAll(const Optional<RequestOrUSVString>& aRequest,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CacheChild::AutoLock actorLock(mActor);
|
||||
|
||||
CacheQueryParams params;
|
||||
ToCacheQueryParams(params, aOptions);
|
||||
|
||||
@@ -291,6 +315,8 @@ Cache::Add(JSContext* aContext, const RequestOrUSVString& aRequest,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CacheChild::AutoLock actorLock(mActor);
|
||||
|
||||
if (!IsValidPutRequestMethod(aRequest, aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -325,6 +351,8 @@ Cache::AddAll(JSContext* aContext,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CacheChild::AutoLock actorLock(mActor);
|
||||
|
||||
GlobalObject global(aContext, mGlobal->GetGlobalJSObject());
|
||||
MOZ_ASSERT(!global.Failed());
|
||||
|
||||
@@ -371,6 +399,8 @@ Cache::Put(const RequestOrUSVString& aRequest, Response& aResponse,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CacheChild::AutoLock actorLock(mActor);
|
||||
|
||||
if (NS_WARN_IF(!IsValidPutRequestMethod(aRequest, aRv))) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -400,6 +430,8 @@ Cache::Delete(const RequestOrUSVString& aRequest,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CacheChild::AutoLock actorLock(mActor);
|
||||
|
||||
RefPtr<InternalRequest> ir = ToInternalRequest(aRequest, IgnoreBody, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
@@ -427,6 +459,8 @@ Cache::Keys(const Optional<RequestOrUSVString>& aRequest,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CacheChild::AutoLock actorLock(mActor);
|
||||
|
||||
CacheQueryParams params;
|
||||
ToCacheQueryParams(params, aOptions);
|
||||
|
||||
@@ -529,6 +563,8 @@ Cache::~Cache()
|
||||
already_AddRefed<Promise>
|
||||
Cache::ExecuteOp(AutoChildOpArgs& aOpArgs, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mActor);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
|
||||
if (NS_WARN_IF(!promise)) {
|
||||
return nullptr;
|
||||
@@ -603,6 +639,8 @@ Cache::PutAll(const nsTArray<RefPtr<Request>>& aRequestList,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CacheChild::AutoLock actorLock(mActor);
|
||||
|
||||
AutoChildOpArgs args(this, CachePutAllArgs());
|
||||
|
||||
for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
|
||||
|
||||
Vendored
+29
-3
@@ -34,6 +34,7 @@ CacheChild::CacheChild()
|
||||
: mListener(nullptr)
|
||||
, mNumChildActors(0)
|
||||
, mDelayedDestroy(false)
|
||||
, mLocked(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(cache::CacheChild);
|
||||
}
|
||||
@@ -44,6 +45,7 @@ CacheChild::~CacheChild()
|
||||
NS_ASSERT_OWNINGTHREAD(CacheChild);
|
||||
MOZ_ASSERT(!mListener);
|
||||
MOZ_ASSERT(!mNumChildActors);
|
||||
MOZ_ASSERT(!mLocked);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -103,8 +105,9 @@ CacheChild::StartDestroy()
|
||||
// If we have outstanding child actors, then don't destroy ourself yet.
|
||||
// The child actors should be short lived and we should allow them to complete
|
||||
// if possible. NoteDeletedActor() will call back into this Shutdown()
|
||||
// method when the last child actor is gone.
|
||||
if (mNumChildActors) {
|
||||
// method when the last child actor is gone. Also, delay destruction if we
|
||||
// have been explicitly locked by someone using us on the stack.
|
||||
if (mNumChildActors || mLocked) {
|
||||
mDelayedDestroy = true;
|
||||
return;
|
||||
}
|
||||
@@ -175,11 +178,34 @@ void
|
||||
CacheChild::NoteDeletedActor()
|
||||
{
|
||||
mNumChildActors -= 1;
|
||||
if (!mNumChildActors && mDelayedDestroy) {
|
||||
MaybeFlushDelayedDestroy();
|
||||
}
|
||||
|
||||
void
|
||||
CacheChild::MaybeFlushDelayedDestroy()
|
||||
{
|
||||
if (!mNumChildActors && !mLocked && mDelayedDestroy) {
|
||||
StartDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CacheChild::Lock()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(CacheChild);
|
||||
MOZ_ASSERT(!mLocked);
|
||||
mLocked = true;
|
||||
}
|
||||
|
||||
void
|
||||
CacheChild::Unlock()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(CacheChild);
|
||||
MOZ_ASSERT(mLocked);
|
||||
mLocked = false;
|
||||
MaybeFlushDelayedDestroy();
|
||||
}
|
||||
|
||||
} // namespace cache
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
Vendored
+30
@@ -28,6 +28,24 @@ class CacheChild final : public PCacheChild
|
||||
, public ActorChild
|
||||
{
|
||||
public:
|
||||
class MOZ_RAII AutoLock final
|
||||
{
|
||||
CacheChild* mActor;
|
||||
|
||||
public:
|
||||
explicit AutoLock(CacheChild* aActor)
|
||||
: mActor(aActor)
|
||||
{
|
||||
MOZ_ASSERT(mActor);
|
||||
mActor->Lock();
|
||||
}
|
||||
|
||||
~AutoLock()
|
||||
{
|
||||
mActor->Unlock();
|
||||
}
|
||||
};
|
||||
|
||||
CacheChild();
|
||||
~CacheChild();
|
||||
|
||||
@@ -74,12 +92,24 @@ private:
|
||||
void
|
||||
NoteDeletedActor();
|
||||
|
||||
void
|
||||
MaybeFlushDelayedDestroy();
|
||||
|
||||
// Methods used to temporarily force the actor alive. Only called from
|
||||
// AutoLock.
|
||||
void
|
||||
Lock();
|
||||
|
||||
void
|
||||
Unlock();
|
||||
|
||||
// Use a weak ref so actor does not hold DOM object alive past content use.
|
||||
// The Cache object must call ClearListener() to null this before its
|
||||
// destroyed.
|
||||
Cache* MOZ_NON_OWNING_REF mListener;
|
||||
uint32_t mNumChildActors;
|
||||
bool mDelayedDestroy;
|
||||
bool mLocked;
|
||||
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
Vendored
-1
@@ -119,7 +119,6 @@ IsTrusted(const PrincipalInfo& aPrincipalInfo, bool aTestingPrefEnabled)
|
||||
|
||||
nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
|
||||
if (scheme.LowerCaseEqualsLiteral("https") ||
|
||||
scheme.LowerCaseEqualsLiteral("app") ||
|
||||
scheme.LowerCaseEqualsLiteral("file")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Vendored
+1
-2
@@ -417,8 +417,7 @@ TypeUtils::ProcessURL(nsACString& aUrl, bool* aSchemeValidOut,
|
||||
if (aSchemeValidOut) {
|
||||
nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
|
||||
*aSchemeValidOut = scheme.LowerCaseEqualsLiteral("http") ||
|
||||
scheme.LowerCaseEqualsLiteral("https") ||
|
||||
scheme.LowerCaseEqualsLiteral("app");
|
||||
scheme.LowerCaseEqualsLiteral("https");
|
||||
}
|
||||
|
||||
uint32_t queryPos;
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1172562</title>
|
||||
<script src='test.js'></script>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
|
||||
function runTests() {
|
||||
return Promise.resolve()
|
||||
.then(() => { return navigator.serviceWorker.ready })
|
||||
.then((registration) => {
|
||||
return new Promise((resolve) => {
|
||||
var worker = registration.waiting || registration.active;
|
||||
worker.postMessage('read');
|
||||
navigator.serviceWorker.onmessage = (message) => {
|
||||
if (message.data.type == 'done') {
|
||||
ok(!message.data.cached, 'No cached data');
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
});
|
||||
})
|
||||
.then(done);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='runTests()'>
|
||||
</body>
|
||||
</html>
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1172562</title>
|
||||
<script src='test.js'></script>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
|
||||
function runTests() {
|
||||
return Promise.resolve()
|
||||
.then(() => { return navigator.serviceWorker.ready })
|
||||
.then((registration) => {
|
||||
return new Promise((resolve) => {
|
||||
var worker = registration.waiting || registration.active;
|
||||
worker.postMessage('write');
|
||||
navigator.serviceWorker.onmessage = (message) => {
|
||||
if (message.data.type == 'written') {
|
||||
worker.postMessage('read');
|
||||
} else if (message.data.type == 'done') {
|
||||
ok(message.data.cached, 'Write success');
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
});
|
||||
})
|
||||
.then(done);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='runTests()'>
|
||||
</body>
|
||||
</html>
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1169249</title>
|
||||
<title>Test app for bug 1172562</title>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
function ok(aCondition, aMessage) {
|
||||
if (aCondition) {
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "App",
|
||||
"launch_path": "/index.html",
|
||||
"description": "Test app for bug 1161684"
|
||||
"description": "Test app for bug 1172562"
|
||||
}
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
var url = 'index.html';
|
||||
self.addEventListener('message', (message) => {
|
||||
caches.open('acache').then((cache) => {
|
||||
if(message.data == 'write') {
|
||||
cache.add(url).then(() => {
|
||||
message.source.postMessage({
|
||||
type: 'written'
|
||||
});
|
||||
});
|
||||
} else if (message.data == 'read') {
|
||||
cache.match(url).then((result) => {
|
||||
message.source.postMessage({
|
||||
type: 'done',
|
||||
cached: !!result
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
function ok(aCondition, aMessage) {
|
||||
if (aCondition) {
|
||||
alert('OK: ' + aMessage);
|
||||
} else {
|
||||
alert('KO: ' + aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function ready() {
|
||||
alert('READY');
|
||||
}
|
||||
|
||||
function done() {
|
||||
alert('DONE');
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- This is only used to give us access to the caches global after setting the pref. -->
|
||||
+4
@@ -22,6 +22,8 @@ support-files =
|
||||
test_cache_put_reorder.js
|
||||
test_cache_https.js
|
||||
large_url_list.js
|
||||
empty.html
|
||||
app/*
|
||||
|
||||
[test_cache.html]
|
||||
[test_cache_add.html]
|
||||
@@ -39,6 +41,8 @@ support-files =
|
||||
skip-if = buildapp == 'b2g' # bug 1162353
|
||||
[test_cache_restart.html]
|
||||
[test_cache_shrink.html]
|
||||
[test_cache_clear_on_app_uninstall.html]
|
||||
skip-if = e10s || buildapp == 'b2g' # bug 1178685
|
||||
[test_cache_orphaned_cache.html]
|
||||
[test_cache_orphaned_body.html]
|
||||
[test_cache_untrusted.html]
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
var singleUrl = './test_cache_add.js';
|
||||
var urlList = [
|
||||
'./helloworld.txt',
|
||||
'./foobar.txt',
|
||||
'./empty.html',
|
||||
'./frame.html',
|
||||
'./test_cache.js'
|
||||
];
|
||||
var cache;
|
||||
|
||||
+21
-22
@@ -5,7 +5,7 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1161684 - Allow JAR channels to be intercepted by service workers</title>
|
||||
<title>Bug 1172562 - Clear QuotaManager storage when uninstalling an app</title>
|
||||
<script type='text/javascript' src='/tests/SimpleTest/SimpleTest.js'></script>
|
||||
<link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css' />
|
||||
</head>
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const appManifestURL =
|
||||
'http://mochi.test:8888/tests/dom/workers/test/serviceworkers/app-protocol/update.webapp';
|
||||
const gOrigin = 'http://mochi.test:8888/tests/dom/cache/test/mochitest/app';
|
||||
const appManifestURL = gOrigin + '/manifest.webapp';
|
||||
let gApp;
|
||||
|
||||
function setup() {
|
||||
@@ -27,7 +27,6 @@ function setup() {
|
||||
SpecialPowers.pushPrefEnv({'set': [
|
||||
['dom.mozBrowserFramesEnabled', true],
|
||||
['dom.serviceWorkers.exemptFromPerDomainMax', true],
|
||||
["dom.serviceWorkers.interception.enabled", true],
|
||||
['dom.serviceWorkers.enabled', true],
|
||||
['dom.serviceWorkers.testing.enabled', true],
|
||||
['dom.caches.enabled', true],
|
||||
@@ -47,7 +46,7 @@ function setup() {
|
||||
|
||||
function installApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req = navigator.mozApps.installPackage(appManifestURL);
|
||||
let req = navigator.mozApps.install(appManifestURL);
|
||||
req.onsuccess = function() {
|
||||
gApp = req.result;
|
||||
is(req.result.manifestURL, appManifestURL, 'app installed');
|
||||
@@ -90,11 +89,11 @@ function launchApp() {
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.appendChild(iframe);
|
||||
SpecialPowers.wrap(iframe.contentWindow).location =
|
||||
gApp.origin + gApp.manifest.launch_path;
|
||||
gOrigin + gApp.manifest.launch_path;
|
||||
});
|
||||
}
|
||||
|
||||
function loadControlled() {
|
||||
function loadControlled(aUrl) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
@@ -105,18 +104,6 @@ function loadControlled() {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/HTTPSIFRAMELOADED/.exec(message)) {
|
||||
let doc = SpecialPowers.wrap(iframe).contentDocument;
|
||||
let innerDoc = SpecialPowers.wrap(doc.getElementById("redirected-https").contentDocument);
|
||||
let innerLocation = innerDoc.defaultView.location;
|
||||
is(innerDoc.domain, "example.org", "Correct domain expected (https)");
|
||||
is(innerLocation.origin, "https://example.org", "Correct origin expected (https)");
|
||||
} else if (/IFRAMELOADED/.exec(message)) {
|
||||
let doc = SpecialPowers.wrap(iframe).contentDocument;
|
||||
let innerDoc = SpecialPowers.wrap(doc.getElementById("redirected").contentDocument);
|
||||
let innerLocation = innerDoc.defaultView.location;
|
||||
is(innerDoc.domain, "example.org", "Correct domain expected");
|
||||
is(innerLocation.origin, "http://example.org", "Correct origin expected");
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
iframe.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
@@ -130,10 +117,18 @@ function loadControlled() {
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.appendChild(iframe);
|
||||
SpecialPowers.wrap(iframe.contentWindow).location =
|
||||
gApp.origin + '/controlled.html';
|
||||
gOrigin + aUrl;
|
||||
});
|
||||
}
|
||||
|
||||
function loadBeforeClear() {
|
||||
return loadControlled('/before_clear.html');
|
||||
}
|
||||
|
||||
function loadAfterClear() {
|
||||
return loadControlled('/after_clear.html');
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!gApp) {
|
||||
@@ -149,11 +144,15 @@ function runTests() {
|
||||
setup()
|
||||
.then(installApp)
|
||||
.then(launchApp)
|
||||
.then(loadControlled)
|
||||
.then(loadBeforeClear)
|
||||
.then(uninstallApp)
|
||||
.then(installApp)
|
||||
.then(launchApp)
|
||||
.then(loadAfterClear)
|
||||
.then(uninstallApp)
|
||||
.then(SimpleTest.finish)
|
||||
.catch((e) => {
|
||||
ok(false, 'Unexpected error ' + e);
|
||||
ok(false, 'Unexpected error ' + e.target.error.name);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
+10
-2
@@ -4,10 +4,18 @@ var urlBase = 'https://example.com/tests/dom/cache/test/mochitest';
|
||||
var url1 = urlBase + '/test_cache.js';
|
||||
var url2 = urlBase + '/test_cache_add.js';
|
||||
|
||||
function addOpaque(cache, url) {
|
||||
return fetch(new Request(url, { mode: 'no-cors' })).then(function(response) {
|
||||
return cache.put(url, response);
|
||||
});
|
||||
}
|
||||
|
||||
caches.open(name).then(function(c) {
|
||||
cache = c;
|
||||
return cache.addAll([new Request(url1, { mode: 'no-cors' }),
|
||||
new Request(url2, { mode: 'no-cors' })]);
|
||||
return Promise.all([
|
||||
addOpaque(cache, url1),
|
||||
addOpaque(cache, url2)
|
||||
]);
|
||||
}).then(function() {
|
||||
return cache.delete(url1);
|
||||
}).then(function(result) {
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ SpecialPowers.pushPrefEnv({
|
||||
var fullUsage = 0;
|
||||
var resetUsage = 0;
|
||||
var endUsage = 0;
|
||||
var url = 'cache_add.js';
|
||||
var url = 'test_cache_add.js';
|
||||
|
||||
// start from a fresh origin directory so other tests do not influence our
|
||||
// results
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ SpecialPowers.pushPrefEnv({
|
||||
var fullUsage = 0;
|
||||
var resetUsage = 0;
|
||||
var endUsage = 0;
|
||||
var url = 'cache_add.js';
|
||||
var url = 'test_cache_add.js';
|
||||
|
||||
// start from a fresh origin directory so other tests do not influence our
|
||||
// results
|
||||
|
||||
+15
-1
@@ -9,6 +9,18 @@
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
function setupTestIframe() {
|
||||
return new Promise(function(resolve) {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = "empty.html";
|
||||
iframe.onload = function() {
|
||||
window.caches = iframe.contentWindow.caches;
|
||||
resolve();
|
||||
};
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
function resetStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
@@ -24,7 +36,9 @@ SpecialPowers.pushPrefEnv({
|
||||
var name = 'foo';
|
||||
var url = './test_cache_add.js';
|
||||
var cache;
|
||||
caches.open(name).then(function(c) {
|
||||
setupTestIframe().then(function() {
|
||||
return caches.open(name);
|
||||
}).then(function(c) {
|
||||
cache = c;
|
||||
return cache.add(url);
|
||||
}).then(function() {
|
||||
|
||||
+15
-1
@@ -10,6 +10,18 @@
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
function setupTestIframe() {
|
||||
return new Promise(function(resolve) {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = "empty.html";
|
||||
iframe.onload = function() {
|
||||
window.caches = iframe.contentWindow.caches;
|
||||
resolve();
|
||||
};
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
function clearStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
@@ -47,7 +59,9 @@ SpecialPowers.pushPrefEnv({
|
||||
var endUsage = 0;
|
||||
// start from a fresh origin directory so other tests do not influence our
|
||||
// results
|
||||
clearStorage().then(function() {
|
||||
setupTestIframe().then(function() {
|
||||
return clearStorage();
|
||||
}).then(function() {
|
||||
return storageUsage();
|
||||
}).then(function(usage) {
|
||||
is(0, usage, 'disk usage should be zero to start');
|
||||
|
||||
@@ -12,11 +12,11 @@ namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class BlobImpl;
|
||||
}
|
||||
} // namespace dom
|
||||
|
||||
namespace layers {
|
||||
class Image;
|
||||
}
|
||||
} // namespace layers
|
||||
|
||||
class CameraControlListener
|
||||
{
|
||||
|
||||
@@ -1648,7 +1648,7 @@ nsDOMCameraControl::OnUserError(CameraControlListener::UserContext aContext, nsr
|
||||
break;
|
||||
|
||||
case CameraControlListener::kInSetConfiguration:
|
||||
if (mSetInitialConfig) {
|
||||
if (mSetInitialConfig && mCameraControl) {
|
||||
// If the SetConfiguration() call in the constructor fails, there
|
||||
// is nothing we can do except release the camera hardware. This
|
||||
// will trigger a hardware state change, and when the flag that
|
||||
|
||||
@@ -2213,17 +2213,6 @@ nsGonkCameraControl::LoadRecorderProfiles()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
nsGonkCameraControl::Enumerate(const nsAString& aProfileName,
|
||||
RecorderProfile* aProfile,
|
||||
void* aUserArg)
|
||||
{
|
||||
nsTArray<nsString>* profiles = static_cast<nsTArray<nsString>*>(aUserArg);
|
||||
MOZ_ASSERT(profiles);
|
||||
profiles->AppendElement(aProfileName);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGonkCameraControl::GetRecorderProfiles(nsTArray<nsString>& aProfiles)
|
||||
{
|
||||
@@ -2233,7 +2222,9 @@ nsGonkCameraControl::GetRecorderProfiles(nsTArray<nsString>& aProfiles)
|
||||
}
|
||||
|
||||
aProfiles.Clear();
|
||||
mRecorderProfiles.EnumerateRead(Enumerate, static_cast<void*>(&aProfiles));
|
||||
for (auto iter = mRecorderProfiles.Iter(); !iter.Done(); iter.Next()) {
|
||||
aProfiles.AppendElement(iter.Key());
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,9 +156,6 @@ protected:
|
||||
void CreatePoster(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight, int32_t aRotation);
|
||||
|
||||
nsresult LoadRecorderProfiles();
|
||||
static PLDHashOperator Enumerate(const nsAString& aProfileName,
|
||||
RecorderProfile* aProfile,
|
||||
void* aUserArg);
|
||||
|
||||
friend class SetPictureSize;
|
||||
friend class SetThumbnailSize;
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "CameraPreferences.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
|
||||
#include "GonkBufferQueueProducer.h"
|
||||
#endif
|
||||
#include "GonkCameraControl.h"
|
||||
#include "CameraCommon.h"
|
||||
|
||||
@@ -50,6 +53,7 @@ GonkCameraHardware::GonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, ui
|
||||
, mTarget(aTarget)
|
||||
, mRawSensorOrientation(0)
|
||||
, mSensorOrientation(0)
|
||||
, mEmulated(false)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p (aTarget=%p)\n", __func__, __LINE__, (void*)this, (void*)aTarget);
|
||||
}
|
||||
@@ -191,6 +195,11 @@ GonkCameraHardware::Init()
|
||||
}
|
||||
DOM_CAMERA_LOGI("Sensor orientation: base=%d, offset=%d, final=%d\n", info.orientation, offset, mSensorOrientation);
|
||||
|
||||
if (__system_property_get("ro.kernel.qemu", prop) > 0 && atoi(prop)) {
|
||||
DOM_CAMERA_LOGI("Using emulated camera\n");
|
||||
mEmulated = true;
|
||||
}
|
||||
|
||||
// Disable shutter sound in android CameraService because gaia camera app will play it
|
||||
mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
|
||||
|
||||
@@ -198,6 +207,7 @@ GonkCameraHardware::Init()
|
||||
sp<IGraphicBufferProducer> producer;
|
||||
sp<IGonkGraphicBufferConsumer> consumer;
|
||||
GonkBufferQueue::createBufferQueue(&producer, &consumer);
|
||||
static_cast<GonkBufferQueueProducer*>(producer.get())->setSynchronousMode(false);
|
||||
mNativeWindow = new GonkNativeWindow(consumer, GonkCameraHardware::MIN_UNDEQUEUED_BUFFERS);
|
||||
mCamera->setPreviewTarget(producer);
|
||||
#elif ANDROID_VERSION >= 19
|
||||
@@ -318,10 +328,19 @@ GonkCameraHardware::GetSensorOrientation(uint32_t aType)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GonkCameraHardware::IsEmulated()
|
||||
{
|
||||
return mEmulated;
|
||||
}
|
||||
|
||||
int
|
||||
GonkCameraHardware::AutoFocus()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->autoFocus();
|
||||
}
|
||||
|
||||
@@ -329,6 +348,9 @@ int
|
||||
GonkCameraHardware::CancelAutoFocus()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->cancelAutoFocus();
|
||||
}
|
||||
|
||||
@@ -336,8 +358,11 @@ int
|
||||
GonkCameraHardware::StartFaceDetection()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
int rv = INVALID_OPERATION;
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
int rv = INVALID_OPERATION;
|
||||
#if ANDROID_VERSION >= 15
|
||||
rv = mCamera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, CAMERA_FACE_DETECTION_HW, 0);
|
||||
#endif
|
||||
@@ -352,8 +377,11 @@ int
|
||||
GonkCameraHardware::StopFaceDetection()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
int rv = INVALID_OPERATION;
|
||||
if (mClosing) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
int rv = INVALID_OPERATION;
|
||||
#if ANDROID_VERSION >= 15
|
||||
rv = mCamera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0);
|
||||
#endif
|
||||
@@ -367,6 +395,9 @@ GonkCameraHardware::StopFaceDetection()
|
||||
int
|
||||
GonkCameraHardware::TakePicture()
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->takePicture(CAMERA_MSG_SHUTTER | CAMERA_MSG_COMPRESSED_IMAGE);
|
||||
}
|
||||
|
||||
@@ -379,6 +410,9 @@ GonkCameraHardware::CancelTakePicture()
|
||||
int
|
||||
GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
const String8 s = aParams.Flatten();
|
||||
return mCamera->setParameters(s);
|
||||
}
|
||||
@@ -386,6 +420,9 @@ GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
|
||||
nsresult
|
||||
GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
const String8 s = mCamera->getParameters();
|
||||
return aParams.Unflatten(s);
|
||||
}
|
||||
@@ -394,6 +431,9 @@ GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
|
||||
int
|
||||
GonkCameraHardware::PushParameters(const CameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
String8 s = aParams.flatten();
|
||||
return mCamera->setParameters(s);
|
||||
}
|
||||
@@ -401,8 +441,10 @@ GonkCameraHardware::PushParameters(const CameraParameters& aParams)
|
||||
void
|
||||
GonkCameraHardware::PullParameters(CameraParameters& aParams)
|
||||
{
|
||||
const String8 s = mCamera->getParameters();
|
||||
aParams.unflatten(s);
|
||||
if (!NS_WARN_IF(mClosing)) {
|
||||
const String8 s = mCamera->getParameters();
|
||||
aParams.unflatten(s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -410,6 +452,9 @@ int
|
||||
GonkCameraHardware::StartPreview()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->startPreview();
|
||||
}
|
||||
|
||||
@@ -417,16 +462,20 @@ void
|
||||
GonkCameraHardware::StopPreview()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
mCamera->stopPreview();
|
||||
if (!mClosing) {
|
||||
mCamera->stopPreview();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
GonkCameraHardware::StartRecording()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
int rv = OK;
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
rv = mCamera->startRecording();
|
||||
int rv = mCamera->startRecording();
|
||||
if (rv != OK) {
|
||||
DOM_CAMERA_LOGE("mHardware->startRecording() failed with status %d", rv);
|
||||
}
|
||||
@@ -437,6 +486,9 @@ int
|
||||
GonkCameraHardware::StopRecording()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (mClosing) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
mCamera->stopRecording();
|
||||
return OK;
|
||||
}
|
||||
@@ -452,12 +504,17 @@ GonkCameraHardware::SetListener(const sp<GonkCameraListener>& aListener)
|
||||
void
|
||||
GonkCameraHardware::ReleaseRecordingFrame(const sp<IMemory>& aFrame)
|
||||
{
|
||||
mCamera->releaseRecordingFrame(aFrame);
|
||||
if (!NS_WARN_IF(mClosing)) {
|
||||
mCamera->releaseRecordingFrame(aFrame);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
GonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->storeMetaDataInBuffers(aEnabled);
|
||||
}
|
||||
|
||||
@@ -99,6 +99,8 @@ public:
|
||||
};
|
||||
virtual int GetSensorOrientation(uint32_t aType = RAW_SENSOR_ORIENTATION);
|
||||
|
||||
virtual bool IsEmulated();
|
||||
|
||||
/**
|
||||
* MIN_UNDEQUEUED_BUFFERS has increased to 4 since Android JB. For FFOS, more
|
||||
* than 3 gralloc buffers are necessary between ImageHost and GonkBufferQueue
|
||||
@@ -140,6 +142,7 @@ protected:
|
||||
#endif
|
||||
int mRawSensorOrientation;
|
||||
int mSensorOrientation;
|
||||
bool mEmulated;
|
||||
|
||||
private:
|
||||
GonkCameraHardware(const GonkCameraHardware&) = delete;
|
||||
|
||||
@@ -69,27 +69,19 @@ GonkCameraParameters::FindVendorSpecificKey(const char* aPotentialKeys[],
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
GonkCameraParameters::EnumerateFlatten(const nsACString& aKey,
|
||||
nsCString* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
nsCString* data = static_cast<nsCString*>(aUserArg);
|
||||
if (!data->IsEmpty()) {
|
||||
data->Append(';');
|
||||
}
|
||||
data->Append(aKey);
|
||||
data->Append('=');
|
||||
data->Append(*aValue);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
String8
|
||||
GonkCameraParameters::Flatten() const
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
nsCString data;
|
||||
mParams.EnumerateRead(EnumerateFlatten, static_cast<void*>(&data));
|
||||
for (auto iter = mParams.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
if (!data.IsEmpty()) {
|
||||
data.Append(';');
|
||||
}
|
||||
data.Append(iter.Key());
|
||||
data.Append('=');
|
||||
data.Append(*iter.UserData());
|
||||
}
|
||||
return String8(data.Data());
|
||||
}
|
||||
|
||||
@@ -106,7 +98,7 @@ GonkCameraParameters::Unflatten(const String8& aFlatParameters)
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString key(data, pos - data);
|
||||
nsDependentCSubstring key(data, pos - data);
|
||||
data = pos + 1;
|
||||
|
||||
nsCString* value;
|
||||
|
||||
@@ -93,18 +93,19 @@ protected:
|
||||
nsClassHashtable<nsStringHashKey, nsCString> mIsoModeMap;
|
||||
nsClassHashtable<nsCStringHashKey, nsCString> mParams;
|
||||
|
||||
static PLDHashOperator EnumerateFlatten(const nsACString& aKey, nsCString* aValue, void* aUserArg);
|
||||
|
||||
nsresult SetImpl(const char* aKey, const char* aValue)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
if (!aValue || strchr(aValue, ';') || strchr(aValue, '=')) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
nsDependentCString key(aKey);
|
||||
mParams.Put(key, new nsCString(aValue));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SetImpl(const char* aKey, int aValue)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
nsCString* value = new nsCString();
|
||||
value->AppendInt(aValue);
|
||||
mParams.Put(key, value);
|
||||
@@ -113,7 +114,7 @@ protected:
|
||||
|
||||
nsresult SetImpl(const char* aKey, double aValue)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
nsCString* value = new nsCString();
|
||||
value->AppendFloat(aValue);
|
||||
mParams.Put(key, value);
|
||||
@@ -122,7 +123,7 @@ protected:
|
||||
|
||||
nsresult SetImpl(const char* aKey, float aValue)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
nsCString* value = new nsCString();
|
||||
value->AppendFloat(aValue);
|
||||
mParams.Put(key, value);
|
||||
@@ -131,14 +132,14 @@ protected:
|
||||
|
||||
nsresult SetImpl(const char* aKey, bool aValue)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
mParams.Put(key, new nsCString(aValue ? "true" : "false"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetImpl(const char* aKey, const char*& aRet)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
nsCString* value;
|
||||
if (!mParams.Get(key, &value)) {
|
||||
aRet = nullptr;
|
||||
@@ -150,7 +151,7 @@ protected:
|
||||
|
||||
nsresult GetImpl(const char* aKey, float& aRet)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
nsCString* value;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (mParams.Get(key, &value)) {
|
||||
@@ -163,7 +164,7 @@ protected:
|
||||
|
||||
nsresult GetImpl(const char* aKey, double& aRet)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
nsCString* value;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (mParams.Get(key, &value)) {
|
||||
@@ -176,7 +177,7 @@ protected:
|
||||
|
||||
nsresult GetImpl(const char* aKey, int& aRet)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
nsCString* value;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (mParams.Get(key, &value)) {
|
||||
@@ -189,7 +190,7 @@ protected:
|
||||
|
||||
nsresult GetImpl(const char* aKey, bool& aRet)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
nsCString* value;
|
||||
if (!mParams.Get(key, &value)) {
|
||||
aRet = false;
|
||||
@@ -228,7 +229,7 @@ protected:
|
||||
nsresult
|
||||
ClearImpl(const char* aKey)
|
||||
{
|
||||
nsCString key(aKey);
|
||||
nsDependentCString key(aKey);
|
||||
mParams.Remove(key);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1561,7 +1561,9 @@ status_t GonkRecorder::setupVideoEncoder(
|
||||
// CHECK_EQ causes an abort if the given condition fails.
|
||||
CHECK_EQ(client.connect(), (status_t)OK);
|
||||
|
||||
uint32_t encoder_flags = OMXCodec::kHardwareCodecsOnly;
|
||||
uint32_t encoder_flags = mCameraHw->IsEmulated()
|
||||
? 0
|
||||
: OMXCodec::kHardwareCodecsOnly;
|
||||
if (mIsMetaDataStoredInVideoBuffers) {
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||
encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
|
||||
|
||||
@@ -269,18 +269,6 @@ GonkRecorderProfile::GonkRecorderProfile(uint32_t aCameraId,
|
||||
mIsValid = isValid && mAudio.IsValid() && mVideo.IsValid();
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
GonkRecorderProfile::Enumerate(const nsAString& aProfileName,
|
||||
GonkRecorderProfile* aProfile,
|
||||
void* aUserArg)
|
||||
{
|
||||
nsTArray<RefPtr<ICameraControl::RecorderProfile>>* profiles =
|
||||
static_cast<nsTArray<RefPtr<ICameraControl::RecorderProfile>>*>(aUserArg);
|
||||
MOZ_ASSERT(profiles);
|
||||
profiles->AppendElement(aProfile);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<GonkRecorderProfile>
|
||||
GonkRecorderProfile::CreateProfile(uint32_t aCameraId, int aQuality)
|
||||
@@ -379,7 +367,9 @@ GonkRecorderProfile::GetAll(uint32_t aCameraId,
|
||||
}
|
||||
|
||||
aProfiles.Clear();
|
||||
profiles->EnumerateRead(Enumerate, static_cast<void*>(&aProfiles));
|
||||
for (auto iter = profiles->Iter(); !iter.Done(); iter.Next()) {
|
||||
aProfiles.AppendElement(iter.UserData());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -142,9 +142,6 @@ protected:
|
||||
static already_AddRefed<GonkRecorderProfile> CreateProfile(uint32_t aCameraId,
|
||||
int aQuality);
|
||||
static ProfileHashtable* GetProfileHashtable(uint32_t aCameraId);
|
||||
static PLDHashOperator Enumerate(const nsAString& aProfileName,
|
||||
GonkRecorderProfile* aProfile,
|
||||
void* aUserArg);
|
||||
|
||||
uint32_t mCameraId;
|
||||
int mQuality;
|
||||
|
||||
@@ -357,6 +357,12 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
|
||||
return JS::NumberValue(uint32_t(mBoundVertexArray->mAttribs[index].type));
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_INTEGER:
|
||||
if (IsWebGL2())
|
||||
return JS::BooleanValue(mBoundVertexArray->mAttribs[index].integer);
|
||||
|
||||
break;
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
|
||||
if (IsWebGL2() ||
|
||||
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
|
||||
|
||||
@@ -32,15 +32,17 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
|
||||
fua->AllowUnsizedTexFormat(pi, usage);
|
||||
};
|
||||
|
||||
const bool needSizedInternal = !gl->IsGLES();
|
||||
MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle));
|
||||
const bool needsSwizzle = gl->IsCoreProfile();
|
||||
MOZ_ASSERT_IF(needsSwizzle, gl->IsSupported(gl::GLFeature::texture_swizzle));
|
||||
|
||||
const bool needsSizedFormat = !gl->IsGLES();
|
||||
|
||||
////////////////
|
||||
|
||||
pi = {LOCAL_GL_RGBA, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_RGBA32F;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::RGBA32F);
|
||||
@@ -50,7 +52,7 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
|
||||
pi = {LOCAL_GL_RGB, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_RGB32F;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::RGB32F);
|
||||
@@ -60,9 +62,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
|
||||
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSwizzle) {
|
||||
dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT};
|
||||
swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
|
||||
} else if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Luminance32F);
|
||||
|
||||
@@ -71,9 +75,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
|
||||
pi = {LOCAL_GL_ALPHA, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSwizzle) {
|
||||
dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT};
|
||||
swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
|
||||
} else if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_ALPHA32F_ARB;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Alpha32F);
|
||||
|
||||
@@ -82,9 +88,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
|
||||
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT};
|
||||
dui = {pi.format, pi.format, pi.type};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSwizzle) {
|
||||
dui = {LOCAL_GL_RG32F, LOCAL_GL_RG, LOCAL_GL_FLOAT};
|
||||
swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
|
||||
} else if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F);
|
||||
}
|
||||
@@ -101,10 +109,9 @@ WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl)
|
||||
if (!gl->IsSupported(gl::GLFeature::texture_float))
|
||||
return false;
|
||||
|
||||
const bool needSizedInternal = !gl->IsGLES();
|
||||
const bool needsSwizzle = gl->IsCoreProfile();
|
||||
const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
|
||||
|
||||
if (needSizedInternal && !hasSwizzle)
|
||||
if (needsSwizzle && !hasSwizzle)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -30,8 +30,10 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
|
||||
fua->AllowUnsizedTexFormat(pi, usage);
|
||||
};
|
||||
|
||||
const bool needSizedInternal = !gl->IsGLES();
|
||||
MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle));
|
||||
const bool needsSwizzle = gl->IsCoreProfile();
|
||||
MOZ_ASSERT_IF(needsSwizzle, gl->IsSupported(gl::GLFeature::texture_swizzle));
|
||||
|
||||
const bool needsSizedFormat = !gl->IsGLES();
|
||||
|
||||
GLenum driverUnpackType = LOCAL_GL_HALF_FLOAT;
|
||||
if (!gl->IsSupported(gl::GLFeature::texture_half_float)) {
|
||||
@@ -44,7 +46,7 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
|
||||
pi = {LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_RGBA16F;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::RGBA16F);
|
||||
@@ -54,7 +56,7 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
|
||||
pi = {LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_RGB16F;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::RGB16F);
|
||||
@@ -64,9 +66,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
|
||||
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSwizzle) {
|
||||
dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType};
|
||||
swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
|
||||
} else if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Luminance16F);
|
||||
|
||||
@@ -75,9 +79,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
|
||||
pi = {LOCAL_GL_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSwizzle) {
|
||||
dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType};
|
||||
swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
|
||||
} else if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_ALPHA16F_ARB;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Alpha16F);
|
||||
|
||||
@@ -86,9 +92,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web
|
||||
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
|
||||
dui = {pi.format, pi.format, driverUnpackType};
|
||||
swizzle = nullptr;
|
||||
if (needSizedInternal) {
|
||||
if (needsSwizzle) {
|
||||
dui = {LOCAL_GL_RG16F, LOCAL_GL_RG, driverUnpackType};
|
||||
swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
|
||||
} else if (needsSizedFormat) {
|
||||
dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
|
||||
}
|
||||
fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F);
|
||||
}
|
||||
@@ -108,10 +116,9 @@ WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl)
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool needSizedInternal = !gl->IsGLES();
|
||||
const bool needsSwizzle = gl->IsCoreProfile();
|
||||
const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
|
||||
|
||||
if (needSizedInternal && !hasSwizzle)
|
||||
if (needsSwizzle && !hasSwizzle)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -560,11 +560,14 @@ FormatUsageAuthority::CreateForWebGL1(gl::GLContext* gl)
|
||||
// RGBA8 is made renderable in WebGL 1.0, "Framebuffer Object Attachments"
|
||||
// render filter
|
||||
// able able
|
||||
fnSet(EffectiveFormat::RGBA8 , true , true);
|
||||
fnSet(EffectiveFormat::RGBA4 , true , true);
|
||||
fnSet(EffectiveFormat::RGB5_A1, true , true);
|
||||
fnSet(EffectiveFormat::RGB8 , false, true);
|
||||
fnSet(EffectiveFormat::RGB565 , true , true);
|
||||
fnSet(EffectiveFormat::RGBA8 , true, true);
|
||||
fnSet(EffectiveFormat::RGBA4 , true, true);
|
||||
fnSet(EffectiveFormat::RGB5_A1, true, true);
|
||||
fnSet(EffectiveFormat::RGB565 , true, true);
|
||||
|
||||
// RGB8 is not guaranteed to be renderable, but we should allow it for web-compat.
|
||||
// Min-capability mode should mark this as non-renderable.
|
||||
fnSet(EffectiveFormat::RGB8, true, true);
|
||||
|
||||
fnSet(EffectiveFormat::Luminance8Alpha8, false, true);
|
||||
fnSet(EffectiveFormat::Luminance8 , false, true);
|
||||
@@ -803,7 +806,7 @@ FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl)
|
||||
|
||||
// GLES 3.0.4, p147, table 3.19
|
||||
// GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
|
||||
|
||||
#if ALLOW_ES3_FORMATS
|
||||
// Note that all compressed texture formats are filterable:
|
||||
// GLES 3.0.4 p161:
|
||||
// "[A] texture is complete unless any of the following conditions hold true:
|
||||
@@ -823,7 +826,7 @@ FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl)
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_SIGNED_RG11_EAC ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ), false, true);
|
||||
fnAllowES3TexFormat(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2), false, true);
|
||||
|
||||
#endif
|
||||
#undef FOO
|
||||
|
||||
// GLES 3.0.4, p206, "Required Renderbuffer Formats":
|
||||
@@ -840,6 +843,9 @@ FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl)
|
||||
if (!AddUnsizedFormats(ptr, gl))
|
||||
return nullptr;
|
||||
|
||||
ptr->AllowRBFormat(LOCAL_GL_DEPTH_STENCIL,
|
||||
ptr->GetUsage(EffectiveFormat::DEPTH24_STENCIL8));
|
||||
|
||||
if (gfxPrefs::WebGL2CompatMode()) {
|
||||
AddSimpleUnsized(ptr, LOCAL_GL_RGBA, LOCAL_GL_FLOAT, EffectiveFormat::RGBA32F);
|
||||
AddSimpleUnsized(ptr, LOCAL_GL_RGB , LOCAL_GL_FLOAT, EffectiveFormat::RGB32F );
|
||||
|
||||
@@ -172,10 +172,12 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
|
||||
|
||||
// Collect active locations:
|
||||
GLint loc = gl->fGetAttribLocation(prog->mGLName, mappedName.BeginReading());
|
||||
if (loc == -1)
|
||||
MOZ_CRASH("Active attrib has no location.");
|
||||
|
||||
info->activeAttribLocs.insert(loc);
|
||||
if (loc == -1) {
|
||||
if (mappedName != "gl_InstanceID")
|
||||
MOZ_CRASH("Active attrib has no location.");
|
||||
} else {
|
||||
info->activeAttribLocs.insert(loc);
|
||||
}
|
||||
}
|
||||
|
||||
// Uniforms
|
||||
@@ -599,6 +601,7 @@ WebGLProgram::GetProgramParameter(GLenum pname) const
|
||||
if (mContext->IsWebGL2()) {
|
||||
switch (pname) {
|
||||
case LOCAL_GL_ACTIVE_UNIFORM_BLOCKS:
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
|
||||
return JS::Int32Value(GetProgramiv(gl, mGLName, pname));
|
||||
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS:
|
||||
|
||||
@@ -133,7 +133,13 @@ WebGLContext::CreateShaderValidator(GLenum shaderType) const
|
||||
return nullptr;
|
||||
|
||||
ShShaderSpec spec = IsWebGL2() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
|
||||
ShShaderOutput outputLanguage = ShaderOutput(gl);
|
||||
ShShaderOutput outputLanguage = gl->IsGLES() ? SH_ESSL_OUTPUT
|
||||
: SH_GLSL_OUTPUT;
|
||||
|
||||
// If we're using WebGL2 we want a more specific version of GLSL
|
||||
if (IsWebGL2())
|
||||
outputLanguage = ShaderOutput(gl);
|
||||
|
||||
ShBuiltInResources resources;
|
||||
memset(&resources, 0, sizeof(resources));
|
||||
ShInitBuiltInResources(&resources);
|
||||
@@ -147,18 +153,21 @@ WebGLContext::CreateShaderValidator(GLenum shaderType) const
|
||||
resources.MaxCombinedTextureImageUnits = mGLMaxTextureUnits;
|
||||
resources.MaxTextureImageUnits = mGLMaxTextureImageUnits;
|
||||
resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
|
||||
resources.MaxDrawBuffers = mGLMaxDrawBuffers;
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
|
||||
const bool hasMRTs = (IsWebGL2() ||
|
||||
IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers));
|
||||
resources.MaxDrawBuffers = (hasMRTs ? mGLMaxDrawBuffers : 1);
|
||||
|
||||
if (IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
|
||||
resources.EXT_frag_depth = 1;
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
|
||||
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
|
||||
resources.OES_standard_derivatives = 1;
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
|
||||
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
|
||||
resources.EXT_draw_buffers = 1;
|
||||
|
||||
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
|
||||
if (IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
|
||||
resources.EXT_shader_texture_lod = 1;
|
||||
|
||||
// Tell ANGLE to allow highp in frag shaders. (unless disabled)
|
||||
@@ -247,6 +256,15 @@ ShaderValidator::CanLinkTo(const ShaderValidator* prev, nsCString* const out_log
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ShGetShaderVersion(prev->mHandle) != ShGetShaderVersion(mHandle)) {
|
||||
nsPrintfCString error("Vertex shader version %d does not match"
|
||||
" fragment shader version %d.",
|
||||
ShGetShaderVersion(prev->mHandle),
|
||||
ShGetShaderVersion(mHandle));
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
const std::vector<sh::Uniform>* vertPtr = ShGetUniforms(prev->mHandle);
|
||||
const std::vector<sh::Uniform>* fragPtr = ShGetUniforms(mHandle);
|
||||
|
||||
@@ -275,14 +275,14 @@ STRONG_GLENUM_BEGIN(TexCompareMode)
|
||||
STRONG_GLENUM_END(TexCompareMode)
|
||||
|
||||
STRONG_GLENUM_BEGIN(TexCompareFunc)
|
||||
STRONG_GLENUM_VALUE(LEQUAL),
|
||||
STRONG_GLENUM_VALUE(GEQUAL),
|
||||
STRONG_GLENUM_VALUE(LESS),
|
||||
STRONG_GLENUM_VALUE(GREATER),
|
||||
STRONG_GLENUM_VALUE(EQUAL),
|
||||
STRONG_GLENUM_VALUE(NOTEQUAL),
|
||||
STRONG_GLENUM_VALUE(ALWAYS),
|
||||
STRONG_GLENUM_VALUE(NEVER),
|
||||
STRONG_GLENUM_VALUE(LESS),
|
||||
STRONG_GLENUM_VALUE(EQUAL),
|
||||
STRONG_GLENUM_VALUE(LEQUAL),
|
||||
STRONG_GLENUM_VALUE(GREATER),
|
||||
STRONG_GLENUM_VALUE(NOTEQUAL),
|
||||
STRONG_GLENUM_VALUE(GEQUAL),
|
||||
STRONG_GLENUM_VALUE(ALWAYS),
|
||||
STRONG_GLENUM_END(TexCompareFunc)
|
||||
|
||||
STRONG_GLENUM_BEGIN(TexFormat)
|
||||
|
||||
@@ -164,9 +164,11 @@ WebGLTexture::MemoryUsage() const
|
||||
if (IsDeleted())
|
||||
return 0;
|
||||
|
||||
size_t result = 0;
|
||||
MOZ_CRASH("todo");
|
||||
return result;
|
||||
size_t accum = 0;
|
||||
for (const auto& cur : mImageInfoArr) {
|
||||
accum += cur.MemoryUsage();
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -740,6 +742,31 @@ WebGLTexture::GenerateMipmap(TexTarget texTarget)
|
||||
return;
|
||||
}
|
||||
|
||||
// OpenGL ES 3.0.4 p160:
|
||||
// If the level base array was not specified with an unsized internal format from
|
||||
// table 3.3 or a sized internal format that is both color-renderable and
|
||||
// texture-filterable according to table 3.13, an INVALID_OPERATION error
|
||||
// is generated.
|
||||
const auto usage = baseImageInfo.mFormat;
|
||||
bool canGenerateMipmap = (usage->isRenderable && usage->isFilterable);
|
||||
switch (usage->format->effectiveFormat) {
|
||||
case webgl::EffectiveFormat::Luminance8:
|
||||
case webgl::EffectiveFormat::Alpha8:
|
||||
case webgl::EffectiveFormat::Luminance8Alpha8:
|
||||
// Non-color-renderable formats from Table 3.3.
|
||||
canGenerateMipmap = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!canGenerateMipmap) {
|
||||
mContext->ErrorInvalidOperation("generateMipmap: Texture at base level is not unsized"
|
||||
" internal format or is not"
|
||||
" color-renderable or texture-filterable.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Done with validation. Do the operation.
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
|
||||
@@ -1784,7 +1784,8 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal
|
||||
|
||||
GLenum error;
|
||||
if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height)) {
|
||||
error = DoCopyTexImage2D(gl, target, level, internalFormat, x, y, width, height,
|
||||
MOZ_ASSERT(dstUsage->idealUnpack);
|
||||
error = DoCopyTexImage2D(gl, target, level, dstUsage->idealUnpack->internalFormat, x, y, width, height,
|
||||
border);
|
||||
} else {
|
||||
// 1. Zero the texture data.
|
||||
|
||||
@@ -141,7 +141,7 @@ ValidateGLSLVariableName(const nsAString& name, WebGLContext* webgl, const char*
|
||||
if (name.IsEmpty())
|
||||
return false;
|
||||
|
||||
const uint32_t maxSize = 256;
|
||||
const uint32_t maxSize = webgl->IsWebGL2() ? 1024 : 256;
|
||||
if (name.Length() > maxSize) {
|
||||
webgl->ErrorInvalidValue("%s: Identifier is %d characters long, exceeds the"
|
||||
" maximum allowed length of %d characters.",
|
||||
|
||||
@@ -52,12 +52,18 @@ struct WebGLVertexAttribData
|
||||
case LOCAL_GL_UNSIGNED_SHORT:
|
||||
return sizeof(GLushort);
|
||||
|
||||
case LOCAL_GL_INT:
|
||||
return sizeof(GLint);
|
||||
|
||||
case LOCAL_GL_UNSIGNED_INT:
|
||||
return sizeof(GLuint);
|
||||
|
||||
// case LOCAL_GL_FIXED:
|
||||
case LOCAL_GL_FLOAT:
|
||||
return sizeof(GLfloat);
|
||||
|
||||
default:
|
||||
NS_ERROR("Should never get here!");
|
||||
MOZ_ASSERT(false, "Should never get here!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,11 +205,7 @@ function beginTest() {
|
||||
}
|
||||
}
|
||||
|
||||
var prefs = [
|
||||
[ "canvas.capturestream.enabled", true ],
|
||||
];
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
|
||||
beginTest();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
@@ -211,13 +211,8 @@ function beginTest() {
|
||||
document.manager.runTests(corsTests, startTest);
|
||||
}
|
||||
|
||||
var prefs = [
|
||||
[ "canvas.capturestream.enabled", true ],
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
|
||||
beginTest();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
@@ -20,7 +20,7 @@ pref(webgl.force-layers-readback,true) == webgl-clear-test.html?readback wrappe
|
||||
== webgl-resize-test.html wrapper.html?green.png
|
||||
|
||||
# Check that captureStream() displays in a local video element
|
||||
pref(canvas.capturestream.enabled,true) skip-if(winWidget&&layersGPUAccelerated&&d2d) == webgl-capturestream-test.html?preserve wrapper.html?green.png
|
||||
skip-if(winWidget&&layersGPUAccelerated&&d2d) == webgl-capturestream-test.html?preserve wrapper.html?green.png
|
||||
|
||||
# Some of the failure conditions are a little crazy. I'm (jgilbert) setting these based on
|
||||
# failures encountered when running on Try, and then targetting the Try config by
|
||||
@@ -157,6 +157,6 @@ pref(canvas.focusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidVersion
|
||||
pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidVersion<15,8,500) skip-if(winWidget) needs-focus == drawCustomFocusRing.html drawCustomFocusRing-ref.html
|
||||
|
||||
# Check that captureStream() displays in a local video element
|
||||
pref(canvas.capturestream.enabled,true) skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
|
||||
skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
|
||||
|
||||
fuzzy-if(Android,3,40) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
|
||||
|
||||
@@ -107,9 +107,6 @@ function beginTest() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var prefs = [
|
||||
[ "canvas.capturestream.enabled", true ],
|
||||
];
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
beginTest();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -171,9 +171,6 @@ function beginTest() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var prefs = [
|
||||
[ "canvas.capturestream.enabled", true ],
|
||||
];
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
beginTest();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@ XPCOMUtils.defineLazyServiceGetter(this, "volumeService",
|
||||
"@mozilla.org/telephony/volume-service;1",
|
||||
"nsIVolumeService");
|
||||
|
||||
/**
|
||||
* The content process implementations of navigator.mozDownloadManager and its
|
||||
* DOMDownload download objects. Uses DownloadsIPC.jsm to communicate with
|
||||
* DownloadsAPI.jsm in the parent process.
|
||||
*/
|
||||
|
||||
function debug(aStr) {
|
||||
#ifdef MOZ_DEBUG
|
||||
dump("-*- DownloadsAPI.js : " + aStr + "\n");
|
||||
@@ -40,6 +46,15 @@ DOMDownloadManagerImpl.prototype = {
|
||||
this.initDOMRequestHelper(aWindow,
|
||||
["Downloads:Added",
|
||||
"Downloads:Removed"]);
|
||||
|
||||
// Get the manifest URL if this is an installed app
|
||||
let appsService = Cc["@mozilla.org/AppsService;1"]
|
||||
.getService(Ci.nsIAppsService);
|
||||
let principal = aWindow.document.nodePrincipal;
|
||||
// This returns the empty string if we're not an installed app. Coerce to
|
||||
// null.
|
||||
this._manifestURL = appsService.getManifestURLByLocalId(principal.appId) ||
|
||||
null;
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
@@ -79,23 +94,8 @@ DOMDownloadManagerImpl.prototype = {
|
||||
|
||||
clearAllDone: function() {
|
||||
debug("clearAllDone()");
|
||||
return this.createPromise(function (aResolve, aReject) {
|
||||
DownloadsIPC.clearAllDone().then(
|
||||
function(aDownloads) {
|
||||
// Turn the list of download objects into DOM objects and
|
||||
// send them.
|
||||
let array = new this._window.Array();
|
||||
for (let id in aDownloads) {
|
||||
let dom = createDOMDownloadObject(this._window, aDownloads[id]);
|
||||
array.push(this._prepareForContent(dom));
|
||||
}
|
||||
aResolve(array);
|
||||
}.bind(this),
|
||||
function() {
|
||||
aReject("ClearAllDoneError");
|
||||
}
|
||||
);
|
||||
}.bind(this));
|
||||
// This is a void function; we just kick it off. No promises, etc.
|
||||
DownloadsIPC.clearAllDone();
|
||||
},
|
||||
|
||||
remove: function(aDownload) {
|
||||
@@ -121,6 +121,67 @@ DOMDownloadManagerImpl.prototype = {
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
adoptDownload: function(aAdoptDownloadDict) {
|
||||
// Our AdoptDownloadDict only includes simple types, which WebIDL enforces.
|
||||
// We have no object/any types so we do not need to worry about invoking
|
||||
// JSON.stringify (and it inheriting our security privileges).
|
||||
debug("adoptDownload");
|
||||
return this.createPromise(function (aResolve, aReject) {
|
||||
if (!aAdoptDownloadDict) {
|
||||
debug("Download dictionary is required!");
|
||||
aReject("InvalidDownload");
|
||||
return;
|
||||
}
|
||||
if (!aAdoptDownloadDict.storageName || !aAdoptDownloadDict.storagePath ||
|
||||
!aAdoptDownloadDict.contentType) {
|
||||
debug("Missing one of: storageName, storagePath, contentType");
|
||||
aReject("InvalidDownload");
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert storageName/storagePath to a local filesystem path.
|
||||
let volume;
|
||||
// getVolumeByName throws if you give it something it doesn't like
|
||||
// because XPConnect converts the NS_ERROR_NOT_AVAILABLE to an
|
||||
// exception. So catch it.
|
||||
try {
|
||||
volume = volumeService.getVolumeByName(aAdoptDownloadDict.storageName);
|
||||
} catch (ex) {}
|
||||
if (!volume) {
|
||||
debug("Invalid storage name: " + aAdoptDownloadDict.storageName);
|
||||
aReject("InvalidDownload");
|
||||
return;
|
||||
}
|
||||
let computedPath = volume.mountPoint + '/' +
|
||||
aAdoptDownloadDict.storagePath;
|
||||
// We validate that there is actually a file at the given path in the
|
||||
// parent process in DownloadsAPI.js because that's where the file
|
||||
// access would actually occur either way.
|
||||
|
||||
// Create a DownloadsAPI.jsm 'jsonDownload' style representation.
|
||||
let jsonDownload = {
|
||||
url: aAdoptDownloadDict.url,
|
||||
path: computedPath,
|
||||
contentType: aAdoptDownloadDict.contentType,
|
||||
startTime: aAdoptDownloadDict.startTime.valueOf() || Date.now(),
|
||||
sourceAppManifestURL: this._manifestURL
|
||||
};
|
||||
|
||||
DownloadsIPC.adoptDownload(jsonDownload).then(
|
||||
function(aResult) {
|
||||
let domDownload = createDOMDownloadObject(this._window, aResult);
|
||||
aResolve(this._prepareForContent(domDownload));
|
||||
}.bind(this),
|
||||
function(aResult) {
|
||||
// This will be one of: AdoptError (generic catch-all),
|
||||
// AdoptNoSuchFile, AdoptFileIsDirectory
|
||||
aReject(aResult.error);
|
||||
}
|
||||
);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Turns a chrome download object into a content accessible one.
|
||||
* When we have __DOM_IMPL__ available we just use that, otherwise
|
||||
@@ -295,6 +356,11 @@ DOMDownloadImpl.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize a DOMDownload instance for the given window using the
|
||||
* 'jsonDownload' serialized format of the download encoded by
|
||||
* DownloadsAPI.jsm.
|
||||
*/
|
||||
_init: function(aWindow, aDownload) {
|
||||
this._window = aWindow;
|
||||
this.id = aDownload.id;
|
||||
@@ -314,12 +380,13 @@ DOMDownloadImpl.prototype = {
|
||||
}
|
||||
|
||||
let props = ["totalBytes", "currentBytes", "url", "path", "storageName",
|
||||
"storagePath", "state", "contentType", "startTime"];
|
||||
"storagePath", "state", "contentType", "startTime",
|
||||
"sourceAppManifestURL"];
|
||||
let changed = false;
|
||||
let changedProps = {};
|
||||
|
||||
props.forEach((prop) => {
|
||||
if (aDownload[prop] && (aDownload[prop] != this[prop])) {
|
||||
if (prop in aDownload && (aDownload[prop] != this[prop])) {
|
||||
this[prop] = aDownload[prop];
|
||||
changedProps[prop] = changed = true;
|
||||
}
|
||||
|
||||
+108
-11
@@ -13,11 +13,19 @@ this.EXPORTED_SYMBOLS = [];
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Downloads.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
"@mozilla.org/parentprocessmessagemanager;1",
|
||||
"nsIMessageBroadcaster");
|
||||
|
||||
/**
|
||||
* Parent process logic that services download API requests from the
|
||||
* DownloadAPI.js instances in content processeses. The actual work of managing
|
||||
* downloads is done by Toolkit's Downloads.jsm. This module is loaded by B2G's
|
||||
* shell.js
|
||||
*/
|
||||
|
||||
function debug(aStr) {
|
||||
#ifdef MOZ_DEBUG
|
||||
dump("-*- DownloadsAPI.jsm : " + aStr + "\n");
|
||||
@@ -49,7 +57,8 @@ let DownloadsAPI = {
|
||||
"Downloads:ClearAllDone",
|
||||
"Downloads:Remove",
|
||||
"Downloads:Pause",
|
||||
"Downloads:Resume"].forEach((msgName) => {
|
||||
"Downloads:Resume",
|
||||
"Downloads:Adopt"].forEach((msgName) => {
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
});
|
||||
|
||||
@@ -92,7 +101,9 @@ let DownloadsAPI = {
|
||||
url: aDownload.source.url,
|
||||
path: aDownload.target.path,
|
||||
contentType: aDownload.contentType,
|
||||
startTime: aDownload.startTime.getTime()
|
||||
startTime: aDownload.startTime.getTime(),
|
||||
sourceAppManifestURL: aDownload._unknownProperties &&
|
||||
aDownload._unknownProperties.sourceAppManifestURL
|
||||
};
|
||||
|
||||
if (aDownload.error) {
|
||||
@@ -165,6 +176,9 @@ let DownloadsAPI = {
|
||||
case "Downloads:Resume":
|
||||
this.resume(aMessage.data, aMessage.target);
|
||||
break;
|
||||
case "Downloads:Adopt":
|
||||
this.adoptDownload(aMessage.data, aMessage.target);
|
||||
break;
|
||||
default:
|
||||
debug("Invalid message: " + aMessage.name);
|
||||
}
|
||||
@@ -186,17 +200,9 @@ let DownloadsAPI = {
|
||||
|
||||
clearAllDone: function(aData, aMm) {
|
||||
debug("clearAllDone called!");
|
||||
let self = this;
|
||||
Task.spawn(function () {
|
||||
let list = yield Downloads.getList(Downloads.ALL);
|
||||
yield list.removeFinished();
|
||||
list = yield Downloads.getList(Downloads.ALL);
|
||||
let downloads = yield list.getAll();
|
||||
let res = [];
|
||||
downloads.forEach((aDownload) => {
|
||||
res.push(self.jsonDownload(aDownload));
|
||||
});
|
||||
aMm.sendAsyncMessage("Downloads:ClearAllDone:Return", res);
|
||||
list.removeFinished();
|
||||
}).then(null, Components.utils.reportError);
|
||||
},
|
||||
|
||||
@@ -262,6 +268,97 @@ let DownloadsAPI = {
|
||||
aData, "ResumeError");
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Receive a download to adopt in the same representation we produce from
|
||||
* our "jsonDownload" normalizer and add it to the list of downloads.
|
||||
*/
|
||||
adoptDownload: function(aData, aMm) {
|
||||
let adoptJsonRep = aData.jsonDownload;
|
||||
debug("adoptDownload " + uneval(adoptJsonRep));
|
||||
|
||||
Task.spawn(function* () {
|
||||
// Verify that the file exists on disk. This will result in a rejection
|
||||
// if the file does not exist. We will also use this information for the
|
||||
// file size to avoid weird inconsistencies. We ignore the filesystem
|
||||
// timestamp in favor of whatever the caller is telling us.
|
||||
let fileInfo = yield OS.File.stat(adoptJsonRep.path);
|
||||
|
||||
// We also require that the file is not a directory.
|
||||
if (fileInfo.isDir) {
|
||||
throw new Error("AdoptFileIsDirectory");
|
||||
}
|
||||
|
||||
// We need to create a Download instance to add to the list. Create a
|
||||
// serialized representation and then from there the instance.
|
||||
let serializedRep = {
|
||||
// explicit initializations in toSerializable
|
||||
source: {
|
||||
url: adoptJsonRep.url
|
||||
// This is where isPrivate would go if adoption supported private
|
||||
// browsing.
|
||||
},
|
||||
target: {
|
||||
path: adoptJsonRep.path,
|
||||
},
|
||||
startTime: adoptJsonRep.startTime,
|
||||
// kPlainSerializableDownloadProperties propagations
|
||||
succeeded: true, // (all adopted downloads are required to be completed)
|
||||
totalBytes: fileInfo.size,
|
||||
contentType: adoptJsonRep.contentType,
|
||||
// unknown properties added/used by the DownloadsAPI
|
||||
currentBytes: fileInfo.size,
|
||||
sourceAppManifestURL: adoptJsonRep.sourceAppManifestURL
|
||||
};
|
||||
|
||||
let download = yield Downloads.createDownload(serializedRep);
|
||||
|
||||
// The ALL list is a DownloadCombinedList instance that combines the
|
||||
// PUBLIC (persisted to disk) and PRIVATE (ephemeral) download lists..
|
||||
// When we call add on it, it dispatches to the appropriate list based on
|
||||
// the 'isPrivate' field of the source. (Which we don't initialize and
|
||||
// defaults to false.)
|
||||
let allDownloadList = yield Downloads.getList(Downloads.ALL);
|
||||
|
||||
// This add will automatically notify all views of the added download,
|
||||
// including DownloadsAPI instances and the DownloadAutoSaveView that's
|
||||
// subscribed to the PUBLIC list and will save the download.
|
||||
yield allDownloadList.add(download);
|
||||
|
||||
debug("download adopted");
|
||||
// The notification above occurred synchronously, and so we will have
|
||||
// already dispatched an added notification for our download to the child
|
||||
// process in question. As such, we only need to relay the download id
|
||||
// since the download will already have been cached.
|
||||
return download;
|
||||
}.bind(this)).then(
|
||||
(download) => {
|
||||
sendPromiseMessage(aMm, "Downloads:Adopt:Return",
|
||||
{
|
||||
id: this.downloadId(download),
|
||||
promiseId: aData.promiseId
|
||||
});
|
||||
},
|
||||
(ex) => {
|
||||
let reportAs = "AdoptError";
|
||||
// Provide better error codes for expected errors.
|
||||
if (ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
|
||||
reportAs = "AdoptNoSuchFile";
|
||||
} else if (ex.message === "AdoptFileIsDirectory") {
|
||||
reportAs = ex.message;
|
||||
} else {
|
||||
// Anything else is unexpected and should be reported to help track
|
||||
// down what's going wrong.
|
||||
debug("unexpected download error: " + ex);
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
sendPromiseMessage(aMm, "Downloads:Adopt:Return",
|
||||
{
|
||||
promiseId: aData.promiseId
|
||||
},
|
||||
reportAs);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -36,10 +36,10 @@ const ipcMessages = ["Downloads:Added",
|
||||
"Downloads:Removed",
|
||||
"Downloads:Changed",
|
||||
"Downloads:GetList:Return",
|
||||
"Downloads:ClearAllDone:Return",
|
||||
"Downloads:Remove:Return",
|
||||
"Downloads:Pause:Return",
|
||||
"Downloads:Resume:Return"];
|
||||
"Downloads:Resume:Return",
|
||||
"Downloads:Adopt:Return"];
|
||||
|
||||
this.DownloadsIPC = {
|
||||
downloads: {},
|
||||
@@ -54,7 +54,6 @@ this.DownloadsIPC = {
|
||||
// We need to get the list of current downloads.
|
||||
this.ready = false;
|
||||
this.getListPromises = [];
|
||||
this.clearAllPromises = [];
|
||||
this.downloadPromises = {};
|
||||
cpmm.sendAsyncMessage("Downloads:GetList", {});
|
||||
this._promiseId = 0;
|
||||
@@ -93,12 +92,6 @@ this.DownloadsIPC = {
|
||||
}
|
||||
this.ready = true;
|
||||
break;
|
||||
case "Downloads:ClearAllDone:Return":
|
||||
this._updateDownloadsArray(download);
|
||||
this.clearAllPromises.forEach(aPromise =>
|
||||
aPromise.resolve(this.downloads));
|
||||
this.clearAllPromises.length = 0;
|
||||
break;
|
||||
case "Downloads:Added":
|
||||
this.downloads[download.id] = download;
|
||||
this.notifyChanges(download.id);
|
||||
@@ -139,6 +132,7 @@ this.DownloadsIPC = {
|
||||
case "Downloads:Remove:Return":
|
||||
case "Downloads:Pause:Return":
|
||||
case "Downloads:Resume:Return":
|
||||
case "Downloads:Adopt:Return":
|
||||
if (this.downloadPromises[download.promiseId]) {
|
||||
if (!download.error) {
|
||||
this.downloadPromises[download.promiseId].resolve(download);
|
||||
@@ -167,14 +161,11 @@ this.DownloadsIPC = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a promise that is resolved with the list of current downloads.
|
||||
*/
|
||||
* Void function to trigger removal of completed downloads.
|
||||
*/
|
||||
clearAllDone: function() {
|
||||
debug("clearAllDone");
|
||||
let deferred = Promise.defer();
|
||||
this.clearAllPromises.push(deferred);
|
||||
cpmm.sendAsyncMessage("Downloads:ClearAllDone", {});
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
promiseId: function() {
|
||||
@@ -211,6 +202,16 @@ this.DownloadsIPC = {
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
adoptDownload: function(aJsonDownload) {
|
||||
debug("adoptDownload");
|
||||
let deferred = Promise.defer();
|
||||
let pId = this.promiseId();
|
||||
this.downloadPromises[pId] = deferred;
|
||||
cpmm.sendAsyncMessage("Downloads:Adopt",
|
||||
{ jsonDownload: aJsonDownload, promiseId: pId });
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "xpcom-shutdown") {
|
||||
ipcMessages.forEach((aMessage) => {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* A helper to clear out the existing downloads known to the mozDownloadManager
|
||||
* / downloads.js.
|
||||
*
|
||||
* It exists because previously mozDownloadManager.clearAllDone() thought that
|
||||
* when it returned that all the completed downloads would be cleared out. It
|
||||
* was wrong and this led to various intermittent test failurse. In discussion
|
||||
* on https://bugzil.la/979446#c13 and onwards, it was decided that
|
||||
* clearAllDone() was in the wrong and that the jsdownloads API it depends on
|
||||
* was not going to change to make it be in the right.
|
||||
*
|
||||
* The existing uses of clearAllDone() in tests seemed to be about:
|
||||
* - Exploding if there was somehow still a download in progress
|
||||
* - Clearing out the download list at the start of a test so that calls to
|
||||
* getDownloads() wouldn't have to worry about existing downloads, etc.
|
||||
*
|
||||
* From discussion, the right way to handle clearing is to wait for the expected
|
||||
* removal events to occur for the existing downloads. So that's what we do.
|
||||
* We still generate a test failure if there are any in-progress downloads.
|
||||
*
|
||||
* @param {Boolean} [getDownloads=false]
|
||||
* If true, invoke getDownloads after clearing the download list and return
|
||||
* its value.
|
||||
*/
|
||||
function clearAllDoneHelper(getDownloads) {
|
||||
var clearedPromise = new Promise(function(resolve, reject) {
|
||||
function gotDownloads(downloads) {
|
||||
// If there are no downloads, we're already done.
|
||||
if (downloads.length === 0) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
// Track the set of expected downloads that will be finalized.
|
||||
var expectedIds = new Set();
|
||||
function changeHandler(evt) {
|
||||
var download = evt.download;
|
||||
if (download.state === "finalized") {
|
||||
expectedIds.delete(download.id);
|
||||
if (expectedIds.size === 0) {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
downloads.forEach(function(download) {
|
||||
if (download.state === "downloading") {
|
||||
ok(false, "A download is still active: " + download.path);
|
||||
reject("Active download");
|
||||
}
|
||||
download.onstatechange = changeHandler;
|
||||
expectedIds.add(download.id);
|
||||
});
|
||||
navigator.mozDownloadManager.clearAllDone();
|
||||
}
|
||||
function gotBadNews(err) {
|
||||
ok(false, "Problem clearing all downloads: " + err);
|
||||
reject(err);
|
||||
}
|
||||
navigator.mozDownloadManager.getDownloads().then(gotDownloads, gotBadNews);
|
||||
});
|
||||
if (!getDownloads) {
|
||||
return clearedPromise;
|
||||
}
|
||||
return clearedPromise.then(function() {
|
||||
return navigator.mozDownloadManager.getDownloads();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + a + ' should equal ' + b + ': ' + msg);
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg);
|
||||
}
|
||||
|
||||
function info(msg) {
|
||||
alert('INFO ' + msg);
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
var gBasePath = "tests/dom/downloads/tests/";
|
||||
var gTemplate = "file_app.template.webapp";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var query = getQuery(request);
|
||||
|
||||
var testToken = query.testToken || '';
|
||||
var appType = query.appType || 'web';
|
||||
|
||||
var template = gBasePath + gTemplate;
|
||||
response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
|
||||
var body = readTemplate(template)
|
||||
.replace(/TESTTOKEN/g, testToken)
|
||||
.replace(/APPTYPE/g, appType);
|
||||
response.write();
|
||||
}
|
||||
|
||||
// Copy-pasted incantations. There ought to be a better way to synchronously read
|
||||
// a file into a string, but I guess we're trying to discourage that.
|
||||
function readTemplate(path) {
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties).
|
||||
get("CurWorkD", Components.interfaces.nsILocalFile);
|
||||
var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
var cis = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
|
||||
createInstance(Components.interfaces.nsIConverterInputStream);
|
||||
var split = path.split("/");
|
||||
for(var i = 0; i < split.length; ++i) {
|
||||
file.append(split[i]);
|
||||
}
|
||||
fis.init(file, -1, -1, false);
|
||||
cis.init(fis, "UTF-8", 0, 0);
|
||||
|
||||
var data = "";
|
||||
let (str = {}) {
|
||||
let read = 0;
|
||||
do {
|
||||
read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
data += str.value;
|
||||
} while (read != 0);
|
||||
}
|
||||
cis.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
function getQuery(request) {
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
return query;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "Really Rapid Release (hosted)",
|
||||
"description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
|
||||
"type": "APPTYPE",
|
||||
"launch_path": "/tests/dom/downloads/tests/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" }
|
||||
}
|
||||
@@ -1,12 +1,24 @@
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' # bug 979446, frequent failures
|
||||
# The actual requirement for mozDownloadManager is MOZ_GONK because of
|
||||
# the nsIVolumeService dependency. Until https://bugzil.la/1130264 is
|
||||
# addressed, there is no way for mulet to run these tests.
|
||||
run-if = toolkit == 'gonk'
|
||||
support-files =
|
||||
serve_file.sjs
|
||||
clear_all_done_helper.js
|
||||
file_app.template.webapp
|
||||
file_app.sjs
|
||||
common_app.js
|
||||
shim_app_as_test.js
|
||||
shim_app_as_test_chrome.js
|
||||
testapp_downloads_adopt_download.html
|
||||
testapp_downloads_adopt_download.js
|
||||
testapp_downloads_adopt_download.manifest
|
||||
|
||||
[test_downloads_navigator_object.html]
|
||||
[test_downloads_basic.html]
|
||||
[test_downloads_large.html]
|
||||
[test_downloads_adopt_download.html]
|
||||
[test_downloads_bad_file.html]
|
||||
[test_downloads_pause_remove.html]
|
||||
[test_downloads_pause_resume.html]
|
||||
skip-if = toolkit=='gonk' # b2g(bug 947167) b2g-debug(bug 947167)
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Support logic to run a test file as an installed app. This file is derived
|
||||
* from dom/requestsync/tests/test_basic_app.html but uses
|
||||
* DOMApplicationRegistry in a chrome script (shim_app_as_test_chrome.js) to
|
||||
* directly install the apps instead of mozApps.install because mozApps.install
|
||||
* can't install privileged/certified apps. (This is the same mechanism used by
|
||||
* the Firefox OS Gaia email app's backend test runner.)
|
||||
*
|
||||
* You really only want to do this if your test cares about the app's origin
|
||||
* or you REALLY want to double-check AvailableIn and other WebIDL-provided
|
||||
* security mechanisms.
|
||||
*
|
||||
* If you trust WebIDL, your life may be made significantly easier by just
|
||||
* setting the pref "dom.ignore_webidl_scope_checks" to true, which makes
|
||||
* BindingUtils.cpp's IsInPrivilegedApp and IsInCertifiedApp return true no
|
||||
* matter what *on the main thread*. You are potentially out of luck on
|
||||
* workers since at the time of writing this since the values stored on
|
||||
* WorkerPrivateParent are based on the app status and ignore the pref.
|
||||
*
|
||||
* TO USE THIS:
|
||||
*
|
||||
* Make sure you have the usual header boilerplate:
|
||||
* <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
* <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
*
|
||||
* You also want to add this file!
|
||||
* <script type="application/javascript" src="shim_app_as_test.js"></script>
|
||||
*
|
||||
* In your script body, issue a call like so:
|
||||
* runAppTest({
|
||||
* appFile: 'testapp_downloads_adopt_download.html',
|
||||
* appManifest: 'testapp_downloads_adopt_download.manifest',
|
||||
* appType: 'certified',
|
||||
* extraPrefs: {
|
||||
* set: [["dom.mozDownloads.enabled", true]]
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* You shouldn't be adding other stuff to that file. Instead, you want
|
||||
* everything in your testapp_*.html file. And you probably just want to copy
|
||||
* and paste from an existing one of those...
|
||||
*/
|
||||
|
||||
var gManifestURL;
|
||||
var gApp;
|
||||
var gOptions;
|
||||
|
||||
// Load the chrome script.
|
||||
var gChromeHelper = SpecialPowers.loadChromeScript(
|
||||
SimpleTest.getTestFileURL('shim_app_as_test_chrome.js'));
|
||||
|
||||
function installApp() {
|
||||
info("installing app");
|
||||
var useOrigin = document.location.origin;
|
||||
gChromeHelper.sendAsyncMessage(
|
||||
'install',
|
||||
{
|
||||
origin: useOrigin,
|
||||
manifestURL: SimpleTest.getTestFileURL(gOptions.appManifest),
|
||||
});
|
||||
}
|
||||
|
||||
function installedApp(appInfo) {
|
||||
gApp = appInfo;
|
||||
ok(!!appInfo, 'installed app');
|
||||
runTests();
|
||||
}
|
||||
gChromeHelper.addMessageListener('installed', installedApp);
|
||||
|
||||
function uninstallApp() {
|
||||
info('uninstalling app');
|
||||
gChromeHelper.sendAsyncMessage('uninstall', gApp);
|
||||
}
|
||||
|
||||
function uninstalledApp(success) {
|
||||
ok(success, 'uninstalled app');
|
||||
runTests();
|
||||
}
|
||||
gChromeHelper.addMessageListener('uninstalled', uninstalledApp);
|
||||
|
||||
function testApp() {
|
||||
var cleanupFrame;
|
||||
var handleTestMessage = function(message) {
|
||||
if (/^OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/^KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/^INFO/.exec(message)) {
|
||||
info("Message from app: " + message.substring(5));
|
||||
} else if (/^DONE$/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
cleanupFrame();
|
||||
runTests();
|
||||
}
|
||||
};
|
||||
|
||||
// Bug 1097479 means that embed-webapps does not work if you are already
|
||||
// OOP, as we are for b2g. So we need to have the chrome script run our
|
||||
// app in a sibling iframe to the one we're living in. When that bug is
|
||||
// fixed or we are run in a non-b2g context, we can set this value to false
|
||||
// or otherwise conditionalize based on behaviour.
|
||||
var needSiblingIframeHack = true;
|
||||
|
||||
if (needSiblingIframeHack) {
|
||||
gChromeHelper.sendAsyncMessage('run', gApp);
|
||||
|
||||
gChromeHelper.addMessageListener('appMessage', handleTestMessage);
|
||||
gChromeHelper.addMessageListener('appError', function(data) {
|
||||
ok(false, "Error in app frame: " + data.message);
|
||||
});
|
||||
|
||||
cleanupFrame = function() {
|
||||
gChromeHelper.sendAsyncMessage('close', {});
|
||||
};
|
||||
} else {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApp.manifestURL);
|
||||
|
||||
cleanupFrame = function() {
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
};
|
||||
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
var message = e.detail.message; // e.detail.message;
|
||||
handleTestMessage(message);
|
||||
};
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
ifr.addEventListener('mozbrowsererror', function(evt) {
|
||||
ok(false, "Error in app frame: " + evt.detail);
|
||||
});
|
||||
|
||||
ifr.setAttribute('src', gApp.manifest.launch_path);
|
||||
var domParent = document.getElementById('content');
|
||||
if (!domParent) {
|
||||
document.createElement('div');
|
||||
document.body.insertBefore(domParent, document.body.firstChild);
|
||||
}
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Permissions
|
||||
function() {
|
||||
info("pushing permissions");
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document },
|
||||
{ "type": "webapps-manage", "allow": 1, "context": document }
|
||||
],
|
||||
runTests);
|
||||
},
|
||||
|
||||
// Preferences
|
||||
function() {
|
||||
info("pushing preferences: " + gOptions.extraPrefs.set);
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": gOptions.extraPrefs.set
|
||||
}, runTests);
|
||||
},
|
||||
|
||||
function() {
|
||||
info("enabling use of mozbrowser");
|
||||
//SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
|
||||
runTests();
|
||||
},
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(function() {
|
||||
SpecialPowers.autoConfirmAppUninstall(runTests);
|
||||
});
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
installApp,
|
||||
|
||||
// Run tests in app
|
||||
testApp,
|
||||
|
||||
// Uninstall the app
|
||||
uninstallApp,
|
||||
];
|
||||
|
||||
function runTests() {
|
||||
if (!tests.length) {
|
||||
ok(true, 'DONE!');
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function runAppTest(options) {
|
||||
gOptions = options;
|
||||
var href = document.location.href;
|
||||
gManifestURL = href.substring(0, href.lastIndexOf('/') + 1) +
|
||||
options.appManifest;
|
||||
runTests();
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* This is the chrome helper for shim_app_as_test.js. Its load is triggered by
|
||||
* shim_app_as_test.js by a call to SpecialPowers.loadChromeScript and runs
|
||||
* in the parent process in a sandbox created with the system principal. (Which
|
||||
* seems like it can never get collected because it's reachable via the
|
||||
* apparently singleton SpecialPowersObserverAPI instance and there's no logic
|
||||
* to support reaping. Wuh-oh.)
|
||||
*
|
||||
* It exists to help install fake privileged/certified applications. It needs
|
||||
* to exist because:
|
||||
* - We need to poke at DOMApplicationRegistry directly.
|
||||
* - By using SpecialPowers.loadChromeScript we are able to ensure this file
|
||||
* is run in the parent process. This is important because
|
||||
* DOMApplicationRegistry only lives in the parent process!
|
||||
* - By running entirely in a chrome privileged compartment, we avoid crazy
|
||||
* wrapper problems that we would otherwise face with our shenanigans of
|
||||
* directly meddling with DOMApplicationRegistry. (And hopefully save
|
||||
* anyone changing DOMApplicationRegistry from frustration/hating us if
|
||||
* things were just barely working.)
|
||||
* - Bug 1097479 means that embed-webapps doesn't work when the content process
|
||||
* that is telling us to do things is itself OOP. So it falls upon us to
|
||||
* handle the running of the app by creating a sibling mozbrowser/mozapp
|
||||
* iframe to the one running the mochitests.
|
||||
*
|
||||
* Note that in this file we try to do *only* those things that can't otherwise
|
||||
* be cleanly done using SpecialPowers.
|
||||
*
|
||||
* Want to better understand our execution context? Check out
|
||||
* SpecialPowersObserverAPI.js and search on SPLoadChromeScript.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
Cu.import('resource://gre/modules/Webapps.jsm'); // for DOMApplicationRegistry
|
||||
Cu.import('resource://gre/modules/AppsUtils.jsm'); // for AppUtils
|
||||
Cu.import('resource://gre/modules/Services.jsm'); // for AppUtils
|
||||
|
||||
// Yes, you would think there was something like this already exposed easily
|
||||
// in a JSM somewhere. No.
|
||||
function fetchManifest(manifestURL) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("GET", manifestURL, true);
|
||||
xhr.responseType = "json";
|
||||
|
||||
xhr.addEventListener("load", function() {
|
||||
if (xhr.status == 200) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener("error", function() {
|
||||
reject();
|
||||
});
|
||||
|
||||
xhr.send(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Install an app using confirmInstall using pre-chewed data. This avoids the
|
||||
* check in the normal installApp flow that gets all judgemental about the
|
||||
* installation of privileged and certified apps.
|
||||
*/
|
||||
function installApp(req) {
|
||||
fetchManifest(req.manifestURL).then(function(manifestObj) {
|
||||
var data = {
|
||||
// cloneAppObj normalizes the representation for us
|
||||
app: AppsUtils.cloneAppObject({
|
||||
installOrigin: req.origin,
|
||||
origin: req.origin,
|
||||
manifestURL: req.manifestURL,
|
||||
appStatus: AppsUtils.getAppManifestStatus(manifestObj),
|
||||
receipts: [],
|
||||
categories: []
|
||||
}),
|
||||
|
||||
from: req.origin, // unused?
|
||||
oid: 0, // unused?
|
||||
requestID: 0, // unused-ish
|
||||
appId: 0, // unused
|
||||
isBrowser: false,
|
||||
isPackage: false, // used
|
||||
// magic to auto-ack... don't think we care about this...
|
||||
forceSuccessAck: false
|
||||
// stuff that probably doesn't matter: 'mm', 'apkInstall',
|
||||
};
|
||||
// cloneAppObject does not propagate the manifest
|
||||
data.app.manifest = manifestObj;
|
||||
|
||||
return DOMApplicationRegistry.confirmInstall(data).then(
|
||||
function() {
|
||||
var appId =
|
||||
DOMApplicationRegistry.getAppLocalIdByManifestURL(req.manifestURL);
|
||||
// act like this is a privileged app having all of its permissions
|
||||
// authorized at first run.
|
||||
DOMApplicationRegistry.updatePermissionsForApp(
|
||||
appId,
|
||||
/* preinstalled */ true,
|
||||
/* system update? */ true);
|
||||
|
||||
sendAsyncMessage(
|
||||
'installed',
|
||||
{
|
||||
appId: appId,
|
||||
manifestURL: req.manifestURL,
|
||||
manifest: manifestObj
|
||||
});
|
||||
},
|
||||
function(err) {
|
||||
sendAsyncMessage('installed', false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function uninstallApp(appInfo) {
|
||||
DOMApplicationRegistry.uninstall(appInfo.manifestURL).then(
|
||||
function() {
|
||||
sendAsyncMessage('uninstalled', true);
|
||||
},
|
||||
function() {
|
||||
sendAsyncMessage('uninstalled', false);
|
||||
});
|
||||
}
|
||||
|
||||
var activeIframe = null;
|
||||
|
||||
/**
|
||||
* Run our app in a sibling mozbrowser/mozapp iframe to the mochitest iframe.
|
||||
* This is needed because we can't nest mozbrowser/mozapp iframes inside our
|
||||
* already-OOP iframe until bug 1097479 is resolved.
|
||||
*/
|
||||
function runApp(appInfo) {
|
||||
let shellDomWindow = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
let sysAppFrame = shellDomWindow.document.body.querySelector('#systemapp');
|
||||
let sysAppDoc = sysAppFrame.contentDocument;
|
||||
|
||||
let siblingFrame = sysAppDoc.body.querySelector('#test-container');
|
||||
|
||||
let ifr = activeIframe = sysAppDoc.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('remote', 'true');
|
||||
ifr.setAttribute('mozapp', appInfo.manifestURL);
|
||||
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', function(evt) {
|
||||
var message = evt.detail.message;
|
||||
// only send the message as long as we haven't been told to clean up.
|
||||
if (activeIframe) {
|
||||
sendAsyncMessage('appMessage', message);
|
||||
}
|
||||
}, false);
|
||||
ifr.addEventListener('mozbrowsererror', function(evt) {
|
||||
if (activeIframe) {
|
||||
sendAsyncMessage('appError', { message: '' + evt.detail });
|
||||
}
|
||||
});
|
||||
|
||||
ifr.setAttribute('src', appInfo.manifest.launch_path);
|
||||
siblingFrame.parentElement.appendChild(ifr);
|
||||
}
|
||||
|
||||
function closeApp() {
|
||||
if (activeIframe) {
|
||||
activeIframe.parentElement.removeChild(activeIframe);
|
||||
activeIframe = null;
|
||||
}
|
||||
}
|
||||
|
||||
addMessageListener('install', installApp);
|
||||
addMessageListener('uninstall', uninstallApp);
|
||||
addMessageListener('run', runApp);
|
||||
addMessageListener('close', closeApp);
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=825318
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 825318 mozDownloadManager.adoptDownload</title>
|
||||
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.7" src="shim_app_as_test.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=825318">Mozilla Bug 825318</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
|
||||
runAppTest({
|
||||
appFile: 'testapp_downloads_adopt_download.html',
|
||||
appManifest: 'testapp_downloads_adopt_download.manifest',
|
||||
appType: 'certified',
|
||||
extraPrefs: {
|
||||
set: [["dom.mozDownloads.enabled", true]]
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -72,6 +72,10 @@ function downloadChange(evt) {
|
||||
is(download.currentBytes, 1024, "Download current size is 1024 bytes");
|
||||
SimpleTest.finish();
|
||||
} else if (download.state === "downloading") {
|
||||
// Note that this case may or may not trigger, depending on whether the
|
||||
// download is initially reported with 0 bytes (we should happen) or with
|
||||
// 1024 bytes (we should not happen). If we do happen, an additional 8
|
||||
// TEST-PASS events should be logged.
|
||||
ok(download.currentBytes > lastKnownCurrentBytes,
|
||||
"Download current size is larger than last download change event");
|
||||
lastKnownCurrentBytes = download.currentBytes;
|
||||
@@ -84,7 +88,8 @@ function downloadStart(evt) {
|
||||
var download = evt.download;
|
||||
checkConsistentDownloadAttributes(download);
|
||||
|
||||
is(download.currentBytes, 0, "Download current size is zero");
|
||||
// We used to check that the currentBytes was 0. This was incorrect. It
|
||||
// is very common to first hear about the download already at 1024 bytes.
|
||||
is(download.state, "downloading", "Download state is downloading");
|
||||
|
||||
download.onstatechange = downloadChange;
|
||||
|
||||
@@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=938023
|
||||
<title>Test for Bug 938023 Downloads API</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="clear_all_done_helper.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
@@ -46,7 +47,7 @@ function error() {
|
||||
|
||||
function getDownloads(downloads) {
|
||||
ok(downloads.length == 1, "One downloads after getDownloads");
|
||||
navigator.mozDownloadManager.clearAllDone().then(clearAllDone, error);
|
||||
clearAllDoneHelper(true).then(clearAllDone, error);
|
||||
}
|
||||
|
||||
function clearAllDone(downloads) {
|
||||
@@ -76,7 +77,7 @@ var steps = [
|
||||
SpecialPowers.pushPermissions([
|
||||
{type: "downloads", allow: true, context: document}
|
||||
], function() {
|
||||
navigator.mozDownloadManager.clearAllDone().then(next, error);
|
||||
clearAllDoneHelper(true).then(next, error);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=938023
|
||||
<title>Test for Bug 938023 Downloads API</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="clear_all_done_helper.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
@@ -83,7 +84,7 @@ var steps = [
|
||||
SpecialPowers.pushPermissions([
|
||||
{type: "downloads", allow: true, context: document}
|
||||
], function() {
|
||||
navigator.mozDownloadManager.clearAllDone().then(next, error);
|
||||
clearAllDoneHelper(true).then(next, error);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=938023
|
||||
<title>Test for Bug 938023 Downloads API</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="clear_all_done_helper.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
@@ -54,8 +55,7 @@ function checkDownloadList(downloads) {
|
||||
|
||||
function checkResumeSucceeded(download) {
|
||||
ok(download.state == "succeeded", "Download resumed successfully.");
|
||||
navigator.mozDownloadManager.clearAllDone()
|
||||
.then(checkDownloadList, error);
|
||||
clearAllDoneHelper(true).then(checkDownloadList, error);
|
||||
}
|
||||
|
||||
function downloadChange(evt) {
|
||||
@@ -88,7 +88,7 @@ var steps = [
|
||||
SpecialPowers.pushPermissions([
|
||||
{type: "downloads", allow: true, context: document}
|
||||
], function() {
|
||||
navigator.mozDownloadManager.clearAllDone().then(next, error);
|
||||
clearAllDoneHelper(true).then(next, error);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/javascript" src="common_app.js"></script>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="blah">initial text</div>
|
||||
<pre id="test">
|
||||
<!-- because of certified CSP, this code must NOT be inline -->
|
||||
<script class="testbody" type="text/javascript;version=1.7" src="testapp_downloads_adopt_download.js"></script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* Test the adoptDownload API. Specifically, we expect that when we call
|
||||
* adoptDownload with a valid payload that:
|
||||
* - The method will be resolved with a valid, fully populated DOMDownload
|
||||
* instance, including an id.
|
||||
* - An ondownloadstart notification will be generated and the DOMDownload
|
||||
* instance it receives will be logically equivalent.
|
||||
*
|
||||
* We also explicitly verify that invalid adoptDownload payloads result in a
|
||||
* rejection and that no download is added.
|
||||
*
|
||||
* This test explicitly does not test that the download is correctly persisted
|
||||
* to the database. This is done because Downloads.jsm does not provide a means
|
||||
* of safely restarting itself, so Firefox would need to be restarted. Because
|
||||
* the adoptDownload code is using the Downloads API in a straightforward
|
||||
* manner, it's not considered likely this would regress, and certainly not
|
||||
* considered worth the automated testing overhead of a restart.
|
||||
*/
|
||||
|
||||
function checkInvalidResult(dict, expectedErr, explanation) {
|
||||
navigator.mozDownloadManager.ondownloadstart = function() {
|
||||
ok(false, "No download should have been added!");
|
||||
};
|
||||
navigator.mozDownloadManager.adoptDownload(dict).then(
|
||||
function() {
|
||||
ok(false, "Invalid adoptDownload did not reject!");
|
||||
runTests();
|
||||
},
|
||||
function(rejectedWith) {
|
||||
is(rejectedWith, expectedErr, explanation + " rejection value");
|
||||
runTests();
|
||||
});
|
||||
}
|
||||
|
||||
// Pick a date that Date.now() could not possibly return by picking a date in
|
||||
// the past. (We want to make sure the date we provide works.)
|
||||
var arbitraryDate = new Date(Date.now() - 60000);
|
||||
|
||||
var blobContents = new Uint8Array(256);
|
||||
var memBlob = new Blob([blobContents], { type: 'application/octet-stream' });
|
||||
var blobStorageName;
|
||||
var blobStoragePath = 'blobby.blob';
|
||||
|
||||
function checkAdoptedDownload(download, validPayload) {
|
||||
is(download.totalBytes, memBlob.size, 'size');
|
||||
is(download.url, validPayload.url, 'url');
|
||||
// The filesystem path is not practical to check since we can't hard-code it
|
||||
// and the only way to check is to effectively duplicate the logic in
|
||||
// DownloadsAPI.js. The good news, however, is that the value is
|
||||
// round-tripped from storageName/storagePath to path and back again, and we
|
||||
// also verify the file exists on disk, so we can be reasonably confident this
|
||||
// is correct. We output it to aid in debugging if things should break,
|
||||
// of course.
|
||||
info('path (not checked): ' + download.path);
|
||||
is(download.storageName, validPayload.storageName, 'storageName');
|
||||
is(download.storagePath, validPayload.storagePath, 'storagePath');
|
||||
is(download.state, 'succeeded', 'state');
|
||||
is(download.contentType, validPayload.contentType, 'contentType');
|
||||
is(download.startTime.valueOf(), arbitraryDate.valueOf(), 'startTime');
|
||||
is(download.sourceAppManifestURL,
|
||||
'http://mochi.test:8888/' +
|
||||
'tests/dom/downloads/tests/testapp_downloads_adopt_download.manifest',
|
||||
'app manifest');
|
||||
};
|
||||
|
||||
var tests = [
|
||||
function saveBlobToDeviceStorage() {
|
||||
// Only sdcard can handle arbitrary MIME types and is guaranteed to be a
|
||||
// thing.
|
||||
var storage = navigator.getDeviceStorage('sdcard');
|
||||
// We used the non-array helper, so the name we get may be different than
|
||||
// what we asked for.
|
||||
blobStorageName = storage.storageName;
|
||||
ok(!!storage, 'have storage');
|
||||
var req = storage.addNamed(memBlob, blobStoragePath);
|
||||
req.onerror = function() {
|
||||
ok(false, 'problem saving blob to storage: ' + req.error.name);
|
||||
};
|
||||
req.onsuccess = function(evt) {
|
||||
ok(true, 'saved blob: ' + evt.target.result);
|
||||
runTests();
|
||||
};
|
||||
},
|
||||
function addValid() {
|
||||
var validPayload = {
|
||||
// All currently expected consumers are unable to provide a valid URL, and
|
||||
// as a result need to provide an empty string.
|
||||
url: "",
|
||||
storageName: blobStorageName,
|
||||
storagePath: blobStoragePath,
|
||||
contentType: memBlob.type,
|
||||
startTime: arbitraryDate
|
||||
};
|
||||
// Wrap the notification in a check so we can force our logic to be
|
||||
// consistently ordered in the test even if it's not in reality.
|
||||
var notifiedPromise = new Promise(function(resolve, reject) {
|
||||
navigator.mozDownloadManager.ondownloadstart = function(evt) {
|
||||
resolve(evt.download);
|
||||
};
|
||||
});
|
||||
|
||||
// Start the download
|
||||
navigator.mozDownloadManager.adoptDownload(validPayload).then(
|
||||
function(apiDownload) {
|
||||
checkAdoptedDownload(apiDownload, validPayload);
|
||||
ok(!!apiDownload.id, "Need a download id!");
|
||||
notifiedPromise.then(function(notifiedDownload) {
|
||||
checkAdoptedDownload(notifiedDownload, validPayload);
|
||||
is(apiDownload.id, notifiedDownload.id,
|
||||
"Notification should be for the download we adopted");
|
||||
runTests();
|
||||
});
|
||||
},
|
||||
function() {
|
||||
ok(false, "adoptDownload should not have rejected");
|
||||
runTests();
|
||||
});
|
||||
},
|
||||
|
||||
function dictionaryNotProvided() {
|
||||
checkInvalidResult(undefined, "InvalidDownload");
|
||||
},
|
||||
// Missing fields immediately result in rejection with InvalidDownload
|
||||
function missingStorageName() {
|
||||
checkInvalidResult({
|
||||
url: "",
|
||||
// no storageName
|
||||
storagePath: "relpath/filename.txt",
|
||||
contentType: "text/plain",
|
||||
startTime: arbitraryDate
|
||||
}, "InvalidDownload", "missing storage name");
|
||||
},
|
||||
function nullStorageName() {
|
||||
checkInvalidResult({
|
||||
url: "",
|
||||
storageName: null,
|
||||
storagePath: "relpath/filename.txt",
|
||||
contentType: "text/plain",
|
||||
startTime: arbitraryDate
|
||||
}, "InvalidDownload", "null storage name");
|
||||
},
|
||||
function missingStoragePath() {
|
||||
checkInvalidResult({
|
||||
url: "",
|
||||
storageName: blobStorageName,
|
||||
// no storagePath
|
||||
contentType: "text/plain",
|
||||
startTime: arbitraryDate
|
||||
}, "InvalidDownload", "missing storage path");
|
||||
},
|
||||
function nullStoragePath() {
|
||||
checkInvalidResult({
|
||||
url: "",
|
||||
storageName: blobStorageName,
|
||||
storagePath: null,
|
||||
contentType: "text/plain",
|
||||
startTime: arbitraryDate
|
||||
}, "InvalidDownload", "null storage path");
|
||||
},
|
||||
function missingContentType() {
|
||||
checkInvalidResult({
|
||||
url: "",
|
||||
storageName: "sdcard",
|
||||
storagePath: "relpath/filename.txt",
|
||||
// no contentType
|
||||
startTime: arbitraryDate
|
||||
}, "InvalidDownload", "missing content type");
|
||||
},
|
||||
function nullContentType() {
|
||||
checkInvalidResult({
|
||||
url: "",
|
||||
storageName: "sdcard",
|
||||
storagePath: "relpath/filename.txt",
|
||||
contentType: null,
|
||||
startTime: arbitraryDate
|
||||
}, "InvalidDownload", "null content type");
|
||||
},
|
||||
// Incorrect storage names are likewise immediately invalidated
|
||||
function invalidStorageName() {
|
||||
checkInvalidResult({
|
||||
url: "",
|
||||
storageName: "ALMOST CERTAINLY DOES NOT EXIST",
|
||||
storagePath: "relpath/filename.txt",
|
||||
contentType: "text/plain",
|
||||
startTime: arbitraryDate
|
||||
}, "InvalidDownload", "invalid storage name");
|
||||
},
|
||||
// The existence of the file is validated in the parent process
|
||||
function legitStorageInvalidPath() {
|
||||
checkInvalidResult({
|
||||
url: "",
|
||||
storageName: blobStorageName,
|
||||
storagePath: "ALMOST CERTAINLY DOES NOT EXIST",
|
||||
contentType: "text/plain",
|
||||
startTime: arbitraryDate
|
||||
}, "AdoptNoSuchFile", "invalid path");
|
||||
},
|
||||
function allDone() {
|
||||
// Just in case, make sure no other mochitest could mess with us after we've
|
||||
// finished.
|
||||
navigator.mozDownloadManager.ondownloadstart = null;
|
||||
runTests();
|
||||
}
|
||||
];
|
||||
|
||||
function runTests() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
if (test.name) {
|
||||
info('starting test: ' + test.name);
|
||||
}
|
||||
test();
|
||||
}
|
||||
runTests();
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Downloads certified test fake app",
|
||||
"description": "Test",
|
||||
"launch_path": "http://mochi.test:8888/tests/dom/downloads/tests/testapp_downloads_adopt_download.html",
|
||||
"type": "certified",
|
||||
"permissions": {
|
||||
"device-storage:sdcard":{ "access": "readcreate" },
|
||||
"downloads": {}
|
||||
}
|
||||
}
|
||||
@@ -484,6 +484,30 @@ EventStateManager::TryToFlushPendingNotificationsToIME()
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
IsMessageMouseUserActivity(EventMessage aMessage)
|
||||
{
|
||||
return aMessage == eMouseMove ||
|
||||
aMessage == eMouseUp ||
|
||||
aMessage == eMouseDown ||
|
||||
aMessage == eMouseDoubleClick ||
|
||||
aMessage == eMouseClick ||
|
||||
aMessage == eMouseActivate ||
|
||||
aMessage == eMouseLongTap;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsMessageGamepadUserActivity(EventMessage aMessage)
|
||||
{
|
||||
#ifndef MOZ_GAMEPAD
|
||||
return false;
|
||||
#else
|
||||
return aMessage == eGamepadButtonDown ||
|
||||
aMessage == eGamepadButtonUp ||
|
||||
aMessage == eGamepadAxisMove;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
@@ -515,12 +539,12 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
||||
if (aEvent->mFlags.mIsTrusted &&
|
||||
((mouseEvent && mouseEvent->IsReal() &&
|
||||
mouseEvent->mMessage != eMouseEnterIntoWidget &&
|
||||
mouseEvent->mMessage != eMouseExitFromWidget) ||
|
||||
IsMessageMouseUserActivity(mouseEvent->mMessage)) ||
|
||||
aEvent->mClass == eWheelEventClass ||
|
||||
aEvent->mClass == ePointerEventClass ||
|
||||
aEvent->mClass == eTouchEventClass ||
|
||||
aEvent->mClass == eKeyboardEventClass)) {
|
||||
aEvent->mClass == eKeyboardEventClass ||
|
||||
IsMessageGamepadUserActivity(aEvent->mMessage))) {
|
||||
if (gMouseOrKeyboardEventCounter == 0) {
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
mozilla::services::GetObserverService();
|
||||
@@ -1992,6 +2016,7 @@ EventStateManager::GetContentViewer(nsIContentViewer** aCv)
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> focusedWindow;
|
||||
fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
|
||||
if (!focusedWindow) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> ourWindow = do_QueryInterface(focusedWindow);
|
||||
if(!ourWindow) return NS_ERROR_FAILURE;
|
||||
@@ -2577,6 +2602,8 @@ EventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
||||
case WidgetWheelEvent::SCROLL_DEFAULT:
|
||||
if (isDeltaModePixel) {
|
||||
mode = nsIScrollableFrame::NORMAL;
|
||||
} else if (aEvent->mFlags.mHandledByAPZ) {
|
||||
mode = nsIScrollableFrame::SMOOTH_MSD;
|
||||
} else {
|
||||
mode = nsIScrollableFrame::SMOOTH;
|
||||
}
|
||||
|
||||
@@ -958,7 +958,7 @@ IMEStateManager::SetInputContextForChildProcess(
|
||||
GetActionFocusChangeName(aAction.mFocusChange),
|
||||
sPresContext, sActiveTabParent.get()));
|
||||
|
||||
if (NS_WARN_IF(aTabParent != sActiveTabParent)) {
|
||||
if (aTabParent != sActiveTabParent) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Error,
|
||||
("ISM: IMEStateManager::SetInputContextForChildProcess(), FAILED, "
|
||||
"because non-focused tab parent tries to set input context"));
|
||||
@@ -1473,8 +1473,19 @@ IMEStateManager::NotifyIME(const IMENotification& aNotification,
|
||||
return composition ?
|
||||
composition->RequestToCommit(aWidget, true) : NS_OK;
|
||||
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
|
||||
return composition && !isSynthesizedForTests ?
|
||||
aWidget->NotifyIME(aNotification) : NS_OK;
|
||||
if (!aOriginIsRemote && (!composition || isSynthesizedForTests)) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("ISM: IMEStateManager::NotifyIME(), FAILED, received content "
|
||||
"change notification from this process but there is no compostion"));
|
||||
return NS_OK;
|
||||
}
|
||||
if (!sRemoteHasFocus && aOriginIsRemote) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("ISM: IMEStateManager::NotifyIME(), received content change "
|
||||
"notification from the remote but it's already lost focus"));
|
||||
return NS_OK;
|
||||
}
|
||||
return aWidget->NotifyIME(aNotification);
|
||||
default:
|
||||
MOZ_CRASH("Unsupported notification");
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user