test_file_put_deleted.html (5604B)
1 <!-- 2 Any copyright is dedicated to the Public Domain. 3 http://creativecommons.org/publicdomain/zero/1.0/ 4 --> 5 <html> 6 <head> 7 <title>Indexed Database Property Test</title> 8 9 <script src="/tests/SimpleTest/SimpleTest.js"></script> 10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 11 12 <script type="text/javascript"> 13 /** 14 * Test that a put of a file-backed Blob/File whose backing file has been 15 * deleted results in a failure of that put failure. 16 * 17 * In order to create a file-backed Blob and ensure that we actually try and 18 * copy its contents (rather than triggering a reference-count increment), we 19 * use two separate databases. This test is derived from 20 * test_file_cross_database_copying.html. 21 */ 22 function* testSteps() 23 { 24 const READ_WRITE = "readwrite"; 25 26 const databaseInfo = [ 27 { name: window.location.pathname + "1", source: true }, 28 { name: window.location.pathname + "2", source: false }, 29 ]; 30 31 const objectStoreName = "Blobs"; 32 33 const fileData = { key: 1, file: getRandomFile("random.bin", 10000) }; 34 35 SpecialPowers.pushPrefEnv({ set: [["dom.indexedDB.dataThreshold", -1]] }, 36 continueToNextStep); 37 yield undefined; 38 39 // Open both databases, put the File in the source. 40 let databases = []; 41 for (let info of databaseInfo) { 42 let request = indexedDB.open(info.name, 1); 43 request.onerror = errorHandler; 44 request.onupgradeneeded = grabEventAndContinueHandler; 45 request.onsuccess = grabEventAndContinueHandler; 46 let event = yield undefined; 47 48 is(event.type, "upgradeneeded", "Got correct event type"); 49 50 let db = event.target.result; 51 // We don't expect any errors yet for either database, but will later on. 52 db.onerror = errorHandler; 53 54 let objectStore = db.createObjectStore(objectStoreName, { }); 55 if (info.source) { 56 objectStore.add(fileData.file, fileData.key); 57 } 58 59 event = yield undefined; 60 61 is(event.type, "success", "Got correct event type"); 62 63 databases.push(db); 64 } 65 66 // Get a reference to the file-backed File. 67 let fileBackedFile; 68 for (let db of databases.slice(0, 1)) { 69 let request = db.transaction([objectStoreName]) 70 .objectStore(objectStoreName).get(fileData.key); 71 request.onsuccess = grabEventAndContinueHandler; 72 let event = yield undefined; 73 74 let result = event.target.result; 75 verifyBlob(result, fileData.file, 1); 76 yield undefined; 77 78 fileBackedFile = result; 79 } 80 81 // Delete the backing file... 82 let fileFullPath = getFilePath(fileBackedFile); 83 // (We want to chop off the profile root and the resulting path component 84 // must not start with a directory separator.) 85 let fileRelPath = 86 fileFullPath.substring(fileFullPath.search(/[/\\]storage[/\\](default|private)[/\\]/) + 1); 87 info("trying to delete: " + fileRelPath); 88 // by using the existing SpecialPowers mechanism to create files and clean 89 // them up. We clobber our existing content, then trigger deletion to 90 // clean up after it. 91 SpecialPowers.createFiles( 92 [{ name: fileRelPath, data: "" }], 93 grabEventAndContinueHandler, errorCallbackHandler); 94 yield undefined; 95 // This is async without a callback because it's intended for cleanup. 96 // Since IDB is PBackground, we can't depend on serial ordering, so we need 97 // to use another async action. 98 SpecialPowers.removeFiles(); 99 SpecialPowers.executeAfterFlushingMessageQueue(grabEventAndContinueHandler); 100 yield undefined; 101 // The file is now deleted! 102 103 // Try and put the file-backed Blob in the database, expect failure on the 104 // request and transaction. 105 info("attempt to store deleted file-backed blob"); // context for NS_WARN_IF 106 for (let i = 1; i < databases.length; i++) { 107 let db = databases[i]; 108 109 let trans = db.transaction([objectStoreName], READ_WRITE); 110 let objectStore = trans.objectStore(objectStoreName); 111 112 let request = objectStore.add(fileBackedFile, 2); 113 request.onsuccess = unexpectedSuccessHandler; 114 request.onerror = expectedErrorHandler("UnknownError"); 115 trans.onsuccess = unexpectedSuccessHandler; 116 trans.onerror = expectedErrorHandler("UnknownError"); 117 // the database will also throw an error. 118 db.onerror = expectedErrorHandler("UnknownError"); 119 yield undefined; 120 yield undefined; 121 yield undefined; 122 // the database shouldn't throw any more errors now. 123 db.onerror = errorHandler; 124 } 125 126 // Ensure there's nothing with that key in the target database. 127 info("now that the transaction failed, make sure our put got rolled back"); 128 for (let i = 1; i < databases.length; i++) { 129 let db = databases[i]; 130 131 let objectStore = db.transaction([objectStoreName], "readonly") 132 .objectStore(objectStoreName); 133 134 // Attempt to fetch the key to verify there's nothing in the DB rather 135 // than the value which could return undefined as a misleading error. 136 let request = objectStore.getKey(2); 137 request.onsuccess = grabEventAndContinueHandler; 138 request.onerror = errorHandler; 139 let event = yield undefined; 140 141 let result = event.target.result; 142 is(result, undefined, "no key found"); // (the get returns undefined) 143 } 144 145 finishTest(); 146 } 147 </script> 148 <script type="text/javascript" src="file.js"></script> 149 <script type="text/javascript" src="helpers.js"></script> 150 151 </head> 152 153 <body onload="runTest();"></body> 154 155 </html>