Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp
Warning:line 2589, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_components_places0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/components/places -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/components/places -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/components/places -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/build -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-07-21-021012-413605-1 -x c++ Unified_cpp_components_places0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include <stdio.h>
8
9#include "mozilla/Components.h"
10#include "mozilla/DebugOnly.h"
11#include "mozilla/IntegerPrintfMacros.h"
12#include "mozilla/intl/LocaleService.h"
13
14#include "nsNavHistory.h"
15
16#include "mozIPlacesAutoComplete.h"
17#include "nsNavBookmarks.h"
18#include "nsFaviconService.h"
19#include "nsPlacesMacros.h"
20#include "nsPlacesTriggers.h"
21#include "mozilla/intl/AppDateTimeFormat.h"
22#include "History.h"
23#include "Helpers.h"
24#include "NotifyRankingChanged.h"
25
26#include "mozIStorageValueArray.h"
27#include "nsTArray.h"
28#include "nsNetUtil.h"
29#include "nsPrintfCString.h"
30#include "nsPromiseFlatString.h"
31#include "nsString.h"
32#include "nsUnicharUtils.h"
33#include "prsystem.h"
34#include "prtime.h"
35#include "nsEscape.h"
36#include "nsIEffectiveTLDService.h"
37#include "nsIClassInfoImpl.h"
38#include "nsIIDNService.h"
39#include "nsQueryObject.h"
40#include "nsThreadUtils.h"
41#include "nsAppDirectoryServiceDefs.h"
42#include "nsMathUtils.h"
43#include "nsReadableUtils.h"
44#include "mozilla/storage.h"
45#include "mozilla/Preferences.h"
46#include <algorithm>
47
48using namespace mozilla;
49using namespace mozilla::places;
50
51// The maximum number of things that we will store in the recent events list
52// before calling ExpireNonrecentEvents. This number should be big enough so it
53// is very difficult to get that many unconsumed events (for example, typed but
54// never visited) in the RECENT_EVENT_THRESHOLD. Otherwise, we'll start
55// checking each one for every page visit, which will be somewhat slower.
56#define RECENT_EVENT_QUEUE_MAX_LENGTH128 128
57
58// preference ID strings
59#define PREF_HISTORY_ENABLED"places.history.enabled" "places.history.enabled"
60#define PREF_MATCH_DIACRITICS"places.search.matchDiacritics" "places.search.matchDiacritics"
61
62#define PREF_FREC_NUM_VISITS"places.frecency.numVisits" "places.frecency.numVisits"
63#define PREF_FREC_NUM_VISITS_DEF10 10
64#define PREF_FREC_FIRST_BUCKET_CUTOFF"places.frecency.firstBucketCutoff" "places.frecency.firstBucketCutoff"
65#define PREF_FREC_FIRST_BUCKET_CUTOFF_DEF4 4
66#define PREF_FREC_SECOND_BUCKET_CUTOFF"places.frecency.secondBucketCutoff" "places.frecency.secondBucketCutoff"
67#define PREF_FREC_SECOND_BUCKET_CUTOFF_DEF14 14
68#define PREF_FREC_THIRD_BUCKET_CUTOFF"places.frecency.thirdBucketCutoff" "places.frecency.thirdBucketCutoff"
69#define PREF_FREC_THIRD_BUCKET_CUTOFF_DEF31 31
70#define PREF_FREC_FOURTH_BUCKET_CUTOFF"places.frecency.fourthBucketCutoff" "places.frecency.fourthBucketCutoff"
71#define PREF_FREC_FOURTH_BUCKET_CUTOFF_DEF90 90
72#define PREF_FREC_FIRST_BUCKET_WEIGHT"places.frecency.firstBucketWeight" "places.frecency.firstBucketWeight"
73#define PREF_FREC_FIRST_BUCKET_WEIGHT_DEF100 100
74#define PREF_FREC_SECOND_BUCKET_WEIGHT"places.frecency.secondBucketWeight" "places.frecency.secondBucketWeight"
75#define PREF_FREC_SECOND_BUCKET_WEIGHT_DEF70 70
76#define PREF_FREC_THIRD_BUCKET_WEIGHT"places.frecency.thirdBucketWeight" "places.frecency.thirdBucketWeight"
77#define PREF_FREC_THIRD_BUCKET_WEIGHT_DEF50 50
78#define PREF_FREC_FOURTH_BUCKET_WEIGHT"places.frecency.fourthBucketWeight" "places.frecency.fourthBucketWeight"
79#define PREF_FREC_FOURTH_BUCKET_WEIGHT_DEF30 30
80#define PREF_FREC_DEFAULT_BUCKET_WEIGHT"places.frecency.defaultBucketWeight" "places.frecency.defaultBucketWeight"
81#define PREF_FREC_DEFAULT_BUCKET_WEIGHT_DEF10 10
82#define PREF_FREC_EMBED_VISIT_BONUS"places.frecency.embedVisitBonus" "places.frecency.embedVisitBonus"
83#define PREF_FREC_EMBED_VISIT_BONUS_DEF0 0
84#define PREF_FREC_FRAMED_LINK_VISIT_BONUS"places.frecency.framedLinkVisitBonus" "places.frecency.framedLinkVisitBonus"
85#define PREF_FREC_FRAMED_LINK_VISIT_BONUS_DEF0 0
86#define PREF_FREC_LINK_VISIT_BONUS"places.frecency.linkVisitBonus" "places.frecency.linkVisitBonus"
87#define PREF_FREC_LINK_VISIT_BONUS_DEF100 100
88#define PREF_FREC_TYPED_VISIT_BONUS"places.frecency.typedVisitBonus" "places.frecency.typedVisitBonus"
89#define PREF_FREC_TYPED_VISIT_BONUS_DEF2000 2000
90#define PREF_FREC_BOOKMARK_VISIT_BONUS"places.frecency.bookmarkVisitBonus" "places.frecency.bookmarkVisitBonus"
91#define PREF_FREC_BOOKMARK_VISIT_BONUS_DEF75 75
92#define PREF_FREC_DOWNLOAD_VISIT_BONUS"places.frecency.downloadVisitBonus" "places.frecency.downloadVisitBonus"
93#define PREF_FREC_DOWNLOAD_VISIT_BONUS_DEF0 0
94#define PREF_FREC_PERM_REDIRECT_VISIT_BONUS"places.frecency.permRedirectVisitBonus" \
95 "places.frecency.permRedirectVisitBonus"
96#define PREF_FREC_PERM_REDIRECT_VISIT_BONUS_DEF0 0
97#define PREF_FREC_TEMP_REDIRECT_VISIT_BONUS"places.frecency.tempRedirectVisitBonus" \
98 "places.frecency.tempRedirectVisitBonus"
99#define PREF_FREC_TEMP_REDIRECT_VISIT_BONUS_DEF0 0
100#define PREF_FREC_REDIR_SOURCE_VISIT_BONUS"places.frecency.redirectSourceVisitBonus" \
101 "places.frecency.redirectSourceVisitBonus"
102#define PREF_FREC_REDIR_SOURCE_VISIT_BONUS_DEF25 25
103#define PREF_FREC_DEFAULT_VISIT_BONUS"places.frecency.defaultVisitBonus" "places.frecency.defaultVisitBonus"
104#define PREF_FREC_DEFAULT_VISIT_BONUS_DEF0 0
105#define PREF_FREC_UNVISITED_BOOKMARK_BONUS"places.frecency.unvisitedBookmarkBonus" \
106 "places.frecency.unvisitedBookmarkBonus"
107#define PREF_FREC_UNVISITED_BOOKMARK_BONUS_DEF140 140
108#define PREF_FREC_UNVISITED_TYPED_BONUS"places.frecency.unvisitedTypedBonus" "places.frecency.unvisitedTypedBonus"
109#define PREF_FREC_UNVISITED_TYPED_BONUS_DEF200 200
110#define PREF_FREC_RELOAD_VISIT_BONUS"places.frecency.reloadVisitBonus" "places.frecency.reloadVisitBonus"
111#define PREF_FREC_RELOAD_VISIT_BONUS_DEF0 0
112
113// In order to avoid calling PR_now() too often we use a cached "now" value
114// for repeating stuff. These are milliseconds between "now" cache refreshes.
115#define RENEW_CACHED_NOW_TIMEOUT((int32_t)3 * 1000L) ((int32_t)3 * PR_MSEC_PER_SEC1000L)
116
117// These macros are used when splitting history by date.
118// These are the day containers and catch-all final container.
119#define HISTORY_ADDITIONAL_DATE_CONT_NUM3 3
120// We use a guess of the number of months considering all of them 30 days
121// long, but we split only the last 6 months.
122#define HISTORY_DATE_CONT_NUM(_daysFromOldestVisit)(3 + std::min(6, (int32_t)ceilf((float)_daysFromOldestVisit /
30)))
\
123 (HISTORY_ADDITIONAL_DATE_CONT_NUM3 + \
124 std::min(6, (int32_t)ceilf((float)_daysFromOldestVisit / 30)))
125// Max number of containers, used to initialize the params hash.
126#define HISTORY_DATE_CONT_LENGTH8 8
127
128// Initial length of the recent events cache.
129#define RECENT_EVENTS_INITIAL_CACHE_LENGTH64 64
130
131// Observed topics.
132#define TOPIC_IDLE_DAILY"idle-daily" "idle-daily"
133#define TOPIC_PREF_CHANGED"nsPref:changed" "nsPref:changed"
134#define TOPIC_PROFILE_TEARDOWN"profile-change-teardown" "profile-change-teardown"
135#define TOPIC_PROFILE_CHANGE"profile-before-change" "profile-before-change"
136#define TOPIC_APP_LOCALES_CHANGED"intl:app-locales-changed" "intl:app-locales-changed"
137
138static const char* kObservedPrefs[] = {PREF_HISTORY_ENABLED"places.history.enabled",
139 PREF_MATCH_DIACRITICS"places.search.matchDiacritics",
140 PREF_FREC_NUM_VISITS"places.frecency.numVisits",
141 PREF_FREC_FIRST_BUCKET_CUTOFF"places.frecency.firstBucketCutoff",
142 PREF_FREC_SECOND_BUCKET_CUTOFF"places.frecency.secondBucketCutoff",
143 PREF_FREC_THIRD_BUCKET_CUTOFF"places.frecency.thirdBucketCutoff",
144 PREF_FREC_FOURTH_BUCKET_CUTOFF"places.frecency.fourthBucketCutoff",
145 PREF_FREC_FIRST_BUCKET_WEIGHT"places.frecency.firstBucketWeight",
146 PREF_FREC_SECOND_BUCKET_WEIGHT"places.frecency.secondBucketWeight",
147 PREF_FREC_THIRD_BUCKET_WEIGHT"places.frecency.thirdBucketWeight",
148 PREF_FREC_FOURTH_BUCKET_WEIGHT"places.frecency.fourthBucketWeight",
149 PREF_FREC_DEFAULT_BUCKET_WEIGHT"places.frecency.defaultBucketWeight",
150 PREF_FREC_EMBED_VISIT_BONUS"places.frecency.embedVisitBonus",
151 PREF_FREC_FRAMED_LINK_VISIT_BONUS"places.frecency.framedLinkVisitBonus",
152 PREF_FREC_LINK_VISIT_BONUS"places.frecency.linkVisitBonus",
153 PREF_FREC_TYPED_VISIT_BONUS"places.frecency.typedVisitBonus",
154 PREF_FREC_BOOKMARK_VISIT_BONUS"places.frecency.bookmarkVisitBonus",
155 PREF_FREC_DOWNLOAD_VISIT_BONUS"places.frecency.downloadVisitBonus",
156 PREF_FREC_PERM_REDIRECT_VISIT_BONUS"places.frecency.permRedirectVisitBonus",
157 PREF_FREC_TEMP_REDIRECT_VISIT_BONUS"places.frecency.tempRedirectVisitBonus",
158 PREF_FREC_REDIR_SOURCE_VISIT_BONUS"places.frecency.redirectSourceVisitBonus",
159 PREF_FREC_DEFAULT_VISIT_BONUS"places.frecency.defaultVisitBonus",
160 PREF_FREC_UNVISITED_BOOKMARK_BONUS"places.frecency.unvisitedBookmarkBonus",
161 PREF_FREC_UNVISITED_TYPED_BONUS"places.frecency.unvisitedTypedBonus",
162 nullptr};
163
164NS_IMPL_ADDREF(nsNavHistory)MozExternalRefCountType nsNavHistory::AddRef(void) { static_assert
(!std::is_destructible_v<nsNavHistory>, "Reference-counted class "
"nsNavHistory" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
164; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsNavHistory" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsNavHistory" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsNavHistory\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsNavHistory\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 164; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsNavHistory" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsNavHistory"
), (uint32_t)(sizeof(*this))); return count; }
165NS_IMPL_RELEASE(nsNavHistory)MozExternalRefCountType nsNavHistory::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 165
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsNavHistory" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsNavHistory" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsNavHistory\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsNavHistory\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 165; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsNavHistory" " not thread-safe"); const char
* const nametmp = "nsNavHistory"; nsrefcnt count = --mRefCnt;
NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; }
166
167NS_IMPL_CLASSINFO(nsNavHistory, nullptr, nsIClassInfo::SINGLETON,extern nsresult nsNavHistory_GetInterfacesHelper(nsTArray<
nsIID> & array); static const GenericClassInfo::ClassInfoData
knsNavHistoryClassInfoData = { nsNavHistory_GetInterfacesHelper
, nullptr, nsIClassInfo::SINGLETON | nsIClassInfo::SINGLETON_CLASSINFO
, { 0x88cecbb7, 0x6c63, 0x4b3b, { 0x8c, 0xd4, 0x84, 0xf3, 0xb8
, 0x22, 0x8c, 0x69 } }, }; mozilla::AlignedStorage2<GenericClassInfo
> knsNavHistoryClassInfoDataPlace; nsIClassInfo* gnsNavHistory_classInfoGlobal
= nullptr;
168 NS_NAVHISTORYSERVICE_CID)extern nsresult nsNavHistory_GetInterfacesHelper(nsTArray<
nsIID> & array); static const GenericClassInfo::ClassInfoData
knsNavHistoryClassInfoData = { nsNavHistory_GetInterfacesHelper
, nullptr, nsIClassInfo::SINGLETON | nsIClassInfo::SINGLETON_CLASSINFO
, { 0x88cecbb7, 0x6c63, 0x4b3b, { 0x8c, 0xd4, 0x84, 0xf3, 0xb8
, 0x22, 0x8c, 0x69 } }, }; mozilla::AlignedStorage2<GenericClassInfo
> knsNavHistoryClassInfoDataPlace; nsIClassInfo* gnsNavHistory_classInfoGlobal
= nullptr;
169NS_INTERFACE_MAP_BEGIN(nsNavHistory)nsresult nsNavHistory::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 169); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
170 NS_INTERFACE_MAP_ENTRY(nsINavHistoryService)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsINavHistoryService>)) foundInterface
= static_cast<nsINavHistoryService*>(this); else
171 NS_INTERFACE_MAP_ENTRY(nsIObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIObserver>)) foundInterface = static_cast
<nsIObserver*>(this); else
172 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
173 NS_INTERFACE_MAP_ENTRY(mozIStorageVacuumParticipant)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIStorageVacuumParticipant>)) foundInterface
= static_cast<mozIStorageVacuumParticipant*>(this); else
174 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINavHistoryService)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsINavHistoryService*>
(this)); else
175 NS_IMPL_QUERY_CLASSINFO(nsNavHistory)if (aIID.Equals((nsIClassInfo::COMTypeInfo<nsIClassInfo, void
>::kIID))) { if (!gnsNavHistory_classInfoGlobal) gnsNavHistory_classInfoGlobal
= new (knsNavHistoryClassInfoDataPlace.addr()) GenericClassInfo
(&knsNavHistoryClassInfoData); foundInterface = gnsNavHistory_classInfoGlobal
; } else
176NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports
, void>::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo
<nsISupports, void>::kIID))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 176; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
177
178// We don't care about flattening everything
179NS_IMPL_CI_INTERFACE_GETTER(nsNavHistory, nsINavHistoryService)static_assert(1 > 0, "Need more arguments to NS_IMPL_CI_INTERFACE_GETTER"
); nsresult nsNavHistory_GetInterfacesHelper(nsTArray<nsIID
> & array) { array.Clear(); array.SetCapacity(1); array
.AppendElement((nsINavHistoryService::COMTypeInfo<nsINavHistoryService
, void>::kIID)); return NS_OK; }
180
181namespace {
182
183static Maybe<nsCString> GetSimpleBookmarksQueryParent(
184 const RefPtr<nsNavHistoryQuery>& aQuery,
185 const RefPtr<nsNavHistoryQueryOptions>& aOptions);
186static void ParseSearchTermsFromQuery(const RefPtr<nsNavHistoryQuery>& aQuery,
187 nsTArray<nsString>* aTerms);
188
189nsresult FetchInfo(const RefPtr<mozilla::places::Database>& aDB,
190 const nsCString& aGUID, int32_t& aType, int64_t& aId,
191 nsCString& aTitle, PRTime& aDateAdded,
192 PRTime& aLastModified) {
193 nsCOMPtr<mozIStorageStatement> statement = aDB->GetStatement(
194 "SELECT type, id, title, dateAdded, lastModified FROM moz_bookmarks "
195 "WHERE guid = :guid");
196 NS_ENSURE_STATE(statement)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 196); return NS_ERROR_UNEXPECTED; } } while (false)
;
197 mozStorageStatementScoper scoper(statement);
198 nsresult rv = statement->BindUTF8StringByName("guid"_ns, aGUID);
199 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 199); return rv; } } while (false)
;
200
201 bool hasResult;
202 rv = statement->ExecuteStep(&hasResult);
203 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 203); return rv; } } while (false)
;
204 if (!hasResult) {
205 return NS_ERROR_INVALID_ARG;
206 }
207
208 aType = statement->AsInt32(0);
209 aId = statement->AsInt64(1);
210
211 bool isNull;
212 rv = statement->GetIsNull(2, &isNull);
213 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 213); return rv; } } while (false)
;
214 if (isNull) {
215 aTitle.SetIsVoid(true);
216 } else {
217 rv = statement->GetUTF8String(2, aTitle);
218 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 218); return rv; } } while (false)
;
219 }
220
221 aDateAdded = statement->AsInt64(3);
222 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 222); return rv; } } while (false)
;
223 aLastModified = statement->AsInt64(4);
224 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 224); return rv; } } while (false)
;
225
226 return NS_OK;
227}
228
229} // namespace
230
231// Queries rows indexes to bind or get values, if adding a new one, be sure to
232// update nsNavBookmarks statements and its kGetChildrenIndex_* constants
233const int32_t nsNavHistory::kGetInfoIndex_PageID = 0;
234const int32_t nsNavHistory::kGetInfoIndex_URL = 1;
235const int32_t nsNavHistory::kGetInfoIndex_Title = 2;
236const int32_t nsNavHistory::kGetInfoIndex_RevHost = 3;
237const int32_t nsNavHistory::kGetInfoIndex_VisitCount = 4;
238const int32_t nsNavHistory::kGetInfoIndex_VisitDate = 5;
239const int32_t nsNavHistory::kGetInfoIndex_FaviconURL = 6;
240const int32_t nsNavHistory::kGetInfoIndex_ItemId = 7;
241const int32_t nsNavHistory::kGetInfoIndex_ItemDateAdded = 8;
242const int32_t nsNavHistory::kGetInfoIndex_ItemLastModified = 9;
243const int32_t nsNavHistory::kGetInfoIndex_ItemParentId = 10;
244const int32_t nsNavHistory::kGetInfoIndex_ItemTags = 11;
245const int32_t nsNavHistory::kGetInfoIndex_Frecency = 12;
246const int32_t nsNavHistory::kGetInfoIndex_Hidden = 13;
247const int32_t nsNavHistory::kGetInfoIndex_Guid = 14;
248const int32_t nsNavHistory::kGetInfoIndex_VisitId = 15;
249const int32_t nsNavHistory::kGetInfoIndex_FromVisitId = 16;
250const int32_t nsNavHistory::kGetInfoIndex_VisitType = 17;
251// These columns are followed by corresponding constants in nsNavBookmarks.cpp,
252// which must be kept in sync:
253// nsNavBookmarks::kGetChildrenIndex_Guid = 18;
254// nsNavBookmarks::kGetChildrenIndex_Position = 19;
255// nsNavBookmarks::kGetChildrenIndex_Type = 20;
256// nsNavBookmarks::kGetChildrenIndex_PlaceID = 21;
257const int32_t nsNavHistory::kGetTargetFolder_Guid = 22;
258const int32_t nsNavHistory::kGetTargetFolder_ItemId = 23;
259const int32_t nsNavHistory::kGetTargetFolder_Title = 24;
260
261PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsNavHistory, gHistoryService)nsNavHistory* nsNavHistory::gHistoryService = nullptr; already_AddRefed
<nsNavHistory> nsNavHistory::GetSingleton() { if (gHistoryService
) { RefPtr<nsNavHistory> ret = gHistoryService; return ret
.forget(); } gHistoryService = new nsNavHistory(); RefPtr<
nsNavHistory> ret = gHistoryService; if (((bool)(__builtin_expect
(!!(NS_FAILED_impl(gHistoryService->Init())), 0)))) { ret =
nullptr; gHistoryService = nullptr; return nullptr; } return
ret.forget(); }
262
263nsNavHistory::nsNavHistory()
264 : mCachedNow(0),
265 mRecentTyped(RECENT_EVENTS_INITIAL_CACHE_LENGTH64),
266 mRecentLink(RECENT_EVENTS_INITIAL_CACHE_LENGTH64),
267 mRecentBookmark(RECENT_EVENTS_INITIAL_CACHE_LENGTH64),
268 mHistoryEnabled(true),
269 mMatchDiacritics(false),
270 mNumVisitsForFrecency(10),
271 mTagsFolder(-1),
272 mLastCachedStartOfDay(INT64_MAX(9223372036854775807L)),
273 mLastCachedEndOfDay(0) {
274 NS_ASSERTION(!gHistoryService,do { if (!(!gHistoryService)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Attempting to create two instances of the service!", "!gHistoryService"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 275); MOZ_PretendNoReturn(); } } while (0)
275 "Attempting to create two instances of the service!")do { if (!(!gHistoryService)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Attempting to create two instances of the service!", "!gHistoryService"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 275); MOZ_PretendNoReturn(); } } while (0)
;
276 gHistoryService = this;
277}
278
279nsNavHistory::~nsNavHistory() {
280 MOZ_ASSERT(NS_IsMainThread(), "Must be called on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Must be called on the main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 280); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { *((volatile
int*)__null) = 280; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
281
282 // remove the static reference to the service. Check to make sure its us
283 // in case somebody creates an extra instance of the service.
284 NS_ASSERTION(gHistoryService == this,do { if (!(gHistoryService == this)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Deleting a non-singleton instance of the service", "gHistoryService == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 285); MOZ_PretendNoReturn(); } } while (0)
285 "Deleting a non-singleton instance of the service")do { if (!(gHistoryService == this)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Deleting a non-singleton instance of the service", "gHistoryService == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 285); MOZ_PretendNoReturn(); } } while (0)
;
286
287 if (gHistoryService == this) gHistoryService = nullptr;
288}
289
290nsresult nsNavHistory::Init() {
291 LoadPrefs();
292
293 mDB = Database::GetDatabase();
294 NS_ENSURE_STATE(mDB)do { if ((__builtin_expect(!!(!(mDB)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "mDB" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 294); return NS_ERROR_UNEXPECTED; } } while (false)
;
295
296 /*****************************************************************************
297 *** IMPORTANT NOTICE!
298 ***
299 *** Nothing after these add observer calls should return anything but NS_OK.
300 *** If a failure code is returned, this nsNavHistory object will be held onto
301 *** by the observer service and the preference service.
302 ****************************************************************************/
303
304 // Observe preferences changes.
305 Preferences::AddWeakObservers(this, kObservedPrefs);
306
307 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
308 if (obsSvc) {
309 (void)obsSvc->AddObserver(this, TOPIC_PLACES_CONNECTION_CLOSED"places-connection-closed", true);
310 (void)obsSvc->AddObserver(this, TOPIC_IDLE_DAILY"idle-daily", true);
311 (void)obsSvc->AddObserver(this, TOPIC_APP_LOCALES_CHANGED"intl:app-locales-changed", true);
312 }
313
314 // Don't add code that can fail here! Do it up above, before we add our
315 // observers.
316
317 return NS_OK;
318}
319
320NS_IMETHODIMPnsresult
321nsNavHistory::GetDatabaseStatus(uint16_t* aDatabaseStatus) {
322 NS_ENSURE_ARG_POINTER(aDatabaseStatus)do { if ((__builtin_expect(!!(!(aDatabaseStatus)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDatabaseStatus" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 322); return NS_ERROR_INVALID_POINTER; } } while (false)
;
323 *aDatabaseStatus = mDB->GetDatabaseStatus();
324 return NS_OK;
325}
326
327uint32_t nsNavHistory::GetRecentFlags(nsIURI* aURI) {
328 uint32_t result = 0;
329 nsAutoCString spec;
330 nsresult rv = aURI->GetSpec(spec);
331 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Unable to get aURI's spec")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Unable to get aURI's spec"
, "NS_SUCCEEDED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 331); } } while (false)
;
332
333 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
334 if (CheckIsRecentEvent(&mRecentTyped, spec)) result |= RECENT_TYPED;
335 if (CheckIsRecentEvent(&mRecentLink, spec)) result |= RECENT_ACTIVATED;
336 if (CheckIsRecentEvent(&mRecentBookmark, spec)) result |= RECENT_BOOKMARKED;
337 }
338
339 return result;
340}
341
342nsresult nsNavHistory::GetIdForPage(nsIURI* aURI, int64_t* _pageId,
343 nsCString& _GUID) {
344 *_pageId = 0;
345
346 nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
347 "SELECT id, url, title, rev_host, visit_count, guid "
348 "FROM moz_places "
349 "WHERE url_hash = hash(:page_url) AND url = :page_url ");
350 NS_ENSURE_STATE(stmt)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 350); return NS_ERROR_UNEXPECTED; } } while (false)
;
351 mozStorageStatementScoper scoper(stmt);
352
353 nsresult rv = URIBinder::Bind(stmt, "page_url"_ns, aURI);
354 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 354); return rv; } } while (false)
;
355
356 bool hasEntry = false;
357 rv = stmt->ExecuteStep(&hasEntry);
358 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 358); return rv; } } while (false)
;
359
360 if (hasEntry) {
361 rv = stmt->GetInt64(0, _pageId);
362 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 362); return rv; } } while (false)
;
363 rv = stmt->GetUTF8String(5, _GUID);
364 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 364); return rv; } } while (false)
;
365 }
366
367 return NS_OK;
368}
369
370nsresult nsNavHistory::GetOrCreateIdForPage(nsIURI* aURI, int64_t* _pageId,
371 nsCString& _GUID) {
372 nsresult rv = GetIdForPage(aURI, _pageId, _GUID);
373 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 373); return rv; } } while (false)
;
374
375 if (*_pageId != 0) {
376 return NS_OK;
377 }
378
379 {
380 // Create a new hidden, untyped and unvisited entry.
381 nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
382 "INSERT INTO moz_places (url, url_hash, rev_host, hidden, frecency, "
383 "guid) "
384 "VALUES (:page_url, hash(:page_url), :rev_host, :hidden, :frecency, "
385 ":guid) ");
386 NS_ENSURE_STATE(stmt)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 386); return NS_ERROR_UNEXPECTED; } } while (false)
;
387 mozStorageStatementScoper scoper(stmt);
388
389 rv = URIBinder::Bind(stmt, "page_url"_ns, aURI);
390 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 390); return rv; } } while (false)
;
391 // host (reversed with trailing period)
392 nsAutoString revHost;
393 rv = GetReversedHostname(aURI, revHost);
394 // Not all URI types have hostnames, so this is optional.
395 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
396 rv = stmt->BindStringByName("rev_host"_ns, revHost);
397 } else {
398 rv = stmt->BindNullByName("rev_host"_ns);
399 }
400 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 400); return rv; } } while (false)
;
401 rv = stmt->BindInt32ByName("hidden"_ns, 1);
402 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 402); return rv; } } while (false)
;
403 nsAutoCString spec;
404 rv = aURI->GetSpec(spec);
405 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 405); return rv; } } while (false)
;
406 rv = stmt->BindInt32ByName("frecency"_ns, IsQueryURI(spec) ? 0 : -1);
407 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 407); return rv; } } while (false)
;
408 rv = GenerateGUID(_GUID);
409 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 409); return rv; } } while (false)
;
410 rv = stmt->BindUTF8StringByName("guid"_ns, _GUID);
411 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 411); return rv; } } while (false)
;
412
413 rv = stmt->Execute();
414 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 414); return rv; } } while (false)
;
415
416 *_pageId = sLastInsertedPlaceId;
417 }
418
419 return NS_OK;
420}
421
422void nsNavHistory::LoadPrefs() {
423 // History preferences.
424 mHistoryEnabled = Preferences::GetBool(PREF_HISTORY_ENABLED"places.history.enabled", true);
425 mMatchDiacritics = Preferences::GetBool(PREF_MATCH_DIACRITICS"places.search.matchDiacritics", false);
426
427 // Frecency preferences.
428#define FRECENCY_PREF(_prop, _pref) \
429 _prop = Preferences::GetInt(_pref, _pref##_DEF)
430
431 FRECENCY_PREF(mNumVisitsForFrecency, PREF_FREC_NUM_VISITS"places.frecency.numVisits");
432 FRECENCY_PREF(mFirstBucketCutoffInDays, PREF_FREC_FIRST_BUCKET_CUTOFF"places.frecency.firstBucketCutoff");
433 FRECENCY_PREF(mSecondBucketCutoffInDays, PREF_FREC_SECOND_BUCKET_CUTOFF"places.frecency.secondBucketCutoff");
434 FRECENCY_PREF(mThirdBucketCutoffInDays, PREF_FREC_THIRD_BUCKET_CUTOFF"places.frecency.thirdBucketCutoff");
435 FRECENCY_PREF(mFourthBucketCutoffInDays, PREF_FREC_FOURTH_BUCKET_CUTOFF"places.frecency.fourthBucketCutoff");
436 FRECENCY_PREF(mEmbedVisitBonus, PREF_FREC_EMBED_VISIT_BONUS"places.frecency.embedVisitBonus");
437 FRECENCY_PREF(mFramedLinkVisitBonus, PREF_FREC_FRAMED_LINK_VISIT_BONUS"places.frecency.framedLinkVisitBonus");
438 FRECENCY_PREF(mLinkVisitBonus, PREF_FREC_LINK_VISIT_BONUS"places.frecency.linkVisitBonus");
439 FRECENCY_PREF(mTypedVisitBonus, PREF_FREC_TYPED_VISIT_BONUS"places.frecency.typedVisitBonus");
440 FRECENCY_PREF(mBookmarkVisitBonus, PREF_FREC_BOOKMARK_VISIT_BONUS"places.frecency.bookmarkVisitBonus");
441 FRECENCY_PREF(mDownloadVisitBonus, PREF_FREC_DOWNLOAD_VISIT_BONUS"places.frecency.downloadVisitBonus");
442 FRECENCY_PREF(mPermRedirectVisitBonus, PREF_FREC_PERM_REDIRECT_VISIT_BONUS"places.frecency.permRedirectVisitBonus");
443 FRECENCY_PREF(mTempRedirectVisitBonus, PREF_FREC_TEMP_REDIRECT_VISIT_BONUS"places.frecency.tempRedirectVisitBonus");
444 FRECENCY_PREF(mRedirectSourceVisitBonus, PREF_FREC_REDIR_SOURCE_VISIT_BONUS"places.frecency.redirectSourceVisitBonus");
445 FRECENCY_PREF(mDefaultVisitBonus, PREF_FREC_DEFAULT_VISIT_BONUS"places.frecency.defaultVisitBonus");
446 FRECENCY_PREF(mUnvisitedBookmarkBonus, PREF_FREC_UNVISITED_BOOKMARK_BONUS"places.frecency.unvisitedBookmarkBonus");
447 FRECENCY_PREF(mUnvisitedTypedBonus, PREF_FREC_UNVISITED_TYPED_BONUS"places.frecency.unvisitedTypedBonus");
448 FRECENCY_PREF(mReloadVisitBonus, PREF_FREC_RELOAD_VISIT_BONUS"places.frecency.reloadVisitBonus");
449 FRECENCY_PREF(mFirstBucketWeight, PREF_FREC_FIRST_BUCKET_WEIGHT"places.frecency.firstBucketWeight");
450 FRECENCY_PREF(mSecondBucketWeight, PREF_FREC_SECOND_BUCKET_WEIGHT"places.frecency.secondBucketWeight");
451 FRECENCY_PREF(mThirdBucketWeight, PREF_FREC_THIRD_BUCKET_WEIGHT"places.frecency.thirdBucketWeight");
452 FRECENCY_PREF(mFourthBucketWeight, PREF_FREC_FOURTH_BUCKET_WEIGHT"places.frecency.fourthBucketWeight");
453 FRECENCY_PREF(mDefaultWeight, PREF_FREC_DEFAULT_BUCKET_WEIGHT"places.frecency.defaultBucketWeight");
454
455#undef FRECENCY_PREF
456}
457
458void nsNavHistory::UpdateDaysOfHistory(PRTime visitTime) {
459 if (sDaysOfHistory == 0) {
460 sDaysOfHistory = 1;
461 }
462
463 if (visitTime > mLastCachedEndOfDay || visitTime < mLastCachedStartOfDay) {
464 InvalidateDaysOfHistory();
465 }
466}
467
468/** static */
469nsLiteralCString nsNavHistory::GetTagsSqlFragment(const uint16_t aQueryType,
470 bool aExcludeItems) {
471 if (aQueryType != nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS ||
472 aExcludeItems) {
473 return "WITH tagged(place_id, tags) AS (VALUES(NULL, NULL)) "_ns;
474 }
475 return "WITH tagged(place_id, tags) AS ( "
476 " SELECT b.fk, group_concat(p.title ORDER BY p.title) "
477 " FROM moz_bookmarks b "
478 " JOIN moz_bookmarks p ON p.id = b.parent "
479 " JOIN moz_bookmarks g ON g.id = p.parent "
480 " WHERE g.guid = " SQL_QUOTE(TAGS_ROOT_GUID)"'" "tags________" "'"
481 " GROUP BY b.fk "
482 ") "_ns;
483}
484
485/* static */
486mozilla::Maybe<nsCString> nsNavHistory::GetTargetFolderGuid(
487 const nsACString& aQueryURI) {
488 nsCOMPtr<nsINavHistoryQuery> query;
489 nsCOMPtr<nsINavHistoryQueryOptions> options;
490 if (!IsQueryURI(aQueryURI) ||
491 NS_FAILED(nsNavHistoryQuery::QueryStringToQuery(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsNavHistoryQuery::
QueryStringToQuery( aQueryURI, getter_AddRefs(query), getter_AddRefs
(options)))), 0)))
492 aQueryURI, getter_AddRefs(query), getter_AddRefs(options)))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsNavHistoryQuery::
QueryStringToQuery( aQueryURI, getter_AddRefs(query), getter_AddRefs
(options)))), 0)))
) {
493 return Nothing();
494 }
495
496 RefPtr<nsNavHistoryQuery> queryObj = do_QueryObject(query);
497 RefPtr<nsNavHistoryQueryOptions> optionsObj = do_QueryObject(options);
498 if (!queryObj || !optionsObj) {
499 return Nothing();
500 }
501
502 return GetSimpleBookmarksQueryParent(queryObj, optionsObj);
503}
504
505Atomic<int64_t> nsNavHistory::sLastInsertedPlaceId(0);
506Atomic<int64_t> nsNavHistory::sLastInsertedVisitId(0);
507Atomic<bool> nsNavHistory::sIsFrecencyDecaying(false);
508Atomic<bool> nsNavHistory::sShouldStartFrecencyRecalculation(false);
509
510void // static
511nsNavHistory::StoreLastInsertedId(const nsACString& aTable,
512 const int64_t aLastInsertedId) {
513 if (aTable.EqualsLiteral("moz_places")) {
514 nsNavHistory::sLastInsertedPlaceId = aLastInsertedId;
515 } else if (aTable.EqualsLiteral("moz_historyvisits")) {
516 nsNavHistory::sLastInsertedVisitId = aLastInsertedId;
517 } else {
518 MOZ_ASSERT(false, "Trying to store the insert id for an unknown table?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Trying to store the insert id for an unknown table?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Trying to store the insert id for an unknown table?" ")"); do
{ *((volatile int*)__null) = 518; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
519 }
520}
521
522Atomic<int32_t> nsNavHistory::sDaysOfHistory(-1);
523
524void // static
525nsNavHistory::InvalidateDaysOfHistory() {
526 sDaysOfHistory = -1;
527}
528
529int32_t nsNavHistory::GetDaysOfHistory() {
530 MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "This can only be called on the main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This can only be called on the main thread" ")"); do {
*((volatile int*)__null) = 530; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
531
532 if (sDaysOfHistory != -1) return sDaysOfHistory;
533
534 // SQLite doesn't have a CEIL() function, so we must do that later.
535 // We should also take into account timers resolution, that may be as bad as
536 // 16ms on Windows, so in some cases the difference may be 0, if the
537 // check is done near the visit. Thus remember to check for NULL separately.
538 nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
539 "SELECT CAST(( "
540 "strftime('%s','now','localtime','utc') - "
541 "(SELECT MIN(visit_date)/1000000 FROM moz_historyvisits) "
542 ") AS DOUBLE) "
543 "/86400, "
544 "strftime('%s','now','localtime','+1 day','start of day','utc') * "
545 "1000000");
546 NS_ENSURE_TRUE(stmt, 0)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 546); return 0; } } while (false)
;
547 mozStorageStatementScoper scoper(stmt);
548
549 bool hasResult;
550 if (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
551 // If we get NULL, then there are no visits, otherwise there must always be
552 // at least 1 day of history.
553 bool hasNoVisits;
554 (void)stmt->GetIsNull(0, &hasNoVisits);
555 sDaysOfHistory =
556 hasNoVisits
557 ? 0
558 : std::max(1, static_cast<int32_t>(ceil(stmt->AsDouble(0))));
559 mLastCachedStartOfDay =
560 NormalizeTime(nsINavHistoryQuery::TIME_RELATIVE_TODAY, 0);
561 mLastCachedEndOfDay = stmt->AsInt64(1) - 1; // Start of tomorrow - 1.
562 }
563
564 return sDaysOfHistory;
565}
566
567PRTime nsNavHistory::GetNow() {
568 if (!mCachedNow) {
569 mCachedNow = PR_Now();
570 if (!mExpireNowTimer) mExpireNowTimer = NS_NewTimer();
571 if (mExpireNowTimer)
572 mExpireNowTimer->InitWithNamedFuncCallback(
573 expireNowTimerCallback, this, RENEW_CACHED_NOW_TIMEOUT((int32_t)3 * 1000L),
574 nsITimer::TYPE_ONE_SHOT, "nsNavHistory::GetNow");
575 }
576 return mCachedNow;
577}
578
579void nsNavHistory::expireNowTimerCallback(nsITimer* aTimer, void* aClosure) {
580 nsNavHistory* history = static_cast<nsNavHistory*>(aClosure);
581 if (history) {
582 history->mCachedNow = 0;
583 history->mExpireNowTimer = nullptr;
584 }
585}
586
587/**
588 * Code borrowed from mozilla/xpfe/components/history/src/nsGlobalHistory.cpp
589 * Pass in a pre-normalized now and a date, and we'll find the difference since
590 * midnight on each of the days.
591 */
592static PRTime NormalizeTimeRelativeToday(PRTime aTime) {
593 // round to midnight this morning
594 PRExplodedTime explodedTime;
595 PR_ExplodeTime(aTime, PR_LocalTimeParameters, &explodedTime);
596
597 // set to midnight (0:00)
598 explodedTime.tm_min = explodedTime.tm_hour = explodedTime.tm_sec =
599 explodedTime.tm_usec = 0;
600
601 return PR_ImplodeTime(&explodedTime);
602}
603
604// nsNavHistory::NormalizeTime
605//
606// Converts a nsINavHistoryQuery reference+offset time into a PRTime
607// relative to the epoch.
608//
609// It is important that this function NOT use the current time optimization.
610// It is called to update queries, and we really need to know what right
611// now is because those incoming values will also have current times that
612// we will have to compare against.
613
614PRTime // static
615nsNavHistory::NormalizeTime(uint32_t aRelative, PRTime aOffset) {
616 PRTime ref;
617 switch (aRelative) {
618 case nsINavHistoryQuery::TIME_RELATIVE_EPOCH:
619 return aOffset;
620 case nsINavHistoryQuery::TIME_RELATIVE_TODAY:
621 ref = NormalizeTimeRelativeToday(PR_Now());
622 break;
623 case nsINavHistoryQuery::TIME_RELATIVE_NOW:
624 ref = PR_Now();
625 break;
626 default:
627 MOZ_ASSERT_UNREACHABLE("Invalid relative time")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Invalid relative time" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid relative time" ")"); do {
*((volatile int*)__null) = 627; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
628 return 0;
629 }
630 return ref + aOffset;
631}
632
633// nsNavHistory::DomainNameFromURI
634//
635// This does the www.mozilla.org -> mozilla.org and
636// foo.theregister.co.uk -> theregister.co.uk conversion
637void nsNavHistory::DomainNameFromURI(nsIURI* aURI, nsACString& aDomainName) {
638 // lazily get the effective tld service
639 if (!mTLDService)
640 mTLDService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
641
642 if (mTLDService) {
643 // get the base domain for a given hostname.
644 // e.g. for "images.bbc.co.uk", this would be "bbc.co.uk".
645 nsresult rv = mTLDService->GetBaseDomain(aURI, 0, aDomainName);
646 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) return;
647 }
648
649 // just return the original hostname
650 // (it's also possible the host is an IP address)
651 aURI->GetAsciiHost(aDomainName);
652}
653
654bool nsNavHistory::hasHistoryEntries() { return GetDaysOfHistory() > 0; }
655
656// Call this method before visiting a URL in order to help determine the
657// transition type of the visit.
658//
659// @see MarkPageAsTyped
660
661NS_IMETHODIMPnsresult
662nsNavHistory::MarkPageAsFollowedBookmark(nsIURI* aURI) {
663 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 663); MOZ_PretendNoReturn(); } } while (0)
;
664 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 664); return NS_ERROR_INVALID_ARG; } } while (false)
;
665
666 // don't add when history is disabled
667 if (IsHistoryDisabled()) return NS_OK;
668
669 nsAutoCString uriString;
670 nsresult rv = aURI->GetSpec(uriString);
671 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 671); return rv; } } while (false)
;
672
673 mRecentBookmark.InsertOrUpdate(uriString, GetNow());
674
675 if (mRecentBookmark.Count() > RECENT_EVENT_QUEUE_MAX_LENGTH128)
676 ExpireNonrecentEvents(&mRecentBookmark);
677
678 return NS_OK;
679}
680
681// nsNavHistory::CanAddURI
682//
683// Filter out unwanted URIs such as "chrome:", "mailbox:", etc.
684//
685// The model is if we don't know differently then add which basically means
686// we are suppose to try all the things we know not to allow in and then if
687// we don't bail go on and allow it in.
688
689NS_IMETHODIMPnsresult
690nsNavHistory::CanAddURI(nsIURI* aURI, bool* canAdd) {
691 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 691); MOZ_PretendNoReturn(); } } while (0)
;
692 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 692); return NS_ERROR_INVALID_ARG; } } while (false)
;
693 NS_ENSURE_ARG_POINTER(canAdd)do { if ((__builtin_expect(!!(!(canAdd)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "canAdd" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 693); return NS_ERROR_INVALID_POINTER; } } while (false)
;
694
695 // If history is disabled, don't add any entry.
696 *canAdd = !IsHistoryDisabled() && BaseHistory::CanStore(aURI);
697 return NS_OK;
698}
699
700NS_IMETHODIMPnsresult
701nsNavHistory::GetNewQuery(nsINavHistoryQuery** _retval) {
702 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 702); MOZ_PretendNoReturn(); } } while (0)
;
703 NS_ENSURE_ARG_POINTER(_retval)do { if ((__builtin_expect(!!(!(_retval)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_retval" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 703); return NS_ERROR_INVALID_POINTER; } } while (false)
;
704
705 RefPtr<nsNavHistoryQuery> query = new nsNavHistoryQuery();
706 query.forget(_retval);
707 return NS_OK;
708}
709
710// nsNavHistory::GetNewQueryOptions
711
712NS_IMETHODIMPnsresult
713nsNavHistory::GetNewQueryOptions(nsINavHistoryQueryOptions** _retval) {
714 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 714); MOZ_PretendNoReturn(); } } while (0)
;
715 NS_ENSURE_ARG_POINTER(_retval)do { if ((__builtin_expect(!!(!(_retval)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_retval" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 715); return NS_ERROR_INVALID_POINTER; } } while (false)
;
716
717 RefPtr<nsNavHistoryQueryOptions> queryOptions =
718 new nsNavHistoryQueryOptions();
719 queryOptions.forget(_retval);
720 return NS_OK;
721}
722
723NS_IMETHODIMPnsresult
724nsNavHistory::ExecuteQuery(nsINavHistoryQuery* aQuery,
725 nsINavHistoryQueryOptions* aOptions,
726 nsINavHistoryResult** _retval) {
727 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 727); MOZ_PretendNoReturn(); } } while (0)
;
728 NS_ENSURE_ARG(aQuery)do { if ((__builtin_expect(!!(!(aQuery)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aQuery" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 728); return NS_ERROR_INVALID_ARG; } } while (false)
;
729 NS_ENSURE_ARG(aOptions)do { if ((__builtin_expect(!!(!(aOptions)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOptions" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 729); return NS_ERROR_INVALID_ARG; } } while (false)
;
730 NS_ENSURE_ARG_POINTER(_retval)do { if ((__builtin_expect(!!(!(_retval)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_retval" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 730); return NS_ERROR_INVALID_POINTER; } } while (false)
;
731
732 // Clone the input query and options, because the caller might change the
733 // objects, but we always want to reflect the original parameters.
734 nsCOMPtr<nsINavHistoryQuery> queryClone;
735 aQuery->Clone(getter_AddRefs(queryClone));
736 NS_ENSURE_STATE(queryClone)do { if ((__builtin_expect(!!(!(queryClone)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "queryClone" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 736); return NS_ERROR_UNEXPECTED; } } while (false)
;
737 RefPtr<nsNavHistoryQuery> query = do_QueryObject(queryClone);
738 NS_ENSURE_STATE(query)do { if ((__builtin_expect(!!(!(query)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "query" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 738); return NS_ERROR_UNEXPECTED; } } while (false)
;
739 nsCOMPtr<nsINavHistoryQueryOptions> optionsClone;
740 aOptions->Clone(getter_AddRefs(optionsClone));
741 NS_ENSURE_STATE(optionsClone)do { if ((__builtin_expect(!!(!(optionsClone)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "optionsClone" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 741); return NS_ERROR_UNEXPECTED; } } while (false)
;
742 RefPtr<nsNavHistoryQueryOptions> options = do_QueryObject(optionsClone);
743 NS_ENSURE_STATE(options)do { if ((__builtin_expect(!!(!(options)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "options" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 743); return NS_ERROR_UNEXPECTED; } } while (false)
;
744
745 // Create the root node.
746 RefPtr<nsNavHistoryContainerResultNode> rootNode;
747
748 Maybe<nsCString> targetFolderGuid =
749 GetSimpleBookmarksQueryParent(query, options);
750 if (targetFolderGuid.isSome()) {
751 int32_t targetFolderType = 0;
752 int64_t targetFolderId = -1;
753 nsCString targetFolderTitle;
754 PRTime dateAdded;
755 PRTime lastModified;
756 nsresult rv =
757 FetchInfo(mDB, *targetFolderGuid, targetFolderType, targetFolderId,
758 targetFolderTitle, dateAdded, lastModified);
759 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
760 targetFolderType == nsINavBookmarksService::TYPE_FOLDER) {
761 auto* node = new nsNavHistoryFolderResultNode(
762 targetFolderId, *targetFolderGuid, targetFolderId, *targetFolderGuid,
763 targetFolderTitle, options);
764 node->mDateAdded = dateAdded;
765 node->mLastModified = lastModified;
766 rootNode = node->GetAsContainer();
767 } else {
768 NS_WARNING("Generating a generic empty node for a broken query!")NS_DebugBreak(NS_DEBUG_WARNING, "Generating a generic empty node for a broken query!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 768)
;
769 // This is a perf hack to generate an empty query that skips filtering.
770 options->SetExcludeItems(true);
771 }
772 }
773
774 if (!rootNode) {
775 // Either this is not a folder shortcut, or is a broken one. In both cases
776 // just generate a query node.
777 nsAutoCString queryUri;
778 nsresult rv = QueryToQueryString(query, options, queryUri);
779 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 779); return rv; } } while (false)
;
780 rootNode =
781 new nsNavHistoryQueryResultNode(""_ns, 0, queryUri, query, options);
782 }
783
784 // Create the result that will hold nodes. Inject batching status into it.
785 RefPtr<nsNavHistoryResult> result =
786 new nsNavHistoryResult(rootNode, query, options);
787 result.forget(_retval);
788 return NS_OK;
789}
790
791// determine from our nsNavHistoryQuery array and nsNavHistoryQueryOptions
792// if this is the place query from the history menu.
793// from browser-menubar.inc, our history menu query is:
794// place:sort=4&maxResults=10
795// note, any maxResult > 0 will still be considered a history menu query
796// or if this is the place query from the old "Most Visited" item in some
797// profiles: folder: place:sort=8&maxResults=10 note, any maxResult > 0 will
798// still be considered a Most Visited menu query
799static bool IsOptimizableHistoryQuery(
800 const RefPtr<nsNavHistoryQuery>& aQuery,
801 const RefPtr<nsNavHistoryQueryOptions>& aOptions, uint16_t aSortMode) {
802 if (aOptions->QueryType() != nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY)
803 return false;
804
805 if (aOptions->ResultType() != nsINavHistoryQueryOptions::RESULTS_AS_URI)
806 return false;
807
808 if (aOptions->SortingMode() != aSortMode) return false;
809
810 if (aOptions->MaxResults() <= 0) return false;
811
812 if (aOptions->ExcludeItems()) return false;
813
814 if (aOptions->IncludeHidden()) return false;
815
816 if (aQuery->MinVisits() != -1 || aQuery->MaxVisits() != -1) return false;
817
818 if (aQuery->BeginTime() || aQuery->BeginTimeReference()) return false;
819
820 if (aQuery->EndTime() || aQuery->EndTimeReference()) return false;
821
822 if (!aQuery->SearchTerms().IsEmpty()) return false;
823
824 if (aQuery->DomainIsHost() || !aQuery->Domain().IsEmpty()) return false;
825
826 if (aQuery->Parents().Length() > 0) return false;
827
828 if (aQuery->Tags().Length() > 0) return false;
829
830 if (aQuery->Transitions().Length() > 0) return false;
831
832 return true;
833}
834
835static bool NeedToFilterResultSet(const RefPtr<nsNavHistoryQuery>& aQuery,
836 nsNavHistoryQueryOptions* aOptions) {
837 return aOptions->ExcludeQueries();
838}
839
840// ** Helper class for ConstructQueryString **/
841
842class PlacesSQLQueryBuilder {
843 public:
844 PlacesSQLQueryBuilder(const nsCString& aConditions,
845 const RefPtr<nsNavHistoryQuery>& aQuery,
846 const RefPtr<nsNavHistoryQueryOptions>& aOptions,
847 bool aUseLimit, nsNavHistory::StringHash& aAddParams);
848
849 nsresult GetQueryString(nsCString& aQueryString);
850
851 private:
852 nsresult Select();
853
854 nsresult SelectAsURI();
855 nsresult SelectAsVisit();
856 nsresult SelectAsDay();
857 nsresult SelectAsSite();
858 nsresult SelectAsTag();
859 nsresult SelectAsRoots();
860 nsresult SelectAsLeftPane();
861
862 nsresult Where();
863 nsresult GroupBy();
864 nsresult OrderBy();
865 nsresult Limit();
866
867 void OrderByColumnIndexAsc(int32_t aIndex);
868 void OrderByColumnIndexDesc(int32_t aIndex);
869 // Use these if you want a case insensitive sorting.
870 void OrderByTextColumnIndexAsc(int32_t aIndex);
871 void OrderByTextColumnIndexDesc(int32_t aIndex);
872
873 const nsCString& mConditions;
874 bool mUseLimit;
875
876 uint16_t mResultType;
877 uint16_t mQueryType;
878 bool mExcludeItems;
879 bool mIncludeHidden;
880 uint16_t mSortingMode;
881 uint32_t mMaxResults;
882
883 nsCString mQueryString;
884 nsCString mGroupBy;
885 bool mHasDateColumns;
886 bool mSkipOrderBy;
887
888 nsNavHistory::StringHash& mAddParams;
889};
890
891PlacesSQLQueryBuilder::PlacesSQLQueryBuilder(
892 const nsCString& aConditions, const RefPtr<nsNavHistoryQuery>& aQuery,
893 const RefPtr<nsNavHistoryQueryOptions>& aOptions, bool aUseLimit,
894 nsNavHistory::StringHash& aAddParams)
895 : mConditions(aConditions),
896 mUseLimit(aUseLimit),
897 mResultType(aOptions->ResultType()),
898 mQueryType(aOptions->QueryType()),
899 mExcludeItems(aOptions->ExcludeItems()),
900 mIncludeHidden(aOptions->IncludeHidden()),
901 mSortingMode(aOptions->SortingMode()),
902 mMaxResults(aOptions->MaxResults()),
903 mSkipOrderBy(false),
904 mAddParams(aAddParams) {
905 mHasDateColumns =
906 (mQueryType == nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS);
907 // Force the default sorting mode for tag queries.
908 if (mSortingMode == nsINavHistoryQueryOptions::SORT_BY_NONE &&
909 aQuery->Tags().Length() > 0) {
910 mSortingMode = nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING;
911 }
912}
913
914nsresult PlacesSQLQueryBuilder::GetQueryString(nsCString& aQueryString) {
915 nsresult rv = Select();
916 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 916); return rv; } } while (false)
;
917 rv = Where();
918 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 918); return rv; } } while (false)
;
919 rv = GroupBy();
920 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 920); return rv; } } while (false)
;
921 rv = OrderBy();
922 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 922); return rv; } } while (false)
;
923 rv = Limit();
924 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 924); return rv; } } while (false)
;
925
926 aQueryString = mQueryString;
927 return NS_OK;
928}
929
930nsresult PlacesSQLQueryBuilder::Select() {
931 nsresult rv;
932
933 switch (mResultType) {
934 case nsINavHistoryQueryOptions::RESULTS_AS_URI:
935 rv = SelectAsURI();
936 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 936); return rv; } } while (false)
;
937 break;
938
939 case nsINavHistoryQueryOptions::RESULTS_AS_VISIT:
940 rv = SelectAsVisit();
941 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 941); return rv; } } while (false)
;
942 break;
943
944 case nsINavHistoryQueryOptions::RESULTS_AS_DATE_QUERY:
945 case nsINavHistoryQueryOptions::RESULTS_AS_DATE_SITE_QUERY:
946 rv = SelectAsDay();
947 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 947); return rv; } } while (false)
;
948 break;
949
950 case nsINavHistoryQueryOptions::RESULTS_AS_SITE_QUERY:
951 rv = SelectAsSite();
952 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 952); return rv; } } while (false)
;
953 break;
954
955 case nsINavHistoryQueryOptions::RESULTS_AS_TAGS_ROOT:
956 rv = SelectAsTag();
957 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 957); return rv; } } while (false)
;
958 break;
959
960 case nsINavHistoryQueryOptions::RESULTS_AS_ROOTS_QUERY:
961 rv = SelectAsRoots();
962 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 962); return rv; } } while (false)
;
963 break;
964
965 case nsINavHistoryQueryOptions::RESULTS_AS_LEFT_PANE_QUERY:
966 rv = SelectAsLeftPane();
967 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 967); return rv; } } while (false)
;
968 break;
969
970 default:
971 MOZ_ASSERT_UNREACHABLE("Invalid result type")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Invalid result type" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 971); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid result type" ")"); do { *
((volatile int*)__null) = 971; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
972 }
973 return NS_OK;
974}
975
976nsresult PlacesSQLQueryBuilder::SelectAsURI() {
977 nsNavHistory* history = nsNavHistory::GetHistoryService();
978 NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(history)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "history" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 978); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
979
980 switch (mQueryType) {
981 case nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY: {
982 mQueryString =
983 nsNavHistory::GetTagsSqlFragment(mQueryType, mExcludeItems) +
984 "SELECT h.id, h.url, h.title AS page_title, h.rev_host, "
985 " h.visit_count, h.last_visit_date, null, null, null, null, null, "
986 " (SELECT tags FROM tagged WHERE place_id = h.id) AS tags, "
987 " h.frecency, h.hidden, h.guid, null, null, null, "
988 " null, null, null, null, null, null, null "
989 "FROM moz_places h "
990 // WHERE 1 is a no-op since additonal conditions will
991 // start with AND.
992 "WHERE 1 "
993 "{QUERY_OPTIONS_VISITS} {QUERY_OPTIONS_PLACES} "
994 "{ADDITIONAL_CONDITIONS} "_ns;
995 break;
996 }
997 case nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS: {
998 mQueryString =
999 nsNavHistory::GetTagsSqlFragment(mQueryType, mExcludeItems) +
1000 "SELECT b.fk, h.url, b.title AS page_title, "
1001 " h.rev_host, h.visit_count, h.last_visit_date, null, b.id, "
1002 " b.dateAdded, b.lastModified, b.parent, "
1003 " (SELECT tags FROM tagged WHERE place_id = h.id) AS tags, "
1004 " h.frecency, h.hidden, h.guid, null, null, null, b.guid, "
1005 " b.position, b.type, b.fk, t.guid, t.id, t.title "
1006 "FROM moz_bookmarks b "
1007 "JOIN moz_places h ON b.fk = h.id "
1008 "LEFT JOIN moz_bookmarks t ON t.guid = target_folder_guid(h.url) "
1009 "WHERE NOT EXISTS "
1010 "(SELECT id FROM moz_bookmarks "
1011 "WHERE id = b.parent AND parent = "_ns +
1012 nsPrintfCString("%" PRId64"l" "d", history->GetTagsFolder()) +
1013 ") "
1014 "AND NOT h.url_hash BETWEEN hash('place', 'prefix_lo') "
1015 " AND hash('place', 'prefix_hi') "
1016 "{ADDITIONAL_CONDITIONS}"_ns;
1017 break;
1018 }
1019 default: {
1020 return NS_ERROR_NOT_IMPLEMENTED;
1021 }
1022 }
1023 return NS_OK;
1024}
1025
1026nsresult PlacesSQLQueryBuilder::SelectAsVisit() {
1027 mQueryString =
1028 nsNavHistory::GetTagsSqlFragment(mQueryType, mExcludeItems) +
1029 "SELECT h.id, h.url, h.title AS page_title, h.rev_host, h.visit_count, "
1030 " v.visit_date, null, null, null, null, null, "
1031 " (SELECT tags FROM tagged WHERE place_id = h.id) AS tags, "
1032 " h.frecency, h.hidden, h.guid, v.id, v.from_visit, v.visit_type, "
1033 " null, null, null, null, null, null, null "
1034 "FROM moz_places h "
1035 "JOIN moz_historyvisits v ON h.id = v.place_id "
1036 // WHERE 1 is a no-op since additonal conditions will start with AND.
1037 "WHERE 1 "
1038 "{QUERY_OPTIONS_VISITS} {QUERY_OPTIONS_PLACES} "
1039 "{ADDITIONAL_CONDITIONS} "_ns;
1040
1041 return NS_OK;
1042}
1043
1044nsresult PlacesSQLQueryBuilder::SelectAsDay() {
1045 mSkipOrderBy = true;
1046
1047 // Sort child queries based on sorting mode if it's provided, otherwise
1048 // fallback to default sort by title ascending.
1049 uint16_t sortingMode = nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING;
1050 if (mSortingMode != nsINavHistoryQueryOptions::SORT_BY_NONE &&
1051 mResultType == nsINavHistoryQueryOptions::RESULTS_AS_DATE_QUERY)
1052 sortingMode = mSortingMode;
1053
1054 uint16_t resultType =
1055 mResultType == nsINavHistoryQueryOptions::RESULTS_AS_DATE_QUERY
1056 ? (uint16_t)nsINavHistoryQueryOptions::RESULTS_AS_URI
1057 : (uint16_t)nsINavHistoryQueryOptions::RESULTS_AS_SITE_QUERY;
1058
1059 // beginTime will become the node's time property, we don't use endTime
1060 // because it could overlap, and we use time to sort containers and find
1061 // insert position in a result.
1062 mQueryString = nsPrintfCString(
1063 "SELECT null, "
1064 "'place:type=%d&sort=%d&beginTime='||beginTime||'&endTime='||endTime, "
1065 "dayTitle, null, null, beginTime, null, null, null, null, null, null, "
1066 "null, null, null, null, null, null, null, null, null, null, "
1067 "null, null, null "
1068 "FROM (", // TOUTER BEGIN
1069 resultType, sortingMode);
1070
1071 nsNavHistory* history = nsNavHistory::GetHistoryService();
1072 NS_ENSURE_STATE(history)do { if ((__builtin_expect(!!(!(history)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "history" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1072); return NS_ERROR_UNEXPECTED; } } while (false)
;
1073
1074 int32_t daysOfHistory = history->GetDaysOfHistory();
1075 for (int32_t i = 0; i <= HISTORY_DATE_CONT_NUM(daysOfHistory)(3 + std::min(6, (int32_t)ceilf((float)daysOfHistory / 30))); i++) {
1076 nsAutoCString dateName;
1077 // Timeframes are calculated as BeginTime <= container < EndTime.
1078 // Notice times can't be relative to now, since to recognize a query we
1079 // must ensure it won't change based on the time it is built.
1080 // So, to select till now, we really select till start of tomorrow, that is
1081 // a fixed timestamp.
1082 // These are used as limits for the inside containers.
1083 nsAutoCString sqlFragmentContainerBeginTime, sqlFragmentContainerEndTime;
1084 // These are used to query if the container should be visible.
1085 nsAutoCString sqlFragmentSearchBeginTime, sqlFragmentSearchEndTime;
1086 switch (i) {
1087 case 0:
1088 // Today
1089 history->GetStringFromName("finduri-AgeInDays-is-0", dateName);
1090 // From start of today
1091 sqlFragmentContainerBeginTime = nsLiteralCString(
1092 "(strftime('%s','now','localtime','start of day','utc')*1000000)");
1093 // To now (tomorrow)
1094 sqlFragmentContainerEndTime = nsLiteralCString(
1095 "(strftime('%s','now','localtime','start of day','+1 "
1096 "day','utc')*1000000)");
1097 // Search for the same timeframe.
1098 sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
1099 sqlFragmentSearchEndTime = sqlFragmentContainerEndTime;
1100 break;
1101 case 1:
1102 // Yesterday
1103 history->GetStringFromName("finduri-AgeInDays-is-1", dateName);
1104 // From start of yesterday
1105 sqlFragmentContainerBeginTime = nsLiteralCString(
1106 "(strftime('%s','now','localtime','start of day','-1 "
1107 "day','utc')*1000000)");
1108 // To start of today
1109 sqlFragmentContainerEndTime = nsLiteralCString(
1110 "(strftime('%s','now','localtime','start of day','utc')*1000000)");
1111 // Search for the same timeframe.
1112 sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
1113 sqlFragmentSearchEndTime = sqlFragmentContainerEndTime;
1114 break;
1115 case 2:
1116 // Last 7 days
1117 history->GetAgeInDaysString(7, "finduri-AgeInDays-last-is", dateName);
1118 // From start of 7 days ago
1119 sqlFragmentContainerBeginTime = nsLiteralCString(
1120 "(strftime('%s','now','localtime','start of day','-7 "
1121 "days','utc')*1000000)");
1122 // To now (tomorrow)
1123 sqlFragmentContainerEndTime = nsLiteralCString(
1124 "(strftime('%s','now','localtime','start of day','+1 "
1125 "day','utc')*1000000)");
1126 // This is an overlapped container, but we show it only if there are
1127 // visits older than yesterday.
1128 sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
1129 sqlFragmentSearchEndTime = nsLiteralCString(
1130 "(strftime('%s','now','localtime','start of day','-1 "
1131 "day','utc')*1000000)");
1132 break;
1133 case 3:
1134 // This month
1135 history->GetStringFromName("finduri-AgeInMonths-is-0", dateName);
1136 // From start of this month
1137 sqlFragmentContainerBeginTime = nsLiteralCString(
1138 "(strftime('%s','now','localtime','start of "
1139 "month','utc')*1000000)");
1140 // To now (tomorrow)
1141 sqlFragmentContainerEndTime = nsLiteralCString(
1142 "(strftime('%s','now','localtime','start of day','+1 "
1143 "day','utc')*1000000)");
1144 // This is an overlapped container, but we show it only if there are
1145 // visits older than 7 days ago.
1146 sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
1147 sqlFragmentSearchEndTime = nsLiteralCString(
1148 "(strftime('%s','now','localtime','start of day','-7 "
1149 "days','utc')*1000000)");
1150 break;
1151 default:
1152 if (i == HISTORY_ADDITIONAL_DATE_CONT_NUM3 + 6) {
1153 // Older than 6 months
1154 history->GetAgeInDaysString(6, "finduri-AgeInMonths-isgreater",
1155 dateName);
1156 // From start of epoch
1157 sqlFragmentContainerBeginTime =
1158 "(datetime(0, 'unixepoch')*1000000)"_ns;
1159 // To start of 6 months ago ( 5 months + this month).
1160 sqlFragmentContainerEndTime = nsLiteralCString(
1161 "(strftime('%s','now','localtime','start of month','-5 "
1162 "months','utc')*1000000)");
1163 // Search for the same timeframe.
1164 sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
1165 sqlFragmentSearchEndTime = sqlFragmentContainerEndTime;
1166 break;
1167 }
1168 int32_t MonthIndex = i - HISTORY_ADDITIONAL_DATE_CONT_NUM3;
1169 // Previous months' titles are month's name if inside this year,
1170 // month's name and year for previous years.
1171 PRExplodedTime tm;
1172 PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &tm);
1173 uint16_t currentYear = tm.tm_year;
1174 // Set day before month, setting month without day could cause issues.
1175 // For example setting month to February when today is 30, since
1176 // February has not 30 days, will return March instead.
1177 // Also, we use day 2 instead of day 1, so that the GMT month is always
1178 // the same as the local month. (Bug 603002)
1179 tm.tm_mday = 2;
1180 tm.tm_month -= MonthIndex;
1181 // Notice we use GMTParameters because we just want to get the first
1182 // day of each month. Using LocalTimeParameters would instead force us
1183 // to apply a DST correction that we don't really need here.
1184 PR_NormalizeTime(&tm, PR_GMTParameters);
1185 // If the container is for a past year, add the year to its title,
1186 // otherwise just show the month name.
1187 if (tm.tm_year < currentYear) {
1188 nsNavHistory::GetMonthYear(tm, dateName);
1189 } else {
1190 nsNavHistory::GetMonthName(tm, dateName);
1191 }
1192
1193 // From start of MonthIndex + 1 months ago
1194 sqlFragmentContainerBeginTime = nsLiteralCString(
1195 "(strftime('%s','now','localtime','start of month','-");
1196 sqlFragmentContainerBeginTime.AppendInt(MonthIndex);
1197 sqlFragmentContainerBeginTime.AppendLiteral(" months','utc')*1000000)");
1198 // To start of MonthIndex months ago
1199 sqlFragmentContainerEndTime = nsLiteralCString(
1200 "(strftime('%s','now','localtime','start of month','-");
1201 sqlFragmentContainerEndTime.AppendInt(MonthIndex - 1);
1202 sqlFragmentContainerEndTime.AppendLiteral(" months','utc')*1000000)");
1203 // Search for the same timeframe.
1204 sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
1205 sqlFragmentSearchEndTime = sqlFragmentContainerEndTime;
1206 break;
1207 }
1208
1209 nsPrintfCString dateParam("dayTitle%d", i);
1210 mAddParams.InsertOrUpdate(dateParam, dateName);
1211
1212 nsPrintfCString dayRange(
1213 "SELECT :%s AS dayTitle, "
1214 "%s AS beginTime, "
1215 "%s AS endTime "
1216 "WHERE EXISTS ( "
1217 "SELECT id FROM moz_historyvisits "
1218 "WHERE visit_date >= %s "
1219 "AND visit_date < %s "
1220 "AND visit_type NOT IN (0,%d,%d) "
1221 "{QUERY_OPTIONS_VISITS} "
1222 "LIMIT 1 "
1223 ") ",
1224 dateParam.get(), sqlFragmentContainerBeginTime.get(),
1225 sqlFragmentContainerEndTime.get(), sqlFragmentSearchBeginTime.get(),
1226 sqlFragmentSearchEndTime.get(), nsINavHistoryService::TRANSITION_EMBED,
1227 nsINavHistoryService::TRANSITION_FRAMED_LINK);
1228
1229 mQueryString.Append(dayRange);
1230
1231 if (i < HISTORY_DATE_CONT_NUM(daysOfHistory)(3 + std::min(6, (int32_t)ceilf((float)daysOfHistory / 30))))
1232 mQueryString.AppendLiteral(" UNION ALL ");
1233 }
1234
1235 mQueryString.AppendLiteral(") "); // TOUTER END
1236
1237 return NS_OK;
1238}
1239
1240nsresult PlacesSQLQueryBuilder::SelectAsSite() {
1241 nsAutoCString localFiles;
1242
1243 nsNavHistory* history = nsNavHistory::GetHistoryService();
1244 NS_ENSURE_STATE(history)do { if ((__builtin_expect(!!(!(history)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "history" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1244); return NS_ERROR_UNEXPECTED; } } while (false)
;
1245
1246 history->GetStringFromName("localhost", localFiles);
1247 mAddParams.InsertOrUpdate("localhost"_ns, localFiles);
1248
1249 // If there are additional conditions the query has to join on visits too.
1250 nsAutoCString visitsJoin;
1251 nsAutoCString additionalConditions;
1252 nsAutoCString timeConstraints;
1253 if (!mConditions.IsEmpty()) {
1254 visitsJoin.AssignLiteral("JOIN moz_historyvisits v ON v.place_id = h.id ");
1255 additionalConditions.AssignLiteral(
1256 "{QUERY_OPTIONS_VISITS} "
1257 "{QUERY_OPTIONS_PLACES} "
1258 "{ADDITIONAL_CONDITIONS} ");
1259 timeConstraints.AssignLiteral(
1260 "||'&beginTime='||:begin_time||"
1261 "'&endTime='||:end_time");
1262 }
1263
1264 mQueryString = nsPrintfCString(
1265 "SELECT null, 'place:type=%d&sort=%d&domain=&domainIsHost=true'%s, "
1266 ":localhost, :localhost, null, null, null, null, null, null, null, "
1267 "null, null, null, null, null, null, null, null, null, null, "
1268 "null, null, null, null "
1269 "WHERE EXISTS ( "
1270 "SELECT h.id FROM moz_places h "
1271 "%s "
1272 "WHERE h.hidden = 0 "
1273 "AND h.visit_count > 0 "
1274 "AND h.url_hash BETWEEN hash('file', 'prefix_lo') AND "
1275 "hash('file', 'prefix_hi') "
1276 "%s "
1277 "LIMIT 1 "
1278 ") "
1279 "UNION ALL "
1280 "SELECT null, "
1281 "'place:type=%d&sort=%d&domain='||host||'&domainIsHost=true'%s, "
1282 "host, host, null, null, null, null, null, null, null, "
1283 "null, null, null, null, null, null, null, null, null, null, "
1284 "null, null, null, null "
1285 "FROM ( "
1286 "SELECT get_unreversed_host(h.rev_host) AS host "
1287 "FROM moz_places h "
1288 "%s "
1289 "WHERE h.hidden = 0 "
1290 "AND h.rev_host <> '.' "
1291 "AND h.visit_count > 0 "
1292 "%s "
1293 "GROUP BY h.rev_host "
1294 "ORDER BY host ASC "
1295 ") ",
1296 nsINavHistoryQueryOptions::RESULTS_AS_URI, mSortingMode,
1297 timeConstraints.get(), visitsJoin.get(), additionalConditions.get(),
1298 nsINavHistoryQueryOptions::RESULTS_AS_URI, mSortingMode,
1299 timeConstraints.get(), visitsJoin.get(), additionalConditions.get());
1300
1301 return NS_OK;
1302}
1303
1304nsresult PlacesSQLQueryBuilder::SelectAsTag() {
1305 nsNavHistory* history = nsNavHistory::GetHistoryService();
1306 NS_ENSURE_STATE(history)do { if ((__builtin_expect(!!(!(history)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "history" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1306); return NS_ERROR_UNEXPECTED; } } while (false)
;
1307
1308 // This allows sorting by date fields what is not possible with
1309 // other history queries.
1310 mHasDateColumns = true;
1311
1312 // TODO (Bug 1449939): This is likely wrong, since the tag name should
1313 // probably be urlencoded, and we have no util for that in SQL, yet.
1314 // We could encode the tag when the user sets it though.
1315 mQueryString = nsPrintfCString(
1316 "SELECT null, 'place:tag=' || title, "
1317 "title, null, null, null, null, null, dateAdded, "
1318 "lastModified, null, null, null, null, null, null, "
1319 "null, null, null, null, null, null, null, null, null "
1320 "FROM moz_bookmarks "
1321 "WHERE parent = %" PRId64"l" "d",
1322 history->GetTagsFolder());
1323
1324 return NS_OK;
1325}
1326
1327nsresult PlacesSQLQueryBuilder::SelectAsRoots() {
1328 nsNavHistory* history = nsNavHistory::GetHistoryService();
1329 NS_ENSURE_STATE(history)do { if ((__builtin_expect(!!(!(history)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "history" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1329); return NS_ERROR_UNEXPECTED; } } while (false)
;
1330
1331 nsAutoCString toolbarTitle;
1332 nsAutoCString menuTitle;
1333 nsAutoCString unfiledTitle;
1334
1335 history->GetStringFromName("BookmarksToolbarFolderTitle", toolbarTitle);
1336 mAddParams.InsertOrUpdate("BookmarksToolbarFolderTitle"_ns, toolbarTitle);
1337 history->GetStringFromName("BookmarksMenuFolderTitle", menuTitle);
1338 mAddParams.InsertOrUpdate("BookmarksMenuFolderTitle"_ns, menuTitle);
1339 history->GetStringFromName("OtherBookmarksFolderTitle", unfiledTitle);
1340 mAddParams.InsertOrUpdate("OtherBookmarksFolderTitle"_ns, unfiledTitle);
1341
1342 nsAutoCString mobileString;
1343
1344 if (Preferences::GetBool(MOBILE_BOOKMARKS_PREF"browser.bookmarks.showMobileBookmarks", false)) {
1345 nsAutoCString mobileTitle;
1346 history->GetStringFromName("MobileBookmarksFolderTitle", mobileTitle);
1347 mAddParams.InsertOrUpdate("MobileBookmarksFolderTitle"_ns, mobileTitle);
1348
1349 mobileString = nsLiteralCString(
1350 ","
1351 "(null, 'place:parent=" MOBILE_ROOT_GUID"mobile______"
1352 "', :MobileBookmarksFolderTitle, null, null, null, "
1353 "null, null, 0, 0, null, null, null, null, "
1354 SQL_QUOTE(MOBILE_BOOKMARKS_VIRTUAL_GUID)"'" "mobile_____v" "'" ", null, "
1355 "null, null, null, null, null, null, " SQL_QUOTE(MOBILE_ROOT_GUID)"'" "mobile______" "'" ", "
1356 "(SELECT id FROM moz_bookmarks WHERE guid = " SQL_QUOTE(MOBILE_ROOT_GUID)"'" "mobile______" "'" "), "
1357 ":MobileBookmarksFolderTitle)");
1358 }
1359
1360 mQueryString =
1361 nsLiteralCString(
1362 "SELECT * FROM ("
1363 "VALUES(null, 'place:parent=" TOOLBAR_ROOT_GUID"toolbar_____"
1364 "', :BookmarksToolbarFolderTitle, null, null, null, "
1365 "null, null, 0, 0, null, null, null, null, 'toolbar____v', null, "
1366 "null, null, null, null, null, null, " SQL_QUOTE(TOOLBAR_ROOT_GUID)"'" "toolbar_____" "'" ", "
1367 "(SELECT id FROM moz_bookmarks WHERE guid = " SQL_QUOTE(TOOLBAR_ROOT_GUID)"'" "toolbar_____" "'" "), "
1368 ":BookmarksToolbarFolderTitle), "
1369 "(null, 'place:parent=" MENU_ROOT_GUID"menu________"
1370 "', :BookmarksMenuFolderTitle, null, null, null, "
1371 "null, null, 0, 0, null, null, null, null, 'menu_______v', null, "
1372 "null, null, null, null, null, null, " SQL_QUOTE(MENU_ROOT_GUID)"'" "menu________" "'" ", "
1373 "(SELECT id FROM moz_bookmarks WHERE guid = " SQL_QUOTE(MENU_ROOT_GUID)"'" "menu________" "'" "), "
1374 ":BookmarksMenuFolderTitle), "
1375 "(null, 'place:parent=" UNFILED_ROOT_GUID"unfiled_____"
1376 "', :OtherBookmarksFolderTitle, null, null, null, "
1377 "null, null, 0, 0, null, null, null, null, 'unfiled____v', null, "
1378 "null, null, null, null, null, null, " SQL_QUOTE(UNFILED_ROOT_GUID)"'" "unfiled_____" "'" ", "
1379 "(SELECT id FROM moz_bookmarks WHERE guid = " SQL_QUOTE(UNFILED_ROOT_GUID)"'" "unfiled_____" "'" "), "
1380 ":OtherBookmarksFolderTitle)") +
1381 mobileString + ")"_ns;
1382
1383 return NS_OK;
1384}
1385
1386nsresult PlacesSQLQueryBuilder::SelectAsLeftPane() {
1387 nsNavHistory* history = nsNavHistory::GetHistoryService();
1388 NS_ENSURE_STATE(history)do { if ((__builtin_expect(!!(!(history)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "history" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1388); return NS_ERROR_UNEXPECTED; } } while (false)
;
1389
1390 nsAutoCString historyTitle;
1391 nsAutoCString downloadsTitle;
1392 nsAutoCString tagsTitle;
1393 nsAutoCString allBookmarksTitle;
1394
1395 history->GetStringFromName("OrganizerQueryHistory", historyTitle);
1396 mAddParams.InsertOrUpdate("OrganizerQueryHistory"_ns, historyTitle);
1397 history->GetStringFromName("OrganizerQueryDownloads", downloadsTitle);
1398 mAddParams.InsertOrUpdate("OrganizerQueryDownloads"_ns, downloadsTitle);
1399 history->GetStringFromName("TagsFolderTitle", tagsTitle);
1400 mAddParams.InsertOrUpdate("TagsFolderTitle"_ns, tagsTitle);
1401 history->GetStringFromName("OrganizerQueryAllBookmarks", allBookmarksTitle);
1402 mAddParams.InsertOrUpdate("OrganizerQueryAllBookmarks"_ns, allBookmarksTitle);
1403
1404 mQueryString = nsPrintfCString(
1405 "SELECT * FROM ("
1406 "VALUES"
1407 "(null, 'place:type=%d&sort=%d', :OrganizerQueryHistory, null, null, "
1408 "null, "
1409 "null, null, 0, 0, null, null, null, null, 'history____v', null, "
1410 "null, null, null, null, null, null, null), "
1411 "(null, 'place:transition=%d&sort=%d', :OrganizerQueryDownloads, null, "
1412 "null, null, "
1413 "null, null, 0, 0, null, null, null, null, 'downloads__v', null, "
1414 "null, null, null, null, null, null, null), "
1415 "(null, 'place:type=%d&sort=%d', :TagsFolderTitle, null, null, null, "
1416 "null, null, 0, 0, null, null, null, null, 'tags_______v', null, "
1417 "null, null, null, null, null, null, null), "
1418 "(null, 'place:type=%d', :OrganizerQueryAllBookmarks, null, null, null, "
1419 "null, null, 0, 0, null, null, null, null, 'allbms_____v', null, "
1420 "null, null, null, null, null, null, null) "
1421 ")",
1422 nsINavHistoryQueryOptions::RESULTS_AS_DATE_QUERY,
1423 nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING,
1424 nsINavHistoryService::TRANSITION_DOWNLOAD,
1425 nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING,
1426 nsINavHistoryQueryOptions::RESULTS_AS_TAGS_ROOT,
1427 nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING,
1428 nsINavHistoryQueryOptions::RESULTS_AS_ROOTS_QUERY);
1429 return NS_OK;
1430}
1431
1432nsresult PlacesSQLQueryBuilder::Where() {
1433 // Set query options
1434 nsAutoCString additionalVisitsConditions;
1435 nsAutoCString additionalPlacesConditions;
1436
1437 if (!mIncludeHidden) {
1438 additionalPlacesConditions += "AND hidden = 0 "_ns;
1439 }
1440
1441 if (mQueryType == nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY) {
1442 // last_visit_date is updated for any kind of visit, so it's a good
1443 // indicator whether the page has visits.
1444 additionalPlacesConditions += "AND last_visit_date NOTNULL "_ns;
1445 }
1446
1447 if (mResultType == nsINavHistoryQueryOptions::RESULTS_AS_URI &&
1448 !additionalVisitsConditions.IsEmpty()) {
1449 // URI results don't join on visits.
1450 nsAutoCString tmp = additionalVisitsConditions;
1451 additionalVisitsConditions =
1452 "AND EXISTS (SELECT 1 FROM moz_historyvisits WHERE place_id = h.id ";
1453 additionalVisitsConditions.Append(tmp);
1454 additionalVisitsConditions.AppendLiteral("LIMIT 1)");
1455 }
1456
1457 mQueryString.ReplaceSubstring("{QUERY_OPTIONS_VISITS}",
1458 additionalVisitsConditions.get());
1459 mQueryString.ReplaceSubstring("{QUERY_OPTIONS_PLACES}",
1460 additionalPlacesConditions.get());
1461
1462 // If we used WHERE already, we inject the conditions
1463 // in place of {ADDITIONAL_CONDITIONS}
1464 if (mQueryString.Find("{ADDITIONAL_CONDITIONS}") != kNotFound) {
1465 nsAutoCString innerCondition;
1466 // If we have condition AND it
1467 if (!mConditions.IsEmpty()) {
1468 innerCondition = " AND (";
1469 innerCondition += mConditions;
1470 innerCondition += ")";
1471 }
1472 mQueryString.ReplaceSubstring("{ADDITIONAL_CONDITIONS}",
1473 innerCondition.get());
1474
1475 } else if (!mConditions.IsEmpty()) {
1476 mQueryString += "WHERE ";
1477 mQueryString += mConditions;
1478 }
1479 return NS_OK;
1480}
1481
1482nsresult PlacesSQLQueryBuilder::GroupBy() {
1483 mQueryString += mGroupBy;
1484 return NS_OK;
1485}
1486
1487nsresult PlacesSQLQueryBuilder::OrderBy() {
1488 if (mSkipOrderBy) return NS_OK;
1489
1490 // Sort clause: we will sort later, but if it comes out of the DB sorted,
1491 // our later sort will be basically free. The DB can sort these for free
1492 // most of the time anyway, because it has indices over these items.
1493 switch (mSortingMode) {
1494 case nsINavHistoryQueryOptions::SORT_BY_NONE:
1495 // Ensure sorting does not change based on tables status.
1496 if (mResultType == nsINavHistoryQueryOptions::RESULTS_AS_URI) {
1497 if (mQueryType == nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS)
1498 mQueryString += " ORDER BY b.id ASC "_ns;
1499 else if (mQueryType == nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY)
1500 mQueryString += " ORDER BY h.id ASC "_ns;
1501 }
1502 break;
1503 case nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING:
1504 case nsINavHistoryQueryOptions::SORT_BY_TITLE_DESCENDING:
1505 // If the user wants few results, we limit them by date, necessitating
1506 // a sort by date here (see the IDL definition for maxResults).
1507 // Otherwise we will do actual sorting by title, but since we could need
1508 // to special sort for some locale we will repeat a second sorting at the
1509 // end in nsNavHistoryResult, that should be faster since the list will be
1510 // almost ordered.
1511 if (mMaxResults > 0)
1512 OrderByColumnIndexDesc(nsNavHistory::kGetInfoIndex_VisitDate);
1513 else if (mSortingMode ==
1514 nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING)
1515 OrderByTextColumnIndexAsc(nsNavHistory::kGetInfoIndex_Title);
1516 else
1517 OrderByTextColumnIndexDesc(nsNavHistory::kGetInfoIndex_Title);
1518 break;
1519 case nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING:
1520 OrderByColumnIndexAsc(nsNavHistory::kGetInfoIndex_VisitDate);
1521 break;
1522 case nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING:
1523 OrderByColumnIndexDesc(nsNavHistory::kGetInfoIndex_VisitDate);
1524 break;
1525 case nsINavHistoryQueryOptions::SORT_BY_URI_ASCENDING:
1526 OrderByColumnIndexAsc(nsNavHistory::kGetInfoIndex_URL);
1527 break;
1528 case nsINavHistoryQueryOptions::SORT_BY_URI_DESCENDING:
1529 OrderByColumnIndexDesc(nsNavHistory::kGetInfoIndex_URL);
1530 break;
1531 case nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_ASCENDING:
1532 OrderByColumnIndexAsc(nsNavHistory::kGetInfoIndex_VisitCount);
1533 break;
1534 case nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING:
1535 OrderByColumnIndexDesc(nsNavHistory::kGetInfoIndex_VisitCount);
1536 break;
1537 case nsINavHistoryQueryOptions::SORT_BY_DATEADDED_ASCENDING:
1538 if (mHasDateColumns)
1539 OrderByColumnIndexAsc(nsNavHistory::kGetInfoIndex_ItemDateAdded);
1540 break;
1541 case nsINavHistoryQueryOptions::SORT_BY_DATEADDED_DESCENDING:
1542 if (mHasDateColumns)
1543 OrderByColumnIndexDesc(nsNavHistory::kGetInfoIndex_ItemDateAdded);
1544 break;
1545 case nsINavHistoryQueryOptions::SORT_BY_LASTMODIFIED_ASCENDING:
1546 if (mHasDateColumns)
1547 OrderByColumnIndexAsc(nsNavHistory::kGetInfoIndex_ItemLastModified);
1548 break;
1549 case nsINavHistoryQueryOptions::SORT_BY_LASTMODIFIED_DESCENDING:
1550 if (mHasDateColumns)
1551 OrderByColumnIndexDesc(nsNavHistory::kGetInfoIndex_ItemLastModified);
1552 break;
1553 case nsINavHistoryQueryOptions::SORT_BY_TAGS_ASCENDING:
1554 case nsINavHistoryQueryOptions::SORT_BY_TAGS_DESCENDING:
1555 break; // Sort later in nsNavHistoryQueryResultNode::FillChildren()
1556 case nsINavHistoryQueryOptions::SORT_BY_FRECENCY_ASCENDING:
1557 OrderByColumnIndexAsc(nsNavHistory::kGetInfoIndex_Frecency);
1558 break;
1559 case nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING:
1560 OrderByColumnIndexDesc(nsNavHistory::kGetInfoIndex_Frecency);
1561 break;
1562 default:
1563 MOZ_ASSERT_UNREACHABLE("Invalid sorting mode")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Invalid sorting mode" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid sorting mode" ")"); do {
*((volatile int*)__null) = 1563; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1564 }
1565 return NS_OK;
1566}
1567
1568void PlacesSQLQueryBuilder::OrderByColumnIndexAsc(int32_t aIndex) {
1569 mQueryString += nsPrintfCString(" ORDER BY %d ASC", aIndex + 1);
1570}
1571
1572void PlacesSQLQueryBuilder::OrderByColumnIndexDesc(int32_t aIndex) {
1573 mQueryString += nsPrintfCString(" ORDER BY %d DESC", aIndex + 1);
1574}
1575
1576void PlacesSQLQueryBuilder::OrderByTextColumnIndexAsc(int32_t aIndex) {
1577 mQueryString +=
1578 nsPrintfCString(" ORDER BY %d COLLATE NOCASE ASC", aIndex + 1);
1579}
1580
1581void PlacesSQLQueryBuilder::OrderByTextColumnIndexDesc(int32_t aIndex) {
1582 mQueryString +=
1583 nsPrintfCString(" ORDER BY %d COLLATE NOCASE DESC", aIndex + 1);
1584}
1585
1586nsresult PlacesSQLQueryBuilder::Limit() {
1587 if (mUseLimit && mMaxResults > 0) {
1588 mQueryString += " LIMIT "_ns;
1589 mQueryString.AppendInt(mMaxResults);
1590 mQueryString.Append(' ');
1591 }
1592 return NS_OK;
1593}
1594
1595nsresult nsNavHistory::ConstructQueryString(
1596 const RefPtr<nsNavHistoryQuery>& aQuery,
1597 const RefPtr<nsNavHistoryQueryOptions>& aOptions, nsCString& queryString,
1598 bool& aParamsPresent, nsNavHistory::StringHash& aAddParams) {
1599 // For information about visit_type see nsINavHistoryService.idl.
1600 // visitType == 0 is undefined (see bug #375777 for details).
1601 // Some sites, especially Javascript-heavy ones, load things in frames to
1602 // display them, resulting in a lot of these entries. This is the reason
1603 // why such visits are filtered out.
1604 nsresult rv;
1605 aParamsPresent = false;
1606
1607 int32_t sortingMode = aOptions->SortingMode();
1608 NS_ASSERTION(do { if (!(sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE
&& sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Invalid sortingMode found while building query!"
, "sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE && sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1611); MOZ_PretendNoReturn(); } } while (0)
1609 sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE &&do { if (!(sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE
&& sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Invalid sortingMode found while building query!"
, "sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE && sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1611); MOZ_PretendNoReturn(); } } while (0)
1610 sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING,do { if (!(sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE
&& sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Invalid sortingMode found while building query!"
, "sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE && sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1611); MOZ_PretendNoReturn(); } } while (0)
1611 "Invalid sortingMode found while building query!")do { if (!(sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE
&& sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Invalid sortingMode found while building query!"
, "sortingMode >= nsINavHistoryQueryOptions::SORT_BY_NONE && sortingMode <= nsINavHistoryQueryOptions::SORT_BY_FRECENCY_DESCENDING"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1611); MOZ_PretendNoReturn(); } } while (0)
;
1612
1613 if (IsOptimizableHistoryQuery(
1614 aQuery, aOptions,
1615 nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING) ||
1616 IsOptimizableHistoryQuery(
1617 aQuery, aOptions,
1618 nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING)) {
1619 // Generate an optimized query for the history menu and the old most visited
1620 // bookmark that was inserted into profiles.
1621 queryString =
1622 GetTagsSqlFragment(aOptions->QueryType(), aOptions->ExcludeItems()) +
1623 "SELECT h.id, h.url, h.title AS page_title, h.rev_host, "
1624 " h.visit_count, h.last_visit_date, null, null, null, null, null, "
1625 " (SELECT tags FROM tagged WHERE place_id = h.id) AS tags, "
1626 " h.frecency, h.hidden, h.guid, null, null, null, "
1627 " null, null, null, null, null, null, null "
1628 "FROM moz_places h "
1629 "WHERE h.hidden = 0 "
1630 "AND EXISTS (SELECT id FROM moz_historyvisits WHERE place_id = "
1631 "h.id "
1632 "AND visit_type NOT IN "_ns +
1633 nsPrintfCString("(0,%d,%d) ", nsINavHistoryService::TRANSITION_EMBED,
1634 nsINavHistoryService::TRANSITION_FRAMED_LINK) +
1635 "LIMIT 1) "
1636 "{QUERY_OPTIONS} "_ns;
1637
1638 queryString.AppendLiteral("ORDER BY ");
1639 if (sortingMode == nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING)
1640 queryString.AppendLiteral("last_visit_date DESC ");
1641 else
1642 queryString.AppendLiteral("visit_count DESC ");
1643
1644 queryString.AppendLiteral("LIMIT ");
1645 queryString.AppendInt(aOptions->MaxResults());
1646
1647 nsAutoCString additionalQueryOptions;
1648
1649 queryString.ReplaceSubstring("{QUERY_OPTIONS}",
1650 additionalQueryOptions.get());
1651 return NS_OK;
1652 }
1653
1654 // If the query is a tag query, the type is bookmarks.
1655 if (!aQuery->Tags().IsEmpty()) {
1656 aOptions->SetQueryType(nsNavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS);
1657 }
1658
1659 nsAutoCString conditions;
1660 nsCString queryClause;
1661 rv = QueryToSelectClause(aQuery, aOptions, &queryClause);
1662 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1662); return rv; } } while (false)
;
1663 if (!queryClause.IsEmpty()) {
1664 // TODO: This should be set on a case basis, not blindly.
1665 aParamsPresent = true;
1666 conditions += queryClause;
1667 }
1668
1669 // Determine whether we can push maxResults constraints into the query
1670 // as LIMIT, or if we need to do result count clamping later
1671 // using FilterResultSet()
1672 bool useLimitClause = !NeedToFilterResultSet(aQuery, aOptions);
1673
1674 PlacesSQLQueryBuilder queryStringBuilder(conditions, aQuery, aOptions,
1675 useLimitClause, aAddParams);
1676 rv = queryStringBuilder.GetQueryString(queryString);
1677 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1677); return rv; } } while (false)
;
1678
1679 return NS_OK;
1680}
1681
1682// nsNavHistory::GetQueryResults
1683//
1684// Call this to get the results from a complex query. This is used by
1685// nsNavHistoryQueryResultNode to populate its children. For simple bookmark
1686// queries, use nsNavBookmarks::QueryFolderChildren.
1687//
1688// THIS DOES NOT DO SORTING. You will need to sort the container yourself
1689// when you get the results. This is because sorting depends on tree
1690// statistics that will be built from the perspective of the tree. See
1691// nsNavHistoryQueryResultNode::FillChildren
1692//
1693// FIXME: This only does keyword searching for the first query, and does
1694// it ANDed with the all the rest of the queries.
1695
1696nsresult nsNavHistory::GetQueryResults(
1697 nsNavHistoryQueryResultNode* aResultNode,
1698 const RefPtr<nsNavHistoryQuery>& aQuery,
1699 const RefPtr<nsNavHistoryQueryOptions>& aOptions,
1700 nsCOMArray<nsNavHistoryResultNode>* aResults) {
1701 NS_ENSURE_ARG_POINTER(aQuery)do { if ((__builtin_expect(!!(!(aQuery)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aQuery" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1701); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1702 NS_ENSURE_ARG_POINTER(aOptions)do { if ((__builtin_expect(!!(!(aOptions)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOptions" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1702); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1703 NS_ASSERTION(aResults->Count() == 0, "Initial result array must be empty")do { if (!(aResults->Count() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initial result array must be empty", "aResults->Count() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1703); MOZ_PretendNoReturn(); } } while (0)
;
1704
1705 nsCString queryString;
1706 bool paramsPresent = false;
1707 nsNavHistory::StringHash addParams(HISTORY_DATE_CONT_LENGTH8);
1708 nsresult rv = ConstructQueryString(aQuery, aOptions, queryString,
1709 paramsPresent, addParams);
1710 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1710); return rv; } } while (false)
;
1711
1712 // create statement
1713 nsCOMPtr<mozIStorageStatement> statement = mDB->GetStatement(queryString);
1714#ifdef DEBUG1
1715 if (!statement) {
1716 nsCOMPtr<mozIStorageConnection> conn = mDB->MainConn();
1717 if (conn) {
1718 nsAutoCString lastErrorString;
1719 (void)conn->GetLastErrorString(lastErrorString);
1720 int32_t lastError = 0;
1721 (void)conn->GetLastError(&lastError);
1722 printf(
1723 "Places failed to create a statement from this query:\n%s\nStorage "
1724 "error (%d): %s\n",
1725 queryString.get(), lastError, lastErrorString.get());
1726 }
1727 }
1728#endif
1729 NS_ENSURE_STATE(statement)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1729); return NS_ERROR_UNEXPECTED; } } while (false)
;
1730 mozStorageStatementScoper scoper(statement);
1731
1732 if (paramsPresent) {
1733 rv = BindQueryClauseParameters(statement, aQuery, aOptions);
1734 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1734); return rv; } } while (false)
;
1735 }
1736
1737 for (const auto& entry : addParams) {
1738 nsresult rv =
1739 statement->BindUTF8StringByName(entry.GetKey(), entry.GetData());
1740 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1741 break;
1742 }
1743 }
1744
1745 // Optimize the case where there is no need for any post-query filtering.
1746 if (NeedToFilterResultSet(aQuery, aOptions)) {
1747 // Generate the top-level results.
1748 nsCOMArray<nsNavHistoryResultNode> toplevel;
1749 rv = ResultsAsList(statement, aOptions, &toplevel);
1750 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1750); return rv; } } while (false)
;
1751
1752 FilterResultSet(aResultNode, toplevel, aResults, aQuery, aOptions);
1753 } else {
1754 rv = ResultsAsList(statement, aOptions, aResults);
1755 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1755); return rv; } } while (false)
;
1756 }
1757
1758 return NS_OK;
1759}
1760
1761NS_IMETHODIMPnsresult
1762nsNavHistory::GetHistoryDisabled(bool* _retval) {
1763 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1763); MOZ_PretendNoReturn(); } } while (0)
;
1764 NS_ENSURE_ARG_POINTER(_retval)do { if ((__builtin_expect(!!(!(_retval)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_retval" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1764); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1765
1766 *_retval = IsHistoryDisabled();
1767 return NS_OK;
1768}
1769
1770// Call this method before visiting a URL in order to help determine the
1771// transition type of the visit.
1772//
1773// @see MarkPageAsFollowedBookmark
1774
1775NS_IMETHODIMPnsresult
1776nsNavHistory::MarkPageAsTyped(nsIURI* aURI) {
1777 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1777); MOZ_PretendNoReturn(); } } while (0)
;
1778 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1778); return NS_ERROR_INVALID_ARG; } } while (false)
;
1779
1780 // don't add when history is disabled
1781 if (IsHistoryDisabled()) return NS_OK;
1782
1783 nsAutoCString uriString;
1784 nsresult rv = aURI->GetSpec(uriString);
1785 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1785); return rv; } } while (false)
;
1786
1787 mRecentTyped.InsertOrUpdate(uriString, GetNow());
1788
1789 if (mRecentTyped.Count() > RECENT_EVENT_QUEUE_MAX_LENGTH128)
1790 ExpireNonrecentEvents(&mRecentTyped);
1791
1792 return NS_OK;
1793}
1794
1795// Call this method before visiting a URL in order to help determine the
1796// transition type of the visit.
1797//
1798// @see MarkPageAsTyped
1799
1800NS_IMETHODIMPnsresult
1801nsNavHistory::MarkPageAsFollowedLink(nsIURI* aURI) {
1802 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1802); MOZ_PretendNoReturn(); } } while (0)
;
1803 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1803); return NS_ERROR_INVALID_ARG; } } while (false)
;
1804
1805 // don't add when history is disabled
1806 if (IsHistoryDisabled()) return NS_OK;
1807
1808 nsAutoCString uriString;
1809 nsresult rv = aURI->GetSpec(uriString);
1810 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1810); return rv; } } while (false)
;
1811
1812 mRecentLink.InsertOrUpdate(uriString, GetNow());
1813
1814 if (mRecentLink.Count() > RECENT_EVENT_QUEUE_MAX_LENGTH128)
1815 ExpireNonrecentEvents(&mRecentLink);
1816
1817 return NS_OK;
1818}
1819
1820NS_IMETHODIMPnsresult
1821nsNavHistory::GetIsFrecencyDecaying(bool* _out) {
1822 NS_ENSURE_ARG_POINTER(_out)do { if ((__builtin_expect(!!(!(_out)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_out" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1822); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1823 *_out = nsNavHistory::sIsFrecencyDecaying;
1824 return NS_OK;
1825}
1826
1827NS_IMETHODIMPnsresult
1828nsNavHistory::SetIsFrecencyDecaying(bool aVal) {
1829 nsNavHistory::sIsFrecencyDecaying = aVal;
1830 return NS_OK;
1831}
1832
1833NS_IMETHODIMPnsresult
1834nsNavHistory::GetShouldStartFrecencyRecalculation(bool* _out) {
1835 NS_ENSURE_ARG_POINTER(_out)do { if ((__builtin_expect(!!(!(_out)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_out" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1835); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1836 *_out = nsNavHistory::sShouldStartFrecencyRecalculation;
1837 return NS_OK;
1838}
1839
1840NS_IMETHODIMPnsresult
1841nsNavHistory::SetShouldStartFrecencyRecalculation(bool aVal) {
1842 nsNavHistory::sShouldStartFrecencyRecalculation = aVal;
1843 return NS_OK;
1844}
1845
1846////////////////////////////////////////////////////////////////////////////////
1847//// mozIStorageVacuumParticipant
1848
1849NS_IMETHODIMPnsresult
1850nsNavHistory::GetDatabaseConnection(
1851 mozIStorageAsyncConnection** _DBConnection) {
1852 NS_ENSURE_ARG_POINTER(_DBConnection)do { if ((__builtin_expect(!!(!(_DBConnection)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_DBConnection" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1852); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1853 nsCOMPtr<mozIStorageAsyncConnection> connection = mDB->MainConn();
1854 connection.forget(_DBConnection);
1855 return NS_OK;
1856}
1857
1858NS_IMETHODIMPnsresult
1859nsNavHistory::GetUseIncrementalVacuum(bool* _useIncremental) {
1860 *_useIncremental = false;
1861 return NS_OK;
1862}
1863
1864NS_IMETHODIMPnsresult
1865nsNavHistory::GetExpectedDatabasePageSize(int32_t* _expectedPageSize) {
1866 NS_ENSURE_STATE(mDB)do { if ((__builtin_expect(!!(!(mDB)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "mDB" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1866); return NS_ERROR_UNEXPECTED; } } while (false)
;
1867 NS_ENSURE_STATE(mDB->MainConn())do { if ((__builtin_expect(!!(!(mDB->MainConn())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDB->MainConn()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1867); return NS_ERROR_UNEXPECTED; } } while (false)
;
1868 return mDB->MainConn()->GetDefaultPageSize(_expectedPageSize);
1869}
1870
1871NS_IMETHODIMPnsresult
1872nsNavHistory::OnBeginVacuum(bool* _vacuumGranted) {
1873 // TODO: Check if we have to deny the vacuum in some heavy-load case.
1874 // We could maybe want to do that during batches?
1875 *_vacuumGranted = true;
1876 return NS_OK;
1877}
1878
1879NS_IMETHODIMPnsresult
1880nsNavHistory::OnEndVacuum(bool aSucceeded) {
1881 NS_WARNING_ASSERTION(aSucceeded, "Places.sqlite vacuum failed.")do { if (!(aSucceeded)) { NS_DebugBreak(NS_DEBUG_WARNING, "Places.sqlite vacuum failed."
, "aSucceeded", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1881); } } while (false)
;
1882 return NS_OK;
1883}
1884
1885NS_IMETHODIMPnsresult
1886nsNavHistory::GetDBConnection(mozIStorageConnection** _DBConnection) {
1887 NS_ENSURE_ARG_POINTER(_DBConnection)do { if ((__builtin_expect(!!(!(_DBConnection)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_DBConnection" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1887); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1888 nsCOMPtr<mozIStorageConnection> connection = mDB->MainConn();
1889 connection.forget(_DBConnection);
1890
1891 return NS_OK;
1892}
1893
1894NS_IMETHODIMPnsresult
1895nsNavHistory::GetShutdownClient(nsIAsyncShutdownClient** _shutdownClient) {
1896 NS_ENSURE_ARG_POINTER(_shutdownClient)do { if ((__builtin_expect(!!(!(_shutdownClient)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_shutdownClient" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1896); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1897 nsCOMPtr<nsIAsyncShutdownClient> client = mDB->GetClientsShutdown();
1898 if (!client) {
1899 return NS_ERROR_UNEXPECTED;
1900 }
1901 client.forget(_shutdownClient);
1902 return NS_OK;
1903}
1904
1905NS_IMETHODIMPnsresult
1906nsNavHistory::GetConnectionShutdownClient(
1907 nsIAsyncShutdownClient** _shutdownClient) {
1908 NS_ENSURE_ARG_POINTER(_shutdownClient)do { if ((__builtin_expect(!!(!(_shutdownClient)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_shutdownClient" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1908); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1909 nsCOMPtr<nsIAsyncShutdownClient> client = mDB->GetConnectionShutdown();
1910 if (!client) {
1911 return NS_ERROR_UNEXPECTED;
1912 }
1913 client.forget(_shutdownClient);
1914 return NS_OK;
1915}
1916
1917NS_IMETHODIMPnsresult
1918nsNavHistory::AsyncExecuteLegacyQuery(nsINavHistoryQuery* aQuery,
1919 nsINavHistoryQueryOptions* aOptions,
1920 mozIStorageStatementCallback* aCallback,
1921 mozIStoragePendingStatement** _stmt) {
1922 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1922); MOZ_PretendNoReturn(); } } while (0)
;
1923 NS_ENSURE_ARG(aQuery)do { if ((__builtin_expect(!!(!(aQuery)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aQuery" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1923); return NS_ERROR_INVALID_ARG; } } while (false)
;
1924 NS_ENSURE_ARG(aOptions)do { if ((__builtin_expect(!!(!(aOptions)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOptions" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1924); return NS_ERROR_INVALID_ARG; } } while (false)
;
1925 NS_ENSURE_ARG(aCallback)do { if ((__builtin_expect(!!(!(aCallback)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCallback" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1925); return NS_ERROR_INVALID_ARG; } } while (false)
;
1926 NS_ENSURE_ARG_POINTER(_stmt)do { if ((__builtin_expect(!!(!(_stmt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_stmt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1926); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1927
1928 RefPtr<nsNavHistoryQuery> query = do_QueryObject(aQuery);
1929 NS_ENSURE_STATE(query)do { if ((__builtin_expect(!!(!(query)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "query" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1929); return NS_ERROR_UNEXPECTED; } } while (false)
;
1930 RefPtr<nsNavHistoryQueryOptions> options = do_QueryObject(aOptions);
1931 NS_ENSURE_ARG(options)do { if ((__builtin_expect(!!(!(options)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "options" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1931); return NS_ERROR_INVALID_ARG; } } while (false)
;
1932
1933 nsCString queryString;
1934 bool paramsPresent = false;
1935 nsNavHistory::StringHash addParams(HISTORY_DATE_CONT_LENGTH8);
1936 nsresult rv = ConstructQueryString(query, options, queryString, paramsPresent,
1937 addParams);
1938 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1938); return rv; } } while (false)
;
1939
1940 nsCOMPtr<mozIStorageAsyncStatement> statement =
1941 mDB->GetAsyncStatement(queryString);
1942 NS_ENSURE_STATE(statement)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1942); return NS_ERROR_UNEXPECTED; } } while (false)
;
1943
1944#ifdef DEBUG1
1945 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1946 nsCOMPtr<mozIStorageConnection> conn = mDB->MainConn();
1947 if (conn) {
1948 nsAutoCString lastErrorString;
1949 (void)mDB->MainConn()->GetLastErrorString(lastErrorString);
1950 int32_t lastError = 0;
1951 (void)mDB->MainConn()->GetLastError(&lastError);
1952 printf(
1953 "Places failed to create a statement from this query:\n%s\nStorage "
1954 "error (%d): %s\n",
1955 queryString.get(), lastError, lastErrorString.get());
1956 }
1957 }
1958#endif
1959 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1959); return rv; } } while (false)
;
1960
1961 if (paramsPresent) {
1962 rv = BindQueryClauseParameters(statement, query, options);
1963 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1963); return rv; } } while (false)
;
1964 }
1965
1966 for (const auto& entry : addParams) {
1967 nsresult rv =
1968 statement->BindUTF8StringByName(entry.GetKey(), entry.GetData());
1969 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1970 break;
1971 }
1972 }
1973
1974 rv = statement->ExecuteAsync(aCallback, _stmt);
1975 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1975); return rv; } } while (false)
;
1976
1977 return NS_OK;
1978}
1979
1980////////////////////////////////////////////////////////////////////////////////
1981//// nsIObserver
1982
1983NS_IMETHODIMPnsresult
1984nsNavHistory::Observe(nsISupports* aSubject, const char* aTopic,
1985 const char16_t* aData) {
1986 NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This can only be called on the main thread", "NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 1986); MOZ_PretendNoReturn(); } } while (0)
;
1987 if (strcmp(aTopic, TOPIC_PROFILE_TEARDOWN"profile-change-teardown") == 0 ||
1988 strcmp(aTopic, TOPIC_PROFILE_CHANGE"profile-before-change") == 0 ||
1989 strcmp(aTopic, TOPIC_SIMULATE_PLACES_SHUTDOWN"test-simulate-places-shutdown") == 0) {
1990 // These notifications are used by tests to simulate a Places shutdown.
1991 // They should just be forwarded to the Database handle.
1992 mDB->Observe(aSubject, aTopic, aData);
1993 }
1994
1995 else if (strcmp(aTopic, TOPIC_PREF_CHANGED"nsPref:changed") == 0) {
1996 LoadPrefs();
1997 }
1998
1999 else if (strcmp(aTopic, TOPIC_APP_LOCALES_CHANGED"intl:app-locales-changed") == 0) {
2000 mBundle = nullptr;
2001 }
2002
2003 return NS_OK;
2004}
2005
2006// Query stuff *****************************************************************
2007
2008// Helper class for QueryToSelectClause
2009//
2010// This class helps to build part of the WHERE clause.
2011
2012class ConditionBuilder {
2013 public:
2014 ConditionBuilder& Condition(const char* aStr) {
2015 if (!mClause.IsEmpty()) mClause.AppendLiteral(" AND ");
2016 Str(aStr);
2017 return *this;
2018 }
2019
2020 ConditionBuilder& Str(const char* aStr) {
2021 mClause.Append(' ');
2022 mClause.Append(aStr);
2023 mClause.Append(' ');
2024 return *this;
2025 }
2026
2027 ConditionBuilder& Param(const char* aParam) {
2028 mClause.Append(' ');
2029 mClause.Append(aParam);
2030 mClause.Append(' ');
2031 return *this;
2032 }
2033
2034 void GetClauseString(nsCString& aResult) { aResult = mClause; }
2035
2036 private:
2037 nsCString mClause;
2038};
2039
2040// nsNavHistory::QueryToSelectClause
2041//
2042// THE BEHAVIOR SHOULD BE IN SYNC WITH BindQueryClauseParameters
2043//
2044// I don't check return values from the query object getters because there's
2045// no way for those to fail.
2046
2047nsresult nsNavHistory::QueryToSelectClause(
2048 const RefPtr<nsNavHistoryQuery>& aQuery,
2049 const RefPtr<nsNavHistoryQueryOptions>& aOptions, nsCString* aClause) {
2050 bool hasIt;
2051 // We don't use the value from options here - we post filter if that
2052 // is set.
2053 bool excludeQueries = false;
2054
2055 ConditionBuilder clause;
2056
2057 if ((NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aQuery->GetHasBeginTime
(&hasIt))), 1)))
&& hasIt) ||
2058 (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aQuery->GetHasEndTime
(&hasIt))), 1)))
&& hasIt)) {
2059 clause.Condition(
2060 "EXISTS (SELECT 1 FROM moz_historyvisits "
2061 "WHERE place_id = h.id");
2062 // begin time
2063 if (NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aQuery->GetHasBeginTime
(&hasIt))), 1)))
&& hasIt)
2064 clause.Condition("visit_date >=").Param(":begin_time");
2065 // end time
2066 if (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aQuery->GetHasEndTime
(&hasIt))), 1)))
&& hasIt)
2067 clause.Condition("visit_date <=").Param(":end_time");
2068 clause.Str(" LIMIT 1)");
2069 }
2070
2071 // search terms
2072 int32_t searchBehavior = mozIPlacesAutoComplete::BEHAVIOR_HISTORY |
2073 mozIPlacesAutoComplete::BEHAVIOR_BOOKMARK;
2074 if (!aQuery->SearchTerms().IsEmpty()) {
2075 // Re-use the autocomplete_match function. Setting the behavior to match
2076 // history or typed history or bookmarks or open pages will match almost
2077 // everything.
2078 clause.Condition("AUTOCOMPLETE_MATCH(")
2079 .Param(":search_string")
2080 .Str(", h.url, page_title, tags, ")
2081 .Str(nsPrintfCString("1, 1, 1, 1, %d, %d",
2082 mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED,
2083 searchBehavior)
2084 .get())
2085 .Str(", NULL)");
2086 // Serching by terms implicitly exclude queries.
2087 excludeQueries = true;
2088 }
2089
2090 // min and max visit count
2091 if (aQuery->MinVisits() >= 0)
2092 clause.Condition("h.visit_count >=").Param(":min_visits");
2093
2094 if (aQuery->MaxVisits() >= 0)
2095 clause.Condition("h.visit_count <=").Param(":max_visits");
2096
2097 // domain
2098 if (!aQuery->Domain().IsVoid()) {
2099 bool domainIsHost = false;
2100 aQuery->GetDomainIsHost(&domainIsHost);
2101 if (domainIsHost)
2102 clause.Condition("h.rev_host =").Param(":domain_lower");
2103 else
2104 // see domain setting in BindQueryClauseParameters for why we do this
2105 clause.Condition("h.rev_host >=")
2106 .Param(":domain_lower")
2107 .Condition("h.rev_host <")
2108 .Param(":domain_upper");
2109 }
2110
2111 // URI
2112 if (aQuery->Uri()) {
2113 clause.Condition("h.url_hash = hash(")
2114 .Param(":uri")
2115 .Str(")")
2116 .Condition("h.url =")
2117 .Param(":uri");
2118 }
2119
2120 // tags
2121 const nsTArray<nsString>& tags = aQuery->Tags();
2122 if (tags.Length() > 0) {
2123 clause.Condition("h.id");
2124 if (aQuery->TagsAreNot()) clause.Str("NOT");
2125 clause
2126 .Str(
2127 "IN "
2128 "(SELECT bms.fk "
2129 "FROM moz_bookmarks bms "
2130 "JOIN moz_bookmarks tags ON bms.parent = tags.id "
2131 "WHERE tags.parent =")
2132 .Param(":tags_folder")
2133 .Str("AND lower(tags.title) IN (");
2134 for (uint32_t i = 0; i < tags.Length(); ++i) {
2135 nsPrintfCString param(":tag%d_", i);
2136 clause.Param(param.get());
2137 if (i < tags.Length() - 1) clause.Str(",");
2138 }
2139 clause.Str(")");
2140 if (!aQuery->TagsAreNot()) {
2141 clause.Str("GROUP BY bms.fk HAVING count(*) >=").Param(":tag_count");
2142 }
2143 clause.Str(")");
2144 }
2145
2146 // transitions
2147 const nsTArray<uint32_t>& transitions = aQuery->Transitions();
2148 for (uint32_t i = 0; i < transitions.Length(); ++i) {
2149 nsPrintfCString param(":transition%d_", i);
2150 clause
2151 .Condition(
2152 "h.id IN (SELECT place_id FROM moz_historyvisits "
2153 "WHERE visit_type = ")
2154 .Param(param.get())
2155 .Str(")");
2156 }
2157
2158 // parents
2159 const nsTArray<nsCString>& parents = aQuery->Parents();
2160 if (parents.Length() > 0) {
2161 aOptions->SetQueryType(nsNavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS);
2162 clause.Condition(
2163 "b.parent IN( "
2164 "WITH RECURSIVE parents(id) AS ( "
2165 "SELECT id FROM moz_bookmarks WHERE GUID IN (");
2166
2167 for (uint32_t i = 0; i < parents.Length(); ++i) {
2168 nsPrintfCString param(":parentguid%d_", i);
2169 clause.Param(param.get());
2170 if (i < parents.Length() - 1) {
2171 clause.Str(",");
2172 }
2173 }
2174 clause.Str(
2175 ") "
2176 "UNION ALL "
2177 "SELECT b2.id "
2178 "FROM moz_bookmarks b2 "
2179 "JOIN parents p ON b2.parent = p.id "
2180 "WHERE b2.type = 2 "
2181 ") "
2182 "SELECT id FROM parents "
2183 ")");
2184 }
2185
2186 if (excludeQueries) {
2187 // Serching by terms implicitly exclude queries and folder shortcuts.
2188 clause.Condition(
2189 "NOT h.url_hash BETWEEN hash('place', 'prefix_lo') AND "
2190 "hash('place', 'prefix_hi')");
2191 }
2192
2193 clause.GetClauseString(*aClause);
2194 return NS_OK;
2195}
2196
2197// nsNavHistory::BindQueryClauseParameters
2198//
2199// THE BEHAVIOR SHOULD BE IN SYNC WITH QueryToSelectClause
2200
2201nsresult nsNavHistory::BindQueryClauseParameters(
2202 mozIStorageBaseStatement* statement,
2203 const RefPtr<nsNavHistoryQuery>& aQuery,
2204 const RefPtr<nsNavHistoryQueryOptions>& aOptions) {
2205 nsresult rv;
2206
2207 bool hasIt;
2208 // begin time
2209 if (NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aQuery->GetHasBeginTime
(&hasIt))), 1)))
&& hasIt) {
2210 PRTime time =
2211 NormalizeTime(aQuery->BeginTimeReference(), aQuery->BeginTime());
2212 rv = statement->BindInt64ByName("begin_time"_ns, time);
2213 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2213); return rv; } } while (false)
;
2214 }
2215
2216 // end time
2217 if (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aQuery->GetHasEndTime
(&hasIt))), 1)))
&& hasIt) {
2218 PRTime time = NormalizeTime(aQuery->EndTimeReference(), aQuery->EndTime());
2219 rv = statement->BindInt64ByName("end_time"_ns, time);
2220 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2220); return rv; } } while (false)
;
2221 }
2222
2223 // search terms
2224 if (!aQuery->SearchTerms().IsEmpty()) {
2225 rv = statement->BindStringByName("search_string"_ns, aQuery->SearchTerms());
2226 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2226); return rv; } } while (false)
;
2227 }
2228
2229 // min and max visit count
2230 int32_t visits = aQuery->MinVisits();
2231 if (visits >= 0) {
2232 rv = statement->BindInt32ByName("min_visits"_ns, visits);
2233 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2233); return rv; } } while (false)
;
2234 }
2235
2236 visits = aQuery->MaxVisits();
2237 if (visits >= 0) {
2238 rv = statement->BindInt32ByName("max_visits"_ns, visits);
2239 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2239); return rv; } } while (false)
;
2240 }
2241
2242 // domain (see GetReversedHostname for more info on reversed host names)
2243 if (!aQuery->Domain().IsVoid()) {
2244 nsString revDomain;
2245 GetReversedHostname(NS_ConvertUTF8toUTF16(aQuery->Domain()), revDomain);
2246
2247 if (aQuery->DomainIsHost()) {
2248 rv = statement->BindStringByName("domain_lower"_ns, revDomain);
2249 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2249); return rv; } } while (false)
;
2250 } else {
2251 // for "mozilla.org" do query >= "gro.allizom." AND < "gro.allizom/"
2252 // which will get everything starting with "gro.allizom." while using the
2253 // index (using SUBSTRING() causes indexes to be discarded).
2254 NS_ASSERTION(revDomain[revDomain.Length() - 1] == '.',do { if (!(revDomain[revDomain.Length() - 1] == '.')) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Invalid rev. host", "revDomain[revDomain.Length() - 1] == '.'"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2255); MOZ_PretendNoReturn(); } } while (0)
2255 "Invalid rev. host")do { if (!(revDomain[revDomain.Length() - 1] == '.')) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Invalid rev. host", "revDomain[revDomain.Length() - 1] == '.'"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2255); MOZ_PretendNoReturn(); } } while (0)
;
2256 rv = statement->BindStringByName("domain_lower"_ns, revDomain);
2257 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2257); return rv; } } while (false)
;
2258 revDomain.Truncate(revDomain.Length() - 1);
2259 revDomain.Append(char16_t('/'));
2260 rv = statement->BindStringByName("domain_upper"_ns, revDomain);
2261 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2261); return rv; } } while (false)
;
2262 }
2263 }
2264
2265 // URI
2266 if (aQuery->Uri()) {
2267 rv = URIBinder::Bind(statement, "uri"_ns, aQuery->Uri());
2268 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2268); return rv; } } while (false)
;
2269 }
2270
2271 // tags
2272 const nsTArray<nsString>& tags = aQuery->Tags();
2273 if (tags.Length() > 0) {
2274 for (uint32_t i = 0; i < tags.Length(); ++i) {
2275 nsPrintfCString paramName("tag%d_", i);
2276 nsString utf16Tag = tags[i];
2277 ToLowerCase(utf16Tag);
2278 NS_ConvertUTF16toUTF8 tag(utf16Tag);
2279 rv = statement->BindUTF8StringByName(paramName, tag);
2280 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2280); return rv; } } while (false)
;
2281 }
2282 int64_t tagsFolder = GetTagsFolder();
2283 rv = statement->BindInt64ByName("tags_folder"_ns, tagsFolder);
2284 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2284); return rv; } } while (false)
;
2285 if (!aQuery->TagsAreNot()) {
2286 rv = statement->BindInt32ByName("tag_count"_ns, tags.Length());
2287 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2287); return rv; } } while (false)
;
2288 }
2289 }
2290
2291 // transitions
2292 const nsTArray<uint32_t>& transitions = aQuery->Transitions();
2293 for (uint32_t i = 0; i < transitions.Length(); ++i) {
2294 nsPrintfCString paramName("transition%d_", i);
2295 rv = statement->BindInt64ByName(paramName, transitions[i]);
2296 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2296); return rv; } } while (false)
;
2297 }
2298
2299 // parents
2300 const nsTArray<nsCString>& parents = aQuery->Parents();
2301 for (uint32_t i = 0; i < parents.Length(); ++i) {
2302 nsPrintfCString paramName("parentguid%d_", i);
2303 rv = statement->BindUTF8StringByName(paramName, parents[i]);
2304 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2304); return rv; } } while (false)
;
2305 }
2306
2307 return NS_OK;
2308}
2309
2310// nsNavHistory::ResultsAsList
2311//
2312
2313nsresult nsNavHistory::ResultsAsList(
2314 mozIStorageStatement* statement, nsNavHistoryQueryOptions* aOptions,
2315 nsCOMArray<nsNavHistoryResultNode>* aResults) {
2316 nsresult rv;
2317 nsCOMPtr<mozIStorageValueArray> row = do_QueryInterface(statement, &rv);
2318 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2318); return rv; } } while (false)
;
2319
2320 bool hasMore = false;
2321 while (NS_SUCCEEDED(statement->ExecuteStep(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(statement->ExecuteStep
(&hasMore))), 1)))
&& hasMore) {
2322 RefPtr<nsNavHistoryResultNode> result;
2323 rv = RowToResult(row, aOptions, getter_AddRefs(result));
2324 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2324); return rv; } } while (false)
;
2325 aResults->AppendElement(result.forget());
2326 }
2327 return NS_OK;
2328}
2329
2330int64_t nsNavHistory::GetTagsFolder() {
2331 // cache our tags folder
2332 // note, we can't do this in nsNavHistory::Init(),
2333 // as getting the bookmarks service would initialize it.
2334 if (mTagsFolder == -1) {
2335 nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
2336 NS_ENSURE_TRUE(bookmarks, -1)do { if ((__builtin_expect(!!(!(bookmarks)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "bookmarks" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2336); return -1; } } while (false)
;
2337
2338 nsresult rv = bookmarks->GetTagsFolder(&mTagsFolder);
2339 NS_ENSURE_SUCCESS(rv, -1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "-1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2339); return -1; } } while (false)
;
2340 }
2341 return mTagsFolder;
2342}
2343
2344// nsNavHistory::FilterResultSet
2345//
2346// This does some post-query-execution filtering:
2347// - searching on title, url and tags
2348// - limit count
2349//
2350// Note: changes to filtering in FilterResultSet()
2351// may require changes to NeedToFilterResultSet()
2352
2353// static
2354nsresult nsNavHistory::FilterResultSet(
2355 nsNavHistoryQueryResultNode* aQueryNode,
2356 const nsCOMArray<nsNavHistoryResultNode>& aSet,
2357 nsCOMArray<nsNavHistoryResultNode>* aFiltered,
2358 const RefPtr<nsNavHistoryQuery>& aQuery,
2359 nsNavHistoryQueryOptions* aOptions) {
2360 // parse the search terms
2361 nsTArray<nsString> terms;
2362 ParseSearchTermsFromQuery(aQuery, &terms);
2363
2364 bool excludeQueries = aOptions->ExcludeQueries();
2365 for (int32_t nodeIndex = 0; nodeIndex < aSet.Count(); nodeIndex++) {
2366 if (excludeQueries && aSet[nodeIndex]->IsQuery()) {
2367 continue;
2368 }
2369
2370 if (aSet[nodeIndex]->mItemId != -1 && aQueryNode &&
2371 aQueryNode->mItemId == aSet[nodeIndex]->mItemId) {
2372 continue;
2373 }
2374
2375 // If there are search terms, we are already getting only uri nodes,
2376 // thus we don't need to filter node types. Though, we must check for
2377 // matching terms.
2378 if (terms.Length()) {
2379 // Filter based on search terms.
2380 // Convert title and url for the current node to UTF16 strings.
2381 NS_ConvertUTF8toUTF16 nodeTitle(aSet[nodeIndex]->mTitle);
2382 // Unescape the URL for search terms matching.
2383 nsAutoCString cNodeURL(aSet[nodeIndex]->mURI);
2384 NS_ConvertUTF8toUTF16 nodeURL(NS_UnescapeURL(cNodeURL));
2385
2386 // Determine if every search term matches anywhere in the title, url or
2387 // tag.
2388 bool matchAllTerms = true;
2389 for (int32_t termIndex = terms.Length() - 1;
2390 termIndex >= 0 && matchAllTerms; termIndex--) {
2391 nsString& term = terms.ElementAt(termIndex);
2392 // True if any of them match; false makes us quit the loop
2393 matchAllTerms =
2394 CaseInsensitiveFindInReadable(term, nodeTitle) ||
2395 CaseInsensitiveFindInReadable(term, nodeURL) ||
2396 CaseInsensitiveFindInReadable(term, aSet[nodeIndex]->mTags);
2397 }
2398 // Skip the node if we don't match all terms in the title, url or tag
2399 if (!matchAllTerms) {
2400 continue;
2401 }
2402 }
2403
2404 aFiltered->AppendObject(aSet[nodeIndex]);
2405
2406 // Stop once we have reached max results.
2407 if (aOptions->MaxResults() > 0 &&
2408 (uint32_t)aFiltered->Count() >= aOptions->MaxResults())
2409 break;
2410 }
2411
2412 return NS_OK;
2413}
2414
2415NS_IMETHODIMPnsresult
2416nsNavHistory::MakeGuid(nsACString& aGuid) {
2417 if (NS_FAILED(GenerateGUID(aGuid))((bool)(__builtin_expect(!!(NS_FAILED_impl(GenerateGUID(aGuid
))), 0)))
) {
2418 MOZ_ASSERT(false, "Shouldn't fail to create a guid!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Shouldn't fail to create a guid!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Shouldn't fail to create a guid!" ")"); do { *((volatile int
*)__null) = 2418; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2419 aGuid.SetIsVoid(true);
2420 }
2421 return NS_OK;
2422}
2423
2424NS_IMETHODIMPnsresult
2425nsNavHistory::HashURL(const nsACString& aSpec, const nsACString& aMode,
2426 uint64_t* _hash) {
2427 return places::HashURL(aSpec, aMode, _hash);
2428}
2429
2430// nsNavHistory::CheckIsRecentEvent
2431//
2432// Sees if this URL happened "recently."
2433//
2434// It is always removed from our recent list no matter what. It only counts
2435// as "recent" if the event happened more recently than our event
2436// threshold ago.
2437
2438bool nsNavHistory::CheckIsRecentEvent(RecentEventHash* hashTable,
2439 const nsACString& url) {
2440 PRTime eventTime;
2441 if (hashTable->Get(url, reinterpret_cast<int64_t*>(&eventTime))) {
2442 hashTable->Remove(url);
2443 if (eventTime > GetNow() - RECENT_EVENT_THRESHOLDPRTime((int64_t)15 * 60 * 1000000L)) return true;
2444 return false;
2445 }
2446 return false;
2447}
2448
2449// nsNavHistory::ExpireNonrecentEvents
2450//
2451// This goes through our
2452
2453void nsNavHistory::ExpireNonrecentEvents(RecentEventHash* hashTable) {
2454 int64_t threshold = GetNow() - RECENT_EVENT_THRESHOLDPRTime((int64_t)15 * 60 * 1000000L);
2455 for (auto iter = hashTable->Iter(); !iter.Done(); iter.Next()) {
2456 if (iter.Data() < threshold) {
2457 iter.Remove();
2458 }
2459 }
2460}
2461
2462// nsNavHistory::RowToResult
2463//
2464// Here, we just have a generic row. It could be a query, URL, visit,
2465// or full visit.
2466
2467nsresult nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
2468 nsNavHistoryQueryOptions* aOptions,
2469 nsNavHistoryResultNode** aResult) {
2470 NS_ASSERTION(aRow && aOptions && aResult, "Null pointer in RowToResult")do { if (!(aRow && aOptions && aResult)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Null pointer in RowToResult", "aRow && aOptions && aResult"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2470); MOZ_PretendNoReturn(); } } while (0)
;
2471
2472 // URL
2473 nsAutoCString url;
2474 nsresult rv = aRow->GetUTF8String(kGetInfoIndex_URL, url);
2475 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2475); return rv; } } while (false)
;
2476 // In case of data corruption URL may be null, but our UI code prefers an
2477 // empty string.
2478 if (url.IsVoid()) {
2479 MOZ_ASSERT(false, "Found a NULL url in moz_places")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Found a NULL url in moz_places"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Found a NULL url in moz_places" ")"); do { *((volatile int*
)__null) = 2479; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2480 url.SetIsVoid(false);
2481 }
2482
2483 // title
2484 nsAutoCString title;
2485 bool isNull;
2486 rv = aRow->GetIsNull(kGetInfoIndex_Title, &isNull);
2487 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2487); return rv; } } while (false)
;
2488 if (!isNull) {
2489 rv = aRow->GetUTF8String(kGetInfoIndex_Title, title);
2490 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2490); return rv; } } while (false)
;
2491 }
2492
2493 uint32_t accessCount = aRow->AsInt32(kGetInfoIndex_VisitCount);
2494 PRTime time = aRow->AsInt64(kGetInfoIndex_VisitDate);
2495
2496 // itemId
2497 int64_t itemId = aRow->AsInt64(kGetInfoIndex_ItemId);
2498 if (itemId == 0) {
2499 // This is not a bookmark. For non-bookmarks we use a -1 itemId value.
2500 // Notice ids in sqlite tables start from 1, so itemId cannot ever be 0.
2501 itemId = -1;
2502 }
2503
2504 if (IsQueryURI(url)) {
2505 // Special case "place:" URIs: turn them into containers.
2506 nsAutoCString guid;
2507 if (itemId != -1) {
2508 rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid, guid);
2509 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2509); return rv; } } while (false)
;
2510 }
2511
2512 if (aOptions->ResultType() ==
2513 nsNavHistoryQueryOptions::RESULTS_AS_ROOTS_QUERY ||
2514 aOptions->ResultType() ==
2515 nsNavHistoryQueryOptions::RESULTS_AS_LEFT_PANE_QUERY) {
2516 rv = aRow->GetUTF8String(kGetInfoIndex_Guid, guid);
2517 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2517); return rv; } } while (false)
;
2518 }
2519
2520 int64_t targetFolderItemId = -1;
2521 nsAutoCString targetFolderGuid;
2522 nsAutoCString targetFolderTitle;
2523 rv = aRow->GetIsNull(kGetTargetFolder_Guid, &isNull);
2524 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2524); return rv; } } while (false)
;
2525 if (!isNull) {
2526 targetFolderItemId = aRow->AsInt64(kGetTargetFolder_ItemId);
2527 rv = aRow->GetUTF8String(kGetTargetFolder_Guid, targetFolderGuid);
2528 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2528); return rv; } } while (false)
;
2529 rv = aRow->GetUTF8String(kGetTargetFolder_Title, targetFolderTitle);
2530 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2530); return rv; } } while (false)
;
2531 }
2532
2533 RefPtr<nsNavHistoryResultNode> resultNode;
2534 rv = QueryUriToResult(url, itemId, guid, title, targetFolderItemId,
2535 targetFolderGuid, targetFolderTitle, accessCount,
2536 time, getter_AddRefs(resultNode));
2537 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2537); return rv; } } while (false)
;
2538
2539 if (itemId != -1 || aOptions->ResultType() ==
2540 nsNavHistoryQueryOptions::RESULTS_AS_TAGS_ROOT) {
2541 // RESULTS_AS_TAGS_ROOT has date columns
2542 resultNode->mDateAdded = aRow->AsInt64(kGetInfoIndex_ItemDateAdded);
2543 resultNode->mLastModified = aRow->AsInt64(kGetInfoIndex_ItemLastModified);
2544 if (resultNode->IsFolderOrShortcut()) {
2545 // If it's a simple folder node (i.e. a shortcut to another folder),
2546 // apply our options for it. However, if the parent type was tag query,
2547 // we do not apply them, because it would not yield any results.
2548 resultNode->GetAsContainer()->mOptions = aOptions;
2549 }
2550 }
2551
2552 resultNode.forget(aResult);
2553 return rv;
2554 } else if (aOptions->ResultType() ==
2555 nsNavHistoryQueryOptions::RESULTS_AS_URI) {
2556 RefPtr<nsNavHistoryResultNode> resultNode =
2557 new nsNavHistoryResultNode(url, title, accessCount, time);
2558
2559 if (itemId != -1) {
2560 resultNode->mItemId = itemId;
2561 resultNode->mDateAdded = aRow->AsInt64(kGetInfoIndex_ItemDateAdded);
2562 resultNode->mLastModified = aRow->AsInt64(kGetInfoIndex_ItemLastModified);
2563
2564 rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid,
2565 resultNode->mBookmarkGuid);
2566 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2566); return rv; } } while (false)
;
2567 }
2568
2569 resultNode->mFrecency = aRow->AsInt32(kGetInfoIndex_Frecency);
2570 resultNode->mHidden = !!aRow->AsInt32(kGetInfoIndex_Hidden);
2571
2572 nsAutoString tags;
2573 rv = aRow->GetString(kGetInfoIndex_ItemTags, tags);
2574 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2574); return rv; } } while (false)
;
2575 resultNode->SetTags(tags);
2576
2577 rv = aRow->GetUTF8String(kGetInfoIndex_Guid, resultNode->mPageGuid);
2578 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2578); return rv; } } while (false)
;
2579
2580 resultNode.forget(aResult);
2581 return NS_OK;
2582 }
2583
2584 if (aOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_VISIT) {
2585 RefPtr<nsNavHistoryResultNode> resultNode =
2586 new nsNavHistoryResultNode(url, title, accessCount, time);
2587
2588 nsAutoString tags;
2589 rv = aRow->GetString(kGetInfoIndex_ItemTags, tags);
Value stored to 'rv' is never read
2590 resultNode->SetTags(tags);
2591 rv = aRow->GetUTF8String(kGetInfoIndex_Guid, resultNode->mPageGuid);
2592 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2592); return rv; } } while (false)
;
2593
2594 rv = aRow->GetInt64(kGetInfoIndex_VisitId, &resultNode->mVisitId);
2595 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2595); return rv; } } while (false)
;
2596
2597 resultNode->mTransitionType = aRow->AsInt32(kGetInfoIndex_VisitType);
2598
2599 resultNode.forget(aResult);
2600 return NS_OK;
2601 }
2602
2603 return NS_ERROR_FAILURE;
2604}
2605
2606// When the URI is a place: URI, generate the proper folder or query node.
2607nsresult nsNavHistory::QueryUriToResult(
2608 const nsACString& aQueryURI, int64_t aItemId,
2609 const nsACString& aBookmarkGuid, const nsACString& aTitle,
2610 int64_t aTargetFolderItemId, const nsACString& aTargetFolderGuid,
2611 const nsACString& aTargetFolderTitle, uint32_t aAccessCount, PRTime aTime,
2612 nsNavHistoryResultNode** aNode) {
2613 // Only assert if the aItemId is set. In some cases (e.g. virtual queries), we
2614 // have a guid, but not an aItemId.
2615 if (aItemId != -1) {
2616 MOZ_ASSERT(!aBookmarkGuid.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aBookmarkGuid.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aBookmarkGuid.IsEmpty()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!aBookmarkGuid.IsEmpty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2616); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBookmarkGuid.IsEmpty()"
")"); do { *((volatile int*)__null) = 2616; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2617 }
2618
2619 nsCOMPtr<nsINavHistoryQuery> query;
2620 nsCOMPtr<nsINavHistoryQueryOptions> options;
2621 nsresult rv = QueryStringToQuery(aQueryURI, getter_AddRefs(query),
2622 getter_AddRefs(options));
2623 RefPtr<nsNavHistoryResultNode> resultNode;
2624 RefPtr<nsNavHistoryQuery> queryObj = do_QueryObject(query);
2625 NS_ENSURE_STATE(queryObj)do { if ((__builtin_expect(!!(!(queryObj)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "queryObj" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2625); return NS_ERROR_UNEXPECTED; } } while (false)
;
2626 RefPtr<nsNavHistoryQueryOptions> optionsObj = do_QueryObject(options);
2627 NS_ENSURE_STATE(optionsObj)do { if ((__builtin_expect(!!(!(optionsObj)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "optionsObj" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2627); return NS_ERROR_UNEXPECTED; } } while (false)
;
2628 // If this failed the query does not parse correctly, let the error pass and
2629 // handle it later.
2630 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2631 if (!aTargetFolderGuid.IsEmpty()) {
2632 MOZ_ASSERT(aTargetFolderItemId >= 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTargetFolderItemId >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTargetFolderItemId >= 0)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTargetFolderItemId >= 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTargetFolderItemId >= 0"
")"); do { *((volatile int*)__null) = 2632; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2633 resultNode = new nsNavHistoryFolderResultNode(
2634 aItemId, aBookmarkGuid, aTargetFolderItemId, aTargetFolderGuid,
2635 !aTitle.IsEmpty() ? aTitle : aTargetFolderTitle, optionsObj);
2636 } else {
2637 // This is a regular query.
2638 resultNode = new nsNavHistoryQueryResultNode(aTitle, aTime, aQueryURI,
2639 queryObj, optionsObj);
2640 resultNode->mItemId = aItemId;
2641 resultNode->mBookmarkGuid = aBookmarkGuid;
2642 }
2643 }
2644
2645 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2646 NS_WARNING("Generating a generic empty node for a broken query!")NS_DebugBreak(NS_DEBUG_WARNING, "Generating a generic empty node for a broken query!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2646)
;
2647 // This is a broken query, that either did not parse or points to not
2648 // existing data. We don't want to return failure since that will kill the
2649 // whole result. Instead make a generic empty query node.
2650 resultNode = new nsNavHistoryQueryResultNode(aTitle, 0, aQueryURI, queryObj,
2651 optionsObj);
2652 resultNode->mItemId = aItemId;
2653 resultNode->mBookmarkGuid = aBookmarkGuid;
2654 // This is a perf hack to generate an empty query that skips filtering.
2655 resultNode->GetAsQuery()->Options()->SetExcludeItems(true);
2656 }
2657
2658 resultNode.forget(aNode);
2659 return NS_OK;
2660}
2661
2662void nsNavHistory::GetAgeInDaysString(int32_t aInt, const char* aName,
2663 nsACString& aResult) {
2664 nsIStringBundle* bundle = GetBundle();
2665 if (bundle) {
2666 AutoTArray<nsString, 1> strings;
2667 strings.AppendElement()->AppendInt(aInt);
2668 nsAutoString value;
2669 nsresult rv = bundle->FormatStringFromName(aName, strings, value);
2670 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2671 CopyUTF16toUTF8(value, aResult);
2672 return;
2673 }
2674 }
2675 aResult.Assign(aName);
2676}
2677
2678void nsNavHistory::GetStringFromName(const char* aName, nsACString& aResult) {
2679 nsIStringBundle* bundle = GetBundle();
2680 if (bundle) {
2681 nsAutoString value;
2682 nsresult rv = bundle->GetStringFromName(aName, value);
2683 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2684 CopyUTF16toUTF8(value, aResult);
2685 return;
2686 }
2687 }
2688 aResult.Assign(aName);
2689}
2690
2691// static
2692void nsNavHistory::GetMonthName(const PRExplodedTime& aTime,
2693 nsACString& aResult) {
2694 nsAutoString month;
2695
2696 mozilla::intl::DateTimeFormat::ComponentsBag components;
2697 components.month = Some(mozilla::intl::DateTimeFormat::Month::Long);
2698 nsresult rv =
2699 mozilla::intl::AppDateTimeFormat::Format(components, &aTime, month);
2700 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2701 aResult = nsPrintfCString("[%d]", aTime.tm_month + 1);
2702 return;
2703 }
2704 CopyUTF16toUTF8(month, aResult);
2705}
2706
2707// static
2708void nsNavHistory::GetMonthYear(const PRExplodedTime& aTime,
2709 nsACString& aResult) {
2710 nsAutoString monthYear;
2711 mozilla::intl::DateTimeFormat::ComponentsBag components;
2712 components.month = Some(mozilla::intl::DateTimeFormat::Month::Long);
2713 components.year = Some(mozilla::intl::DateTimeFormat::Numeric::Numeric);
2714 nsresult rv =
2715 mozilla::intl::AppDateTimeFormat::Format(components, &aTime, monthYear);
2716 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2717 aResult = nsPrintfCString("[%d-%d]", aTime.tm_month + 1, aTime.tm_year);
2718 return;
2719 }
2720 CopyUTF16toUTF8(monthYear, aResult);
2721}
2722
2723namespace {
2724
2725// GetSimpleBookmarksQueryParent
2726//
2727// Determines if this is a simple bookmarks query for a
2728// folder with no other constraints. In these common cases, we can more
2729// efficiently compute the results.
2730//
2731// A simple bookmarks query will result in a hierarchical tree of
2732// bookmark items, folders and separators.
2733//
2734// Returns the folder ID as Maybe<nsCString> if it is a simple folder
2735// query, Nothing() if not.
2736static Maybe<nsCString> GetSimpleBookmarksQueryParent(
2737 const RefPtr<nsNavHistoryQuery>& aQuery,
2738 const RefPtr<nsNavHistoryQueryOptions>& aOptions) {
2739 if (aQuery->Parents().Length() != 1) return Nothing();
2740
2741 bool hasIt;
2742 if ((NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aQuery->GetHasBeginTime
(&hasIt))), 1)))
&& hasIt) ||
2743 (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aQuery->GetHasEndTime
(&hasIt))), 1)))
&& hasIt) ||
2744 !aQuery->Domain().IsVoid() || aQuery->Uri() ||
2745 !aQuery->SearchTerms().IsEmpty() || aQuery->Tags().Length() > 0 ||
2746 aOptions->MaxResults() > 0 || !IsValidGUID(aQuery->Parents()[0])) {
2747 return Nothing();
2748 }
2749
2750 return Some(aQuery->Parents()[0]);
2751}
2752
2753// ParseSearchTermsFromQuery
2754//
2755// Construct an array of search terms from the given query.
2756// Within a query, all the terms are ANDed together.
2757//
2758// This just breaks the query up into words. We don't do anything fancy,
2759// not even quoting. We do, however, strip quotes, because people might
2760// try to input quotes expecting them to do something and get no results
2761// back.
2762
2763inline bool isQueryWhitespace(char16_t ch) { return ch == ' '; }
2764
2765void ParseSearchTermsFromQuery(const RefPtr<nsNavHistoryQuery>& aQuery,
2766 nsTArray<nsString>* aTerms) {
2767 int32_t lastBegin = -1;
2768 if (!aQuery->SearchTerms().IsEmpty()) {
2769 const nsString& searchTerms = aQuery->SearchTerms();
2770 for (uint32_t j = 0; j < searchTerms.Length(); j++) {
2771 if (isQueryWhitespace(searchTerms[j]) || searchTerms[j] == '"') {
2772 if (lastBegin >= 0) {
2773 // found the end of a word
2774 aTerms->AppendElement(
2775 Substring(searchTerms, lastBegin, j - lastBegin));
2776 lastBegin = -1;
2777 }
2778 } else {
2779 if (lastBegin < 0) {
2780 // found the beginning of a word
2781 lastBegin = j;
2782 }
2783 }
2784 }
2785 // last word
2786 if (lastBegin >= 0)
2787 aTerms->AppendElement(Substring(searchTerms, lastBegin));
2788 }
2789}
2790
2791} // namespace
2792
2793const mozilla::intl::Collator* nsNavHistory::GetCollator() {
2794 if (mCollator) {
2795 return mCollator.get();
2796 }
2797
2798 auto result = mozilla::intl::LocaleService::TryCreateComponent<
2799 mozilla::intl::Collator>();
2800 NS_ENSURE_TRUE(result.isOk(), nullptr)do { if ((__builtin_expect(!!(!(result.isOk())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "result.isOk()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2800); return nullptr; } } while (false)
;
2801 auto collator = result.unwrap();
2802
2803 // Sort in a case-insensitive way, where "base" letters are considered
2804 // equal, e.g: a = á, a = A, a ≠ b.
2805 using mozilla::intl::Collator;
2806 Collator::Options options{};
2807 options.sensitivity = Collator::Sensitivity::Base;
2808 auto optResult = collator->SetOptions(options);
2809 NS_ENSURE_TRUE(optResult.isOk(), nullptr)do { if ((__builtin_expect(!!(!(optResult.isOk())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "optResult.isOk()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2809); return nullptr; } } while (false)
;
2810
2811 mCollator = UniquePtr<const Collator>(collator.release());
2812
2813 return mCollator.get();
2814}
2815
2816nsIStringBundle* nsNavHistory::GetBundle() {
2817 if (!mBundle) {
2818 nsCOMPtr<nsIStringBundleService> bundleService =
2819 components::StringBundle::Service();
2820 NS_ENSURE_TRUE(bundleService, nullptr)do { if ((__builtin_expect(!!(!(bundleService)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "bundleService" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2820); return nullptr; } } while (false)
;
2821 nsresult rv = bundleService->CreateBundle(
2822 "chrome://places/locale/places.properties", getter_AddRefs(mBundle));
2823 NS_ENSURE_SUCCESS(rv, nullptr)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "nullptr", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/places/nsNavHistory.cpp"
, 2823); return nullptr; } } while (false)
;
2824 }
2825 return mBundle;
2826}