diff --git a/browser/components/places/content/bookmarkProperties.js b/browser/components/places/content/bookmarkProperties.js index a2aed77d0ae..a1a457ee112 100755 --- a/browser/components/places/content/bookmarkProperties.js +++ b/browser/components/places/content/bookmarkProperties.js @@ -736,7 +736,7 @@ var BookmarkPropertiesPanel = { _getDescriptionAnnotation: function BPP__getDescriptionAnnotation(aDescription) { var anno = { name: DESCRIPTION_ANNO, - type: Ci.mozIStorageValueArray.VALUE_TYPE_TEXT, + type: Ci.nsIAnnotationService.TYPE_STRING, flags: 0, value: aDescription, expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; @@ -762,7 +762,7 @@ var BookmarkPropertiesPanel = { _getLoadInSidebarAnnotation: function BPP__getLoadInSidebarAnnotation(aLoadInSidebar) { var anno = { name: LOAD_IN_SIDEBAR_ANNO, - type: Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER, + type: Ci.nsIAnnotationsService.TYPE_INT32, flags: 0, value: aLoadInSidebar, expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js index 9a5fd431300..5b58fa10e81 100755 --- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -2068,7 +2068,7 @@ PlacesSetLoadInSidebarTransaction.prototype = { __proto__: PlacesBaseTransaction.prototype, _anno: { name: LOAD_IN_SIDEBAR_ANNO, - type: Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER, + type: Ci.nsIAnnotationService.TYPE_INT32, value: 1, flags: 0, expires: Ci.nsIAnnotationService.EXPIRE_NEVER diff --git a/browser/components/places/content/utils.js b/browser/components/places/content/utils.js index 5b33de8c2b6..1301a57a213 100644 --- a/browser/components/places/content/utils.js +++ b/browser/components/places/content/utils.js @@ -1111,24 +1111,28 @@ var PlacesUtils = { */ getAnnotationsForURI: function PU_getAnnotationsForURI(aURI) { var annosvc = this.annotations; - var sv = Ci.mozIStorageValueArray; var annos = [], val = null; var annoNames = annosvc.getPageAnnotationNames(aURI, {}); for (var i = 0; i < annoNames.length; i++) { var flags = {}, exp = {}, mimeType = {}, storageType = {}; annosvc.getAnnotationInfo(aURI, annoNames[i], flags, exp, mimeType, storageType); switch (storageType.value) { - case sv.VALUE_TYPE_INTEGER: + case annosvc.TYPE_INT32: + val = annosvc.getAnnotationInt32(aURI, annoNames[i]); + break; + case annosvc.TYPE_INT64: val = annosvc.getAnnotationInt64(aURI, annoNames[i]); break; - case sv.VALUE_TYPE_FLOAT: + case annosvc.TYPE_DOUBLE: val = annosvc.getAnnotationDouble(aURI, annoNames[i]); break; - case sv.VALUE_TYPE_TEXT: + case annosvc.TYPE_STRING: val = annosvc.getAnnotationString(aURI, annoNames[i]); break; - case sv.VALUE_TYPE_BLOB: - val = annosvc.getAnnotationBinary(aURI, annoNames[i]); + case annosvc.TYPE_BINARY: + var data = {}, length = {}, mimeType = {}; + annosvc.getAnnotationBinary(aURI, annoNames[i], data, length, mimeType); + val = data.value; break; } annos.push({name: annoNames[i], @@ -1152,25 +1156,28 @@ var PlacesUtils = { */ setAnnotationsForURI: function PU_setAnnotationsForURI(aURI, aAnnos) { var annosvc = this.annotations; - var sv = Ci["mozIStorageValueArray"]; aAnnos.forEach(function(anno) { switch (anno.type) { - case sv.VALUE_TYPE_INTEGER: + case annosvc.TYPE_INT32: + annosvc.setAnnotationInt32(aURI, anno.name, anno.value, + anno.flags, anno.expires); + break; + case annosvc.TYPE_INT64: annosvc.setAnnotationInt64(aURI, anno.name, anno.value, - anno.flags, anno.expires); + anno.flags, anno.expires); break; - case sv.VALUE_TYPE_FLOAT: + case annosvc.TYPE_DOUBLE: annosvc.setAnnotationDouble(aURI, anno.name, anno.value, - anno.flags, anno.expires); + anno.flags, anno.expires); break; - case sv.VALUE_TYPE_TEXT: + case annosvc.TYPE_STRING: annosvc.setAnnotationString(aURI, anno.name, anno.value, - anno.flags, anno.expires); + anno.flags, anno.expires); break; - case sv.VALUE_TYPE_BLOB: + case annosvc.TYPE_BINARY: annosvc.setAnnotationBinary(aURI, anno.name, anno.value, - anno.value.length, anno.mimeType, - anno.flags, anno.expires); + anno.value.length, anno.mimeType, + anno.flags, anno.expires); break; } }); diff --git a/toolkit/components/places/public/nsIAnnotationService.idl b/toolkit/components/places/public/nsIAnnotationService.idl index 7fd7e60a334..bf315e4c425 100644 --- a/toolkit/components/places/public/nsIAnnotationService.idl +++ b/toolkit/components/places/public/nsIAnnotationService.idl @@ -101,6 +101,13 @@ interface nsIAnnotationService : nsISupports // For small, user-entered data like notes that should never expire. const PRInt32 EXPIRE_NEVER = 4; + // type constants + const PRInt32 TYPE_INT32 = 1; + const PRInt32 TYPE_DOUBLE = 2; + const PRInt32 TYPE_STRING = 3; + const PRInt32 TYPE_BINARY = 4; + const PRInt32 TYPE_INT64 = 5; + /** * Sets an annotation, overwriting any previous annotation with the same * URL/name. IT IS YOUR JOB TO NAMESPACE YOUR ANNOTATION NAMES. diff --git a/toolkit/components/places/src/nsAnnotationService.cpp b/toolkit/components/places/src/nsAnnotationService.cpp index a2048777c5e..d4763e45d45 100644 --- a/toolkit/components/places/src/nsAnnotationService.cpp +++ b/toolkit/components/places/src/nsAnnotationService.cpp @@ -56,6 +56,7 @@ const PRInt32 nsAnnotationService::kAnnoIndex_MimeType = 3; const PRInt32 nsAnnotationService::kAnnoIndex_Content = 4; const PRInt32 nsAnnotationService::kAnnoIndex_Flags = 5; const PRInt32 nsAnnotationService::kAnnoIndex_Expiration = 6; +const PRInt32 nsAnnotationService::kAnnoIndex_Type = 7; nsAnnotationService* nsAnnotationService::gAnnotationService; @@ -103,7 +104,7 @@ nsAnnotationService::Init() // mDBSetAnnotation rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "UPDATE moz_annos " - "SET mime_type = ?4, content = ?5, flags = ?6, expiration = ?7 " + "SET mime_type = ?4, content = ?5, flags = ?6, expiration = ?7, type = ?8 " "WHERE id = ?1"), getter_AddRefs(mDBSetAnnotation)); NS_ENSURE_SUCCESS(rv, rv); @@ -127,7 +128,8 @@ nsAnnotationService::Init() // mDBGetAnnotationFromURI rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( - "SELECT a.id, a.place_id, ?2, a.mime_type, a.content, a.flags, a.expiration " + "SELECT a.id, a.place_id, ?2, a.mime_type, a.content, a.flags, " + "a.expiration, a.type " "FROM moz_places h JOIN moz_annos a ON h.id = a.place_id " "WHERE h.url = ?1 AND a.anno_attribute_id = " "(SELECT id FROM moz_anno_attributes WHERE name = ?2)"), @@ -150,8 +152,8 @@ nsAnnotationService::Init() // Note: kAnnoIndex_Name here is a name ID and not a string like the getters rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "INSERT INTO moz_annos " - "(place_id, anno_attribute_id, mime_type, content, flags, expiration) " - "VALUES (?2, ?3, ?4, ?5, ?6, ?7)"), + "(place_id, anno_attribute_id, mime_type, content, flags, expiration, type) " + "VALUES (?2, ?3, ?4, ?5, ?6, ?7, ?8)"), getter_AddRefs(mDBAddAnnotation)); NS_ENSURE_SUCCESS(rv, rv); @@ -226,7 +228,8 @@ nsAnnotationService::SetAnnotationString(nsIURI* aURI, { mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, &statement); + nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsIAnnotationService::TYPE_STRING, &statement); NS_ENSURE_SUCCESS(rv, rv); mozStorageStatementScoper statementResetter(statement); @@ -258,7 +261,9 @@ nsAnnotationService::SetAnnotationInt32(nsIURI* aURI, { mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, &statement); + nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsIAnnotationService::TYPE_INT32, + &statement); NS_ENSURE_SUCCESS(rv, rv); mozStorageStatementScoper statementResetter(statement); @@ -290,7 +295,9 @@ nsAnnotationService::SetAnnotationInt64(nsIURI* aURI, { mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, &statement); + nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsIAnnotationService::TYPE_INT64, + &statement); NS_ENSURE_SUCCESS(rv, rv); mozStorageStatementScoper statementResetter(statement); @@ -322,7 +329,9 @@ nsAnnotationService::SetAnnotationDouble(nsIURI* aURI, { mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, &statement); + nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsIAnnotationService::TYPE_DOUBLE, + &statement); NS_ENSURE_SUCCESS(rv, rv); mozStorageStatementScoper statementResetter(statement); @@ -359,7 +368,9 @@ nsAnnotationService::SetAnnotationBinary(nsIURI* aURI, mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, &statement); + nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsIAnnotationService::TYPE_BINARY, + &statement); NS_ENSURE_SUCCESS(rv, rv); mozStorageStatementScoper statementResetter(statement); @@ -391,6 +402,8 @@ nsAnnotationService::GetAnnotationString(nsIURI* aURI, nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; + PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); + NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_STRING, NS_ERROR_INVALID_ARG); rv = mDBGetAnnotationFromURI->GetString(kAnnoIndex_Content, _retval); mDBGetAnnotationFromURI->Reset(); return rv; @@ -407,6 +420,8 @@ nsAnnotationService::GetAnnotationInt32(nsIURI* aURI, nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; + PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); + NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_INT32, NS_ERROR_INVALID_ARG); *_retval = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Content); mDBGetAnnotationFromURI->Reset(); return NS_OK; @@ -423,6 +438,8 @@ nsAnnotationService::GetAnnotationInt64(nsIURI* aURI, nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; + PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); + NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_INT64, NS_ERROR_INVALID_ARG); *_retval = mDBGetAnnotationFromURI->AsInt64(kAnnoIndex_Content); mDBGetAnnotationFromURI->Reset(); return NS_OK; @@ -439,6 +456,8 @@ nsAnnotationService::GetAnnotationDouble(nsIURI* aURI, nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; + PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); + NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_DOUBLE, NS_ERROR_INVALID_ARG); *_retval = mDBGetAnnotationFromURI->AsDouble(kAnnoIndex_Content); mDBGetAnnotationFromURI->Reset(); return NS_OK; @@ -456,6 +475,8 @@ nsAnnotationService::GetAnnotationBinary(nsIURI* aURI, nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; + PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); + NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_BINARY, NS_ERROR_INVALID_ARG); rv = mDBGetAnnotationFromURI->GetBlob(kAnnoIndex_Content, aDataLen, aData); if (NS_FAILED(rv)) { mDBGetAnnotationFromURI->Reset(); @@ -485,7 +506,14 @@ nsAnnotationService::GetAnnotationInfo(nsIURI* aURI, *aExpiration = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Expiration); rv = mDBGetAnnotationFromURI->GetUTF8String(kAnnoIndex_MimeType, aMimeType); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBGetAnnotationFromURI->GetTypeOfIndex(kAnnoIndex_Content, aStorageType); + PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); + if (type == 0) { + // For annotations created before explicit typing, + // we can't determine type, just return as string type. + *aStorageType = nsIAnnotationService::TYPE_STRING; + } else { + *aStorageType = type; + } return rv; } @@ -954,6 +982,7 @@ nsresult nsAnnotationService::StartSetAnnotation(nsIURI* aURI, const nsACString& aName, PRInt32 aFlags, PRInt32 aExpiration, + PRInt32 aType, mozIStorageStatement** aStatement) { nsresult rv; @@ -1010,6 +1039,8 @@ nsAnnotationService::StartSetAnnotation(nsIURI* aURI, NS_ENSURE_SUCCESS(rv, rv); rv = (*aStatement)->BindInt32Parameter(kAnnoIndex_Expiration, aExpiration); NS_ENSURE_SUCCESS(rv, rv); + rv = (*aStatement)->BindInt32Parameter(kAnnoIndex_Type, aType); + NS_ENSURE_SUCCESS(rv, rv); // on success, leave the statement open, the caller will set the value // and MIME type and execute the statement diff --git a/toolkit/components/places/src/nsAnnotationService.h b/toolkit/components/places/src/nsAnnotationService.h index 4bd01fee4be..1c04dda625b 100644 --- a/toolkit/components/places/src/nsAnnotationService.h +++ b/toolkit/components/places/src/nsAnnotationService.h @@ -107,6 +107,7 @@ protected: static const int kAnnoIndex_Content; static const int kAnnoIndex_Flags; static const int kAnnoIndex_Expiration; + static const int kAnnoIndex_Type; nsresult HasAnnotationInternal(PRInt64 aURLID, const nsACString& aName, PRBool* hasAnnotation, PRInt64* annotationID); @@ -115,7 +116,7 @@ protected: nsresult StartSetAnnotation(nsIURI* aURI, const nsACString& aName, PRInt32 aFlags, PRInt32 aExpiration, - mozIStorageStatement** aStatement); + PRInt32 aType, mozIStorageStatement** aStatement); void CallSetObservers(nsIURI* aURI, const nsACString& aName); static nsresult MigrateFromAlpha1(mozIStorageConnection* aDBConn); diff --git a/toolkit/components/places/src/nsNavHistory.cpp b/toolkit/components/places/src/nsNavHistory.cpp index e8bc3e26052..bfca8e96ccc 100644 --- a/toolkit/components/places/src/nsNavHistory.cpp +++ b/toolkit/components/places/src/nsNavHistory.cpp @@ -383,7 +383,7 @@ nsNavHistory::Init() // -#define PLACES_SCHEMA_VERSION 2 +#define PLACES_SCHEMA_VERSION 3 nsresult nsNavHistory::InitDB(PRBool *aDoImport) @@ -441,7 +441,7 @@ nsNavHistory::InitDB(PRBool *aDoImport) NS_ENSURE_SUCCESS(rv, rv); // Get the places schema version, which we store in the user_version PRAGMA - PRInt32 schemaVersion; + PRInt32 DBSchemaVersion; { nsCOMPtr statement; rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("PRAGMA user_version"), @@ -452,25 +452,54 @@ nsNavHistory::InitDB(PRBool *aDoImport) rv = statement->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(hasResult, NS_ERROR_FAILURE); - schemaVersion = statement->AsInt32(0); + DBSchemaVersion = statement->AsInt32(0); } - if (PLACES_SCHEMA_VERSION != schemaVersion) { - // NOTE: We don't support downgrading back to History-only. If you want to go from - // newer schema version back to V0, you'll need to blow away your sqlite file. - // Subsequent up/downgrades will have backwards and forward migration code. + if (PLACES_SCHEMA_VERSION != DBSchemaVersion) { + // Migration How-to: // - // Migrating from schema V0 - V1 to V2. - if (schemaVersion < 2) { - // perform upgrade - rv = ForceMigrateBookmarksDB(mDBConn); - NS_ENSURE_SUCCESS(rv, rv); + // 1. increment PLACES_SCHEMA_VERSION. + // 2. implement a method that performs up/sidegrade to your version + // from the current version. + // + // NOTE: We don't support downgrading back to History-only Places. + // If you want to go from newer schema version back to V0, you'll need to + // blow away your sqlite file. Subsequent up/downgrades have backwards and + // forward migration code. + // + // XXX Backup places.sqlite to places-{version}.sqlite when doing db migration? + + if (DBSchemaVersion < PLACES_SCHEMA_VERSION) { + // Upgrading + + // Migrating from schema V0/1 to V2. + if (DBSchemaVersion < 2) { + rv = ForceMigrateBookmarksDB(mDBConn); + NS_ENSURE_SUCCESS(rv, rv); + } + + if (DBSchemaVersion < 3) { + rv = MigrateV3Up(mDBConn); + NS_ENSURE_SUCCESS(rv, rv); + } + + // XXX Upgrades V3 must add migration code here. + } else { - // perform downgrade - // XXX Migrations from V>=3 must add downgrade migration code here, - // replacing this! - rv = ForceMigrateBookmarksDB(mDBConn); - NS_ENSURE_SUCCESS(rv, rv); + // Downgrading + + // XXX Need to prompt user or otherwise notify of + // potential dataloss when downgrading. + + // XXX Downgrades from >V2 must add migration code here. + + // V3: No backwards incompatible changes. + + if (DBSchemaVersion > 2) { + // perform downgrade to v2 + rv = ForceMigrateBookmarksDB(mDBConn); + NS_ENSURE_SUCCESS(rv, rv); + } } // update schema version in the db @@ -767,6 +796,20 @@ nsNavHistory::ForceMigrateBookmarksDB(mozIStorageConnection* aDBConn) return rv; } +// nsNavHistory::MigrateV3Up +nsresult +nsNavHistory::MigrateV3Up(mozIStorageConnection* aDBConn) +{ + // add type column to moz_annos + nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "ALTER TABLE moz_annos ADD type INTEGER DEFAULT 0")); + NS_ENSURE_SUCCESS(rv, rv); + + // call annosvc::InitTables + rv = nsNavBookmarks::InitTables(aDBConn); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; +} #ifdef IN_MEMORY_LINKS // nsNavHistory::InitMemDB diff --git a/toolkit/components/places/src/nsNavHistory.h b/toolkit/components/places/src/nsNavHistory.h index ed766620133..4b2664f2dd9 100644 --- a/toolkit/components/places/src/nsNavHistory.h +++ b/toolkit/components/places/src/nsNavHistory.h @@ -364,6 +364,7 @@ protected: nsresult InitDB(PRBool *aDoImport); nsresult InitStatements(); nsresult ForceMigrateBookmarksDB(mozIStorageConnection *aDBConn); + nsresult MigrateV3Up(mozIStorageConnection *aDBConn); #ifdef IN_MEMORY_LINKS // this is the cache DB in memory used for storing visited URLs diff --git a/toolkit/components/places/tests/unit/test_annotations.js b/toolkit/components/places/tests/unit/test_annotations.js index 8750bec731a..8275ff03711 100644 --- a/toolkit/components/places/tests/unit/test_annotations.js +++ b/toolkit/components/places/tests/unit/test_annotations.js @@ -58,14 +58,14 @@ function run_test() { var testAnnoName = "moz-test-places/annotations"; var testAnnoVal = "test"; - // create new annotation + // create new string annotation try { annosvc.setAnnotationString(testURI, testAnnoName, testAnnoVal, 0, 0); } catch(ex) { do_throw("unable to add annotation"); } - // get annotation + // get string annotation var storedAnnoVal = annosvc.getAnnotationString(testURI, testAnnoName); do_check_eq(testAnnoVal, storedAnnoVal); @@ -81,7 +81,7 @@ function run_test() { do_check_eq(flags.value, 0); do_check_eq(exp.value, 0); do_check_eq(mimeType.value, null); - do_check_eq(storageType.value, Ci.mozIStorageValueArray.VALUE_TYPE_TEXT); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_STRING); // get annotation names for a uri var annoNames = annosvc.getPageAnnotationNames(testURI, {}); @@ -95,4 +95,88 @@ function run_test() { var newAnnoNames = annosvc.getPageAnnotationNames(newURI, {}); do_check_eq(oldAnnoNames.length, newAnnoNames.length); */ + + // test int32 anno type + var int32Key = testAnnoName + "/types/Int32"; + var int32Val = 23; + annosvc.setAnnotationInt32(testURI, int32Key, int32Val, 0, 0); + var flags = {}, exp = {}, mimeType = {}, storageType = {}; + annosvc.getAnnotationInfo(testURI, int32Key, flags, exp, mimeType, storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, null); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_INT32); + var storedVal = annosvc.getAnnotationInt32(testURI, int32Key); + do_check_eq(int32Val, storedVal); + do_check_eq(typeof storedVal, "number"); + + // test int64 anno type + var int64Key = testAnnoName + "/types/Int64"; + var int64Val = 4294967296; + annosvc.setAnnotationInt64(testURI, int64Key, int64Val, 0, 0); + var flags = {}, exp = {}, mimeType = {}, storageType = {}; + annosvc.getAnnotationInfo(testURI, int64Key, flags, exp, mimeType, storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, null); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_INT64); + var storedVal = annosvc.getAnnotationInt64(testURI, int64Key); + do_check_eq(int64Val, storedVal); + do_check_eq(typeof storedVal, "number"); + + // test double anno type + var doubleKey = testAnnoName + "/types/Double"; + var doubleVal = 0.000002342; + annosvc.setAnnotationDouble(testURI, doubleKey, doubleVal, 0, 0); + var flags = {}, exp = {}, mimeType = {}, storageType = {}; + annosvc.getAnnotationInfo(testURI, doubleKey, flags, exp, mimeType, storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, null); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_DOUBLE); + var storedVal = annosvc.getAnnotationDouble(testURI, doubleKey); + do_check_eq(doubleVal, storedVal); + do_check_true(Math.round(storedVal) != storedVal); + + // test binary anno type + var binaryKey = testAnnoName + "/types/Binary"; + var binaryVal = Array.prototype.map.call("splarg", function(x) { return x.charCodeAt(0); }); + annosvc.setAnnotationBinary(testURI, binaryKey, binaryVal, binaryVal.length, "text/plain", 0, 0); + var flags = {}, exp = {}, mimeType = {}, storageType = {}; + annosvc.getAnnotationInfo(testURI, binaryKey, flags, exp, mimeType, storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, "text/plain"); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_BINARY); + var data = {}, length = {}, mimeType = {}; + annosvc.getAnnotationBinary(testURI, binaryKey, data, length, mimeType); + do_check_eq(binaryVal.toString(), data.value.toString()); + do_check_eq(typeof data.value, "object"); + + // test that accessors throw for wrong types + try { + annosvc.getAnnotationString(testURI, int32Key); + do_throw("annotation string accessor didn't throw for a wrong type!"); + } catch(ex) {} + + try { + annosvc.getAnnotationInt32(testURI, int64Key); + do_throw("annotation int32 accessor didn't throw for a wrong type!"); + } catch(ex) {} + + try { + annosvc.getAnnotationInt64(testURI, int32Key); + do_throw("annotation int64 accessor didn't throw for a wrong type!"); + } catch(ex) {} + + try { + annosvc.getAnnotationDouble(testURI, int32Key); + do_throw("annotation double accessor didn't throw for a wrong type!"); + } catch(ex) {} + + try { + var data = {}, length = {}, mimeType = {}; + annosvc.getAnnotationBinary(testURI, int32Key, data, length, mimeType); + do_throw("annotation binary accessor didn't throw for a wrong type!"); + } catch(ex) {} }