1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/places/nsAnnotationService.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1981 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 + 1.11 +#include "nsAnnotationService.h" 1.12 +#include "nsNavHistory.h" 1.13 +#include "nsPlacesTables.h" 1.14 +#include "nsPlacesIndexes.h" 1.15 +#include "nsPlacesMacros.h" 1.16 +#include "Helpers.h" 1.17 + 1.18 +#include "nsNetUtil.h" 1.19 +#include "nsIVariant.h" 1.20 +#include "nsString.h" 1.21 +#include "nsVariant.h" 1.22 +#include "mozilla/storage.h" 1.23 + 1.24 +#include "GeckoProfiler.h" 1.25 + 1.26 +#include "nsNetCID.h" 1.27 + 1.28 +using namespace mozilla; 1.29 +using namespace mozilla::places; 1.30 + 1.31 +#define ENSURE_ANNO_TYPE(_type, _statement) \ 1.32 + PR_BEGIN_MACRO \ 1.33 + int32_t type = _statement->AsInt32(kAnnoIndex_Type); \ 1.34 + NS_ENSURE_TRUE(type == nsIAnnotationService::_type, NS_ERROR_INVALID_ARG); \ 1.35 + PR_END_MACRO 1.36 + 1.37 +#define NOTIFY_ANNOS_OBSERVERS(_notification) \ 1.38 + PR_BEGIN_MACRO \ 1.39 + for (int32_t i = 0; i < mObservers.Count(); i++) \ 1.40 + mObservers[i]->_notification; \ 1.41 + PR_END_MACRO 1.42 + 1.43 +const int32_t nsAnnotationService::kAnnoIndex_ID = 0; 1.44 +const int32_t nsAnnotationService::kAnnoIndex_PageOrItem = 1; 1.45 +const int32_t nsAnnotationService::kAnnoIndex_NameID = 2; 1.46 +const int32_t nsAnnotationService::kAnnoIndex_Content = 3; 1.47 +const int32_t nsAnnotationService::kAnnoIndex_Flags = 4; 1.48 +const int32_t nsAnnotationService::kAnnoIndex_Expiration = 5; 1.49 +const int32_t nsAnnotationService::kAnnoIndex_Type = 6; 1.50 +const int32_t nsAnnotationService::kAnnoIndex_DateAdded = 7; 1.51 +const int32_t nsAnnotationService::kAnnoIndex_LastModified = 8; 1.52 + 1.53 +namespace mozilla { 1.54 +namespace places { 1.55 + 1.56 +//////////////////////////////////////////////////////////////////////////////// 1.57 +//// AnnotatedResult 1.58 + 1.59 +AnnotatedResult::AnnotatedResult(const nsCString& aGUID, 1.60 + nsIURI* aURI, 1.61 + int64_t aItemId, 1.62 + const nsACString& aAnnotationName, 1.63 + nsIVariant* aAnnotationValue) 1.64 +: mGUID(aGUID) 1.65 +, mURI(aURI) 1.66 +, mItemId(aItemId) 1.67 +, mAnnotationName(aAnnotationName) 1.68 +, mAnnotationValue(aAnnotationValue) 1.69 +{ 1.70 +} 1.71 + 1.72 +NS_IMETHODIMP 1.73 +AnnotatedResult::GetGuid(nsACString& _guid) 1.74 +{ 1.75 + _guid = mGUID; 1.76 + return NS_OK; 1.77 +} 1.78 + 1.79 +NS_IMETHODIMP 1.80 +AnnotatedResult::GetUri(nsIURI** _uri) 1.81 +{ 1.82 + NS_IF_ADDREF(*_uri = mURI); 1.83 + return NS_OK; 1.84 +} 1.85 + 1.86 +NS_IMETHODIMP 1.87 +AnnotatedResult::GetItemId(int64_t* _itemId) 1.88 +{ 1.89 + *_itemId = mItemId; 1.90 + return NS_OK; 1.91 +} 1.92 + 1.93 +NS_IMETHODIMP 1.94 +AnnotatedResult::GetAnnotationName(nsACString& _annotationName) 1.95 +{ 1.96 + _annotationName = mAnnotationName; 1.97 + return NS_OK; 1.98 +} 1.99 + 1.100 +NS_IMETHODIMP 1.101 +AnnotatedResult::GetAnnotationValue(nsIVariant** _annotationValue) 1.102 +{ 1.103 + NS_IF_ADDREF(*_annotationValue = mAnnotationValue); 1.104 + return NS_OK; 1.105 +} 1.106 + 1.107 +NS_IMPL_ISUPPORTS(AnnotatedResult, mozIAnnotatedResult) 1.108 + 1.109 +} // namespace places 1.110 +} // namespace mozilla 1.111 + 1.112 +PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsAnnotationService, gAnnotationService) 1.113 + 1.114 +NS_IMPL_ISUPPORTS(nsAnnotationService 1.115 +, nsIAnnotationService 1.116 +, nsIObserver 1.117 +, nsISupportsWeakReference 1.118 +) 1.119 + 1.120 + 1.121 +nsAnnotationService::nsAnnotationService() 1.122 + : mHasSessionAnnotations(false) 1.123 +{ 1.124 + NS_ASSERTION(!gAnnotationService, 1.125 + "Attempting to create two instances of the service!"); 1.126 + gAnnotationService = this; 1.127 +} 1.128 + 1.129 + 1.130 +nsAnnotationService::~nsAnnotationService() 1.131 +{ 1.132 + NS_ASSERTION(gAnnotationService == this, 1.133 + "Deleting a non-singleton instance of the service"); 1.134 + if (gAnnotationService == this) 1.135 + gAnnotationService = nullptr; 1.136 +} 1.137 + 1.138 + 1.139 +nsresult 1.140 +nsAnnotationService::Init() 1.141 +{ 1.142 + mDB = Database::GetDatabase(); 1.143 + NS_ENSURE_STATE(mDB); 1.144 + 1.145 + nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService(); 1.146 + if (obsSvc) { 1.147 + (void)obsSvc->AddObserver(this, TOPIC_PLACES_SHUTDOWN, true); 1.148 + } 1.149 + 1.150 + return NS_OK; 1.151 +} 1.152 + 1.153 +nsresult 1.154 +nsAnnotationService::SetAnnotationStringInternal(nsIURI* aURI, 1.155 + int64_t aItemId, 1.156 + const nsACString& aName, 1.157 + const nsAString& aValue, 1.158 + int32_t aFlags, 1.159 + uint16_t aExpiration) 1.160 +{ 1.161 + mozStorageTransaction transaction(mDB->MainConn(), false); 1.162 + nsCOMPtr<mozIStorageStatement> statement; 1.163 + nsresult rv = StartSetAnnotation(aURI, aItemId, aName, aFlags, aExpiration, 1.164 + nsIAnnotationService::TYPE_STRING, 1.165 + statement); 1.166 + NS_ENSURE_SUCCESS(rv, rv); 1.167 + mozStorageStatementScoper scoper(statement); 1.168 + 1.169 + rv = statement->BindStringByName(NS_LITERAL_CSTRING("content"), aValue); 1.170 + NS_ENSURE_SUCCESS(rv, rv); 1.171 + 1.172 + rv = statement->Execute(); 1.173 + NS_ENSURE_SUCCESS(rv, rv); 1.174 + 1.175 + rv = transaction.Commit(); 1.176 + NS_ENSURE_SUCCESS(rv, rv); 1.177 + 1.178 + return NS_OK; 1.179 +} 1.180 + 1.181 + 1.182 +NS_IMETHODIMP 1.183 +nsAnnotationService::SetPageAnnotation(nsIURI* aURI, 1.184 + const nsACString& aName, 1.185 + nsIVariant* aValue, 1.186 + int32_t aFlags, 1.187 + uint16_t aExpiration) 1.188 +{ 1.189 + NS_ENSURE_ARG(aURI); 1.190 + NS_ENSURE_ARG(aValue); 1.191 + 1.192 + uint16_t dataType; 1.193 + nsresult rv = aValue->GetDataType(&dataType); 1.194 + NS_ENSURE_SUCCESS(rv, rv); 1.195 + 1.196 + switch (dataType) { 1.197 + case nsIDataType::VTYPE_INT8: 1.198 + case nsIDataType::VTYPE_UINT8: 1.199 + case nsIDataType::VTYPE_INT16: 1.200 + case nsIDataType::VTYPE_UINT16: 1.201 + case nsIDataType::VTYPE_INT32: 1.202 + case nsIDataType::VTYPE_UINT32: 1.203 + case nsIDataType::VTYPE_BOOL: { 1.204 + int32_t valueInt; 1.205 + rv = aValue->GetAsInt32(&valueInt); 1.206 + if (NS_SUCCEEDED(rv)) { 1.207 + NS_ENSURE_SUCCESS(rv, rv); 1.208 + rv = SetPageAnnotationInt32(aURI, aName, valueInt, aFlags, aExpiration); 1.209 + NS_ENSURE_SUCCESS(rv, rv); 1.210 + return NS_OK; 1.211 + } 1.212 + // Fall through int64_t case otherwise. 1.213 + } 1.214 + case nsIDataType::VTYPE_INT64: 1.215 + case nsIDataType::VTYPE_UINT64: { 1.216 + int64_t valueLong; 1.217 + rv = aValue->GetAsInt64(&valueLong); 1.218 + if (NS_SUCCEEDED(rv)) { 1.219 + NS_ENSURE_SUCCESS(rv, rv); 1.220 + rv = SetPageAnnotationInt64(aURI, aName, valueLong, aFlags, aExpiration); 1.221 + NS_ENSURE_SUCCESS(rv, rv); 1.222 + return NS_OK; 1.223 + } 1.224 + // Fall through double case otherwise. 1.225 + } 1.226 + case nsIDataType::VTYPE_FLOAT: 1.227 + case nsIDataType::VTYPE_DOUBLE: { 1.228 + double valueDouble; 1.229 + rv = aValue->GetAsDouble(&valueDouble); 1.230 + NS_ENSURE_SUCCESS(rv, rv); 1.231 + rv = SetPageAnnotationDouble(aURI, aName, valueDouble, aFlags, aExpiration); 1.232 + NS_ENSURE_SUCCESS(rv, rv); 1.233 + return NS_OK; 1.234 + } 1.235 + case nsIDataType::VTYPE_CHAR: 1.236 + case nsIDataType::VTYPE_WCHAR: 1.237 + case nsIDataType::VTYPE_DOMSTRING: 1.238 + case nsIDataType::VTYPE_CHAR_STR: 1.239 + case nsIDataType::VTYPE_WCHAR_STR: 1.240 + case nsIDataType::VTYPE_STRING_SIZE_IS: 1.241 + case nsIDataType::VTYPE_WSTRING_SIZE_IS: 1.242 + case nsIDataType::VTYPE_UTF8STRING: 1.243 + case nsIDataType::VTYPE_CSTRING: 1.244 + case nsIDataType::VTYPE_ASTRING: { 1.245 + nsAutoString stringValue; 1.246 + rv = aValue->GetAsAString(stringValue); 1.247 + NS_ENSURE_SUCCESS(rv, rv); 1.248 + rv = SetPageAnnotationString(aURI, aName, stringValue, aFlags, aExpiration); 1.249 + NS_ENSURE_SUCCESS(rv, rv); 1.250 + return NS_OK; 1.251 + } 1.252 + } 1.253 + 1.254 + return NS_ERROR_NOT_IMPLEMENTED; 1.255 +} 1.256 + 1.257 + 1.258 +NS_IMETHODIMP 1.259 +nsAnnotationService::SetItemAnnotation(int64_t aItemId, 1.260 + const nsACString& aName, 1.261 + nsIVariant* aValue, 1.262 + int32_t aFlags, 1.263 + uint16_t aExpiration) 1.264 +{ 1.265 + PROFILER_LABEL("AnnotationService", "SetItemAnnotation"); 1.266 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.267 + NS_ENSURE_ARG(aValue); 1.268 + 1.269 + if (aExpiration == EXPIRE_WITH_HISTORY) 1.270 + return NS_ERROR_INVALID_ARG; 1.271 + 1.272 + uint16_t dataType; 1.273 + nsresult rv = aValue->GetDataType(&dataType); 1.274 + NS_ENSURE_SUCCESS(rv, rv); 1.275 + 1.276 + switch (dataType) { 1.277 + case nsIDataType::VTYPE_INT8: 1.278 + case nsIDataType::VTYPE_UINT8: 1.279 + case nsIDataType::VTYPE_INT16: 1.280 + case nsIDataType::VTYPE_UINT16: 1.281 + case nsIDataType::VTYPE_INT32: 1.282 + case nsIDataType::VTYPE_UINT32: 1.283 + case nsIDataType::VTYPE_BOOL: { 1.284 + int32_t valueInt; 1.285 + rv = aValue->GetAsInt32(&valueInt); 1.286 + if (NS_SUCCEEDED(rv)) { 1.287 + NS_ENSURE_SUCCESS(rv, rv); 1.288 + rv = SetItemAnnotationInt32(aItemId, aName, valueInt, aFlags, aExpiration); 1.289 + NS_ENSURE_SUCCESS(rv, rv); 1.290 + return NS_OK; 1.291 + } 1.292 + // Fall through int64_t case otherwise. 1.293 + } 1.294 + case nsIDataType::VTYPE_INT64: 1.295 + case nsIDataType::VTYPE_UINT64: { 1.296 + int64_t valueLong; 1.297 + rv = aValue->GetAsInt64(&valueLong); 1.298 + if (NS_SUCCEEDED(rv)) { 1.299 + NS_ENSURE_SUCCESS(rv, rv); 1.300 + rv = SetItemAnnotationInt64(aItemId, aName, valueLong, aFlags, aExpiration); 1.301 + NS_ENSURE_SUCCESS(rv, rv); 1.302 + return NS_OK; 1.303 + } 1.304 + // Fall through double case otherwise. 1.305 + } 1.306 + case nsIDataType::VTYPE_FLOAT: 1.307 + case nsIDataType::VTYPE_DOUBLE: { 1.308 + double valueDouble; 1.309 + rv = aValue->GetAsDouble(&valueDouble); 1.310 + NS_ENSURE_SUCCESS(rv, rv); 1.311 + rv = SetItemAnnotationDouble(aItemId, aName, valueDouble, aFlags, aExpiration); 1.312 + NS_ENSURE_SUCCESS(rv, rv); 1.313 + return NS_OK; 1.314 + } 1.315 + case nsIDataType::VTYPE_CHAR: 1.316 + case nsIDataType::VTYPE_WCHAR: 1.317 + case nsIDataType::VTYPE_DOMSTRING: 1.318 + case nsIDataType::VTYPE_CHAR_STR: 1.319 + case nsIDataType::VTYPE_WCHAR_STR: 1.320 + case nsIDataType::VTYPE_STRING_SIZE_IS: 1.321 + case nsIDataType::VTYPE_WSTRING_SIZE_IS: 1.322 + case nsIDataType::VTYPE_UTF8STRING: 1.323 + case nsIDataType::VTYPE_CSTRING: 1.324 + case nsIDataType::VTYPE_ASTRING: { 1.325 + nsAutoString stringValue; 1.326 + rv = aValue->GetAsAString(stringValue); 1.327 + NS_ENSURE_SUCCESS(rv, rv); 1.328 + rv = SetItemAnnotationString(aItemId, aName, stringValue, aFlags, aExpiration); 1.329 + NS_ENSURE_SUCCESS(rv, rv); 1.330 + return NS_OK; 1.331 + } 1.332 + } 1.333 + 1.334 + return NS_ERROR_NOT_IMPLEMENTED; 1.335 +} 1.336 + 1.337 + 1.338 +NS_IMETHODIMP 1.339 +nsAnnotationService::SetPageAnnotationString(nsIURI* aURI, 1.340 + const nsACString& aName, 1.341 + const nsAString& aValue, 1.342 + int32_t aFlags, 1.343 + uint16_t aExpiration) 1.344 +{ 1.345 + NS_ENSURE_ARG(aURI); 1.346 + 1.347 + nsresult rv = SetAnnotationStringInternal(aURI, 0, aName, aValue, 1.348 + aFlags, aExpiration); 1.349 + NS_ENSURE_SUCCESS(rv, rv); 1.350 + 1.351 + NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aURI, aName)); 1.352 + 1.353 + return NS_OK; 1.354 +} 1.355 + 1.356 + 1.357 +NS_IMETHODIMP 1.358 +nsAnnotationService::SetItemAnnotationString(int64_t aItemId, 1.359 + const nsACString& aName, 1.360 + const nsAString& aValue, 1.361 + int32_t aFlags, 1.362 + uint16_t aExpiration) 1.363 +{ 1.364 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.365 + 1.366 + if (aExpiration == EXPIRE_WITH_HISTORY) 1.367 + return NS_ERROR_INVALID_ARG; 1.368 + 1.369 + nsresult rv = SetAnnotationStringInternal(nullptr, aItemId, aName, aValue, 1.370 + aFlags, aExpiration); 1.371 + NS_ENSURE_SUCCESS(rv, rv); 1.372 + 1.373 + NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName)); 1.374 + 1.375 + return NS_OK; 1.376 +} 1.377 + 1.378 + 1.379 +nsresult 1.380 +nsAnnotationService::SetAnnotationInt32Internal(nsIURI* aURI, 1.381 + int64_t aItemId, 1.382 + const nsACString& aName, 1.383 + int32_t aValue, 1.384 + int32_t aFlags, 1.385 + uint16_t aExpiration) 1.386 +{ 1.387 + mozStorageTransaction transaction(mDB->MainConn(), false); 1.388 + nsCOMPtr<mozIStorageStatement> statement; 1.389 + nsresult rv = StartSetAnnotation(aURI, aItemId, aName, aFlags, aExpiration, 1.390 + nsIAnnotationService::TYPE_INT32, 1.391 + statement); 1.392 + NS_ENSURE_SUCCESS(rv, rv); 1.393 + mozStorageStatementScoper scoper(statement); 1.394 + 1.395 + rv = statement->BindInt32ByName(NS_LITERAL_CSTRING("content"), aValue); 1.396 + NS_ENSURE_SUCCESS(rv, rv); 1.397 + 1.398 + rv = statement->Execute(); 1.399 + NS_ENSURE_SUCCESS(rv, rv); 1.400 + 1.401 + rv = transaction.Commit(); 1.402 + NS_ENSURE_SUCCESS(rv, rv); 1.403 + 1.404 + return NS_OK; 1.405 +} 1.406 + 1.407 + 1.408 +NS_IMETHODIMP 1.409 +nsAnnotationService::SetPageAnnotationInt32(nsIURI* aURI, 1.410 + const nsACString& aName, 1.411 + int32_t aValue, 1.412 + int32_t aFlags, 1.413 + uint16_t aExpiration) 1.414 +{ 1.415 + NS_ENSURE_ARG(aURI); 1.416 + 1.417 + nsresult rv = SetAnnotationInt32Internal(aURI, 0, aName, aValue, 1.418 + aFlags, aExpiration); 1.419 + NS_ENSURE_SUCCESS(rv, rv); 1.420 + 1.421 + NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aURI, aName)); 1.422 + 1.423 + return NS_OK; 1.424 +} 1.425 + 1.426 + 1.427 +NS_IMETHODIMP 1.428 +nsAnnotationService::SetItemAnnotationInt32(int64_t aItemId, 1.429 + const nsACString& aName, 1.430 + int32_t aValue, 1.431 + int32_t aFlags, 1.432 + uint16_t aExpiration) 1.433 +{ 1.434 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.435 + 1.436 + if (aExpiration == EXPIRE_WITH_HISTORY) 1.437 + return NS_ERROR_INVALID_ARG; 1.438 + 1.439 + nsresult rv = SetAnnotationInt32Internal(nullptr, aItemId, aName, aValue, 1.440 + aFlags, aExpiration); 1.441 + NS_ENSURE_SUCCESS(rv, rv); 1.442 + 1.443 + NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName)); 1.444 + 1.445 + return NS_OK; 1.446 +} 1.447 + 1.448 + 1.449 +nsresult 1.450 +nsAnnotationService::SetAnnotationInt64Internal(nsIURI* aURI, 1.451 + int64_t aItemId, 1.452 + const nsACString& aName, 1.453 + int64_t aValue, 1.454 + int32_t aFlags, 1.455 + uint16_t aExpiration) 1.456 +{ 1.457 + mozStorageTransaction transaction(mDB->MainConn(), false); 1.458 + nsCOMPtr<mozIStorageStatement> statement; 1.459 + nsresult rv = StartSetAnnotation(aURI, aItemId, aName, aFlags, aExpiration, 1.460 + nsIAnnotationService::TYPE_INT64, 1.461 + statement); 1.462 + NS_ENSURE_SUCCESS(rv, rv); 1.463 + mozStorageStatementScoper scoper(statement); 1.464 + 1.465 + rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("content"), aValue); 1.466 + NS_ENSURE_SUCCESS(rv, rv); 1.467 + 1.468 + rv = statement->Execute(); 1.469 + NS_ENSURE_SUCCESS(rv, rv); 1.470 + 1.471 + rv = transaction.Commit(); 1.472 + NS_ENSURE_SUCCESS(rv, rv); 1.473 + 1.474 + return NS_OK; 1.475 +} 1.476 + 1.477 + 1.478 +NS_IMETHODIMP 1.479 +nsAnnotationService::SetPageAnnotationInt64(nsIURI* aURI, 1.480 + const nsACString& aName, 1.481 + int64_t aValue, 1.482 + int32_t aFlags, 1.483 + uint16_t aExpiration) 1.484 +{ 1.485 + NS_ENSURE_ARG(aURI); 1.486 + 1.487 + nsresult rv = SetAnnotationInt64Internal(aURI, 0, aName, aValue, 1.488 + aFlags, aExpiration); 1.489 + NS_ENSURE_SUCCESS(rv, rv); 1.490 + 1.491 + NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aURI, aName)); 1.492 + 1.493 + return NS_OK; 1.494 +} 1.495 + 1.496 + 1.497 +NS_IMETHODIMP 1.498 +nsAnnotationService::SetItemAnnotationInt64(int64_t aItemId, 1.499 + const nsACString& aName, 1.500 + int64_t aValue, 1.501 + int32_t aFlags, 1.502 + uint16_t aExpiration) 1.503 +{ 1.504 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.505 + 1.506 + if (aExpiration == EXPIRE_WITH_HISTORY) 1.507 + return NS_ERROR_INVALID_ARG; 1.508 + 1.509 + nsresult rv = SetAnnotationInt64Internal(nullptr, aItemId, aName, aValue, 1.510 + aFlags, aExpiration); 1.511 + NS_ENSURE_SUCCESS(rv, rv); 1.512 + 1.513 + NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName)); 1.514 + 1.515 + return NS_OK; 1.516 +} 1.517 + 1.518 + 1.519 +nsresult 1.520 +nsAnnotationService::SetAnnotationDoubleInternal(nsIURI* aURI, 1.521 + int64_t aItemId, 1.522 + const nsACString& aName, 1.523 + double aValue, 1.524 + int32_t aFlags, 1.525 + uint16_t aExpiration) 1.526 +{ 1.527 + mozStorageTransaction transaction(mDB->MainConn(), false); 1.528 + nsCOMPtr<mozIStorageStatement> statement; 1.529 + nsresult rv = StartSetAnnotation(aURI, aItemId, aName, aFlags, aExpiration, 1.530 + nsIAnnotationService::TYPE_DOUBLE, 1.531 + statement); 1.532 + NS_ENSURE_SUCCESS(rv, rv); 1.533 + mozStorageStatementScoper scoper(statement); 1.534 + 1.535 + rv = statement->BindDoubleByName(NS_LITERAL_CSTRING("content"), aValue); 1.536 + NS_ENSURE_SUCCESS(rv, rv); 1.537 + 1.538 + rv = statement->Execute(); 1.539 + NS_ENSURE_SUCCESS(rv, rv); 1.540 + 1.541 + rv = transaction.Commit(); 1.542 + NS_ENSURE_SUCCESS(rv, rv); 1.543 + 1.544 + return NS_OK; 1.545 +} 1.546 + 1.547 + 1.548 +NS_IMETHODIMP 1.549 +nsAnnotationService::SetPageAnnotationDouble(nsIURI* aURI, 1.550 + const nsACString& aName, 1.551 + double aValue, 1.552 + int32_t aFlags, 1.553 + uint16_t aExpiration) 1.554 +{ 1.555 + NS_ENSURE_ARG(aURI); 1.556 + 1.557 + nsresult rv = SetAnnotationDoubleInternal(aURI, 0, aName, aValue, 1.558 + aFlags, aExpiration); 1.559 + NS_ENSURE_SUCCESS(rv, rv); 1.560 + 1.561 + NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aURI, aName)); 1.562 + 1.563 + return NS_OK; 1.564 +} 1.565 + 1.566 + 1.567 +NS_IMETHODIMP 1.568 +nsAnnotationService::SetItemAnnotationDouble(int64_t aItemId, 1.569 + const nsACString& aName, 1.570 + double aValue, 1.571 + int32_t aFlags, 1.572 + uint16_t aExpiration) 1.573 +{ 1.574 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.575 + 1.576 + if (aExpiration == EXPIRE_WITH_HISTORY) 1.577 + return NS_ERROR_INVALID_ARG; 1.578 + 1.579 + nsresult rv = SetAnnotationDoubleInternal(nullptr, aItemId, aName, aValue, 1.580 + aFlags, aExpiration); 1.581 + NS_ENSURE_SUCCESS(rv, rv); 1.582 + 1.583 + NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aItemId, aName)); 1.584 + 1.585 + return NS_OK; 1.586 +} 1.587 + 1.588 +NS_IMETHODIMP 1.589 +nsAnnotationService::GetPageAnnotationString(nsIURI* aURI, 1.590 + const nsACString& aName, 1.591 + nsAString& _retval) 1.592 +{ 1.593 + NS_ENSURE_ARG(aURI); 1.594 + 1.595 + nsCOMPtr<mozIStorageStatement> statement; 1.596 + nsresult rv = StartGetAnnotation(aURI, 0, aName, statement); 1.597 + if (NS_FAILED(rv)) 1.598 + return rv; 1.599 + 1.600 + mozStorageStatementScoper scoper(statement); 1.601 + ENSURE_ANNO_TYPE(TYPE_STRING, statement); 1.602 + rv = statement->GetString(kAnnoIndex_Content, _retval); 1.603 + NS_ENSURE_SUCCESS(rv, rv); 1.604 + 1.605 + return NS_OK; 1.606 +} 1.607 + 1.608 + 1.609 +NS_IMETHODIMP 1.610 +nsAnnotationService::GetItemAnnotationString(int64_t aItemId, 1.611 + const nsACString& aName, 1.612 + nsAString& _retval) 1.613 +{ 1.614 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.615 + 1.616 + nsCOMPtr<mozIStorageStatement> statement; 1.617 + nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement); 1.618 + if (NS_FAILED(rv)) 1.619 + return rv; 1.620 + 1.621 + mozStorageStatementScoper scoper(statement); 1.622 + ENSURE_ANNO_TYPE(TYPE_STRING, statement); 1.623 + rv = statement->GetString(kAnnoIndex_Content, _retval); 1.624 + NS_ENSURE_SUCCESS(rv, rv); 1.625 + 1.626 + return NS_OK; 1.627 +} 1.628 + 1.629 + 1.630 +NS_IMETHODIMP 1.631 +nsAnnotationService::GetPageAnnotation(nsIURI* aURI, 1.632 + const nsACString& aName, 1.633 + nsIVariant** _retval) 1.634 +{ 1.635 + NS_ENSURE_ARG(aURI); 1.636 + NS_ENSURE_ARG_POINTER(_retval); 1.637 + 1.638 + nsCOMPtr<mozIStorageStatement> statement; 1.639 + nsresult rv = StartGetAnnotation(aURI, 0, aName, statement); 1.640 + if (NS_FAILED(rv)) 1.641 + return rv; 1.642 + 1.643 + mozStorageStatementScoper scoper(statement); 1.644 + 1.645 + nsCOMPtr<nsIWritableVariant> value = new nsVariant(); 1.646 + int32_t type = statement->AsInt32(kAnnoIndex_Type); 1.647 + switch (type) { 1.648 + case nsIAnnotationService::TYPE_INT32: 1.649 + case nsIAnnotationService::TYPE_INT64: 1.650 + case nsIAnnotationService::TYPE_DOUBLE: { 1.651 + rv = value->SetAsDouble(statement->AsDouble(kAnnoIndex_Content)); 1.652 + break; 1.653 + } 1.654 + case nsIAnnotationService::TYPE_STRING: { 1.655 + nsAutoString valueString; 1.656 + rv = statement->GetString(kAnnoIndex_Content, valueString); 1.657 + if (NS_SUCCEEDED(rv)) 1.658 + rv = value->SetAsAString(valueString); 1.659 + break; 1.660 + } 1.661 + default: { 1.662 + rv = NS_ERROR_UNEXPECTED; 1.663 + break; 1.664 + } 1.665 + } 1.666 + 1.667 + if (NS_SUCCEEDED(rv)) 1.668 + NS_ADDREF(*_retval = value); 1.669 + 1.670 + return rv; 1.671 +} 1.672 + 1.673 + 1.674 +NS_IMETHODIMP 1.675 +nsAnnotationService::GetItemAnnotation(int64_t aItemId, 1.676 + const nsACString& aName, 1.677 + nsIVariant** _retval) 1.678 +{ 1.679 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.680 + NS_ENSURE_ARG_POINTER(_retval); 1.681 + 1.682 + nsCOMPtr<mozIStorageStatement> statement; 1.683 + nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement); 1.684 + if (NS_FAILED(rv)) 1.685 + return rv; 1.686 + 1.687 + mozStorageStatementScoper scoper(statement); 1.688 + 1.689 + nsCOMPtr<nsIWritableVariant> value = new nsVariant(); 1.690 + int32_t type = statement->AsInt32(kAnnoIndex_Type); 1.691 + switch (type) { 1.692 + case nsIAnnotationService::TYPE_INT32: 1.693 + case nsIAnnotationService::TYPE_INT64: 1.694 + case nsIAnnotationService::TYPE_DOUBLE: { 1.695 + rv = value->SetAsDouble(statement->AsDouble(kAnnoIndex_Content)); 1.696 + break; 1.697 + } 1.698 + case nsIAnnotationService::TYPE_STRING: { 1.699 + nsAutoString valueString; 1.700 + rv = statement->GetString(kAnnoIndex_Content, valueString); 1.701 + if (NS_SUCCEEDED(rv)) 1.702 + rv = value->SetAsAString(valueString); 1.703 + break; 1.704 + } 1.705 + default: { 1.706 + rv = NS_ERROR_UNEXPECTED; 1.707 + break; 1.708 + } 1.709 + } 1.710 + 1.711 + if (NS_SUCCEEDED(rv)) 1.712 + NS_ADDREF(*_retval = value); 1.713 + 1.714 + return rv; 1.715 +} 1.716 + 1.717 + 1.718 +NS_IMETHODIMP 1.719 +nsAnnotationService::GetPageAnnotationInt32(nsIURI* aURI, 1.720 + const nsACString& aName, 1.721 + int32_t* _retval) 1.722 +{ 1.723 + NS_ENSURE_ARG(aURI); 1.724 + NS_ENSURE_ARG_POINTER(_retval); 1.725 + 1.726 + nsCOMPtr<mozIStorageStatement> statement; 1.727 + nsresult rv = StartGetAnnotation(aURI, 0, aName, statement); 1.728 + if (NS_FAILED(rv)) 1.729 + return rv; 1.730 + 1.731 + mozStorageStatementScoper scoper(statement); 1.732 + ENSURE_ANNO_TYPE(TYPE_INT32, statement); 1.733 + *_retval = statement->AsInt32(kAnnoIndex_Content); 1.734 + NS_ENSURE_SUCCESS(rv, rv); 1.735 + 1.736 + return NS_OK; 1.737 +} 1.738 + 1.739 + 1.740 +NS_IMETHODIMP 1.741 +nsAnnotationService::GetItemAnnotationInt32(int64_t aItemId, 1.742 + const nsACString& aName, 1.743 + int32_t* _retval) 1.744 +{ 1.745 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.746 + NS_ENSURE_ARG_POINTER(_retval); 1.747 + 1.748 + nsCOMPtr<mozIStorageStatement> statement; 1.749 + nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement); 1.750 + if (NS_FAILED(rv)) 1.751 + return rv; 1.752 + 1.753 + mozStorageStatementScoper scoper(statement); 1.754 + ENSURE_ANNO_TYPE(TYPE_INT32, statement); 1.755 + *_retval = statement->AsInt32(kAnnoIndex_Content); 1.756 + 1.757 + return NS_OK; 1.758 +} 1.759 + 1.760 + 1.761 +NS_IMETHODIMP 1.762 +nsAnnotationService::GetPageAnnotationInt64(nsIURI* aURI, 1.763 + const nsACString& aName, 1.764 + int64_t* _retval) 1.765 +{ 1.766 + NS_ENSURE_ARG(aURI); 1.767 + NS_ENSURE_ARG_POINTER(_retval); 1.768 + 1.769 + nsCOMPtr<mozIStorageStatement> statement; 1.770 + nsresult rv = StartGetAnnotation(aURI, 0, aName, statement); 1.771 + if (NS_FAILED(rv)) 1.772 + return rv; 1.773 + 1.774 + mozStorageStatementScoper scoper(statement); 1.775 + ENSURE_ANNO_TYPE(TYPE_INT64, statement); 1.776 + *_retval = statement->AsInt64(kAnnoIndex_Content); 1.777 + 1.778 + return NS_OK; 1.779 +} 1.780 + 1.781 + 1.782 +NS_IMETHODIMP 1.783 +nsAnnotationService::GetItemAnnotationInt64(int64_t aItemId, 1.784 + const nsACString& aName, 1.785 + int64_t* _retval) 1.786 +{ 1.787 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.788 + NS_ENSURE_ARG_POINTER(_retval); 1.789 + 1.790 + nsCOMPtr<mozIStorageStatement> statement; 1.791 + nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement); 1.792 + if (NS_FAILED(rv)) 1.793 + return rv; 1.794 + 1.795 + mozStorageStatementScoper scoper(statement); 1.796 + ENSURE_ANNO_TYPE(TYPE_INT64, statement); 1.797 + *_retval = statement->AsInt64(kAnnoIndex_Content); 1.798 + 1.799 + return NS_OK; 1.800 +} 1.801 + 1.802 + 1.803 +NS_IMETHODIMP 1.804 +nsAnnotationService::GetPageAnnotationType(nsIURI* aURI, 1.805 + const nsACString& aName, 1.806 + uint16_t* _retval) 1.807 +{ 1.808 + NS_ENSURE_ARG(aURI); 1.809 + NS_ENSURE_ARG_POINTER(_retval); 1.810 + 1.811 + nsCOMPtr<mozIStorageStatement> statement; 1.812 + nsresult rv = StartGetAnnotation(aURI, 0, aName, statement); 1.813 + if (NS_FAILED(rv)) 1.814 + return rv; 1.815 + 1.816 + mozStorageStatementScoper scoper(statement); 1.817 + *_retval = statement->AsInt32(kAnnoIndex_Type); 1.818 + 1.819 + return NS_OK; 1.820 +} 1.821 + 1.822 + 1.823 +NS_IMETHODIMP 1.824 +nsAnnotationService::GetItemAnnotationType(int64_t aItemId, 1.825 + const nsACString& aName, 1.826 + uint16_t* _retval) 1.827 +{ 1.828 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.829 + NS_ENSURE_ARG_POINTER(_retval); 1.830 + 1.831 + nsCOMPtr<mozIStorageStatement> statement; 1.832 + nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement); 1.833 + if (NS_FAILED(rv)) 1.834 + return rv; 1.835 + 1.836 + mozStorageStatementScoper scoper(statement); 1.837 + *_retval = statement->AsInt32(kAnnoIndex_Type); 1.838 + 1.839 + return NS_OK; 1.840 +} 1.841 + 1.842 + 1.843 +NS_IMETHODIMP 1.844 +nsAnnotationService::GetPageAnnotationDouble(nsIURI* aURI, 1.845 + const nsACString& aName, 1.846 + double* _retval) 1.847 +{ 1.848 + NS_ENSURE_ARG(aURI); 1.849 + NS_ENSURE_ARG_POINTER(_retval); 1.850 + 1.851 + nsCOMPtr<mozIStorageStatement> statement; 1.852 + nsresult rv = StartGetAnnotation(aURI, 0, aName, statement); 1.853 + if (NS_FAILED(rv)) 1.854 + return rv; 1.855 + 1.856 + mozStorageStatementScoper scoper(statement); 1.857 + ENSURE_ANNO_TYPE(TYPE_DOUBLE, statement); 1.858 + *_retval = statement->AsDouble(kAnnoIndex_Content); 1.859 + 1.860 + return NS_OK; 1.861 +} 1.862 + 1.863 + 1.864 +NS_IMETHODIMP 1.865 +nsAnnotationService::GetItemAnnotationDouble(int64_t aItemId, 1.866 + const nsACString& aName, 1.867 + double* _retval) 1.868 +{ 1.869 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.870 + 1.871 + nsCOMPtr<mozIStorageStatement> statement; 1.872 + nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement); 1.873 + if (NS_FAILED(rv)) 1.874 + return rv; 1.875 + 1.876 + mozStorageStatementScoper scoper(statement); 1.877 + ENSURE_ANNO_TYPE(TYPE_DOUBLE, statement); 1.878 + *_retval = statement->AsDouble(kAnnoIndex_Content); 1.879 + 1.880 + return NS_OK; 1.881 +} 1.882 + 1.883 + 1.884 +NS_IMETHODIMP 1.885 +nsAnnotationService::GetPageAnnotationInfo(nsIURI* aURI, 1.886 + const nsACString& aName, 1.887 + int32_t* _flags, 1.888 + uint16_t* _expiration, 1.889 + uint16_t* _storageType) 1.890 +{ 1.891 + NS_ENSURE_ARG(aURI); 1.892 + NS_ENSURE_ARG_POINTER(_flags); 1.893 + NS_ENSURE_ARG_POINTER(_expiration); 1.894 + NS_ENSURE_ARG_POINTER(_storageType); 1.895 + 1.896 + nsCOMPtr<mozIStorageStatement> statement; 1.897 + nsresult rv = StartGetAnnotation(aURI, 0, aName, statement); 1.898 + if (NS_FAILED(rv)) 1.899 + return rv; 1.900 + 1.901 + mozStorageStatementScoper scoper(statement); 1.902 + *_flags = statement->AsInt32(kAnnoIndex_Flags); 1.903 + *_expiration = (uint16_t)statement->AsInt32(kAnnoIndex_Expiration); 1.904 + int32_t type = (uint16_t)statement->AsInt32(kAnnoIndex_Type); 1.905 + if (type == 0) { 1.906 + // For annotations created before explicit typing, 1.907 + // we can't determine type, just return as string type. 1.908 + *_storageType = nsIAnnotationService::TYPE_STRING; 1.909 + } 1.910 + else 1.911 + *_storageType = type; 1.912 + 1.913 + return NS_OK; 1.914 +} 1.915 + 1.916 + 1.917 +NS_IMETHODIMP 1.918 +nsAnnotationService::GetItemAnnotationInfo(int64_t aItemId, 1.919 + const nsACString& aName, 1.920 + int32_t* _flags, 1.921 + uint16_t* _expiration, 1.922 + uint16_t* _storageType) 1.923 +{ 1.924 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.925 + NS_ENSURE_ARG_POINTER(_flags); 1.926 + NS_ENSURE_ARG_POINTER(_expiration); 1.927 + NS_ENSURE_ARG_POINTER(_storageType); 1.928 + 1.929 + nsCOMPtr<mozIStorageStatement> statement; 1.930 + nsresult rv = StartGetAnnotation(nullptr, aItemId, aName, statement); 1.931 + if (NS_FAILED(rv)) 1.932 + return rv; 1.933 + 1.934 + mozStorageStatementScoper scoper(statement); 1.935 + *_flags = statement->AsInt32(kAnnoIndex_Flags); 1.936 + *_expiration = (uint16_t)statement->AsInt32(kAnnoIndex_Expiration); 1.937 + int32_t type = (uint16_t)statement->AsInt32(kAnnoIndex_Type); 1.938 + if (type == 0) { 1.939 + // For annotations created before explicit typing, 1.940 + // we can't determine type, just return as string type. 1.941 + *_storageType = nsIAnnotationService::TYPE_STRING; 1.942 + } 1.943 + else { 1.944 + *_storageType = type; 1.945 + } 1.946 + 1.947 + return NS_OK; 1.948 +} 1.949 + 1.950 + 1.951 +NS_IMETHODIMP 1.952 +nsAnnotationService::GetPagesWithAnnotation(const nsACString& aName, 1.953 + uint32_t* _resultCount, 1.954 + nsIURI*** _results) 1.955 +{ 1.956 + NS_ENSURE_TRUE(!aName.IsEmpty(), NS_ERROR_INVALID_ARG); 1.957 + NS_ENSURE_ARG_POINTER(_resultCount); 1.958 + NS_ENSURE_ARG_POINTER(_results); 1.959 + 1.960 + *_resultCount = 0; 1.961 + *_results = nullptr; 1.962 + nsCOMArray<nsIURI> results; 1.963 + 1.964 + nsresult rv = GetPagesWithAnnotationCOMArray(aName, &results); 1.965 + NS_ENSURE_SUCCESS(rv, rv); 1.966 + 1.967 + // Convert to raw array. 1.968 + if (results.Count() == 0) 1.969 + return NS_OK; 1.970 + 1.971 + *_results = static_cast<nsIURI**> 1.972 + (nsMemory::Alloc(results.Count() * sizeof(nsIURI*))); 1.973 + NS_ENSURE_TRUE(*_results, NS_ERROR_OUT_OF_MEMORY); 1.974 + 1.975 + *_resultCount = results.Count(); 1.976 + for (uint32_t i = 0; i < *_resultCount; i ++) { 1.977 + (*_results)[i] = results[i]; 1.978 + NS_ADDREF((*_results)[i]); 1.979 + } 1.980 + 1.981 + return NS_OK; 1.982 +} 1.983 + 1.984 + 1.985 +nsresult 1.986 +nsAnnotationService::GetPagesWithAnnotationCOMArray(const nsACString& aName, 1.987 + nsCOMArray<nsIURI>* _results) 1.988 +{ 1.989 + nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement( 1.990 + "SELECT h.url " 1.991 + "FROM moz_anno_attributes n " 1.992 + "JOIN moz_annos a ON n.id = a.anno_attribute_id " 1.993 + "JOIN moz_places h ON h.id = a.place_id " 1.994 + "WHERE n.name = :anno_name" 1.995 + ); 1.996 + NS_ENSURE_STATE(stmt); 1.997 + mozStorageStatementScoper scoper(stmt); 1.998 + 1.999 + nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName); 1.1000 + NS_ENSURE_SUCCESS(rv, rv); 1.1001 + 1.1002 + bool hasMore = false; 1.1003 + while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&hasMore)) && 1.1004 + hasMore) { 1.1005 + nsAutoCString uristring; 1.1006 + rv = stmt->GetUTF8String(0, uristring); 1.1007 + NS_ENSURE_SUCCESS(rv, rv); 1.1008 + 1.1009 + // convert to a URI, in case of some invalid URI, just ignore this row 1.1010 + // so we can mostly continue. 1.1011 + nsCOMPtr<nsIURI> uri; 1.1012 + rv = NS_NewURI(getter_AddRefs(uri), uristring); 1.1013 + if (NS_FAILED(rv)) 1.1014 + continue; 1.1015 + 1.1016 + bool added = _results->AppendObject(uri); 1.1017 + NS_ENSURE_TRUE(added, NS_ERROR_OUT_OF_MEMORY); 1.1018 + } 1.1019 + 1.1020 + return NS_OK; 1.1021 +} 1.1022 + 1.1023 + 1.1024 +NS_IMETHODIMP 1.1025 +nsAnnotationService::GetItemsWithAnnotation(const nsACString& aName, 1.1026 + uint32_t* _resultCount, 1.1027 + int64_t** _results) 1.1028 +{ 1.1029 + NS_ENSURE_TRUE(!aName.IsEmpty(), NS_ERROR_INVALID_ARG); 1.1030 + NS_ENSURE_ARG_POINTER(_resultCount); 1.1031 + NS_ENSURE_ARG_POINTER(_results); 1.1032 + 1.1033 + *_resultCount = 0; 1.1034 + *_results = nullptr; 1.1035 + nsTArray<int64_t> results; 1.1036 + 1.1037 + nsresult rv = GetItemsWithAnnotationTArray(aName, &results); 1.1038 + NS_ENSURE_SUCCESS(rv, rv); 1.1039 + 1.1040 + // Convert to raw array. 1.1041 + if (results.Length() == 0) 1.1042 + return NS_OK; 1.1043 + 1.1044 + *_results = static_cast<int64_t*> 1.1045 + (nsMemory::Alloc(results.Length() * sizeof(int64_t))); 1.1046 + NS_ENSURE_TRUE(*_results, NS_ERROR_OUT_OF_MEMORY); 1.1047 + 1.1048 + *_resultCount = results.Length(); 1.1049 + for (uint32_t i = 0; i < *_resultCount; i ++) { 1.1050 + (*_results)[i] = results[i]; 1.1051 + } 1.1052 + 1.1053 + return NS_OK; 1.1054 +} 1.1055 + 1.1056 + 1.1057 +NS_IMETHODIMP 1.1058 +nsAnnotationService::GetAnnotationsWithName(const nsACString& aName, 1.1059 + uint32_t* _count, 1.1060 + mozIAnnotatedResult*** _annotations) 1.1061 +{ 1.1062 + NS_ENSURE_ARG(!aName.IsEmpty()); 1.1063 + NS_ENSURE_ARG_POINTER(_annotations); 1.1064 + 1.1065 + *_count = 0; 1.1066 + *_annotations = nullptr; 1.1067 + nsCOMArray<mozIAnnotatedResult> annotations; 1.1068 + 1.1069 + nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement( 1.1070 + "SELECT h.guid, h.url, -1, a.type, a.content " 1.1071 + "FROM moz_anno_attributes n " 1.1072 + "JOIN moz_annos a ON n.id = a.anno_attribute_id " 1.1073 + "JOIN moz_places h ON h.id = a.place_id " 1.1074 + "WHERE n.name = :anno_name " 1.1075 + "UNION ALL " 1.1076 + "SELECT b.guid, h.url, b.id, a.type, a.content " 1.1077 + "FROM moz_anno_attributes n " 1.1078 + "JOIN moz_items_annos a ON n.id = a.anno_attribute_id " 1.1079 + "JOIN moz_bookmarks b ON b.id = a.item_id " 1.1080 + "LEFT JOIN moz_places h ON h.id = b.fk " 1.1081 + "WHERE n.name = :anno_name " 1.1082 + ); 1.1083 + NS_ENSURE_STATE(stmt); 1.1084 + mozStorageStatementScoper scoper(stmt); 1.1085 + 1.1086 + nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), 1.1087 + aName); 1.1088 + NS_ENSURE_SUCCESS(rv, rv); 1.1089 + 1.1090 + bool hasMore = false; 1.1091 + while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&hasMore)) && hasMore) { 1.1092 + nsAutoCString guid; 1.1093 + rv = stmt->GetUTF8String(0, guid); 1.1094 + NS_ENSURE_SUCCESS(rv, rv); 1.1095 + 1.1096 + nsCOMPtr<nsIURI> uri; 1.1097 + bool uriIsNull = false; 1.1098 + rv = stmt->GetIsNull(1, &uriIsNull); 1.1099 + NS_ENSURE_SUCCESS(rv, rv); 1.1100 + if (!uriIsNull) { 1.1101 + nsAutoCString url; 1.1102 + rv = stmt->GetUTF8String(1, url); 1.1103 + NS_ENSURE_SUCCESS(rv, rv); 1.1104 + rv = NS_NewURI(getter_AddRefs(uri), url); 1.1105 + NS_ENSURE_SUCCESS(rv, rv); 1.1106 + } 1.1107 + 1.1108 + int64_t itemId = stmt->AsInt64(2); 1.1109 + int32_t type = stmt->AsInt32(3); 1.1110 + 1.1111 + nsCOMPtr<nsIWritableVariant> variant = new nsVariant(); 1.1112 + switch (type) { 1.1113 + case nsIAnnotationService::TYPE_INT32: { 1.1114 + rv = variant->SetAsInt32(stmt->AsInt32(4)); 1.1115 + break; 1.1116 + } 1.1117 + case nsIAnnotationService::TYPE_INT64: { 1.1118 + rv = variant->SetAsInt64(stmt->AsInt64(4)); 1.1119 + break; 1.1120 + } 1.1121 + case nsIAnnotationService::TYPE_DOUBLE: { 1.1122 + rv = variant->SetAsDouble(stmt->AsDouble(4)); 1.1123 + break; 1.1124 + } 1.1125 + case nsIAnnotationService::TYPE_STRING: { 1.1126 + nsAutoString valueString; 1.1127 + rv = stmt->GetString(4, valueString); 1.1128 + NS_ENSURE_SUCCESS(rv, rv); 1.1129 + 1.1130 + rv = variant->SetAsAString(valueString); 1.1131 + break; 1.1132 + } 1.1133 + default: 1.1134 + MOZ_ASSERT(false, "Unsupported annotation type"); 1.1135 + // Move to the next result. 1.1136 + continue; 1.1137 + } 1.1138 + NS_ENSURE_SUCCESS(rv, rv); 1.1139 + 1.1140 + nsCOMPtr<mozIAnnotatedResult> anno = new AnnotatedResult(guid, uri, itemId, 1.1141 + aName, variant); 1.1142 + NS_ENSURE_TRUE(annotations.AppendObject(anno), NS_ERROR_OUT_OF_MEMORY); 1.1143 + } 1.1144 + 1.1145 + // Convert to raw array. 1.1146 + if (annotations.Count() == 0) 1.1147 + return NS_OK; 1.1148 + 1.1149 + *_annotations = static_cast<mozIAnnotatedResult**> 1.1150 + (nsMemory::Alloc(annotations.Count() * sizeof(mozIAnnotatedResult*))); 1.1151 + NS_ENSURE_TRUE(*_annotations, NS_ERROR_OUT_OF_MEMORY); 1.1152 + 1.1153 + *_count = annotations.Count(); 1.1154 + for (uint32_t i = 0; i < *_count; ++i) { 1.1155 + NS_ADDREF((*_annotations)[i] = annotations[i]); 1.1156 + } 1.1157 + 1.1158 + return NS_OK; 1.1159 +} 1.1160 + 1.1161 + 1.1162 +nsresult 1.1163 +nsAnnotationService::GetItemsWithAnnotationTArray(const nsACString& aName, 1.1164 + nsTArray<int64_t>* _results) 1.1165 +{ 1.1166 + nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement( 1.1167 + "SELECT a.item_id " 1.1168 + "FROM moz_anno_attributes n " 1.1169 + "JOIN moz_items_annos a ON n.id = a.anno_attribute_id " 1.1170 + "WHERE n.name = :anno_name" 1.1171 + ); 1.1172 + NS_ENSURE_STATE(stmt); 1.1173 + mozStorageStatementScoper scoper(stmt); 1.1174 + 1.1175 + nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName); 1.1176 + NS_ENSURE_SUCCESS(rv, rv); 1.1177 + 1.1178 + bool hasMore = false; 1.1179 + while (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && 1.1180 + hasMore) { 1.1181 + if (!_results->AppendElement(stmt->AsInt64(0))) 1.1182 + return NS_ERROR_OUT_OF_MEMORY; 1.1183 + } 1.1184 + 1.1185 + return NS_OK; 1.1186 +} 1.1187 + 1.1188 + 1.1189 +NS_IMETHODIMP 1.1190 +nsAnnotationService::GetPageAnnotationNames(nsIURI* aURI, 1.1191 + uint32_t* _count, 1.1192 + nsIVariant*** _result) 1.1193 +{ 1.1194 + NS_ENSURE_ARG(aURI); 1.1195 + NS_ENSURE_ARG_POINTER(_count); 1.1196 + NS_ENSURE_ARG_POINTER(_result); 1.1197 + 1.1198 + *_count = 0; 1.1199 + *_result = nullptr; 1.1200 + 1.1201 + nsTArray<nsCString> names; 1.1202 + nsresult rv = GetAnnotationNamesTArray(aURI, 0, &names); 1.1203 + NS_ENSURE_SUCCESS(rv, rv); 1.1204 + 1.1205 + if (names.Length() == 0) 1.1206 + return NS_OK; 1.1207 + 1.1208 + *_result = static_cast<nsIVariant**> 1.1209 + (nsMemory::Alloc(sizeof(nsIVariant*) * names.Length())); 1.1210 + NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY); 1.1211 + 1.1212 + for (uint32_t i = 0; i < names.Length(); i ++) { 1.1213 + nsCOMPtr<nsIWritableVariant> var = new nsVariant(); 1.1214 + if (!var) { 1.1215 + // need to release all the variants we've already created 1.1216 + for (uint32_t j = 0; j < i; j ++) 1.1217 + NS_RELEASE((*_result)[j]); 1.1218 + nsMemory::Free(*_result); 1.1219 + *_result = nullptr; 1.1220 + return NS_ERROR_OUT_OF_MEMORY; 1.1221 + } 1.1222 + var->SetAsAUTF8String(names[i]); 1.1223 + NS_ADDREF((*_result)[i] = var); 1.1224 + } 1.1225 + *_count = names.Length(); 1.1226 + 1.1227 + return NS_OK; 1.1228 +} 1.1229 + 1.1230 + 1.1231 +nsresult 1.1232 +nsAnnotationService::GetAnnotationNamesTArray(nsIURI* aURI, 1.1233 + int64_t aItemId, 1.1234 + nsTArray<nsCString>* _result) 1.1235 +{ 1.1236 + _result->Clear(); 1.1237 + 1.1238 + bool isItemAnnotation = (aItemId > 0); 1.1239 + nsCOMPtr<mozIStorageStatement> statement; 1.1240 + if (isItemAnnotation) { 1.1241 + statement = mDB->GetStatement( 1.1242 + "SELECT n.name " 1.1243 + "FROM moz_anno_attributes n " 1.1244 + "JOIN moz_items_annos a ON a.anno_attribute_id = n.id " 1.1245 + "WHERE a.item_id = :item_id" 1.1246 + ); 1.1247 + } 1.1248 + else { 1.1249 + statement = mDB->GetStatement( 1.1250 + "SELECT n.name " 1.1251 + "FROM moz_anno_attributes n " 1.1252 + "JOIN moz_annos a ON a.anno_attribute_id = n.id " 1.1253 + "JOIN moz_places h ON h.id = a.place_id " 1.1254 + "WHERE h.url = :page_url" 1.1255 + ); 1.1256 + } 1.1257 + NS_ENSURE_STATE(statement); 1.1258 + mozStorageStatementScoper scoper(statement); 1.1259 + 1.1260 + nsresult rv; 1.1261 + if (isItemAnnotation) 1.1262 + rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId); 1.1263 + else 1.1264 + rv = URIBinder::Bind(statement, NS_LITERAL_CSTRING("page_url"), aURI); 1.1265 + NS_ENSURE_SUCCESS(rv, rv); 1.1266 + 1.1267 + bool hasResult = false; 1.1268 + while (NS_SUCCEEDED(statement->ExecuteStep(&hasResult)) && 1.1269 + hasResult) { 1.1270 + nsAutoCString name; 1.1271 + rv = statement->GetUTF8String(0, name); 1.1272 + NS_ENSURE_SUCCESS(rv, rv); 1.1273 + if (!_result->AppendElement(name)) 1.1274 + return NS_ERROR_OUT_OF_MEMORY; 1.1275 + } 1.1276 + 1.1277 + return NS_OK; 1.1278 +} 1.1279 + 1.1280 + 1.1281 +NS_IMETHODIMP 1.1282 +nsAnnotationService::GetItemAnnotationNames(int64_t aItemId, 1.1283 + uint32_t* _count, 1.1284 + nsIVariant*** _result) 1.1285 +{ 1.1286 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.1287 + NS_ENSURE_ARG_POINTER(_count); 1.1288 + NS_ENSURE_ARG_POINTER(_result); 1.1289 + 1.1290 + *_count = 0; 1.1291 + *_result = nullptr; 1.1292 + 1.1293 + nsTArray<nsCString> names; 1.1294 + nsresult rv = GetAnnotationNamesTArray(nullptr, aItemId, &names); 1.1295 + NS_ENSURE_SUCCESS(rv, rv); 1.1296 + 1.1297 + if (names.Length() == 0) 1.1298 + return NS_OK; 1.1299 + 1.1300 + *_result = static_cast<nsIVariant**> 1.1301 + (nsMemory::Alloc(sizeof(nsIVariant*) * names.Length())); 1.1302 + NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY); 1.1303 + 1.1304 + for (uint32_t i = 0; i < names.Length(); i ++) { 1.1305 + nsCOMPtr<nsIWritableVariant> var = new nsVariant(); 1.1306 + if (!var) { 1.1307 + // need to release all the variants we've already created 1.1308 + for (uint32_t j = 0; j < i; j ++) 1.1309 + NS_RELEASE((*_result)[j]); 1.1310 + nsMemory::Free(*_result); 1.1311 + *_result = nullptr; 1.1312 + return NS_ERROR_OUT_OF_MEMORY; 1.1313 + } 1.1314 + var->SetAsAUTF8String(names[i]); 1.1315 + NS_ADDREF((*_result)[i] = var); 1.1316 + } 1.1317 + *_count = names.Length(); 1.1318 + 1.1319 + return NS_OK; 1.1320 +} 1.1321 + 1.1322 + 1.1323 +NS_IMETHODIMP 1.1324 +nsAnnotationService::PageHasAnnotation(nsIURI* aURI, 1.1325 + const nsACString& aName, 1.1326 + bool* _retval) 1.1327 +{ 1.1328 + NS_ENSURE_ARG(aURI); 1.1329 + NS_ENSURE_ARG_POINTER(_retval); 1.1330 + 1.1331 + nsresult rv = HasAnnotationInternal(aURI, 0, aName, _retval); 1.1332 + NS_ENSURE_SUCCESS(rv, rv); 1.1333 + 1.1334 + return NS_OK; 1.1335 +} 1.1336 + 1.1337 + 1.1338 +NS_IMETHODIMP 1.1339 +nsAnnotationService::ItemHasAnnotation(int64_t aItemId, 1.1340 + const nsACString& aName, 1.1341 + bool* _retval) 1.1342 +{ 1.1343 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.1344 + NS_ENSURE_ARG_POINTER(_retval); 1.1345 + 1.1346 + nsresult rv = HasAnnotationInternal(nullptr, aItemId, aName, _retval); 1.1347 + NS_ENSURE_SUCCESS(rv, rv); 1.1348 + 1.1349 + return NS_OK; 1.1350 +} 1.1351 + 1.1352 + 1.1353 +/** 1.1354 + * @note We don't remove anything from the moz_anno_attributes table. If we 1.1355 + * delete the last item of a given name, that item really should go away. 1.1356 + * It will be cleaned up by expiration. 1.1357 + */ 1.1358 +nsresult 1.1359 +nsAnnotationService::RemoveAnnotationInternal(nsIURI* aURI, 1.1360 + int64_t aItemId, 1.1361 + const nsACString& aName) 1.1362 +{ 1.1363 + bool isItemAnnotation = (aItemId > 0); 1.1364 + nsCOMPtr<mozIStorageStatement> statement; 1.1365 + if (isItemAnnotation) { 1.1366 + statement = mDB->GetStatement( 1.1367 + "DELETE FROM moz_items_annos " 1.1368 + "WHERE item_id = :item_id " 1.1369 + "AND anno_attribute_id = " 1.1370 + "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)" 1.1371 + ); 1.1372 + } 1.1373 + else { 1.1374 + statement = mDB->GetStatement( 1.1375 + "DELETE FROM moz_annos " 1.1376 + "WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url) " 1.1377 + "AND anno_attribute_id = " 1.1378 + "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)" 1.1379 + ); 1.1380 + } 1.1381 + NS_ENSURE_STATE(statement); 1.1382 + mozStorageStatementScoper scoper(statement); 1.1383 + 1.1384 + nsresult rv; 1.1385 + if (isItemAnnotation) 1.1386 + rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId); 1.1387 + else 1.1388 + rv = URIBinder::Bind(statement, NS_LITERAL_CSTRING("page_url"), aURI); 1.1389 + NS_ENSURE_SUCCESS(rv, rv); 1.1390 + 1.1391 + rv = statement->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName); 1.1392 + NS_ENSURE_SUCCESS(rv, rv); 1.1393 + 1.1394 + rv = statement->Execute(); 1.1395 + NS_ENSURE_SUCCESS(rv, rv); 1.1396 + 1.1397 + return NS_OK; 1.1398 +} 1.1399 + 1.1400 + 1.1401 +NS_IMETHODIMP 1.1402 +nsAnnotationService::RemovePageAnnotation(nsIURI* aURI, 1.1403 + const nsACString& aName) 1.1404 +{ 1.1405 + NS_ENSURE_ARG(aURI); 1.1406 + 1.1407 + nsresult rv = RemoveAnnotationInternal(aURI, 0, aName); 1.1408 + NS_ENSURE_SUCCESS(rv, rv); 1.1409 + 1.1410 + NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationRemoved(aURI, aName)); 1.1411 + 1.1412 + return NS_OK; 1.1413 +} 1.1414 + 1.1415 + 1.1416 +NS_IMETHODIMP 1.1417 +nsAnnotationService::RemoveItemAnnotation(int64_t aItemId, 1.1418 + const nsACString& aName) 1.1419 +{ 1.1420 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.1421 + 1.1422 + nsresult rv = RemoveAnnotationInternal(nullptr, aItemId, aName); 1.1423 + NS_ENSURE_SUCCESS(rv, rv); 1.1424 + 1.1425 + NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationRemoved(aItemId, aName)); 1.1426 + 1.1427 + return NS_OK; 1.1428 +} 1.1429 + 1.1430 + 1.1431 +NS_IMETHODIMP 1.1432 +nsAnnotationService::RemovePageAnnotations(nsIURI* aURI) 1.1433 +{ 1.1434 + NS_ENSURE_ARG(aURI); 1.1435 + 1.1436 + // Should this be precompiled or a getter? 1.1437 + nsCOMPtr<mozIStorageStatement> statement = mDB->GetStatement( 1.1438 + "DELETE FROM moz_annos WHERE place_id = " 1.1439 + "(SELECT id FROM moz_places WHERE url = :page_url)" 1.1440 + ); 1.1441 + NS_ENSURE_STATE(statement); 1.1442 + mozStorageStatementScoper scoper(statement); 1.1443 + 1.1444 + nsresult rv = URIBinder::Bind(statement, NS_LITERAL_CSTRING("page_url"), aURI); 1.1445 + NS_ENSURE_SUCCESS(rv, rv); 1.1446 + 1.1447 + rv = statement->Execute(); 1.1448 + NS_ENSURE_SUCCESS(rv, rv); 1.1449 + 1.1450 + // Update observers 1.1451 + NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationRemoved(aURI, EmptyCString())); 1.1452 + 1.1453 + return NS_OK; 1.1454 +} 1.1455 + 1.1456 + 1.1457 +NS_IMETHODIMP 1.1458 +nsAnnotationService::RemoveItemAnnotations(int64_t aItemId) 1.1459 +{ 1.1460 + NS_ENSURE_ARG_MIN(aItemId, 1); 1.1461 + 1.1462 + // Should this be precompiled or a getter? 1.1463 + nsCOMPtr<mozIStorageStatement> statement = mDB->GetStatement( 1.1464 + "DELETE FROM moz_items_annos WHERE item_id = :item_id" 1.1465 + ); 1.1466 + NS_ENSURE_STATE(statement); 1.1467 + mozStorageStatementScoper scoper(statement); 1.1468 + 1.1469 + nsresult rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId); 1.1470 + NS_ENSURE_SUCCESS(rv, rv); 1.1471 + 1.1472 + rv = statement->Execute(); 1.1473 + NS_ENSURE_SUCCESS(rv, rv); 1.1474 + 1.1475 + NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationRemoved(aItemId, EmptyCString())); 1.1476 + 1.1477 + return NS_OK; 1.1478 +} 1.1479 + 1.1480 + 1.1481 +/** 1.1482 + * @note If we use annotations for some standard items like GeckoFlags, it 1.1483 + * might be a good idea to blacklist these standard annotations from this 1.1484 + * copy function. 1.1485 + */ 1.1486 +NS_IMETHODIMP 1.1487 +nsAnnotationService::CopyPageAnnotations(nsIURI* aSourceURI, 1.1488 + nsIURI* aDestURI, 1.1489 + bool aOverwriteDest) 1.1490 +{ 1.1491 + NS_ENSURE_ARG(aSourceURI); 1.1492 + NS_ENSURE_ARG(aDestURI); 1.1493 + 1.1494 + mozStorageTransaction transaction(mDB->MainConn(), false); 1.1495 + 1.1496 + nsCOMPtr<mozIStorageStatement> sourceStmt = mDB->GetStatement( 1.1497 + "SELECT h.id, n.id, n.name, a2.id " 1.1498 + "FROM moz_places h " 1.1499 + "JOIN moz_annos a ON a.place_id = h.id " 1.1500 + "JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id " 1.1501 + "LEFT JOIN moz_annos a2 ON a2.place_id = " 1.1502 + "(SELECT id FROM moz_places WHERE url = :dest_url) " 1.1503 + "AND a2.anno_attribute_id = n.id " 1.1504 + "WHERE url = :source_url" 1.1505 + ); 1.1506 + NS_ENSURE_STATE(sourceStmt); 1.1507 + mozStorageStatementScoper sourceScoper(sourceStmt); 1.1508 + 1.1509 + nsresult rv = URIBinder::Bind(sourceStmt, NS_LITERAL_CSTRING("source_url"), aSourceURI); 1.1510 + NS_ENSURE_SUCCESS(rv, rv); 1.1511 + rv = URIBinder::Bind(sourceStmt, NS_LITERAL_CSTRING("dest_url"), aDestURI); 1.1512 + NS_ENSURE_SUCCESS(rv, rv); 1.1513 + 1.1514 + nsCOMPtr<mozIStorageStatement> copyStmt = mDB->GetStatement( 1.1515 + "INSERT INTO moz_annos " 1.1516 + "(place_id, anno_attribute_id, content, flags, expiration, " 1.1517 + "type, dateAdded, lastModified) " 1.1518 + "SELECT (SELECT id FROM moz_places WHERE url = :page_url), " 1.1519 + "anno_attribute_id, content, flags, expiration, type, " 1.1520 + ":date, :date " 1.1521 + "FROM moz_annos " 1.1522 + "WHERE place_id = :page_id " 1.1523 + "AND anno_attribute_id = :name_id" 1.1524 + ); 1.1525 + NS_ENSURE_STATE(copyStmt); 1.1526 + mozStorageStatementScoper copyScoper(copyStmt); 1.1527 + 1.1528 + bool hasResult; 1.1529 + while (NS_SUCCEEDED(sourceStmt->ExecuteStep(&hasResult)) && hasResult) { 1.1530 + int64_t sourcePlaceId = sourceStmt->AsInt64(0); 1.1531 + int64_t annoNameID = sourceStmt->AsInt64(1); 1.1532 + nsAutoCString annoName; 1.1533 + rv = sourceStmt->GetUTF8String(2, annoName); 1.1534 + NS_ENSURE_SUCCESS(rv, rv); 1.1535 + int64_t annoExistsOnDest = sourceStmt->AsInt64(3); 1.1536 + 1.1537 + if (annoExistsOnDest) { 1.1538 + if (!aOverwriteDest) 1.1539 + continue; 1.1540 + rv = RemovePageAnnotation(aDestURI, annoName); 1.1541 + NS_ENSURE_SUCCESS(rv, rv); 1.1542 + } 1.1543 + 1.1544 + // Copy the annotation. 1.1545 + mozStorageStatementScoper scoper(copyStmt); 1.1546 + rv = URIBinder::Bind(copyStmt, NS_LITERAL_CSTRING("page_url"), aDestURI); 1.1547 + NS_ENSURE_SUCCESS(rv, rv); 1.1548 + rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), sourcePlaceId); 1.1549 + NS_ENSURE_SUCCESS(rv, rv); 1.1550 + rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("name_id"), annoNameID); 1.1551 + NS_ENSURE_SUCCESS(rv, rv); 1.1552 + rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("date"), PR_Now()); 1.1553 + NS_ENSURE_SUCCESS(rv, rv); 1.1554 + 1.1555 + rv = copyStmt->Execute(); 1.1556 + NS_ENSURE_SUCCESS(rv, rv); 1.1557 + 1.1558 + NOTIFY_ANNOS_OBSERVERS(OnPageAnnotationSet(aDestURI, annoName)); 1.1559 + } 1.1560 + 1.1561 + rv = transaction.Commit(); 1.1562 + NS_ENSURE_SUCCESS(rv, rv); 1.1563 + 1.1564 + return NS_OK; 1.1565 +} 1.1566 + 1.1567 + 1.1568 +NS_IMETHODIMP 1.1569 +nsAnnotationService::CopyItemAnnotations(int64_t aSourceItemId, 1.1570 + int64_t aDestItemId, 1.1571 + bool aOverwriteDest) 1.1572 +{ 1.1573 + NS_ENSURE_ARG_MIN(aSourceItemId, 1); 1.1574 + NS_ENSURE_ARG_MIN(aDestItemId, 1); 1.1575 + 1.1576 + mozStorageTransaction transaction(mDB->MainConn(), false); 1.1577 + 1.1578 + nsCOMPtr<mozIStorageStatement> sourceStmt = mDB->GetStatement( 1.1579 + "SELECT n.id, n.name, a2.id " 1.1580 + "FROM moz_bookmarks b " 1.1581 + "JOIN moz_items_annos a ON a.item_id = b.id " 1.1582 + "JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id " 1.1583 + "LEFT JOIN moz_items_annos a2 ON a2.item_id = :dest_item_id " 1.1584 + "AND a2.anno_attribute_id = n.id " 1.1585 + "WHERE b.id = :source_item_id" 1.1586 + ); 1.1587 + NS_ENSURE_STATE(sourceStmt); 1.1588 + mozStorageStatementScoper sourceScoper(sourceStmt); 1.1589 + 1.1590 + nsresult rv = sourceStmt->BindInt64ByName(NS_LITERAL_CSTRING("source_item_id"), aSourceItemId); 1.1591 + NS_ENSURE_SUCCESS(rv, rv); 1.1592 + rv = sourceStmt->BindInt64ByName(NS_LITERAL_CSTRING("dest_item_id"), aDestItemId); 1.1593 + NS_ENSURE_SUCCESS(rv, rv); 1.1594 + 1.1595 + nsCOMPtr<mozIStorageStatement> copyStmt = mDB->GetStatement( 1.1596 + "INSERT OR REPLACE INTO moz_items_annos " 1.1597 + "(item_id, anno_attribute_id, content, flags, expiration, " 1.1598 + "type, dateAdded, lastModified) " 1.1599 + "SELECT :dest_item_id, anno_attribute_id, content, flags, expiration, " 1.1600 + "type, :date, :date " 1.1601 + "FROM moz_items_annos " 1.1602 + "WHERE item_id = :source_item_id " 1.1603 + "AND anno_attribute_id = :name_id" 1.1604 + ); 1.1605 + NS_ENSURE_STATE(copyStmt); 1.1606 + mozStorageStatementScoper copyScoper(copyStmt); 1.1607 + 1.1608 + bool hasResult; 1.1609 + while (NS_SUCCEEDED(sourceStmt->ExecuteStep(&hasResult)) && hasResult) { 1.1610 + int64_t annoNameID = sourceStmt->AsInt64(0); 1.1611 + nsAutoCString annoName; 1.1612 + rv = sourceStmt->GetUTF8String(1, annoName); 1.1613 + NS_ENSURE_SUCCESS(rv, rv); 1.1614 + int64_t annoExistsOnDest = sourceStmt->AsInt64(2); 1.1615 + 1.1616 + if (annoExistsOnDest) { 1.1617 + if (!aOverwriteDest) 1.1618 + continue; 1.1619 + rv = RemoveItemAnnotation(aDestItemId, annoName); 1.1620 + NS_ENSURE_SUCCESS(rv, rv); 1.1621 + } 1.1622 + 1.1623 + // Copy the annotation. 1.1624 + mozStorageStatementScoper scoper(copyStmt); 1.1625 + rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("dest_item_id"), aDestItemId); 1.1626 + NS_ENSURE_SUCCESS(rv, rv); 1.1627 + rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("source_item_id"), aSourceItemId); 1.1628 + NS_ENSURE_SUCCESS(rv, rv); 1.1629 + rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("name_id"), annoNameID); 1.1630 + NS_ENSURE_SUCCESS(rv, rv); 1.1631 + rv = copyStmt->BindInt64ByName(NS_LITERAL_CSTRING("date"), PR_Now()); 1.1632 + NS_ENSURE_SUCCESS(rv, rv); 1.1633 + 1.1634 + rv = copyStmt->Execute(); 1.1635 + NS_ENSURE_SUCCESS(rv, rv); 1.1636 + 1.1637 + NOTIFY_ANNOS_OBSERVERS(OnItemAnnotationSet(aDestItemId, annoName)); 1.1638 + } 1.1639 + 1.1640 + rv = transaction.Commit(); 1.1641 + NS_ENSURE_SUCCESS(rv, rv); 1.1642 + 1.1643 + return NS_OK; 1.1644 +} 1.1645 + 1.1646 + 1.1647 +NS_IMETHODIMP 1.1648 +nsAnnotationService::AddObserver(nsIAnnotationObserver* aObserver) 1.1649 +{ 1.1650 + NS_ENSURE_ARG(aObserver); 1.1651 + 1.1652 + if (mObservers.IndexOfObject(aObserver) >= 0) 1.1653 + return NS_ERROR_INVALID_ARG; // Already registered. 1.1654 + if (!mObservers.AppendObject(aObserver)) 1.1655 + return NS_ERROR_OUT_OF_MEMORY; 1.1656 + return NS_OK; 1.1657 +} 1.1658 + 1.1659 + 1.1660 +NS_IMETHODIMP 1.1661 +nsAnnotationService::RemoveObserver(nsIAnnotationObserver* aObserver) 1.1662 +{ 1.1663 + NS_ENSURE_ARG(aObserver); 1.1664 + 1.1665 + if (!mObservers.RemoveObject(aObserver)) 1.1666 + return NS_ERROR_INVALID_ARG; 1.1667 + return NS_OK; 1.1668 +} 1.1669 + 1.1670 +nsresult 1.1671 +nsAnnotationService::HasAnnotationInternal(nsIURI* aURI, 1.1672 + int64_t aItemId, 1.1673 + const nsACString& aName, 1.1674 + bool* _hasAnno) 1.1675 +{ 1.1676 + bool isItemAnnotation = (aItemId > 0); 1.1677 + nsCOMPtr<mozIStorageStatement> stmt; 1.1678 + if (isItemAnnotation) { 1.1679 + stmt = mDB->GetStatement( 1.1680 + "SELECT b.id, " 1.1681 + "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, " 1.1682 + "a.id, a.dateAdded " 1.1683 + "FROM moz_bookmarks b " 1.1684 + "LEFT JOIN moz_items_annos a ON a.item_id = b.id " 1.1685 + "AND a.anno_attribute_id = nameid " 1.1686 + "WHERE b.id = :item_id" 1.1687 + ); 1.1688 + } 1.1689 + else { 1.1690 + stmt = mDB->GetStatement( 1.1691 + "SELECT h.id, " 1.1692 + "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, " 1.1693 + "a.id, a.dateAdded " 1.1694 + "FROM moz_places h " 1.1695 + "LEFT JOIN moz_annos a ON a.place_id = h.id " 1.1696 + "AND a.anno_attribute_id = nameid " 1.1697 + "WHERE h.url = :page_url" 1.1698 + ); 1.1699 + } 1.1700 + NS_ENSURE_STATE(stmt); 1.1701 + mozStorageStatementScoper checkAnnoScoper(stmt); 1.1702 + 1.1703 + nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName); 1.1704 + NS_ENSURE_SUCCESS(rv, rv); 1.1705 + if (isItemAnnotation) 1.1706 + rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId); 1.1707 + else 1.1708 + rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI); 1.1709 + NS_ENSURE_SUCCESS(rv, rv); 1.1710 + 1.1711 + bool hasResult; 1.1712 + rv = stmt->ExecuteStep(&hasResult); 1.1713 + NS_ENSURE_SUCCESS(rv, rv); 1.1714 + if (!hasResult) { 1.1715 + // We are trying to get an annotation on an invalid bookmarks or 1.1716 + // history entry. 1.1717 + // Here we preserve the old behavior, returning that we don't have the 1.1718 + // annotation, ignoring the fact itemId is invalid. 1.1719 + // Otherwise we should return NS_ERROR_INVALID_ARG, but this will somehow 1.1720 + // break the API. In future we could want to be pickier. 1.1721 + *_hasAnno = false; 1.1722 + } 1.1723 + else { 1.1724 + int64_t annotationId = stmt->AsInt64(2); 1.1725 + *_hasAnno = (annotationId > 0); 1.1726 + } 1.1727 + 1.1728 + return NS_OK; 1.1729 +} 1.1730 + 1.1731 + 1.1732 +/** 1.1733 + * This loads the statement and steps it once so you can get data out of it. 1.1734 + * 1.1735 + * @note You have to reset the statement when you're done if this succeeds. 1.1736 + * @throws NS_ERROR_NOT_AVAILABLE if the annotation is not found. 1.1737 + */ 1.1738 + 1.1739 +nsresult 1.1740 +nsAnnotationService::StartGetAnnotation(nsIURI* aURI, 1.1741 + int64_t aItemId, 1.1742 + const nsACString& aName, 1.1743 + nsCOMPtr<mozIStorageStatement>& aStatement) 1.1744 +{ 1.1745 + bool isItemAnnotation = (aItemId > 0); 1.1746 + 1.1747 + if (isItemAnnotation) { 1.1748 + aStatement = mDB->GetStatement( 1.1749 + "SELECT a.id, a.item_id, :anno_name, a.content, a.flags, " 1.1750 + "a.expiration, a.type " 1.1751 + "FROM moz_anno_attributes n " 1.1752 + "JOIN moz_items_annos a ON a.anno_attribute_id = n.id " 1.1753 + "WHERE a.item_id = :item_id " 1.1754 + "AND n.name = :anno_name" 1.1755 + ); 1.1756 + } 1.1757 + else { 1.1758 + aStatement = mDB->GetStatement( 1.1759 + "SELECT a.id, a.place_id, :anno_name, a.content, a.flags, " 1.1760 + "a.expiration, a.type " 1.1761 + "FROM moz_anno_attributes n " 1.1762 + "JOIN moz_annos a ON n.id = a.anno_attribute_id " 1.1763 + "JOIN moz_places h ON h.id = a.place_id " 1.1764 + "WHERE h.url = :page_url " 1.1765 + "AND n.name = :anno_name" 1.1766 + ); 1.1767 + } 1.1768 + NS_ENSURE_STATE(aStatement); 1.1769 + mozStorageStatementScoper getAnnoScoper(aStatement); 1.1770 + 1.1771 + nsresult rv; 1.1772 + if (isItemAnnotation) 1.1773 + rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId); 1.1774 + else 1.1775 + rv = URIBinder::Bind(aStatement, NS_LITERAL_CSTRING("page_url"), aURI); 1.1776 + NS_ENSURE_SUCCESS(rv, rv); 1.1777 + 1.1778 + rv = aStatement->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName); 1.1779 + NS_ENSURE_SUCCESS(rv, rv); 1.1780 + 1.1781 + bool hasResult = false; 1.1782 + rv = aStatement->ExecuteStep(&hasResult); 1.1783 + if (NS_FAILED(rv) || !hasResult) 1.1784 + return NS_ERROR_NOT_AVAILABLE; 1.1785 + 1.1786 + // on success, DON'T reset the statement, the caller needs to read from it, 1.1787 + // and it is the caller's job to reset it. 1.1788 + getAnnoScoper.Abandon(); 1.1789 + 1.1790 + return NS_OK; 1.1791 +} 1.1792 + 1.1793 + 1.1794 +/** 1.1795 + * This does most of the setup work needed to set an annotation, except for 1.1796 + * binding the the actual value and executing the statement. 1.1797 + * It will either update an existing annotation or insert a new one. 1.1798 + * 1.1799 + * @note The aStatement RESULT IS NOT ADDREFED. This is just one of the class 1.1800 + * vars, which control its scope. DO NOT RELEASE. 1.1801 + * The caller must take care of resetting the statement if this succeeds. 1.1802 + */ 1.1803 +nsresult 1.1804 +nsAnnotationService::StartSetAnnotation(nsIURI* aURI, 1.1805 + int64_t aItemId, 1.1806 + const nsACString& aName, 1.1807 + int32_t aFlags, 1.1808 + uint16_t aExpiration, 1.1809 + uint16_t aType, 1.1810 + nsCOMPtr<mozIStorageStatement>& aStatement) 1.1811 +{ 1.1812 + bool isItemAnnotation = (aItemId > 0); 1.1813 + 1.1814 + if (aExpiration == EXPIRE_SESSION) { 1.1815 + mHasSessionAnnotations = true; 1.1816 + } 1.1817 + 1.1818 + // Ensure the annotation name exists. 1.1819 + nsCOMPtr<mozIStorageStatement> addNameStmt = mDB->GetStatement( 1.1820 + "INSERT OR IGNORE INTO moz_anno_attributes (name) VALUES (:anno_name)" 1.1821 + ); 1.1822 + NS_ENSURE_STATE(addNameStmt); 1.1823 + mozStorageStatementScoper scoper(addNameStmt); 1.1824 + 1.1825 + nsresult rv = addNameStmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName); 1.1826 + NS_ENSURE_SUCCESS(rv, rv); 1.1827 + rv = addNameStmt->Execute(); 1.1828 + NS_ENSURE_SUCCESS(rv, rv); 1.1829 + 1.1830 + // We have to check 2 things: 1.1831 + // - if the annotation already exists we should update it. 1.1832 + // - we should not allow setting annotations on invalid URIs or itemIds. 1.1833 + // This query will tell us: 1.1834 + // - whether the item or page exists. 1.1835 + // - whether the annotation already exists. 1.1836 + // - the nameID associated with the annotation name. 1.1837 + // - the id and dateAdded of the old annotation, if it exists. 1.1838 + nsCOMPtr<mozIStorageStatement> stmt; 1.1839 + if (isItemAnnotation) { 1.1840 + stmt = mDB->GetStatement( 1.1841 + "SELECT b.id, " 1.1842 + "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, " 1.1843 + "a.id, a.dateAdded " 1.1844 + "FROM moz_bookmarks b " 1.1845 + "LEFT JOIN moz_items_annos a ON a.item_id = b.id " 1.1846 + "AND a.anno_attribute_id = nameid " 1.1847 + "WHERE b.id = :item_id" 1.1848 + ); 1.1849 + } 1.1850 + else { 1.1851 + stmt = mDB->GetStatement( 1.1852 + "SELECT h.id, " 1.1853 + "(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, " 1.1854 + "a.id, a.dateAdded " 1.1855 + "FROM moz_places h " 1.1856 + "LEFT JOIN moz_annos a ON a.place_id = h.id " 1.1857 + "AND a.anno_attribute_id = nameid " 1.1858 + "WHERE h.url = :page_url" 1.1859 + ); 1.1860 + } 1.1861 + NS_ENSURE_STATE(stmt); 1.1862 + mozStorageStatementScoper checkAnnoScoper(stmt); 1.1863 + 1.1864 + rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aName); 1.1865 + NS_ENSURE_SUCCESS(rv, rv); 1.1866 + if (isItemAnnotation) 1.1867 + rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId); 1.1868 + else 1.1869 + rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI); 1.1870 + NS_ENSURE_SUCCESS(rv, rv); 1.1871 + 1.1872 + bool hasResult; 1.1873 + rv = stmt->ExecuteStep(&hasResult); 1.1874 + NS_ENSURE_SUCCESS(rv, rv); 1.1875 + if (!hasResult) { 1.1876 + // We are trying to create an annotation on an invalid bookmark 1.1877 + // or history entry. 1.1878 + return NS_ERROR_INVALID_ARG; 1.1879 + } 1.1880 + 1.1881 + int64_t fkId = stmt->AsInt64(0); 1.1882 + int64_t nameID = stmt->AsInt64(1); 1.1883 + int64_t oldAnnoId = stmt->AsInt64(2); 1.1884 + int64_t oldAnnoDate = stmt->AsInt64(3); 1.1885 + 1.1886 + if (isItemAnnotation) { 1.1887 + aStatement = mDB->GetStatement( 1.1888 + "INSERT OR REPLACE INTO moz_items_annos " 1.1889 + "(id, item_id, anno_attribute_id, content, flags, " 1.1890 + "expiration, type, dateAdded, lastModified) " 1.1891 + "VALUES (:id, :fk, :name_id, :content, :flags, " 1.1892 + ":expiration, :type, :date_added, :last_modified)" 1.1893 + ); 1.1894 + } 1.1895 + else { 1.1896 + aStatement = mDB->GetStatement( 1.1897 + "INSERT OR REPLACE INTO moz_annos " 1.1898 + "(id, place_id, anno_attribute_id, content, flags, " 1.1899 + "expiration, type, dateAdded, lastModified) " 1.1900 + "VALUES (:id, :fk, :name_id, :content, :flags, " 1.1901 + ":expiration, :type, :date_added, :last_modified)" 1.1902 + ); 1.1903 + } 1.1904 + NS_ENSURE_STATE(aStatement); 1.1905 + mozStorageStatementScoper setAnnoScoper(aStatement); 1.1906 + 1.1907 + // Don't replace existing annotations. 1.1908 + if (oldAnnoId > 0) { 1.1909 + rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("id"), oldAnnoId); 1.1910 + NS_ENSURE_SUCCESS(rv, rv); 1.1911 + rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("date_added"), oldAnnoDate); 1.1912 + NS_ENSURE_SUCCESS(rv, rv); 1.1913 + } 1.1914 + else { 1.1915 + rv = aStatement->BindNullByName(NS_LITERAL_CSTRING("id")); 1.1916 + NS_ENSURE_SUCCESS(rv, rv); 1.1917 + rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("date_added"), PR_Now()); 1.1918 + NS_ENSURE_SUCCESS(rv, rv); 1.1919 + } 1.1920 + 1.1921 + rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("fk"), fkId); 1.1922 + NS_ENSURE_SUCCESS(rv, rv); 1.1923 + rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("name_id"), nameID); 1.1924 + NS_ENSURE_SUCCESS(rv, rv); 1.1925 + 1.1926 + rv = aStatement->BindInt32ByName(NS_LITERAL_CSTRING("flags"), aFlags); 1.1927 + NS_ENSURE_SUCCESS(rv, rv); 1.1928 + rv = aStatement->BindInt32ByName(NS_LITERAL_CSTRING("expiration"), aExpiration); 1.1929 + NS_ENSURE_SUCCESS(rv, rv); 1.1930 + rv = aStatement->BindInt32ByName(NS_LITERAL_CSTRING("type"), aType); 1.1931 + NS_ENSURE_SUCCESS(rv, rv); 1.1932 + rv = aStatement->BindInt64ByName(NS_LITERAL_CSTRING("last_modified"), PR_Now()); 1.1933 + NS_ENSURE_SUCCESS(rv, rv); 1.1934 + 1.1935 + // On success, leave the statement open, the caller will set the value 1.1936 + // and execute the statement. 1.1937 + setAnnoScoper.Abandon(); 1.1938 + 1.1939 + return NS_OK; 1.1940 +} 1.1941 + 1.1942 +//////////////////////////////////////////////////////////////////////////////// 1.1943 +//// nsIObserver 1.1944 + 1.1945 +NS_IMETHODIMP 1.1946 +nsAnnotationService::Observe(nsISupports *aSubject, 1.1947 + const char *aTopic, 1.1948 + const char16_t *aData) 1.1949 +{ 1.1950 + NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread"); 1.1951 + 1.1952 + if (strcmp(aTopic, TOPIC_PLACES_SHUTDOWN) == 0) { 1.1953 + // Remove all session annotations, if any. 1.1954 + if (mHasSessionAnnotations) { 1.1955 + nsCOMPtr<mozIStorageAsyncStatement> pageAnnoStmt = mDB->GetAsyncStatement( 1.1956 + "DELETE FROM moz_annos WHERE expiration = :expire_session" 1.1957 + ); 1.1958 + NS_ENSURE_STATE(pageAnnoStmt); 1.1959 + nsresult rv = pageAnnoStmt->BindInt32ByName(NS_LITERAL_CSTRING("expire_session"), 1.1960 + EXPIRE_SESSION); 1.1961 + NS_ENSURE_SUCCESS(rv, rv); 1.1962 + 1.1963 + nsCOMPtr<mozIStorageAsyncStatement> itemAnnoStmt = mDB->GetAsyncStatement( 1.1964 + "DELETE FROM moz_items_annos WHERE expiration = :expire_session" 1.1965 + ); 1.1966 + NS_ENSURE_STATE(itemAnnoStmt); 1.1967 + rv = itemAnnoStmt->BindInt32ByName(NS_LITERAL_CSTRING("expire_session"), 1.1968 + EXPIRE_SESSION); 1.1969 + NS_ENSURE_SUCCESS(rv, rv); 1.1970 + 1.1971 + mozIStorageBaseStatement *stmts[] = { 1.1972 + pageAnnoStmt.get() 1.1973 + , itemAnnoStmt.get() 1.1974 + }; 1.1975 + 1.1976 + nsCOMPtr<mozIStoragePendingStatement> ps; 1.1977 + rv = mDB->MainConn()->ExecuteAsync(stmts, ArrayLength(stmts), nullptr, 1.1978 + getter_AddRefs(ps)); 1.1979 + NS_ENSURE_SUCCESS(rv, rv); 1.1980 + } 1.1981 + } 1.1982 + 1.1983 + return NS_OK; 1.1984 +}