1 <html> 2 <head> 3 <script> 4 5 function log(message) 6 { 7 document.body.innerHTML += message + "<br>"; 8 } 9 10 function terminateTest() 11 { 12 if (window.layoutTestController) 13 layoutTestController.notifyDone(); 14 } 15 16 function logAndTerminateTest(message, error) 17 { 18 log(message + ": " + error.message); 19 terminateTest(); 20 } 21 22 function cleanup(db) 23 { 24 db.transaction(function(tx) { 25 tx.executeSql("DROP TABLE IF EXISTS Test;"); 26 tx.executeSql("DROP INDEX IF EXISTS TestIndex;"); 27 tx.executeSql("DROP VIEW IF EXISTS TestView;"); 28 tx.executeSql("DROP TRIGGER IF EXISTS TestTrigger;"); 29 }, function(error) { logAndTerminateTest("Cleanup failed", error); }); 30 } 31 32 function statementSuccessCallback(statementType) 33 { 34 log(statementType + " statement succeeded."); 35 } 36 37 function statementErrorCallback(statementType, error) 38 { 39 log(statementType + " statement failed: " + error.message); 40 return false; 41 } 42 43 function executeStatement(tx, statement, operation) 44 { 45 tx.executeSql(statement, [], 46 function(result) { statementSuccessCallback(operation); }, 47 function(tx, error) { return statementErrorCallback(operation, error); }); 48 } 49 50 function createTableCallback(tx) 51 { 52 executeStatement(tx, "CREATE TABLE Test (Foo int);", "SQLITE_CREATE_TABLE"); 53 } 54 55 function createStatementsCallback(tx) 56 { 57 executeStatement(tx, "CREATE INDEX TestIndex ON Test (Foo);", "SQLITE_CREATE_INDEX"); 58 59 // Even though the following query should trigger a SQLITE_CREATE_TEMP_INDEX operation 60 // (according to http://www.sqlite.org/tempfiles.html), it doesn't, and I'm not aware 61 // of any other way to trigger this operation. So we'll skip it for now. 62 //executeStatement(tx, "SELECT * FROM Test WHERE Foo IN (1, 2, 3);", "SQLITE_CREATE_TEMP_INDEX"); 63 64 executeStatement(tx, "CREATE TEMP TABLE TestTempTable (Foo int);", "SQLITE_CREATE_TEMP_TABLE"); 65 executeStatement(tx, "CREATE TEMP TRIGGER TestTempTrigger INSERT ON Test BEGIN SELECT COUNT(*) FROM Test; END;", "SQLITE_CREATE_TEMP_TRIGGER"); 66 executeStatement(tx, "CREATE TEMP VIEW TestTempView AS SELECT COUNT(*) FROM Test;", "SQLITE_CREATE_TEMP_VIEW"); 67 executeStatement(tx, "CREATE TRIGGER TestTrigger INSERT ON Test BEGIN SELECT COUNT(*) FROM Test; END;", "SQLITE_CREATE_TRIGGER"); 68 executeStatement(tx, "CREATE VIEW TestView AS SELECT COUNT(*) FROM Test;", "SQLITE_CREATE_VIEW"); 69 executeStatement(tx, "CREATE VIRTUAL TABLE TestVirtualTable USING MissingModule;", "SQLITE_CREATE_VTABLE"); 70 } 71 72 function otherStatementsCallback(tx) 73 { 74 executeStatement(tx, "SELECT COUNT(*) FROM Test;", "SQLITE_READ"); 75 executeStatement(tx, "SELECT COUNT(*) FROM Test;", "SQLITE_SELECT"); 76 executeStatement(tx, "DELETE FROM Test;", "SQLITE_DELETE"); 77 executeStatement(tx, "INSERT INTO Test VALUES (1);", "SQLITE_INSERT"); 78 executeStatement(tx, "UPDATE Test SET Foo = 2 WHERE Foo = 1;", "SQLITE_UPDATE"); 79 executeStatement(tx, "PRAGMA cache_size;", "SQLITE_PRAGMA"); 80 81 executeStatement(tx, "ALTER TABLE Test RENAME TO TestTable;", "SQLITE_ALTER_TABLE"); 82 // Rename the table back to its original name 83 executeStatement(tx, "ALTER TABLE TestTable RENAME To Test;", "SQLITE_ALTER_TABLE"); 84 85 executeStatement(tx, "BEGIN TRANSACTION;", "SQLITE_TRANSACTION"); 86 executeStatement(tx, "ATTACH main AS TestMain;", "SQLITE_ATTACH"); 87 executeStatement(tx, "DETACH TestMain;", "SQLITE_DETACH"); 88 executeStatement(tx, "REINDEX;", "SQLITE_REINDEX"); 89 executeStatement(tx, "ANALYZE;", "SQLITE_ANALYZE"); 90 91 // SQLITE_FUNCTION: allowed write mode 92 // There is no SQL/Javascript API to add user-defined functions to SQLite, 93 // so we cannot test this operation 94 } 95 96 function dropStatementsCallback(tx) 97 { 98 executeStatement(tx, "DROP INDEX TestIndex;", "SQLITE_DROP_INDEX"); 99 100 // SQLITE_DROP_TEMP_INDEX: allowed in write mode 101 // Not sure how to test this: temp indexes are automatically dropped when 102 // the database is closed, but HTML5 doesn't specify a closeDatabase() call. 103 104 executeStatement(tx, "DROP TABLE TestTempTable;", "SQLITE_DROP_TEMP_TABLE"); 105 executeStatement(tx, "DROP TRIGGER TestTempTrigger;", "SQLITE_DROP_TEMP_TRIGGER"); 106 executeStatement(tx, "DROP VIEW TestTempView;", "SQLITE_DROP_TEMP_VIEW"); 107 executeStatement(tx, "DROP TRIGGER TestTrigger;", "SQLITE_DROP_TRIGGER"); 108 executeStatement(tx, "DROP VIEW TestView;", "SQLITE_DROP_VIEW"); 109 110 // SQLITE_DROP_VTABLE: allowed in write mode 111 // Not sure how to test this: we cannot create a virtual table because we do not 112 // have SQL/Javascript APIs to register a module that implements a virtual table. 113 // Therefore, trying to drop a virtual table will always fail (no such table) 114 // before even getting to the authorizer. 115 116 executeStatement(tx, "DROP TABLE Test;", "SQLITE_DROP_TABLE"); 117 } 118 119 function testReadWriteMode(db) 120 { 121 db.transaction(function(tx) { 122 createTableCallback(tx); 123 createStatementsCallback(tx); 124 otherStatementsCallback(tx); 125 dropStatementsCallback(tx); 126 }, 127 function(error) { logAndTerminateTest("Write transaction failed", error); }, 128 function() { log("Write transaction succeeded."); }); 129 } 130 131 function testReadOnlyMode(db) 132 { 133 // Test the 'CREATE TABLE' operation; it should be disallowed 134 db.readTransaction(createTableCallback, 135 function(error) { logAndTerminateTest("Read 'CREATE TABLE' transaction failed", error); }); 136 137 // In order to test all other 'CREATE' operations, we must create the table first 138 db.transaction(createTableCallback, 139 function(error) { logAndTerminateTest("Write 'CREATE TABLE' transaction failed", error); }); 140 db.readTransaction(createStatementsCallback, 141 function(error) { logAndTerminateTest("Read 'CREATE' transaction failed", error); }); 142 143 // In order to test the 'DROP' and 'other' operations, we need to first create the respective entities 144 db.transaction(createStatementsCallback, 145 function(error) { logAndTerminateTest("Write 'CREATE' transaction failed", error); }); 146 db.readTransaction(otherStatementsCallback, 147 function(error) { logAndTerminateTest("Read 'other' transaction failed", error); }); 148 149 // Hack: insert an empty write transaction to guaratee that these transactions are executed sequentially 150 db.transaction(function(tx) { }); 151 db.readTransaction(dropStatementsCallback, 152 function(error) { logAndTerminateTest("Read 'DROP' transaction failed", error); }, 153 function() { log("Read transactions succeeded."); terminateTest(); }); 154 } 155 156 function runTest() 157 { 158 if (window.layoutTestController) { 159 layoutTestController.dumpAsText(); 160 layoutTestController.waitUntilDone(); 161 } 162 163 try { 164 var db = openDatabase("AuthorizerTest", "1.0", "Tests the database authorizer.", 32768); 165 cleanup(db); 166 testReadWriteMode(db); 167 testReadOnlyMode(db); 168 } catch(err) {} 169 } 170 </script> 171 </head> 172 <body onload="runTest();"> 173 This test tests the database authorizer.<br> 174 </body> 175 </html> 176