toolkit/components/places/nsAnnotationService.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "mozilla/ArrayUtils.h"
michael@0 7
michael@0 8 #include "nsAnnotationService.h"
michael@0 9 #include "nsNavHistory.h"
michael@0 10 #include "nsPlacesTables.h"
michael@0 11 #include "nsPlacesIndexes.h"
michael@0 12 #include "nsPlacesMacros.h"
michael@0 13 #include "Helpers.h"
michael@0 14
michael@0 15 #include "nsNetUtil.h"
michael@0 16 #include "nsIVariant.h"
michael@0 17 #include "nsString.h"
michael@0 18 #include "nsVariant.h"
michael@0 19 #include "mozilla/storage.h"
michael@0 20
michael@0 21 #include "GeckoProfiler.h"
michael@0 22
michael@0 23 #include "nsNetCID.h"
michael@0 24
michael@0 25 using namespace mozilla;
michael@0 26 using namespace mozilla::places;
michael@0 27
michael@0 28 #define ENSURE_ANNO_TYPE(_type, _statement) \
michael@0 29 PR_BEGIN_MACRO \
michael@0 30 int32_t type = _statement->AsInt32(kAnnoIndex_Type); \
michael@0 31 NS_ENSURE_TRUE(type == nsIAnnotationService::_type, NS_ERROR_INVALID_ARG); \
michael@0 32 PR_END_MACRO
michael@0 33
michael@0 34 #define NOTIFY_ANNOS_OBSERVERS(_notification) \
michael@0 35 PR_BEGIN_MACRO \
michael@0 36 for (int32_t i = 0; i < mObservers.Count(); i++) \
michael@0 37 mObservers[i]->_notification; \
michael@0 38 PR_END_MACRO
michael@0 39
michael@0 40 const int32_t nsAnnotationService::kAnnoIndex_ID = 0;
michael@0 41 const int32_t nsAnnotationService::kAnnoIndex_PageOrItem = 1;
michael@0 42 const int32_t nsAnnotationService::kAnnoIndex_NameID = 2;
michael@0 43 const int32_t nsAnnotationService::kAnnoIndex_Content = 3;
michael@0 44 const int32_t nsAnnotationService::kAnnoIndex_Flags = 4;
michael@0 45 const int32_t nsAnnotationService::kAnnoIndex_Expiration = 5;
michael@0 46 const int32_t nsAnnotationService::kAnnoIndex_Type = 6;
michael@0 47 const int32_t nsAnnotationService::kAnnoIndex_DateAdded = 7;
michael@0 48 const int32_t nsAnnotationService::kAnnoIndex_LastModified = 8;
michael@0 49
michael@0 50 namespace mozilla {
michael@0 51 namespace places {
michael@0 52
michael@0 53 ////////////////////////////////////////////////////////////////////////////////
michael@0 54 //// AnnotatedResult
michael@0 55
michael@0 56 AnnotatedResult::AnnotatedResult(const nsCString& aGUID,
michael@0 57 nsIURI* aURI,
michael@0 58 int64_t aItemId,
michael@0 59 const nsACString& aAnnotationName,
michael@0 60 nsIVariant* aAnnotationValue)
michael@0 61 : mGUID(aGUID)
michael@0 62 , mURI(aURI)
michael@0 63 , mItemId(aItemId)
michael@0 64 , mAnnotationName(aAnnotationName)
michael@0 65 , mAnnotationValue(aAnnotationValue)
michael@0 66 {
michael@0 67 }
michael@0 68
michael@0 69 NS_IMETHODIMP
michael@0 70 AnnotatedResult::GetGuid(nsACString& _guid)
michael@0 71 {
michael@0 72 _guid = mGUID;
michael@0 73 return NS_OK;
michael@0 74 }
michael@0 75
michael@0 76 NS_IMETHODIMP
michael@0 77 AnnotatedResult::GetUri(nsIURI** _uri)
michael@0 78 {
michael@0 79 NS_IF_ADDREF(*_uri = mURI);
michael@0 80 return NS_OK;
michael@0 81 }
michael@0 82
michael@0 83 NS_IMETHODIMP
michael@0 84 AnnotatedResult::GetItemId(int64_t* _itemId)
michael@0 85 {
michael@0 86 *_itemId = mItemId;
michael@0 87 return NS_OK;
michael@0 88 }
michael@0 89
michael@0 90 NS_IMETHODIMP
michael@0 91 AnnotatedResult::GetAnnotationName(nsACString& _annotationName)
michael@0 92 {
michael@0 93 _annotationName = mAnnotationName;
michael@0 94 return NS_OK;
michael@0 95 }
michael@0 96
michael@0 97 NS_IMETHODIMP
michael@0 98 AnnotatedResult::GetAnnotationValue(nsIVariant** _annotationValue)
michael@0 99 {
michael@0 100 NS_IF_ADDREF(*_annotationValue = mAnnotationValue);
michael@0 101 return NS_OK;
michael@0 102 }
michael@0 103
michael@0 104 NS_IMPL_ISUPPORTS(AnnotatedResult, mozIAnnotatedResult)
michael@0 105
michael@0 106 } // namespace places
michael@0 107 } // namespace mozilla
michael@0 108
michael@0 109 PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsAnnotationService, gAnnotationService)
michael@0 110
michael@0 111 NS_IMPL_ISUPPORTS(nsAnnotationService
michael@0 112 , nsIAnnotationService
michael@0 113 , nsIObserver
michael@0 114 , nsISupportsWeakReference
michael@0 115 )
michael@0 116
michael@0 117
michael@0 118 nsAnnotationService::nsAnnotationService()
michael@0 119 : mHasSessionAnnotations(false)
michael@0 120 {
michael@0 121 NS_ASSERTION(!gAnnotationService,
michael@0 122 "Attempting to create two instances of the service!");
michael@0 123 gAnnotationService = this;
michael@0 124 }
michael@0 125
michael@0 126
michael@0 127 nsAnnotationService::~nsAnnotationService()
michael@0 128 {
michael@0 129 NS_ASSERTION(gAnnotationService == this,
michael@0 130 "Deleting a non-singleton instance of the service");
michael@0 131 if (gAnnotationService == this)
michael@0 132 gAnnotationService = nullptr;
michael@0 133 }
michael@0 134
michael@0 135
michael@0 136 nsresult
michael@0 137 nsAnnotationService::Init()
michael@0 138 {
michael@0 139 mDB = Database::GetDatabase();
michael@0 140 NS_ENSURE_STATE(mDB);
michael@0 141
michael@0 142 nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
michael@0 143 if (obsSvc) {
michael@0 144 (void)obsSvc->AddObserver(this, TOPIC_PLACES_SHUTDOWN, true);
michael@0 145 }
michael@0 146
michael@0 147 return NS_OK;
michael@0 148 }
michael@0 149
michael@0 150 nsresult
michael@0 151 nsAnnotationService::SetAnnotationStringInternal(nsIURI* aURI,
michael@0 152 int64_t aItemId,
michael@0 153 const nsACString& aName,
michael@0 154 const nsAString& aValue,
michael@0 155 int32_t aFlags,
michael@0 156 uint16_t aExpiration)
michael@0 157 {
michael@0 158 mozStorageTransaction transaction(mDB->MainConn(), false);
michael@0 159 nsCOMPtr<mozIStorageStatement> statement;
michael@0 160 nsresult rv = StartSetAnnotation(aURI, aItemId, aName, aFlags, aExpiration,
michael@0 161 nsIAnnotationService::TYPE_STRING,
michael@0 162 statement);
michael@0 163 NS_ENSURE_SUCCESS(rv, rv);
michael@0 164 mozStorageStatementScoper scoper(statement);
michael@0 165
michael@0 166 rv = statement->BindStringByName(NS_LITERAL_CSTRING("content"), aValue);
michael@0 167 NS_ENSURE_SUCCESS(rv, rv);
michael@0 168
michael@0 169 rv = statement->Execute();
michael@0 170 NS_ENSURE_SUCCESS(rv, rv);
michael@0 171
michael@0 172 rv = transaction.Commit();
michael@0 173 NS_ENSURE_SUCCESS(rv, rv);
michael@0 174
michael@0 175 return NS_OK;
michael@0 176 }
michael@0 177
michael@0 178
michael@0 179 NS_IMETHODIMP
michael@0 180 nsAnnotationService::SetPageAnnotation(nsIURI* aURI,
michael@0 181 const nsACString& aName,
michael@0 182 nsIVariant* aValue,
michael@0 183 int32_t aFlags,
michael@0 184 uint16_t aExpiration)
michael@0 185 {
michael@0 186 NS_ENSURE_ARG(aURI);
michael@0 187 NS_ENSURE_ARG(aValue);
michael@0 188
michael@0 189 uint16_t dataType;
michael@0 190 nsresult rv = aValue->GetDataType(&dataType);
michael@0 191 NS_ENSURE_SUCCESS(rv, rv);
michael@0 192
michael@0 193 switch (dataType) {
michael@0 194 case nsIDataType::VTYPE_INT8:
michael@0 195 case nsIDataType::VTYPE_UINT8:
michael@0 196 case nsIDataType::VTYPE_INT16:
michael@0 197 case nsIDataType::VTYPE_UINT16:
michael@0 198 case nsIDataType::VTYPE_INT32:
michael@0 199 case nsIDataType::VTYPE_UINT32:
michael@0 200 case nsIDataType::VTYPE_BOOL: {
michael@0 201 int32_t valueInt;
michael@0 202 rv = aValue->GetAsInt32(&valueInt);
michael@0 203 if (NS_SUCCEEDED(rv)) {
michael@0 204 NS_ENSURE_SUCCESS(rv, rv);
michael@0 205 rv = SetPageAnnotationInt32(aURI, aName, valueInt, aFlags, aExpiration);
michael@0 206 NS_ENSURE_SUCCESS(rv, rv);
michael@0 207 return NS_OK;
michael@0 208 }
michael@0 209 // Fall through int64_t case otherwise.
michael@0 210 }
michael@0 211 case nsIDataType::VTYPE_INT64:
michael@0 212 case nsIDataType::VTYPE_UINT64: {
michael@0 213 int64_t valueLong;
michael@0 214 rv = aValue->GetAsInt64(&valueLong);
michael@0 215 if (NS_SUCCEEDED(rv)) {
michael@0 216 NS_ENSURE_SUCCESS(rv, rv);
michael@0 217 rv = SetPageAnnotationInt64(aURI, aName, valueLong, aFlags, aExpiration);
michael@0 218 NS_ENSURE_SUCCESS(rv, rv);
michael@0 219 return NS_OK;
michael@0 220 }
michael@0 221 // Fall through double case otherwise.
michael@0 222 }
michael@0 223 case nsIDataType::VTYPE_FLOAT:
michael@0 224 case nsIDataType::VTYPE_DOUBLE: {
michael@0 225 double valueDouble;
michael@0 226 rv = aValue->GetAsDouble(&valueDouble);
michael@0 227 NS_ENSURE_SUCCESS(rv, rv);
michael@0 228 rv = SetPageAnnotationDouble(aURI, aName, valueDouble, aFlags, aExpiration);
michael@0 229 NS_ENSURE_SUCCESS(rv, rv);
michael@0 230 return NS_OK;
michael@0 231 }
michael@0 232 case nsIDataType::VTYPE_CHAR:
michael@0 233 case nsIDataType::VTYPE_WCHAR:
michael@0 234 case nsIDataType::VTYPE_DOMSTRING:
michael@0 235 case nsIDataType::VTYPE_CHAR_STR:
michael@0 236 case nsIDataType::VTYPE_WCHAR_STR:
michael@0 237 case nsIDataType::VTYPE_STRING_SIZE_IS:
michael@0 238 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
michael@0 239 case nsIDataType::VTYPE_UTF8STRING:
michael@0 240 case nsIDataType::VTYPE_CSTRING:
michael@0 241 case nsIDataType::VTYPE_ASTRING: {
michael@0 242 nsAutoString stringValue;
michael@0 243 rv = aValue->GetAsAString(stringValue);
michael@0 244 NS_ENSURE_SUCCESS(rv, rv);
michael@0 245 rv = SetPageAnnotationString(aURI, aName, stringValue, aFlags, aExpiration);
michael@0 246 NS_ENSURE_SUCCESS(rv, rv);
michael@0 247 return NS_OK;
michael@0 248 }
michael@0 249 }
michael@0 250
michael@0 251 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 252 }
michael@0 253
michael@0 254
michael@0 255 NS_IMETHODIMP
michael@0 256 nsAnnotationService::SetItemAnnotation(int64_t aItemId,
michael@0 257 const nsACString& aName,
michael@0 258 nsIVariant* aValue,
michael@0 259 int32_t aFlags,
michael@0 260 uint16_t aExpiration)
michael@0 261 {
michael@0 262 PROFILER_LABEL("AnnotationService", "SetItemAnnotation");
michael@0 263 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 264 NS_ENSURE_ARG(aValue);
michael@0 265
michael@0 266 if (aExpiration == EXPIRE_WITH_HISTORY)
michael@0 267 return NS_ERROR_INVALID_ARG;
michael@0 268
michael@0 269 uint16_t dataType;
michael@0 270 nsresult rv = aValue->GetDataType(&dataType);
michael@0 271 NS_ENSURE_SUCCESS(rv, rv);
michael@0 272
michael@0 273 switch (dataType) {
michael@0 274 case nsIDataType::VTYPE_INT8:
michael@0 275 case nsIDataType::VTYPE_UINT8:
michael@0 276 case nsIDataType::VTYPE_INT16:
michael@0 277 case nsIDataType::VTYPE_UINT16:
michael@0 278 case nsIDataType::VTYPE_INT32:
michael@0 279 case nsIDataType::VTYPE_UINT32:
michael@0 280 case nsIDataType::VTYPE_BOOL: {
michael@0 281 int32_t valueInt;
michael@0 282 rv = aValue->GetAsInt32(&valueInt);
michael@0 283 if (NS_SUCCEEDED(rv)) {
michael@0 284 NS_ENSURE_SUCCESS(rv, rv);
michael@0 285 rv = SetItemAnnotationInt32(aItemId, aName, valueInt, aFlags, aExpiration);
michael@0 286 NS_ENSURE_SUCCESS(rv, rv);
michael@0 287 return NS_OK;
michael@0 288 }
michael@0 289 // Fall through int64_t case otherwise.
michael@0 290 }
michael@0 291 case nsIDataType::VTYPE_INT64:
michael@0 292 case nsIDataType::VTYPE_UINT64: {
michael@0 293 int64_t valueLong;
michael@0 294 rv = aValue->GetAsInt64(&valueLong);
michael@0 295 if (NS_SUCCEEDED(rv)) {
michael@0 296 NS_ENSURE_SUCCESS(rv, rv);
michael@0 297 rv = SetItemAnnotationInt64(aItemId, aName, valueLong, aFlags, aExpiration);
michael@0 298 NS_ENSURE_SUCCESS(rv, rv);
michael@0 299 return NS_OK;
michael@0 300 }
michael@0 301 // Fall through double case otherwise.
michael@0 302 }
michael@0 303 case nsIDataType::VTYPE_FLOAT:
michael@0 304 case nsIDataType::VTYPE_DOUBLE: {
michael@0 305 double valueDouble;
michael@0 306 rv = aValue->GetAsDouble(&valueDouble);
michael@0 307 NS_ENSURE_SUCCESS(rv, rv);
michael@0 308 rv = SetItemAnnotationDouble(aItemId, aName, valueDouble, aFlags, aExpiration);
michael@0 309 NS_ENSURE_SUCCESS(rv, rv);
michael@0 310 return NS_OK;
michael@0 311 }
michael@0 312 case nsIDataType::VTYPE_CHAR:
michael@0 313 case nsIDataType::VTYPE_WCHAR:
michael@0 314 case nsIDataType::VTYPE_DOMSTRING:
michael@0 315 case nsIDataType::VTYPE_CHAR_STR:
michael@0 316 case nsIDataType::VTYPE_WCHAR_STR:
michael@0 317 case nsIDataType::VTYPE_STRING_SIZE_IS:
michael@0 318 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
michael@0 319 case nsIDataType::VTYPE_UTF8STRING:
michael@0 320 case nsIDataType::VTYPE_CSTRING:
michael@0 321 case nsIDataType::VTYPE_ASTRING: {
michael@0 322 nsAutoString stringValue;
michael@0 323 rv = aValue->GetAsAString(stringValue);
michael@0 324 NS_ENSURE_SUCCESS(rv, rv);
michael@0 325 rv = SetItemAnnotationString(aItemId, aName, stringValue, aFlags, aExpiration);
michael@0 326 NS_ENSURE_SUCCESS(rv, rv);
michael@0 327 return NS_OK;
michael@0 328 }
michael@0 329 }
michael@0 330
michael@0 331 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 332 }
michael@0 333
michael@0 334
michael@0 335 NS_IMETHODIMP
michael@0 336 nsAnnotationService::SetPageAnnotationString(nsIURI* aURI,
michael@0 337 const nsACString& aName,
michael@0 338 const nsAString& aValue,
michael@0 339 int32_t aFlags,
michael@0 340 uint16_t aExpiration)
michael@0 341 {
michael@0 342 NS_ENSURE_ARG(aURI);
michael@0 343
michael@0 344 nsresult rv = SetAnnotationStringInternal(aURI, 0, aName, aValue,
michael@0 345 aFlags, aExpiration);
michael@0 346 NS_ENSURE_SUCCESS(rv, rv);
michael@0 347
michael@0 348 NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aURI, aName));
michael@0 349
michael@0 350 return NS_OK;
michael@0 351 }
michael@0 352
michael@0 353
michael@0 354 NS_IMETHODIMP
michael@0 355 nsAnnotationService::SetItemAnnotationString(int64_t aItemId,
michael@0 356 const nsACString& aName,
michael@0 357 const nsAString& aValue,
michael@0 358 int32_t aFlags,
michael@0 359 uint16_t aExpiration)
michael@0 360 {
michael@0 361 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 362
michael@0 363 if (aExpiration == EXPIRE_WITH_HISTORY)
michael@0 364 return NS_ERROR_INVALID_ARG;
michael@0 365
michael@0 366 nsresult rv = SetAnnotationStringInternal(nullptr, aItemId, aName, aValue,
michael@0 367 aFlags, aExpiration);
michael@0 368 NS_ENSURE_SUCCESS(rv, rv);
michael@0 369
michael@0 370 NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName));
michael@0 371
michael@0 372 return NS_OK;
michael@0 373 }
michael@0 374
michael@0 375
michael@0 376 nsresult
michael@0 377 nsAnnotationService::SetAnnotationInt32Internal(nsIURI* aURI,
michael@0 378 int64_t aItemId,
michael@0 379 const nsACString& aName,
michael@0 380 int32_t aValue,
michael@0 381 int32_t aFlags,
michael@0 382 uint16_t aExpiration)
michael@0 383 {
michael@0 384 mozStorageTransaction transaction(mDB->MainConn(), false);
michael@0 385 nsCOMPtr<mozIStorageStatement> statement;
michael@0 386 nsresult rv = StartSetAnnotation(aURI, aItemId, aName, aFlags, aExpiration,
michael@0 387 nsIAnnotationService::TYPE_INT32,
michael@0 388 statement);
michael@0 389 NS_ENSURE_SUCCESS(rv, rv);
michael@0 390 mozStorageStatementScoper scoper(statement);
michael@0 391
michael@0 392 rv = statement->BindInt32ByName(NS_LITERAL_CSTRING("content"), aValue);
michael@0 393 NS_ENSURE_SUCCESS(rv, rv);
michael@0 394
michael@0 395 rv = statement->Execute();
michael@0 396 NS_ENSURE_SUCCESS(rv, rv);
michael@0 397
michael@0 398 rv = transaction.Commit();
michael@0 399 NS_ENSURE_SUCCESS(rv, rv);
michael@0 400
michael@0 401 return NS_OK;
michael@0 402 }
michael@0 403
michael@0 404
michael@0 405 NS_IMETHODIMP
michael@0 406 nsAnnotationService::SetPageAnnotationInt32(nsIURI* aURI,
michael@0 407 const nsACString& aName,
michael@0 408 int32_t aValue,
michael@0 409 int32_t aFlags,
michael@0 410 uint16_t aExpiration)
michael@0 411 {
michael@0 412 NS_ENSURE_ARG(aURI);
michael@0 413
michael@0 414 nsresult rv = SetAnnotationInt32Internal(aURI, 0, aName, aValue,
michael@0 415 aFlags, aExpiration);
michael@0 416 NS_ENSURE_SUCCESS(rv, rv);
michael@0 417
michael@0 418 NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aURI, aName));
michael@0 419
michael@0 420 return NS_OK;
michael@0 421 }
michael@0 422
michael@0 423
michael@0 424 NS_IMETHODIMP
michael@0 425 nsAnnotationService::SetItemAnnotationInt32(int64_t aItemId,
michael@0 426 const nsACString& aName,
michael@0 427 int32_t aValue,
michael@0 428 int32_t aFlags,
michael@0 429 uint16_t aExpiration)
michael@0 430 {
michael@0 431 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 432
michael@0 433 if (aExpiration == EXPIRE_WITH_HISTORY)
michael@0 434 return NS_ERROR_INVALID_ARG;
michael@0 435
michael@0 436 nsresult rv = SetAnnotationInt32Internal(nullptr, aItemId, aName, aValue,
michael@0 437 aFlags, aExpiration);
michael@0 438 NS_ENSURE_SUCCESS(rv, rv);
michael@0 439
michael@0 440 NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName));
michael@0 441
michael@0 442 return NS_OK;
michael@0 443 }
michael@0 444
michael@0 445
michael@0 446 nsresult
michael@0 447 nsAnnotationService::SetAnnotationInt64Internal(nsIURI* aURI,
michael@0 448 int64_t aItemId,
michael@0 449 const nsACString& aName,
michael@0 450 int64_t aValue,
michael@0 451 int32_t aFlags,
michael@0 452 uint16_t aExpiration)
michael@0 453 {
michael@0 454 mozStorageTransaction transaction(mDB->MainConn(), false);
michael@0 455 nsCOMPtr<mozIStorageStatement> statement;
michael@0 456 nsresult rv = StartSetAnnotation(aURI, aItemId, aName, aFlags, aExpiration,
michael@0 457 nsIAnnotationService::TYPE_INT64,
michael@0 458 statement);
michael@0 459 NS_ENSURE_SUCCESS(rv, rv);
michael@0 460 mozStorageStatementScoper scoper(statement);
michael@0 461
michael@0 462 rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("content"), aValue);
michael@0 463 NS_ENSURE_SUCCESS(rv, rv);
michael@0 464
michael@0 465 rv = statement->Execute();
michael@0 466 NS_ENSURE_SUCCESS(rv, rv);
michael@0 467
michael@0 468 rv = transaction.Commit();
michael@0 469 NS_ENSURE_SUCCESS(rv, rv);
michael@0 470
michael@0 471 return NS_OK;
michael@0 472 }
michael@0 473
michael@0 474
michael@0 475 NS_IMETHODIMP
michael@0 476 nsAnnotationService::SetPageAnnotationInt64(nsIURI* aURI,
michael@0 477 const nsACString& aName,
michael@0 478 int64_t aValue,
michael@0 479 int32_t aFlags,
michael@0 480 uint16_t aExpiration)
michael@0 481 {
michael@0 482 NS_ENSURE_ARG(aURI);
michael@0 483
michael@0 484 nsresult rv = SetAnnotationInt64Internal(aURI, 0, aName, aValue,
michael@0 485 aFlags, aExpiration);
michael@0 486 NS_ENSURE_SUCCESS(rv, rv);
michael@0 487
michael@0 488 NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aURI, aName));
michael@0 489
michael@0 490 return NS_OK;
michael@0 491 }
michael@0 492
michael@0 493
michael@0 494 NS_IMETHODIMP
michael@0 495 nsAnnotationService::SetItemAnnotationInt64(int64_t aItemId,
michael@0 496 const nsACString& aName,
michael@0 497 int64_t aValue,
michael@0 498 int32_t aFlags,
michael@0 499 uint16_t aExpiration)
michael@0 500 {
michael@0 501 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 502
michael@0 503 if (aExpiration == EXPIRE_WITH_HISTORY)
michael@0 504 return NS_ERROR_INVALID_ARG;
michael@0 505
michael@0 506 nsresult rv = SetAnnotationInt64Internal(nullptr, aItemId, aName, aValue,
michael@0 507 aFlags, aExpiration);
michael@0 508 NS_ENSURE_SUCCESS(rv, rv);
michael@0 509
michael@0 510 NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName));
michael@0 511
michael@0 512 return NS_OK;
michael@0 513 }
michael@0 514
michael@0 515
michael@0 516 nsresult
michael@0 517 nsAnnotationService::SetAnnotationDoubleInternal(nsIURI* aURI,
michael@0 518 int64_t aItemId,
michael@0 519 const nsACString& aName,
michael@0 520 double aValue,
michael@0 521 int32_t aFlags,
michael@0 522 uint16_t aExpiration)
michael@0 523 {
michael@0 524 mozStorageTransaction transaction(mDB->MainConn(), false);
michael@0 525 nsCOMPtr<mozIStorageStatement> statement;
michael@0 526 nsresult rv = StartSetAnnotation(aURI, aItemId, aName, aFlags, aExpiration,
michael@0 527 nsIAnnotationService::TYPE_DOUBLE,
michael@0 528 statement);
michael@0 529 NS_ENSURE_SUCCESS(rv, rv);
michael@0 530 mozStorageStatementScoper scoper(statement);
michael@0 531
michael@0 532 rv = statement->BindDoubleByName(NS_LITERAL_CSTRING("content"), aValue);
michael@0 533 NS_ENSURE_SUCCESS(rv, rv);
michael@0 534
michael@0 535 rv = statement->Execute();
michael@0 536 NS_ENSURE_SUCCESS(rv, rv);
michael@0 537
michael@0 538 rv = transaction.Commit();
michael@0 539 NS_ENSURE_SUCCESS(rv, rv);
michael@0 540
michael@0 541 return NS_OK;
michael@0 542 }
michael@0 543
michael@0 544
michael@0 545 NS_IMETHODIMP
michael@0 546 nsAnnotationService::SetPageAnnotationDouble(nsIURI* aURI,
michael@0 547 const nsACString& aName,
michael@0 548 double aValue,
michael@0 549 int32_t aFlags,
michael@0 550 uint16_t aExpiration)
michael@0 551 {
michael@0 552 NS_ENSURE_ARG(aURI);
michael@0 553
michael@0 554 nsresult rv = SetAnnotationDoubleInternal(aURI, 0, aName, aValue,
michael@0 555 aFlags, aExpiration);
michael@0 556 NS_ENSURE_SUCCESS(rv, rv);
michael@0 557
michael@0 558 NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aURI, aName));
michael@0 559
michael@0 560 return NS_OK;
michael@0 561 }
michael@0 562
michael@0 563
michael@0 564 NS_IMETHODIMP
michael@0 565 nsAnnotationService::SetItemAnnotationDouble(int64_t aItemId,
michael@0 566 const nsACString& aName,
michael@0 567 double aValue,
michael@0 568 int32_t aFlags,
michael@0 569 uint16_t aExpiration)
michael@0 570 {
michael@0 571 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 572
michael@0 573 if (aExpiration == EXPIRE_WITH_HISTORY)
michael@0 574 return NS_ERROR_INVALID_ARG;
michael@0 575
michael@0 576 nsresult rv = SetAnnotationDoubleInternal(nullptr, aItemId, aName, aValue,
michael@0 577 aFlags, aExpiration);
michael@0 578 NS_ENSURE_SUCCESS(rv, rv);
michael@0 579
michael@0 580 NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName));
michael@0 581
michael@0 582 return NS_OK;
michael@0 583 }
michael@0 584
michael@0 585 NS_IMETHODIMP
michael@0 586 nsAnnotationService::GetPageAnnotationString(nsIURI* aURI,
michael@0 587 const nsACString& aName,
michael@0 588 nsAString& _retval)
michael@0 589 {
michael@0 590 NS_ENSURE_ARG(aURI);
michael@0 591
michael@0 592 nsCOMPtr<mozIStorageStatement> statement;
michael@0 593 nsresult rv = StartGetAnnotation(aURI, 0, aName, statement);
michael@0 594 if (NS_FAILED(rv))
michael@0 595 return rv;
michael@0 596
michael@0 597 mozStorageStatementScoper scoper(statement);
michael@0 598 ENSURE_ANNO_TYPE(TYPE_STRING, statement);
michael@0 599 rv = statement->GetString(kAnnoIndex_Content, _retval);
michael@0 600 NS_ENSURE_SUCCESS(rv, rv);
michael@0 601
michael@0 602 return NS_OK;
michael@0 603 }
michael@0 604
michael@0 605
michael@0 606 NS_IMETHODIMP
michael@0 607 nsAnnotationService::GetItemAnnotationString(int64_t aItemId,
michael@0 608 const nsACString& aName,
michael@0 609 nsAString& _retval)
michael@0 610 {
michael@0 611 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 612
michael@0 613 nsCOMPtr<mozIStorageStatement> statement;
michael@0 614 nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement);
michael@0 615 if (NS_FAILED(rv))
michael@0 616 return rv;
michael@0 617
michael@0 618 mozStorageStatementScoper scoper(statement);
michael@0 619 ENSURE_ANNO_TYPE(TYPE_STRING, statement);
michael@0 620 rv = statement->GetString(kAnnoIndex_Content, _retval);
michael@0 621 NS_ENSURE_SUCCESS(rv, rv);
michael@0 622
michael@0 623 return NS_OK;
michael@0 624 }
michael@0 625
michael@0 626
michael@0 627 NS_IMETHODIMP
michael@0 628 nsAnnotationService::GetPageAnnotation(nsIURI* aURI,
michael@0 629 const nsACString& aName,
michael@0 630 nsIVariant** _retval)
michael@0 631 {
michael@0 632 NS_ENSURE_ARG(aURI);
michael@0 633 NS_ENSURE_ARG_POINTER(_retval);
michael@0 634
michael@0 635 nsCOMPtr<mozIStorageStatement> statement;
michael@0 636 nsresult rv = StartGetAnnotation(aURI, 0, aName, statement);
michael@0 637 if (NS_FAILED(rv))
michael@0 638 return rv;
michael@0 639
michael@0 640 mozStorageStatementScoper scoper(statement);
michael@0 641
michael@0 642 nsCOMPtr<nsIWritableVariant> value = new nsVariant();
michael@0 643 int32_t type = statement->AsInt32(kAnnoIndex_Type);
michael@0 644 switch (type) {
michael@0 645 case nsIAnnotationService::TYPE_INT32:
michael@0 646 case nsIAnnotationService::TYPE_INT64:
michael@0 647 case nsIAnnotationService::TYPE_DOUBLE: {
michael@0 648 rv = value->SetAsDouble(statement->AsDouble(kAnnoIndex_Content));
michael@0 649 break;
michael@0 650 }
michael@0 651 case nsIAnnotationService::TYPE_STRING: {
michael@0 652 nsAutoString valueString;
michael@0 653 rv = statement->GetString(kAnnoIndex_Content, valueString);
michael@0 654 if (NS_SUCCEEDED(rv))
michael@0 655 rv = value->SetAsAString(valueString);
michael@0 656 break;
michael@0 657 }
michael@0 658 default: {
michael@0 659 rv = NS_ERROR_UNEXPECTED;
michael@0 660 break;
michael@0 661 }
michael@0 662 }
michael@0 663
michael@0 664 if (NS_SUCCEEDED(rv))
michael@0 665 NS_ADDREF(*_retval = value);
michael@0 666
michael@0 667 return rv;
michael@0 668 }
michael@0 669
michael@0 670
michael@0 671 NS_IMETHODIMP
michael@0 672 nsAnnotationService::GetItemAnnotation(int64_t aItemId,
michael@0 673 const nsACString& aName,
michael@0 674 nsIVariant** _retval)
michael@0 675 {
michael@0 676 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 677 NS_ENSURE_ARG_POINTER(_retval);
michael@0 678
michael@0 679 nsCOMPtr<mozIStorageStatement> statement;
michael@0 680 nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement);
michael@0 681 if (NS_FAILED(rv))
michael@0 682 return rv;
michael@0 683
michael@0 684 mozStorageStatementScoper scoper(statement);
michael@0 685
michael@0 686 nsCOMPtr<nsIWritableVariant> value = new nsVariant();
michael@0 687 int32_t type = statement->AsInt32(kAnnoIndex_Type);
michael@0 688 switch (type) {
michael@0 689 case nsIAnnotationService::TYPE_INT32:
michael@0 690 case nsIAnnotationService::TYPE_INT64:
michael@0 691 case nsIAnnotationService::TYPE_DOUBLE: {
michael@0 692 rv = value->SetAsDouble(statement->AsDouble(kAnnoIndex_Content));
michael@0 693 break;
michael@0 694 }
michael@0 695 case nsIAnnotationService::TYPE_STRING: {
michael@0 696 nsAutoString valueString;
michael@0 697 rv = statement->GetString(kAnnoIndex_Content, valueString);
michael@0 698 if (NS_SUCCEEDED(rv))
michael@0 699 rv = value->SetAsAString(valueString);
michael@0 700 break;
michael@0 701 }
michael@0 702 default: {
michael@0 703 rv = NS_ERROR_UNEXPECTED;
michael@0 704 break;
michael@0 705 }
michael@0 706 }
michael@0 707
michael@0 708 if (NS_SUCCEEDED(rv))
michael@0 709 NS_ADDREF(*_retval = value);
michael@0 710
michael@0 711 return rv;
michael@0 712 }
michael@0 713
michael@0 714
michael@0 715 NS_IMETHODIMP
michael@0 716 nsAnnotationService::GetPageAnnotationInt32(nsIURI* aURI,
michael@0 717 const nsACString& aName,
michael@0 718 int32_t* _retval)
michael@0 719 {
michael@0 720 NS_ENSURE_ARG(aURI);
michael@0 721 NS_ENSURE_ARG_POINTER(_retval);
michael@0 722
michael@0 723 nsCOMPtr<mozIStorageStatement> statement;
michael@0 724 nsresult rv = StartGetAnnotation(aURI, 0, aName, statement);
michael@0 725 if (NS_FAILED(rv))
michael@0 726 return rv;
michael@0 727
michael@0 728 mozStorageStatementScoper scoper(statement);
michael@0 729 ENSURE_ANNO_TYPE(TYPE_INT32, statement);
michael@0 730 *_retval = statement->AsInt32(kAnnoIndex_Content);
michael@0 731 NS_ENSURE_SUCCESS(rv, rv);
michael@0 732
michael@0 733 return NS_OK;
michael@0 734 }
michael@0 735
michael@0 736
michael@0 737 NS_IMETHODIMP
michael@0 738 nsAnnotationService::GetItemAnnotationInt32(int64_t aItemId,
michael@0 739 const nsACString& aName,
michael@0 740 int32_t* _retval)
michael@0 741 {
michael@0 742 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 743 NS_ENSURE_ARG_POINTER(_retval);
michael@0 744
michael@0 745 nsCOMPtr<mozIStorageStatement> statement;
michael@0 746 nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement);
michael@0 747 if (NS_FAILED(rv))
michael@0 748 return rv;
michael@0 749
michael@0 750 mozStorageStatementScoper scoper(statement);
michael@0 751 ENSURE_ANNO_TYPE(TYPE_INT32, statement);
michael@0 752 *_retval = statement->AsInt32(kAnnoIndex_Content);
michael@0 753
michael@0 754 return NS_OK;
michael@0 755 }
michael@0 756
michael@0 757
michael@0 758 NS_IMETHODIMP
michael@0 759 nsAnnotationService::GetPageAnnotationInt64(nsIURI* aURI,
michael@0 760 const nsACString& aName,
michael@0 761 int64_t* _retval)
michael@0 762 {
michael@0 763 NS_ENSURE_ARG(aURI);
michael@0 764 NS_ENSURE_ARG_POINTER(_retval);
michael@0 765
michael@0 766 nsCOMPtr<mozIStorageStatement> statement;
michael@0 767 nsresult rv = StartGetAnnotation(aURI, 0, aName, statement);
michael@0 768 if (NS_FAILED(rv))
michael@0 769 return rv;
michael@0 770
michael@0 771 mozStorageStatementScoper scoper(statement);
michael@0 772 ENSURE_ANNO_TYPE(TYPE_INT64, statement);
michael@0 773 *_retval = statement->AsInt64(kAnnoIndex_Content);
michael@0 774
michael@0 775 return NS_OK;
michael@0 776 }
michael@0 777
michael@0 778
michael@0 779 NS_IMETHODIMP
michael@0 780 nsAnnotationService::GetItemAnnotationInt64(int64_t aItemId,
michael@0 781 const nsACString& aName,
michael@0 782 int64_t* _retval)
michael@0 783 {
michael@0 784 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 785 NS_ENSURE_ARG_POINTER(_retval);
michael@0 786
michael@0 787 nsCOMPtr<mozIStorageStatement> statement;
michael@0 788 nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement);
michael@0 789 if (NS_FAILED(rv))
michael@0 790 return rv;
michael@0 791
michael@0 792 mozStorageStatementScoper scoper(statement);
michael@0 793 ENSURE_ANNO_TYPE(TYPE_INT64, statement);
michael@0 794 *_retval = statement->AsInt64(kAnnoIndex_Content);
michael@0 795
michael@0 796 return NS_OK;
michael@0 797 }
michael@0 798
michael@0 799
michael@0 800 NS_IMETHODIMP
michael@0 801 nsAnnotationService::GetPageAnnotationType(nsIURI* aURI,
michael@0 802 const nsACString& aName,
michael@0 803 uint16_t* _retval)
michael@0 804 {
michael@0 805 NS_ENSURE_ARG(aURI);
michael@0 806 NS_ENSURE_ARG_POINTER(_retval);
michael@0 807
michael@0 808 nsCOMPtr<mozIStorageStatement> statement;
michael@0 809 nsresult rv = StartGetAnnotation(aURI, 0, aName, statement);
michael@0 810 if (NS_FAILED(rv))
michael@0 811 return rv;
michael@0 812
michael@0 813 mozStorageStatementScoper scoper(statement);
michael@0 814 *_retval = statement->AsInt32(kAnnoIndex_Type);
michael@0 815
michael@0 816 return NS_OK;
michael@0 817 }
michael@0 818
michael@0 819
michael@0 820 NS_IMETHODIMP
michael@0 821 nsAnnotationService::GetItemAnnotationType(int64_t aItemId,
michael@0 822 const nsACString& aName,
michael@0 823 uint16_t* _retval)
michael@0 824 {
michael@0 825 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 826 NS_ENSURE_ARG_POINTER(_retval);
michael@0 827
michael@0 828 nsCOMPtr<mozIStorageStatement> statement;
michael@0 829 nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement);
michael@0 830 if (NS_FAILED(rv))
michael@0 831 return rv;
michael@0 832
michael@0 833 mozStorageStatementScoper scoper(statement);
michael@0 834 *_retval = statement->AsInt32(kAnnoIndex_Type);
michael@0 835
michael@0 836 return NS_OK;
michael@0 837 }
michael@0 838
michael@0 839
michael@0 840 NS_IMETHODIMP
michael@0 841 nsAnnotationService::GetPageAnnotationDouble(nsIURI* aURI,
michael@0 842 const nsACString& aName,
michael@0 843 double* _retval)
michael@0 844 {
michael@0 845 NS_ENSURE_ARG(aURI);
michael@0 846 NS_ENSURE_ARG_POINTER(_retval);
michael@0 847
michael@0 848 nsCOMPtr<mozIStorageStatement> statement;
michael@0 849 nsresult rv = StartGetAnnotation(aURI, 0, aName, statement);
michael@0 850 if (NS_FAILED(rv))
michael@0 851 return rv;
michael@0 852
michael@0 853 mozStorageStatementScoper scoper(statement);
michael@0 854 ENSURE_ANNO_TYPE(TYPE_DOUBLE, statement);
michael@0 855 *_retval = statement->AsDouble(kAnnoIndex_Content);
michael@0 856
michael@0 857 return NS_OK;
michael@0 858 }
michael@0 859
michael@0 860
michael@0 861 NS_IMETHODIMP
michael@0 862 nsAnnotationService::GetItemAnnotationDouble(int64_t aItemId,
michael@0 863 const nsACString& aName,
michael@0 864 double* _retval)
michael@0 865 {
michael@0 866 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 867
michael@0 868 nsCOMPtr<mozIStorageStatement> statement;
michael@0 869 nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement);
michael@0 870 if (NS_FAILED(rv))
michael@0 871 return rv;
michael@0 872
michael@0 873 mozStorageStatementScoper scoper(statement);
michael@0 874 ENSURE_ANNO_TYPE(TYPE_DOUBLE, statement);
michael@0 875 *_retval = statement->AsDouble(kAnnoIndex_Content);
michael@0 876
michael@0 877 return NS_OK;
michael@0 878 }
michael@0 879
michael@0 880
michael@0 881 NS_IMETHODIMP
michael@0 882 nsAnnotationService::GetPageAnnotationInfo(nsIURI* aURI,
michael@0 883 const nsACString& aName,
michael@0 884 int32_t* _flags,
michael@0 885 uint16_t* _expiration,
michael@0 886 uint16_t* _storageType)
michael@0 887 {
michael@0 888 NS_ENSURE_ARG(aURI);
michael@0 889 NS_ENSURE_ARG_POINTER(_flags);
michael@0 890 NS_ENSURE_ARG_POINTER(_expiration);
michael@0 891 NS_ENSURE_ARG_POINTER(_storageType);
michael@0 892
michael@0 893 nsCOMPtr<mozIStorageStatement> statement;
michael@0 894 nsresult rv = StartGetAnnotation(aURI, 0, aName, statement);
michael@0 895 if (NS_FAILED(rv))
michael@0 896 return rv;
michael@0 897
michael@0 898 mozStorageStatementScoper scoper(statement);
michael@0 899 *_flags = statement->AsInt32(kAnnoIndex_Flags);
michael@0 900 *_expiration = (uint16_t)statement->AsInt32(kAnnoIndex_Expiration);
michael@0 901 int32_t type = (uint16_t)statement->AsInt32(kAnnoIndex_Type);
michael@0 902 if (type == 0) {
michael@0 903 // For annotations created before explicit typing,
michael@0 904 // we can't determine type, just return as string type.
michael@0 905 *_storageType = nsIAnnotationService::TYPE_STRING;
michael@0 906 }
michael@0 907 else
michael@0 908 *_storageType = type;
michael@0 909
michael@0 910 return NS_OK;
michael@0 911 }
michael@0 912
michael@0 913
michael@0 914 NS_IMETHODIMP
michael@0 915 nsAnnotationService::GetItemAnnotationInfo(int64_t aItemId,
michael@0 916 const nsACString& aName,
michael@0 917 int32_t* _flags,
michael@0 918 uint16_t* _expiration,
michael@0 919 uint16_t* _storageType)
michael@0 920 {
michael@0 921 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 922 NS_ENSURE_ARG_POINTER(_flags);
michael@0 923 NS_ENSURE_ARG_POINTER(_expiration);
michael@0 924 NS_ENSURE_ARG_POINTER(_storageType);
michael@0 925
michael@0 926 nsCOMPtr<mozIStorageStatement> statement;
michael@0 927 nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement);
michael@0 928 if (NS_FAILED(rv))
michael@0 929 return rv;
michael@0 930
michael@0 931 mozStorageStatementScoper scoper(statement);
michael@0 932 *_flags = statement->AsInt32(kAnnoIndex_Flags);
michael@0 933 *_expiration = (uint16_t)statement->AsInt32(kAnnoIndex_Expiration);
michael@0 934 int32_t type = (uint16_t)statement->AsInt32(kAnnoIndex_Type);
michael@0 935 if (type == 0) {
michael@0 936 // For annotations created before explicit typing,
michael@0 937 // we can't determine type, just return as string type.
michael@0 938 *_storageType = nsIAnnotationService::TYPE_STRING;
michael@0 939 }
michael@0 940 else {
michael@0 941 *_storageType = type;
michael@0 942 }
michael@0 943
michael@0 944 return NS_OK;
michael@0 945 }
michael@0 946
michael@0 947
michael@0 948 NS_IMETHODIMP
michael@0 949 nsAnnotationService::GetPagesWithAnnotation(const nsACString& aName,
michael@0 950 uint32_t* _resultCount,
michael@0 951 nsIURI*** _results)
michael@0 952 {
michael@0 953 NS_ENSURE_TRUE(!aName.IsEmpty(), NS_ERROR_INVALID_ARG);
michael@0 954 NS_ENSURE_ARG_POINTER(_resultCount);
michael@0 955 NS_ENSURE_ARG_POINTER(_results);
michael@0 956
michael@0 957 *_resultCount = 0;
michael@0 958 *_results = nullptr;
michael@0 959 nsCOMArray<nsIURI> results;
michael@0 960
michael@0 961 nsresult rv = GetPagesWithAnnotationCOMArray(aName, &results);
michael@0 962 NS_ENSURE_SUCCESS(rv, rv);
michael@0 963
michael@0 964 // Convert to raw array.
michael@0 965 if (results.Count() == 0)
michael@0 966 return NS_OK;
michael@0 967
michael@0 968 *_results = static_cast<nsIURI**>
michael@0 969 (nsMemory::Alloc(results.Count() * sizeof(nsIURI*)));
michael@0 970 NS_ENSURE_TRUE(*_results, NS_ERROR_OUT_OF_MEMORY);
michael@0 971
michael@0 972 *_resultCount = results.Count();
michael@0 973 for (uint32_t i = 0; i < *_resultCount; i ++) {
michael@0 974 (*_results)[i] = results[i];
michael@0 975 NS_ADDREF((*_results)[i]);
michael@0 976 }
michael@0 977
michael@0 978 return NS_OK;
michael@0 979 }
michael@0 980
michael@0 981
michael@0 982 nsresult
michael@0 983 nsAnnotationService::GetPagesWithAnnotationCOMArray(const nsACString& aName,
michael@0 984 nsCOMArray<nsIURI>* _results)
michael@0 985 {
michael@0 986 nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
michael@0 987 "SELECT h.url "
michael@0 988 "FROM moz_anno_attributes n "
michael@0 989 "JOIN moz_annos a ON n.id = a.anno_attribute_id "
michael@0 990 "JOIN moz_places h ON h.id = a.place_id "
michael@0 991 "WHERE n.name = :anno_name"
michael@0 992 );
michael@0 993 NS_ENSURE_STATE(stmt);
michael@0 994 mozStorageStatementScoper scoper(stmt);
michael@0 995
michael@0 996 nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName);
michael@0 997 NS_ENSURE_SUCCESS(rv, rv);
michael@0 998
michael@0 999 bool hasMore = false;
michael@0 1000 while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&hasMore)) &&
michael@0 1001 hasMore) {
michael@0 1002 nsAutoCString uristring;
michael@0 1003 rv = stmt->GetUTF8String(0, uristring);
michael@0 1004 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1005
michael@0 1006 // convert to a URI, in case of some invalid URI, just ignore this row
michael@0 1007 // so we can mostly continue.
michael@0 1008 nsCOMPtr<nsIURI> uri;
michael@0 1009 rv = NS_NewURI(getter_AddRefs(uri), uristring);
michael@0 1010 if (NS_FAILED(rv))
michael@0 1011 continue;
michael@0 1012
michael@0 1013 bool added = _results->AppendObject(uri);
michael@0 1014 NS_ENSURE_TRUE(added, NS_ERROR_OUT_OF_MEMORY);
michael@0 1015 }
michael@0 1016
michael@0 1017 return NS_OK;
michael@0 1018 }
michael@0 1019
michael@0 1020
michael@0 1021 NS_IMETHODIMP
michael@0 1022 nsAnnotationService::GetItemsWithAnnotation(const nsACString& aName,
michael@0 1023 uint32_t* _resultCount,
michael@0 1024 int64_t** _results)
michael@0 1025 {
michael@0 1026 NS_ENSURE_TRUE(!aName.IsEmpty(), NS_ERROR_INVALID_ARG);
michael@0 1027 NS_ENSURE_ARG_POINTER(_resultCount);
michael@0 1028 NS_ENSURE_ARG_POINTER(_results);
michael@0 1029
michael@0 1030 *_resultCount = 0;
michael@0 1031 *_results = nullptr;
michael@0 1032 nsTArray<int64_t> results;
michael@0 1033
michael@0 1034 nsresult rv = GetItemsWithAnnotationTArray(aName, &results);
michael@0 1035 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1036
michael@0 1037 // Convert to raw array.
michael@0 1038 if (results.Length() == 0)
michael@0 1039 return NS_OK;
michael@0 1040
michael@0 1041 *_results = static_cast<int64_t*>
michael@0 1042 (nsMemory::Alloc(results.Length() * sizeof(int64_t)));
michael@0 1043 NS_ENSURE_TRUE(*_results, NS_ERROR_OUT_OF_MEMORY);
michael@0 1044
michael@0 1045 *_resultCount = results.Length();
michael@0 1046 for (uint32_t i = 0; i < *_resultCount; i ++) {
michael@0 1047 (*_results)[i] = results[i];
michael@0 1048 }
michael@0 1049
michael@0 1050 return NS_OK;
michael@0 1051 }
michael@0 1052
michael@0 1053
michael@0 1054 NS_IMETHODIMP
michael@0 1055 nsAnnotationService::GetAnnotationsWithName(const nsACString& aName,
michael@0 1056 uint32_t* _count,
michael@0 1057 mozIAnnotatedResult*** _annotations)
michael@0 1058 {
michael@0 1059 NS_ENSURE_ARG(!aName.IsEmpty());
michael@0 1060 NS_ENSURE_ARG_POINTER(_annotations);
michael@0 1061
michael@0 1062 *_count = 0;
michael@0 1063 *_annotations = nullptr;
michael@0 1064 nsCOMArray<mozIAnnotatedResult> annotations;
michael@0 1065
michael@0 1066 nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
michael@0 1067 "SELECT h.guid, h.url, -1, a.type, a.content "
michael@0 1068 "FROM moz_anno_attributes n "
michael@0 1069 "JOIN moz_annos a ON n.id = a.anno_attribute_id "
michael@0 1070 "JOIN moz_places h ON h.id = a.place_id "
michael@0 1071 "WHERE n.name = :anno_name "
michael@0 1072 "UNION ALL "
michael@0 1073 "SELECT b.guid, h.url, b.id, a.type, a.content "
michael@0 1074 "FROM moz_anno_attributes n "
michael@0 1075 "JOIN moz_items_annos a ON n.id = a.anno_attribute_id "
michael@0 1076 "JOIN moz_bookmarks b ON b.id = a.item_id "
michael@0 1077 "LEFT JOIN moz_places h ON h.id = b.fk "
michael@0 1078 "WHERE n.name = :anno_name "
michael@0 1079 );
michael@0 1080 NS_ENSURE_STATE(stmt);
michael@0 1081 mozStorageStatementScoper scoper(stmt);
michael@0 1082
michael@0 1083 nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"),
michael@0 1084 aName);
michael@0 1085 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1086
michael@0 1087 bool hasMore = false;
michael@0 1088 while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&hasMore)) && hasMore) {
michael@0 1089 nsAutoCString guid;
michael@0 1090 rv = stmt->GetUTF8String(0, guid);
michael@0 1091 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1092
michael@0 1093 nsCOMPtr<nsIURI> uri;
michael@0 1094 bool uriIsNull = false;
michael@0 1095 rv = stmt->GetIsNull(1, &uriIsNull);
michael@0 1096 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1097 if (!uriIsNull) {
michael@0 1098 nsAutoCString url;
michael@0 1099 rv = stmt->GetUTF8String(1, url);
michael@0 1100 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1101 rv = NS_NewURI(getter_AddRefs(uri), url);
michael@0 1102 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1103 }
michael@0 1104
michael@0 1105 int64_t itemId = stmt->AsInt64(2);
michael@0 1106 int32_t type = stmt->AsInt32(3);
michael@0 1107
michael@0 1108 nsCOMPtr<nsIWritableVariant> variant = new nsVariant();
michael@0 1109 switch (type) {
michael@0 1110 case nsIAnnotationService::TYPE_INT32: {
michael@0 1111 rv = variant->SetAsInt32(stmt->AsInt32(4));
michael@0 1112 break;
michael@0 1113 }
michael@0 1114 case nsIAnnotationService::TYPE_INT64: {
michael@0 1115 rv = variant->SetAsInt64(stmt->AsInt64(4));
michael@0 1116 break;
michael@0 1117 }
michael@0 1118 case nsIAnnotationService::TYPE_DOUBLE: {
michael@0 1119 rv = variant->SetAsDouble(stmt->AsDouble(4));
michael@0 1120 break;
michael@0 1121 }
michael@0 1122 case nsIAnnotationService::TYPE_STRING: {
michael@0 1123 nsAutoString valueString;
michael@0 1124 rv = stmt->GetString(4, valueString);
michael@0 1125 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1126
michael@0 1127 rv = variant->SetAsAString(valueString);
michael@0 1128 break;
michael@0 1129 }
michael@0 1130 default:
michael@0 1131 MOZ_ASSERT(false, "Unsupported annotation type");
michael@0 1132 // Move to the next result.
michael@0 1133 continue;
michael@0 1134 }
michael@0 1135 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1136
michael@0 1137 nsCOMPtr<mozIAnnotatedResult> anno = new AnnotatedResult(guid, uri, itemId,
michael@0 1138 aName, variant);
michael@0 1139 NS_ENSURE_TRUE(annotations.AppendObject(anno), NS_ERROR_OUT_OF_MEMORY);
michael@0 1140 }
michael@0 1141
michael@0 1142 // Convert to raw array.
michael@0 1143 if (annotations.Count() == 0)
michael@0 1144 return NS_OK;
michael@0 1145
michael@0 1146 *_annotations = static_cast<mozIAnnotatedResult**>
michael@0 1147 (nsMemory::Alloc(annotations.Count() * sizeof(mozIAnnotatedResult*)));
michael@0 1148 NS_ENSURE_TRUE(*_annotations, NS_ERROR_OUT_OF_MEMORY);
michael@0 1149
michael@0 1150 *_count = annotations.Count();
michael@0 1151 for (uint32_t i = 0; i < *_count; ++i) {
michael@0 1152 NS_ADDREF((*_annotations)[i] = annotations[i]);
michael@0 1153 }
michael@0 1154
michael@0 1155 return NS_OK;
michael@0 1156 }
michael@0 1157
michael@0 1158
michael@0 1159 nsresult
michael@0 1160 nsAnnotationService::GetItemsWithAnnotationTArray(const nsACString& aName,
michael@0 1161 nsTArray<int64_t>* _results)
michael@0 1162 {
michael@0 1163 nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
michael@0 1164 "SELECT a.item_id "
michael@0 1165 "FROM moz_anno_attributes n "
michael@0 1166 "JOIN moz_items_annos a ON n.id = a.anno_attribute_id "
michael@0 1167 "WHERE n.name = :anno_name"
michael@0 1168 );
michael@0 1169 NS_ENSURE_STATE(stmt);
michael@0 1170 mozStorageStatementScoper scoper(stmt);
michael@0 1171
michael@0 1172 nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName);
michael@0 1173 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1174
michael@0 1175 bool hasMore = false;
michael@0 1176 while (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) &&
michael@0 1177 hasMore) {
michael@0 1178 if (!_results->AppendElement(stmt->AsInt64(0)))
michael@0 1179 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1180 }
michael@0 1181
michael@0 1182 return NS_OK;
michael@0 1183 }
michael@0 1184
michael@0 1185
michael@0 1186 NS_IMETHODIMP
michael@0 1187 nsAnnotationService::GetPageAnnotationNames(nsIURI* aURI,
michael@0 1188 uint32_t* _count,
michael@0 1189 nsIVariant*** _result)
michael@0 1190 {
michael@0 1191 NS_ENSURE_ARG(aURI);
michael@0 1192 NS_ENSURE_ARG_POINTER(_count);
michael@0 1193 NS_ENSURE_ARG_POINTER(_result);
michael@0 1194
michael@0 1195 *_count = 0;
michael@0 1196 *_result = nullptr;
michael@0 1197
michael@0 1198 nsTArray<nsCString> names;
michael@0 1199 nsresult rv = GetAnnotationNamesTArray(aURI, 0, &names);
michael@0 1200 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1201
michael@0 1202 if (names.Length() == 0)
michael@0 1203 return NS_OK;
michael@0 1204
michael@0 1205 *_result = static_cast<nsIVariant**>
michael@0 1206 (nsMemory::Alloc(sizeof(nsIVariant*) * names.Length()));
michael@0 1207 NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
michael@0 1208
michael@0 1209 for (uint32_t i = 0; i < names.Length(); i ++) {
michael@0 1210 nsCOMPtr<nsIWritableVariant> var = new nsVariant();
michael@0 1211 if (!var) {
michael@0 1212 // need to release all the variants we've already created
michael@0 1213 for (uint32_t j = 0; j < i; j ++)
michael@0 1214 NS_RELEASE((*_result)[j]);
michael@0 1215 nsMemory::Free(*_result);
michael@0 1216 *_result = nullptr;
michael@0 1217 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1218 }
michael@0 1219 var->SetAsAUTF8String(names[i]);
michael@0 1220 NS_ADDREF((*_result)[i] = var);
michael@0 1221 }
michael@0 1222 *_count = names.Length();
michael@0 1223
michael@0 1224 return NS_OK;
michael@0 1225 }
michael@0 1226
michael@0 1227
michael@0 1228 nsresult
michael@0 1229 nsAnnotationService::GetAnnotationNamesTArray(nsIURI* aURI,
michael@0 1230 int64_t aItemId,
michael@0 1231 nsTArray<nsCString>* _result)
michael@0 1232 {
michael@0 1233 _result->Clear();
michael@0 1234
michael@0 1235 bool isItemAnnotation = (aItemId > 0);
michael@0 1236 nsCOMPtr<mozIStorageStatement> statement;
michael@0 1237 if (isItemAnnotation) {
michael@0 1238 statement = mDB->GetStatement(
michael@0 1239 "SELECT n.name "
michael@0 1240 "FROM moz_anno_attributes n "
michael@0 1241 "JOIN moz_items_annos a ON a.anno_attribute_id = n.id "
michael@0 1242 "WHERE a.item_id = :item_id"
michael@0 1243 );
michael@0 1244 }
michael@0 1245 else {
michael@0 1246 statement = mDB->GetStatement(
michael@0 1247 "SELECT n.name "
michael@0 1248 "FROM moz_anno_attributes n "
michael@0 1249 "JOIN moz_annos a ON a.anno_attribute_id = n.id "
michael@0 1250 "JOIN moz_places h ON h.id = a.place_id "
michael@0 1251 "WHERE h.url = :page_url"
michael@0 1252 );
michael@0 1253 }
michael@0 1254 NS_ENSURE_STATE(statement);
michael@0 1255 mozStorageStatementScoper scoper(statement);
michael@0 1256
michael@0 1257 nsresult rv;
michael@0 1258 if (isItemAnnotation)
michael@0 1259 rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
michael@0 1260 else
michael@0 1261 rv = URIBinder::Bind(statement, NS_LITERAL_CSTRING("page_url"), aURI);
michael@0 1262 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1263
michael@0 1264 bool hasResult = false;
michael@0 1265 while (NS_SUCCEEDED(statement->ExecuteStep(&hasResult)) &&
michael@0 1266 hasResult) {
michael@0 1267 nsAutoCString name;
michael@0 1268 rv = statement->GetUTF8String(0, name);
michael@0 1269 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1270 if (!_result->AppendElement(name))
michael@0 1271 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1272 }
michael@0 1273
michael@0 1274 return NS_OK;
michael@0 1275 }
michael@0 1276
michael@0 1277
michael@0 1278 NS_IMETHODIMP
michael@0 1279 nsAnnotationService::GetItemAnnotationNames(int64_t aItemId,
michael@0 1280 uint32_t* _count,
michael@0 1281 nsIVariant*** _result)
michael@0 1282 {
michael@0 1283 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 1284 NS_ENSURE_ARG_POINTER(_count);
michael@0 1285 NS_ENSURE_ARG_POINTER(_result);
michael@0 1286
michael@0 1287 *_count = 0;
michael@0 1288 *_result = nullptr;
michael@0 1289
michael@0 1290 nsTArray<nsCString> names;
michael@0 1291 nsresult rv = GetAnnotationNamesTArray(nullptr, aItemId, &names);
michael@0 1292 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1293
michael@0 1294 if (names.Length() == 0)
michael@0 1295 return NS_OK;
michael@0 1296
michael@0 1297 *_result = static_cast<nsIVariant**>
michael@0 1298 (nsMemory::Alloc(sizeof(nsIVariant*) * names.Length()));
michael@0 1299 NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
michael@0 1300
michael@0 1301 for (uint32_t i = 0; i < names.Length(); i ++) {
michael@0 1302 nsCOMPtr<nsIWritableVariant> var = new nsVariant();
michael@0 1303 if (!var) {
michael@0 1304 // need to release all the variants we've already created
michael@0 1305 for (uint32_t j = 0; j < i; j ++)
michael@0 1306 NS_RELEASE((*_result)[j]);
michael@0 1307 nsMemory::Free(*_result);
michael@0 1308 *_result = nullptr;
michael@0 1309 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1310 }
michael@0 1311 var->SetAsAUTF8String(names[i]);
michael@0 1312 NS_ADDREF((*_result)[i] = var);
michael@0 1313 }
michael@0 1314 *_count = names.Length();
michael@0 1315
michael@0 1316 return NS_OK;
michael@0 1317 }
michael@0 1318
michael@0 1319
michael@0 1320 NS_IMETHODIMP
michael@0 1321 nsAnnotationService::PageHasAnnotation(nsIURI* aURI,
michael@0 1322 const nsACString& aName,
michael@0 1323 bool* _retval)
michael@0 1324 {
michael@0 1325 NS_ENSURE_ARG(aURI);
michael@0 1326 NS_ENSURE_ARG_POINTER(_retval);
michael@0 1327
michael@0 1328 nsresult rv = HasAnnotationInternal(aURI, 0, aName, _retval);
michael@0 1329 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1330
michael@0 1331 return NS_OK;
michael@0 1332 }
michael@0 1333
michael@0 1334
michael@0 1335 NS_IMETHODIMP
michael@0 1336 nsAnnotationService::ItemHasAnnotation(int64_t aItemId,
michael@0 1337 const nsACString& aName,
michael@0 1338 bool* _retval)
michael@0 1339 {
michael@0 1340 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 1341 NS_ENSURE_ARG_POINTER(_retval);
michael@0 1342
michael@0 1343 nsresult rv = HasAnnotationInternal(nullptr, aItemId, aName, _retval);
michael@0 1344 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1345
michael@0 1346 return NS_OK;
michael@0 1347 }
michael@0 1348
michael@0 1349
michael@0 1350 /**
michael@0 1351 * @note We don't remove anything from the moz_anno_attributes table. If we
michael@0 1352 * delete the last item of a given name, that item really should go away.
michael@0 1353 * It will be cleaned up by expiration.
michael@0 1354 */
michael@0 1355 nsresult
michael@0 1356 nsAnnotationService::RemoveAnnotationInternal(nsIURI* aURI,
michael@0 1357 int64_t aItemId,
michael@0 1358 const nsACString& aName)
michael@0 1359 {
michael@0 1360 bool isItemAnnotation = (aItemId > 0);
michael@0 1361 nsCOMPtr<mozIStorageStatement> statement;
michael@0 1362 if (isItemAnnotation) {
michael@0 1363 statement = mDB->GetStatement(
michael@0 1364 "DELETE FROM moz_items_annos "
michael@0 1365 "WHERE item_id = :item_id "
michael@0 1366 "AND anno_attribute_id = "
michael@0 1367 "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)"
michael@0 1368 );
michael@0 1369 }
michael@0 1370 else {
michael@0 1371 statement = mDB->GetStatement(
michael@0 1372 "DELETE FROM moz_annos "
michael@0 1373 "WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url) "
michael@0 1374 "AND anno_attribute_id = "
michael@0 1375 "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)"
michael@0 1376 );
michael@0 1377 }
michael@0 1378 NS_ENSURE_STATE(statement);
michael@0 1379 mozStorageStatementScoper scoper(statement);
michael@0 1380
michael@0 1381 nsresult rv;
michael@0 1382 if (isItemAnnotation)
michael@0 1383 rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
michael@0 1384 else
michael@0 1385 rv = URIBinder::Bind(statement, NS_LITERAL_CSTRING("page_url"), aURI);
michael@0 1386 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1387
michael@0 1388 rv = statement->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName);
michael@0 1389 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1390
michael@0 1391 rv = statement->Execute();
michael@0 1392 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1393
michael@0 1394 return NS_OK;
michael@0 1395 }
michael@0 1396
michael@0 1397
michael@0 1398 NS_IMETHODIMP
michael@0 1399 nsAnnotationService::RemovePageAnnotation(nsIURI* aURI,
michael@0 1400 const nsACString& aName)
michael@0 1401 {
michael@0 1402 NS_ENSURE_ARG(aURI);
michael@0 1403
michael@0 1404 nsresult rv = RemoveAnnotationInternal(aURI, 0, aName);
michael@0 1405 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1406
michael@0 1407 NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationRemoved(aURI, aName));
michael@0 1408
michael@0 1409 return NS_OK;
michael@0 1410 }
michael@0 1411
michael@0 1412
michael@0 1413 NS_IMETHODIMP
michael@0 1414 nsAnnotationService::RemoveItemAnnotation(int64_t aItemId,
michael@0 1415 const nsACString& aName)
michael@0 1416 {
michael@0 1417 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 1418
michael@0 1419 nsresult rv = RemoveAnnotationInternal(nullptr, aItemId, aName);
michael@0 1420 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1421
michael@0 1422 NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationRemoved(aItemId, aName));
michael@0 1423
michael@0 1424 return NS_OK;
michael@0 1425 }
michael@0 1426
michael@0 1427
michael@0 1428 NS_IMETHODIMP
michael@0 1429 nsAnnotationService::RemovePageAnnotations(nsIURI* aURI)
michael@0 1430 {
michael@0 1431 NS_ENSURE_ARG(aURI);
michael@0 1432
michael@0 1433 // Should this be precompiled or a getter?
michael@0 1434 nsCOMPtr<mozIStorageStatement> statement = mDB->GetStatement(
michael@0 1435 "DELETE FROM moz_annos WHERE place_id = "
michael@0 1436 "(SELECT id FROM moz_places WHERE url = :page_url)"
michael@0 1437 );
michael@0 1438 NS_ENSURE_STATE(statement);
michael@0 1439 mozStorageStatementScoper scoper(statement);
michael@0 1440
michael@0 1441 nsresult rv = URIBinder::Bind(statement, NS_LITERAL_CSTRING("page_url"), aURI);
michael@0 1442 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1443
michael@0 1444 rv = statement->Execute();
michael@0 1445 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1446
michael@0 1447 // Update observers
michael@0 1448 NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationRemoved(aURI, EmptyCString()));
michael@0 1449
michael@0 1450 return NS_OK;
michael@0 1451 }
michael@0 1452
michael@0 1453
michael@0 1454 NS_IMETHODIMP
michael@0 1455 nsAnnotationService::RemoveItemAnnotations(int64_t aItemId)
michael@0 1456 {
michael@0 1457 NS_ENSURE_ARG_MIN(aItemId, 1);
michael@0 1458
michael@0 1459 // Should this be precompiled or a getter?
michael@0 1460 nsCOMPtr<mozIStorageStatement> statement = mDB->GetStatement(
michael@0 1461 "DELETE FROM moz_items_annos WHERE item_id = :item_id"
michael@0 1462 );
michael@0 1463 NS_ENSURE_STATE(statement);
michael@0 1464 mozStorageStatementScoper scoper(statement);
michael@0 1465
michael@0 1466 nsresult rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
michael@0 1467 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1468
michael@0 1469 rv = statement->Execute();
michael@0 1470 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1471
michael@0 1472 NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationRemoved(aItemId, EmptyCString()));
michael@0 1473
michael@0 1474 return NS_OK;
michael@0 1475 }
michael@0 1476
michael@0 1477
michael@0 1478 /**
michael@0 1479 * @note If we use annotations for some standard items like GeckoFlags, it
michael@0 1480 * might be a good idea to blacklist these standard annotations from this
michael@0 1481 * copy function.
michael@0 1482 */
michael@0 1483 NS_IMETHODIMP
michael@0 1484 nsAnnotationService::CopyPageAnnotations(nsIURI* aSourceURI,
michael@0 1485 nsIURI* aDestURI,
michael@0 1486 bool aOverwriteDest)
michael@0 1487 {
michael@0 1488 NS_ENSURE_ARG(aSourceURI);
michael@0 1489 NS_ENSURE_ARG(aDestURI);
michael@0 1490
michael@0 1491 mozStorageTransaction transaction(mDB->MainConn(), false);
michael@0 1492
michael@0 1493 nsCOMPtr<mozIStorageStatement> sourceStmt = mDB->GetStatement(
michael@0 1494 "SELECT h.id, n.id, n.name, a2.id "
michael@0 1495 "FROM moz_places h "
michael@0 1496 "JOIN moz_annos a ON a.place_id = h.id "
michael@0 1497 "JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id "
michael@0 1498 "LEFT JOIN moz_annos a2 ON a2.place_id = "
michael@0 1499 "(SELECT id FROM moz_places WHERE url = :dest_url) "
michael@0 1500 "AND a2.anno_attribute_id = n.id "
michael@0 1501 "WHERE url = :source_url"
michael@0 1502 );
michael@0 1503 NS_ENSURE_STATE(sourceStmt);
michael@0 1504 mozStorageStatementScoper sourceScoper(sourceStmt);
michael@0 1505
michael@0 1506 nsresult rv = URIBinder::Bind(sourceStmt, NS_LITERAL_CSTRING("source_url"), aSourceURI);
michael@0 1507 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1508 rv = URIBinder::Bind(sourceStmt, NS_LITERAL_CSTRING("dest_url"), aDestURI);
michael@0 1509 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1510
michael@0 1511 nsCOMPtr<mozIStorageStatement> copyStmt = mDB->GetStatement(
michael@0 1512 "INSERT INTO moz_annos "
michael@0 1513 "(place_id, anno_attribute_id, content, flags, expiration, "
michael@0 1514 "type, dateAdded, lastModified) "
michael@0 1515 "SELECT (SELECT id FROM moz_places WHERE url = :page_url), "
michael@0 1516 "anno_attribute_id, content, flags, expiration, type, "
michael@0 1517 ":date, :date "
michael@0 1518 "FROM moz_annos "
michael@0 1519 "WHERE place_id = :page_id "
michael@0 1520 "AND anno_attribute_id = :name_id"
michael@0 1521 );
michael@0 1522 NS_ENSURE_STATE(copyStmt);
michael@0 1523 mozStorageStatementScoper copyScoper(copyStmt);
michael@0 1524
michael@0 1525 bool hasResult;
michael@0 1526 while (NS_SUCCEEDED(sourceStmt->ExecuteStep(&hasResult)) && hasResult) {
michael@0 1527 int64_t sourcePlaceId = sourceStmt->AsInt64(0);
michael@0 1528 int64_t annoNameID = sourceStmt->AsInt64(1);
michael@0 1529 nsAutoCString annoName;
michael@0 1530 rv = sourceStmt->GetUTF8String(2, annoName);
michael@0 1531 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1532 int64_t annoExistsOnDest = sourceStmt->AsInt64(3);
michael@0 1533
michael@0 1534 if (annoExistsOnDest) {
michael@0 1535 if (!aOverwriteDest)
michael@0 1536 continue;
michael@0 1537 rv = RemovePageAnnotation(aDestURI, annoName);
michael@0 1538 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1539 }
michael@0 1540
michael@0 1541 // Copy the annotation.
michael@0 1542 mozStorageStatementScoper scoper(copyStmt);
michael@0 1543 rv = URIBinder::Bind(copyStmt, NS_LITERAL_CSTRING("page_url"), aDestURI);
michael@0 1544 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1545 rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), sourcePlaceId);
michael@0 1546 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1547 rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("name_id"), annoNameID);
michael@0 1548 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1549 rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("date"), PR_Now());
michael@0 1550 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1551
michael@0 1552 rv = copyStmt->Execute();
michael@0 1553 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1554
michael@0 1555 NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aDestURI, annoName));
michael@0 1556 }
michael@0 1557
michael@0 1558 rv = transaction.Commit();
michael@0 1559 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1560
michael@0 1561 return NS_OK;
michael@0 1562 }
michael@0 1563
michael@0 1564
michael@0 1565 NS_IMETHODIMP
michael@0 1566 nsAnnotationService::CopyItemAnnotations(int64_t aSourceItemId,
michael@0 1567 int64_t aDestItemId,
michael@0 1568 bool aOverwriteDest)
michael@0 1569 {
michael@0 1570 NS_ENSURE_ARG_MIN(aSourceItemId, 1);
michael@0 1571 NS_ENSURE_ARG_MIN(aDestItemId, 1);
michael@0 1572
michael@0 1573 mozStorageTransaction transaction(mDB->MainConn(), false);
michael@0 1574
michael@0 1575 nsCOMPtr<mozIStorageStatement> sourceStmt = mDB->GetStatement(
michael@0 1576 "SELECT n.id, n.name, a2.id "
michael@0 1577 "FROM moz_bookmarks b "
michael@0 1578 "JOIN moz_items_annos a ON a.item_id = b.id "
michael@0 1579 "JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id "
michael@0 1580 "LEFT JOIN moz_items_annos a2 ON a2.item_id = :dest_item_id "
michael@0 1581 "AND a2.anno_attribute_id = n.id "
michael@0 1582 "WHERE b.id = :source_item_id"
michael@0 1583 );
michael@0 1584 NS_ENSURE_STATE(sourceStmt);
michael@0 1585 mozStorageStatementScoper sourceScoper(sourceStmt);
michael@0 1586
michael@0 1587 nsresult rv = sourceStmt->BindInt64ByName(NS_LITERAL_CSTRING("source_item_id"), aSourceItemId);
michael@0 1588 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1589 rv = sourceStmt->BindInt64ByName(NS_LITERAL_CSTRING("dest_item_id"), aDestItemId);
michael@0 1590 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1591
michael@0 1592 nsCOMPtr<mozIStorageStatement> copyStmt = mDB->GetStatement(
michael@0 1593 "INSERT OR REPLACE INTO moz_items_annos "
michael@0 1594 "(item_id, anno_attribute_id, content, flags, expiration, "
michael@0 1595 "type, dateAdded, lastModified) "
michael@0 1596 "SELECT :dest_item_id, anno_attribute_id, content, flags, expiration, "
michael@0 1597 "type, :date, :date "
michael@0 1598 "FROM moz_items_annos "
michael@0 1599 "WHERE item_id = :source_item_id "
michael@0 1600 "AND anno_attribute_id = :name_id"
michael@0 1601 );
michael@0 1602 NS_ENSURE_STATE(copyStmt);
michael@0 1603 mozStorageStatementScoper copyScoper(copyStmt);
michael@0 1604
michael@0 1605 bool hasResult;
michael@0 1606 while (NS_SUCCEEDED(sourceStmt->ExecuteStep(&hasResult)) && hasResult) {
michael@0 1607 int64_t annoNameID = sourceStmt->AsInt64(0);
michael@0 1608 nsAutoCString annoName;
michael@0 1609 rv = sourceStmt->GetUTF8String(1, annoName);
michael@0 1610 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1611 int64_t annoExistsOnDest = sourceStmt->AsInt64(2);
michael@0 1612
michael@0 1613 if (annoExistsOnDest) {
michael@0 1614 if (!aOverwriteDest)
michael@0 1615 continue;
michael@0 1616 rv = RemoveItemAnnotation(aDestItemId, annoName);
michael@0 1617 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1618 }
michael@0 1619
michael@0 1620 // Copy the annotation.
michael@0 1621 mozStorageStatementScoper scoper(copyStmt);
michael@0 1622 rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("dest_item_id"), aDestItemId);
michael@0 1623 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1624 rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("source_item_id"), aSourceItemId);
michael@0 1625 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1626 rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("name_id"), annoNameID);
michael@0 1627 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1628 rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("date"), PR_Now());
michael@0 1629 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1630
michael@0 1631 rv = copyStmt->Execute();
michael@0 1632 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1633
michael@0 1634 NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aDestItemId, annoName));
michael@0 1635 }
michael@0 1636
michael@0 1637 rv = transaction.Commit();
michael@0 1638 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1639
michael@0 1640 return NS_OK;
michael@0 1641 }
michael@0 1642
michael@0 1643
michael@0 1644 NS_IMETHODIMP
michael@0 1645 nsAnnotationService::AddObserver(nsIAnnotationObserver* aObserver)
michael@0 1646 {
michael@0 1647 NS_ENSURE_ARG(aObserver);
michael@0 1648
michael@0 1649 if (mObservers.IndexOfObject(aObserver) >= 0)
michael@0 1650 return NS_ERROR_INVALID_ARG; // Already registered.
michael@0 1651 if (!mObservers.AppendObject(aObserver))
michael@0 1652 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1653 return NS_OK;
michael@0 1654 }
michael@0 1655
michael@0 1656
michael@0 1657 NS_IMETHODIMP
michael@0 1658 nsAnnotationService::RemoveObserver(nsIAnnotationObserver* aObserver)
michael@0 1659 {
michael@0 1660 NS_ENSURE_ARG(aObserver);
michael@0 1661
michael@0 1662 if (!mObservers.RemoveObject(aObserver))
michael@0 1663 return NS_ERROR_INVALID_ARG;
michael@0 1664 return NS_OK;
michael@0 1665 }
michael@0 1666
michael@0 1667 nsresult
michael@0 1668 nsAnnotationService::HasAnnotationInternal(nsIURI* aURI,
michael@0 1669 int64_t aItemId,
michael@0 1670 const nsACString& aName,
michael@0 1671 bool* _hasAnno)
michael@0 1672 {
michael@0 1673 bool isItemAnnotation = (aItemId > 0);
michael@0 1674 nsCOMPtr<mozIStorageStatement> stmt;
michael@0 1675 if (isItemAnnotation) {
michael@0 1676 stmt = mDB->GetStatement(
michael@0 1677 "SELECT b.id, "
michael@0 1678 "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, "
michael@0 1679 "a.id, a.dateAdded "
michael@0 1680 "FROM moz_bookmarks b "
michael@0 1681 "LEFT JOIN moz_items_annos a ON a.item_id = b.id "
michael@0 1682 "AND a.anno_attribute_id = nameid "
michael@0 1683 "WHERE b.id = :item_id"
michael@0 1684 );
michael@0 1685 }
michael@0 1686 else {
michael@0 1687 stmt = mDB->GetStatement(
michael@0 1688 "SELECT h.id, "
michael@0 1689 "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, "
michael@0 1690 "a.id, a.dateAdded "
michael@0 1691 "FROM moz_places h "
michael@0 1692 "LEFT JOIN moz_annos a ON a.place_id = h.id "
michael@0 1693 "AND a.anno_attribute_id = nameid "
michael@0 1694 "WHERE h.url = :page_url"
michael@0 1695 );
michael@0 1696 }
michael@0 1697 NS_ENSURE_STATE(stmt);
michael@0 1698 mozStorageStatementScoper checkAnnoScoper(stmt);
michael@0 1699
michael@0 1700 nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName);
michael@0 1701 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1702 if (isItemAnnotation)
michael@0 1703 rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
michael@0 1704 else
michael@0 1705 rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI);
michael@0 1706 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1707
michael@0 1708 bool hasResult;
michael@0 1709 rv = stmt->ExecuteStep(&hasResult);
michael@0 1710 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1711 if (!hasResult) {
michael@0 1712 // We are trying to get an annotation on an invalid bookmarks or
michael@0 1713 // history entry.
michael@0 1714 // Here we preserve the old behavior, returning that we don't have the
michael@0 1715 // annotation, ignoring the fact itemId is invalid.
michael@0 1716 // Otherwise we should return NS_ERROR_INVALID_ARG, but this will somehow
michael@0 1717 // break the API. In future we could want to be pickier.
michael@0 1718 *_hasAnno = false;
michael@0 1719 }
michael@0 1720 else {
michael@0 1721 int64_t annotationId = stmt->AsInt64(2);
michael@0 1722 *_hasAnno = (annotationId > 0);
michael@0 1723 }
michael@0 1724
michael@0 1725 return NS_OK;
michael@0 1726 }
michael@0 1727
michael@0 1728
michael@0 1729 /**
michael@0 1730 * This loads the statement and steps it once so you can get data out of it.
michael@0 1731 *
michael@0 1732 * @note You have to reset the statement when you're done if this succeeds.
michael@0 1733 * @throws NS_ERROR_NOT_AVAILABLE if the annotation is not found.
michael@0 1734 */
michael@0 1735
michael@0 1736 nsresult
michael@0 1737 nsAnnotationService::StartGetAnnotation(nsIURI* aURI,
michael@0 1738 int64_t aItemId,
michael@0 1739 const nsACString& aName,
michael@0 1740 nsCOMPtr<mozIStorageStatement>& aStatement)
michael@0 1741 {
michael@0 1742 bool isItemAnnotation = (aItemId > 0);
michael@0 1743
michael@0 1744 if (isItemAnnotation) {
michael@0 1745 aStatement = mDB->GetStatement(
michael@0 1746 "SELECT a.id, a.item_id, :anno_name, a.content, a.flags, "
michael@0 1747 "a.expiration, a.type "
michael@0 1748 "FROM moz_anno_attributes n "
michael@0 1749 "JOIN moz_items_annos a ON a.anno_attribute_id = n.id "
michael@0 1750 "WHERE a.item_id = :item_id "
michael@0 1751 "AND n.name = :anno_name"
michael@0 1752 );
michael@0 1753 }
michael@0 1754 else {
michael@0 1755 aStatement = mDB->GetStatement(
michael@0 1756 "SELECT a.id, a.place_id, :anno_name, a.content, a.flags, "
michael@0 1757 "a.expiration, a.type "
michael@0 1758 "FROM moz_anno_attributes n "
michael@0 1759 "JOIN moz_annos a ON n.id = a.anno_attribute_id "
michael@0 1760 "JOIN moz_places h ON h.id = a.place_id "
michael@0 1761 "WHERE h.url = :page_url "
michael@0 1762 "AND n.name = :anno_name"
michael@0 1763 );
michael@0 1764 }
michael@0 1765 NS_ENSURE_STATE(aStatement);
michael@0 1766 mozStorageStatementScoper getAnnoScoper(aStatement);
michael@0 1767
michael@0 1768 nsresult rv;
michael@0 1769 if (isItemAnnotation)
michael@0 1770 rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
michael@0 1771 else
michael@0 1772 rv = URIBinder::Bind(aStatement, NS_LITERAL_CSTRING("page_url"), aURI);
michael@0 1773 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1774
michael@0 1775 rv = aStatement->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName);
michael@0 1776 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1777
michael@0 1778 bool hasResult = false;
michael@0 1779 rv = aStatement->ExecuteStep(&hasResult);
michael@0 1780 if (NS_FAILED(rv) || !hasResult)
michael@0 1781 return NS_ERROR_NOT_AVAILABLE;
michael@0 1782
michael@0 1783 // on success, DON'T reset the statement, the caller needs to read from it,
michael@0 1784 // and it is the caller's job to reset it.
michael@0 1785 getAnnoScoper.Abandon();
michael@0 1786
michael@0 1787 return NS_OK;
michael@0 1788 }
michael@0 1789
michael@0 1790
michael@0 1791 /**
michael@0 1792 * This does most of the setup work needed to set an annotation, except for
michael@0 1793 * binding the the actual value and executing the statement.
michael@0 1794 * It will either update an existing annotation or insert a new one.
michael@0 1795 *
michael@0 1796 * @note The aStatement RESULT IS NOT ADDREFED. This is just one of the class
michael@0 1797 * vars, which control its scope. DO NOT RELEASE.
michael@0 1798 * The caller must take care of resetting the statement if this succeeds.
michael@0 1799 */
michael@0 1800 nsresult
michael@0 1801 nsAnnotationService::StartSetAnnotation(nsIURI* aURI,
michael@0 1802 int64_t aItemId,
michael@0 1803 const nsACString& aName,
michael@0 1804 int32_t aFlags,
michael@0 1805 uint16_t aExpiration,
michael@0 1806 uint16_t aType,
michael@0 1807 nsCOMPtr<mozIStorageStatement>& aStatement)
michael@0 1808 {
michael@0 1809 bool isItemAnnotation = (aItemId > 0);
michael@0 1810
michael@0 1811 if (aExpiration == EXPIRE_SESSION) {
michael@0 1812 mHasSessionAnnotations = true;
michael@0 1813 }
michael@0 1814
michael@0 1815 // Ensure the annotation name exists.
michael@0 1816 nsCOMPtr<mozIStorageStatement> addNameStmt = mDB->GetStatement(
michael@0 1817 "INSERT OR IGNORE INTO moz_anno_attributes (name) VALUES (:anno_name)"
michael@0 1818 );
michael@0 1819 NS_ENSURE_STATE(addNameStmt);
michael@0 1820 mozStorageStatementScoper scoper(addNameStmt);
michael@0 1821
michael@0 1822 nsresult rv = addNameStmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName);
michael@0 1823 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1824 rv = addNameStmt->Execute();
michael@0 1825 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1826
michael@0 1827 // We have to check 2 things:
michael@0 1828 // - if the annotation already exists we should update it.
michael@0 1829 // - we should not allow setting annotations on invalid URIs or itemIds.
michael@0 1830 // This query will tell us:
michael@0 1831 // - whether the item or page exists.
michael@0 1832 // - whether the annotation already exists.
michael@0 1833 // - the nameID associated with the annotation name.
michael@0 1834 // - the id and dateAdded of the old annotation, if it exists.
michael@0 1835 nsCOMPtr<mozIStorageStatement> stmt;
michael@0 1836 if (isItemAnnotation) {
michael@0 1837 stmt = mDB->GetStatement(
michael@0 1838 "SELECT b.id, "
michael@0 1839 "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, "
michael@0 1840 "a.id, a.dateAdded "
michael@0 1841 "FROM moz_bookmarks b "
michael@0 1842 "LEFT JOIN moz_items_annos a ON a.item_id = b.id "
michael@0 1843 "AND a.anno_attribute_id = nameid "
michael@0 1844 "WHERE b.id = :item_id"
michael@0 1845 );
michael@0 1846 }
michael@0 1847 else {
michael@0 1848 stmt = mDB->GetStatement(
michael@0 1849 "SELECT h.id, "
michael@0 1850 "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, "
michael@0 1851 "a.id, a.dateAdded "
michael@0 1852 "FROM moz_places h "
michael@0 1853 "LEFT JOIN moz_annos a ON a.place_id = h.id "
michael@0 1854 "AND a.anno_attribute_id = nameid "
michael@0 1855 "WHERE h.url = :page_url"
michael@0 1856 );
michael@0 1857 }
michael@0 1858 NS_ENSURE_STATE(stmt);
michael@0 1859 mozStorageStatementScoper checkAnnoScoper(stmt);
michael@0 1860
michael@0 1861 rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName);
michael@0 1862 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1863 if (isItemAnnotation)
michael@0 1864 rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
michael@0 1865 else
michael@0 1866 rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI);
michael@0 1867 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1868
michael@0 1869 bool hasResult;
michael@0 1870 rv = stmt->ExecuteStep(&hasResult);
michael@0 1871 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1872 if (!hasResult) {
michael@0 1873 // We are trying to create an annotation on an invalid bookmark
michael@0 1874 // or history entry.
michael@0 1875 return NS_ERROR_INVALID_ARG;
michael@0 1876 }
michael@0 1877
michael@0 1878 int64_t fkId = stmt->AsInt64(0);
michael@0 1879 int64_t nameID = stmt->AsInt64(1);
michael@0 1880 int64_t oldAnnoId = stmt->AsInt64(2);
michael@0 1881 int64_t oldAnnoDate = stmt->AsInt64(3);
michael@0 1882
michael@0 1883 if (isItemAnnotation) {
michael@0 1884 aStatement = mDB->GetStatement(
michael@0 1885 "INSERT OR REPLACE INTO moz_items_annos "
michael@0 1886 "(id, item_id, anno_attribute_id, content, flags, "
michael@0 1887 "expiration, type, dateAdded, lastModified) "
michael@0 1888 "VALUES (:id, :fk, :name_id, :content, :flags, "
michael@0 1889 ":expiration, :type, :date_added, :last_modified)"
michael@0 1890 );
michael@0 1891 }
michael@0 1892 else {
michael@0 1893 aStatement = mDB->GetStatement(
michael@0 1894 "INSERT OR REPLACE INTO moz_annos "
michael@0 1895 "(id, place_id, anno_attribute_id, content, flags, "
michael@0 1896 "expiration, type, dateAdded, lastModified) "
michael@0 1897 "VALUES (:id, :fk, :name_id, :content, :flags, "
michael@0 1898 ":expiration, :type, :date_added, :last_modified)"
michael@0 1899 );
michael@0 1900 }
michael@0 1901 NS_ENSURE_STATE(aStatement);
michael@0 1902 mozStorageStatementScoper setAnnoScoper(aStatement);
michael@0 1903
michael@0 1904 // Don't replace existing annotations.
michael@0 1905 if (oldAnnoId > 0) {
michael@0 1906 rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("id"), oldAnnoId);
michael@0 1907 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1908 rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("date_added"), oldAnnoDate);
michael@0 1909 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1910 }
michael@0 1911 else {
michael@0 1912 rv = aStatement->BindNullByName(NS_LITERAL_CSTRING("id"));
michael@0 1913 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1914 rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("date_added"), PR_Now());
michael@0 1915 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1916 }
michael@0 1917
michael@0 1918 rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("fk"), fkId);
michael@0 1919 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1920 rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("name_id"), nameID);
michael@0 1921 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1922
michael@0 1923 rv = aStatement->BindInt32ByName(NS_LITERAL_CSTRING("flags"), aFlags);
michael@0 1924 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1925 rv = aStatement->BindInt32ByName(NS_LITERAL_CSTRING("expiration"), aExpiration);
michael@0 1926 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1927 rv = aStatement->BindInt32ByName(NS_LITERAL_CSTRING("type"), aType);
michael@0 1928 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1929 rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("last_modified"), PR_Now());
michael@0 1930 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1931
michael@0 1932 // On success, leave the statement open, the caller will set the value
michael@0 1933 // and execute the statement.
michael@0 1934 setAnnoScoper.Abandon();
michael@0 1935
michael@0 1936 return NS_OK;
michael@0 1937 }
michael@0 1938
michael@0 1939 ////////////////////////////////////////////////////////////////////////////////
michael@0 1940 //// nsIObserver
michael@0 1941
michael@0 1942 NS_IMETHODIMP
michael@0 1943 nsAnnotationService::Observe(nsISupports *aSubject,
michael@0 1944 const char *aTopic,
michael@0 1945 const char16_t *aData)
michael@0 1946 {
michael@0 1947 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
michael@0 1948
michael@0 1949 if (strcmp(aTopic, TOPIC_PLACES_SHUTDOWN) == 0) {
michael@0 1950 // Remove all session annotations, if any.
michael@0 1951 if (mHasSessionAnnotations) {
michael@0 1952 nsCOMPtr<mozIStorageAsyncStatement> pageAnnoStmt = mDB->GetAsyncStatement(
michael@0 1953 "DELETE FROM moz_annos WHERE expiration = :expire_session"
michael@0 1954 );
michael@0 1955 NS_ENSURE_STATE(pageAnnoStmt);
michael@0 1956 nsresult rv = pageAnnoStmt->BindInt32ByName(NS_LITERAL_CSTRING("expire_session"),
michael@0 1957 EXPIRE_SESSION);
michael@0 1958 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1959
michael@0 1960 nsCOMPtr<mozIStorageAsyncStatement> itemAnnoStmt = mDB->GetAsyncStatement(
michael@0 1961 "DELETE FROM moz_items_annos WHERE expiration = :expire_session"
michael@0 1962 );
michael@0 1963 NS_ENSURE_STATE(itemAnnoStmt);
michael@0 1964 rv = itemAnnoStmt->BindInt32ByName(NS_LITERAL_CSTRING("expire_session"),
michael@0 1965 EXPIRE_SESSION);
michael@0 1966 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1967
michael@0 1968 mozIStorageBaseStatement *stmts[] = {
michael@0 1969 pageAnnoStmt.get()
michael@0 1970 , itemAnnoStmt.get()
michael@0 1971 };
michael@0 1972
michael@0 1973 nsCOMPtr<mozIStoragePendingStatement> ps;
michael@0 1974 rv = mDB->MainConn()->ExecuteAsync(stmts, ArrayLength(stmts), nullptr,
michael@0 1975 getter_AddRefs(ps));
michael@0 1976 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1977 }
michael@0 1978 }
michael@0 1979
michael@0 1980 return NS_OK;
michael@0 1981 }

mercurial