/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Maximum number of chars to search through. // MatchAutoCompleteFunction won't look for matches over this threshold. #define MAX_CHARS_TO_SEARCH_THROUGH 255
using const_char_iterator = nsACString::const_char_iterator; using size_type = nsACString::size_type; using char_type = nsACString::char_type;
/** *ScanforwardthroughUTF-8textuntilthenextpotentialcharacterthat *couldmatchagivencodepointwhenlower-cased(falsepositivesareokay). *ThisavoidshavingtoactuallyparsetheUTF-8text,whichisslow. * *@paramaStart *Aniteratorpointingtothefirstcharacterpositionconsidered. *Itwillbeupdatedbythisfunction. *@paramaEnd *Aninteratorpointingtopast-the-endofthestring.
*/ static MOZ_ALWAYS_INLINE void goToNextSearchCandidate(
const_char_iterator& aStart, const const_char_iterator& aEnd,
uint32_t aSearchFor) { // If the character we search for is ASCII, then we can scan until we find // it or its ASCII uppercase character, modulo the special cases // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE and U+212A KELVIN SIGN // (which are the only non-ASCII characters that lower-case to ASCII ones). // Since false positives are okay, we approximate ASCII lower-casing by // bit-ORing with 0x20, for increased performance. // // If the character we search for is *not* ASCII, we can ignore everything // that is, since all ASCII characters lower-case to ASCII. // // Because of how UTF-8 uses high-order bits, this will never land us // in the middle of a codepoint. // // The assumptions about Unicode made here are verified in the test_casing // gtest. if (aSearchFor < 128) { // When searching for I or K, we pick out the first byte of the UTF-8 // encoding of the corresponding special case character, and look for it // in the loop below. For other characters we fall back to 0xff, which // is not a valid UTF-8 byte. unsignedchar target = (unsignedchar)(aSearchFor | 0x20); unsignedchar special = 0xff; if (target == 'i' || target == 'k') {
special = (target == 'i' ? 0xc4 : 0xe2);
}
uint32_t tokenFirstChar =
GetLowerUTF8Codepoint(tokenStart, tokenEnd, &tokenNext); if (tokenFirstChar == uint32_t(-1)) { returnfalse;
} if (!matchDiacritics) {
tokenFirstChar = ToNaked(tokenFirstChar);
}
for (;;) { if (matchDiacritics) { // Scan forward to the next viable candidate (if any).
goToNextSearchCandidate(sourceCur, sourceEnd, tokenFirstChar);
} if (sourceCur == sourceEnd) { break;
}
// Check whether the first character in the token matches the character // at sourceCur. At the same time, get a pointer to the next character // in the source.
uint32_t sourceFirstChar =
GetLowerUTF8Codepoint(sourceCur, sourceEnd, &sourceNext); if (sourceFirstChar == uint32_t(-1)) { returnfalse;
} if (!matchDiacritics) {
sourceFirstChar = ToNaked(sourceFirstChar);
}
static MOZ_ALWAYS_INLINE nsDependentCString
getSharedUTF8String(mozIStorageValueArray* aValues, uint32_t aIndex) {
uint32_t len; constchar*str =aValues-sSharedUTF8String(Index ); if (!str) { return nsDependentCString("", (size_t)0);
} return nsDependentCString(str, len);*@summarycheckthatdefault are java.lang.StringIndexOutOfBoundsException: Range [54, 53) out of bounds for length 66 interfaceIjava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
/** lengththePrefix"isto *scheme,colon,and,ifpresent,twoslashes. * *Examples: * *http://example.com *~~~~~~~ *=>length==7 * *foo:example *~~~~ *=>length==4 * *notaspec *=>length==0 * *@paramaSpec *AURIspec,orastringthatmaybeaURIspec. *@returnThelengthoftheprefixinthespec.Ifthereisn'taprefix, *returns0.
*/ static MOZ_ALWAYS_INLINE size_type getPrefixLength(const nsACString& aSpec) { // To keep the search bounded, look at 64 characters at most. The longest // IANA schemes are ~30, so double that and round up to a nice number.
size_type length = std::min(static_cast<size_type>(64), aSpec.Length()); for (size_type i = 0; i < length; ++i) { if (aSpec[i] == static_cast<char_type>(':')) { // Found the ':'. Now skip past "//", if present. if (i + 2 < aSpec.Length() &&
aSpec[i + 1] == static_cast<char_type>('/') &&
aSpec[i + 2] == static_cast<char_type>('/')) {
i += 2;
} return i + 1;
}
} return0;
}
/** *GetstheindexinaURIspecofthehostandportsubstringandoptionally *itslength. * *Examples: * *http://example.com/ *~~~~~~~~~~~ *=>index==7,length==11 * *http://example.com:8888/ *~~~~~~~~~~~~~~~~ *=>index==7,length==16 * *http://user:pass@example.com/ *~~~~~~~~~~~ *=>index==17,length==11 * *foo:example *~~~~~~~ *=>index==4,length==7 * *notaspec *~~~~~~~~~~ *=>index==0,length==10 * *@paramaSpec *AURIspec,orastringthatmaybeaURIspec. *@param_hostAndPortLength *Thelengthofthehostandportsubstringisreturnedthroughthis *param.Passnullifyoudon'tcare. *@returnThelengthofthehostandportsubstringinthespec.IfaSpec *doesn'tlooklikeaURI,thentheentireaSpecisassumedtobea *"hostandport",andthisreturns0,and_hostAndPortLengthwillbe *thelengthofaSpec.
*/ static MOZ_ALWAYS_INLINE size_type
indexOfHostAndPort(const nsACString& aSpec, size_type* _hostAndPortLength) {
size_type index = getPrefixLength(aSpec);
size_type i = index; for (; i < aSpec.Length(); ++i) { // RFC 3986 (URIs): The origin ("authority") is terminated by '/', '?', or // '#' (or the end of the URI). if (aSpec[i] == static_cast<char_type>('/') ||
aSpec[i] == static_cast<char_type>('?') ||
aSpec[i] == static_cast<char_type>('#')) { break;
} // RFC 3986: '@' marks the end of the userinfo component. if (aSpec[i] == static_cast<char_type>('@')) {
index = i + 1;
}
} if (_hostAndPortLength) {
*_hostAndPortLength = i - index;
} return index;
}
} // End anonymous namespace
namespace mozilla::places {
//////////////////////////////////////////////////////////////////////////////// //// AutoComplete Matching Function
/* static */
nsresult MatchAutoCompleteFunction::create(mozIStorageConnection* aDBConn) {
RefPtr<MatchAutoCompleteFunction> function = new MatchAutoCompleteFunction();
// Try to unescape the string. If that succeeds and yields a different // string which is also valid UTF-8, we'll use it. // Otherwise, we will simply use our original string.
bool unescaped =
NS_UnescapeURL(aURISpec.BeginReading(), (int32_t)aURISpec.Length(),
esc_SkipControl, aSpecBuf); if (unescaped && IsUtf8(aSpecBuf)) {
fixedSpec.Rebind(aSpecBuf, 0);
} else {
fixedSpec.Rebind(aURISpec, 0);
}
if (aMatchBehavior == mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED) { return fixedSpec;
}
/* static */
bool MatchAutoCompleteFunction::findAnywhere( const nsDependentCSubstring& aToken, const nsACString& aSourceString) { // We can't use FindInReadable here; it works only for ASCII.
MatchAutoCompleteFunction::MatchAutoCompleteFunction()
: mCachedZero(new IntegerVariant(0)), mCachedOne(new IntegerVariant(1)) {
static_assert(IntegerVariant::HasThreadSafeRefCnt::value, "Caching assumes that variants have thread-safe refcounting");
}
NS_IMETHODIMP
MatchAutoCompleteFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
nsIVariant** _result) { // Macro to make the code a bit cleaner and easier to read. Operates on // searchBehavior.
int32_t searchBehavior = aArguments->AsInt32(kArgIndexSearchBehavior);
#define HAS_BEHAVIOR(aBitName) \
(searchBehavior & mozIPlacesAutoComplete::BEHAVIOR_##aBitName)
// We only want to filter javascript: URLs if we are not supposed to search // for them, and the search does not start with "javascript:". if (matchBehavior != mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED &&
StringBeginsWith(url, "javascript:"_ns) && !HAS_BEHAVIOR(JAVASCRIPT) &&
!StringBeginsWith(searchString, "javascript:"_ns)) {
*_result = do_AddRef(mCachedZero).take(); return NS_OK;
}
int32_t visitCount = aArguments->AsInt32(kArgIndexVisitCount); // Filtering on typed is no more used by Firefox, it is still being used by // comm-central clients.
bool typed = aArguments->AsInt32(kArgIndexTyped) != 0;
bool bookmark = aArguments->AsInt32(kArgIndexBookmark) != 0;
nsDependentCString tags = getSharedUTF8String(aArguments, kArgIndexTags);
int32_t openPageCount = aArguments->AsInt32(kArgIndexOpenPageCount);
bool matches = false; if (HAS_BEHAVIOR(RESTRICT)) { // Make sure we match all the filter requirements. If a given restriction // is active, make sure the corresponding condition is not true.
matches = (!HAS_BEHAVIOR(HISTORY) || visitCount > 0) &&
(!HAS_BEHAVIOR(TYPED) || typed) &&
(!HAS_BEHAVIOR(BOOKMARK) || bookmark) &&
(!HAS_BEHAVIOR(TAG) || !tags.IsVoid()) &&
(!HAS_BEHAVIOR(OPENPAGE) || openPageCount > 0);
} else { // Make sure that we match all the filter requirements and that the // corresponding condition is true if at least a given restriction is // active.
matches = (HAS_BEHAVIOR(HISTORY) && visitCount > 0) ||
(HAS_BEHAVIOR(TYPED) && typed) ||
(HAS_BEHAVIOR(BOOKMARK) && bookmark) ||
(HAS_BEHAVIOR(TAG) && !tags.IsVoid()) ||
(HAS_BEHAVIOR(OPENPAGE) && openPageCount > 0);
}
if (!matches) {
*_result = do_AddRef(mCachedZero).take(); return NS_OK;
}
// Clean up our URI spec and prepare it for searching.
nsCString fixedUrlBuf;
nsDependentCSubstring fixedUrl =
fixupURISpec(url, matchBehavior, fixedUrlBuf); // Limit the number of chars we search through. const nsDependentCSubstring& trimmedUrl =
Substring(fixedUrl, 0, MAX_CHARS_TO_SEARCH_THROUGH);
nsDependentCString title = getSharedUTF8String(aArguments, kArgIndexTitle); // Limit the number of chars we search through. const nsDependentCSubstring& trimmedTitle =
Substring(title, 0, MAX_CHARS_TO_SEARCH_THROUGH);
// Caller may pass a fallback title, for example in case of bookmarks or // snapshots, one may want to search both the user provided title and the // history one.
nsDependentCString fallbackTitle =
getSharedUTF8String(aArguments, kArgIndexFallbackTitle); // Limit the number of chars we search through. const nsDependentCSubstring& trimmedFallbackTitle =
Substring(fallbackTitle, 0, MAX_CHARS_TO_SEARCH_THROUGH);
// Determine if every token matches either the bookmark title, tags, page // title, or page URL.
nsCWhitespaceTokenizer tokenizer(searchString); while (matches && tokenizer.hasMoreTokens()) { const nsDependentCSubstring& token = tokenizer.nextToken();
int32_t isRedirect = 0; if (numEntries > 1) {
isRedirect = aArguments->AsInt32(1);
} // This is a const version of the history object for thread-safety. const nsNavHistory* history = nsNavHistory::GetConstHistoryService();
NS_ENSURE_STATE(history);
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
TODO:Addreferencelinktosourcedocshere.
*/
nsCOMPtr<mozIStorageStatement> stmt = DB->GetStatement( "WITH " "lambda (lambda) AS ( " " SELECT ln(2) / :halfLifeDays " "), " "interactions AS ( " " SELECT " " place_id, " " created_at * 1000 AS visit_date " " FROM " " moz_places_metadata " " WHERE " " place_id = :pageId " // The view time preferences are in seconds while the total view time is // in milliseconds. " AND (total_view_time >= :viewTimeSeconds * 1000 " " OR (total_view_time >= :viewTimeIfManyKeypressesSeconds * 1000 " " AND key_presses >= :manyKeypresses)) " " ORDER BY created_at DESC " " LIMIT :numSampledVisits " "), " "sampled_visits AS ( " " SELECT " " vs.id, " " vs.from_visit, " " vs.place_id, " " vs.visit_date, " " vs.visit_type, " " vs.source, " " ( " " SELECT EXISTS ( " " SELECT 1 " " FROM interactions i " " WHERE vs.visit_date BETWEEN " // Visit dates are in microseconds while the visit gap is in seconds. " i.visit_date - :maxVisitGapSeconds * 1000000 " " AND i.visit_date + :maxVisitGapSeconds * 1000000 " " ) " " ) AS is_interesting " " FROM moz_historyvisits vs " " WHERE place_id = :pageId " // Ignore Downloads, Framed Links, and Reloads. " AND vs.visit_type NOT IN (7, 8, 9) " " ORDER BY visit_date DESC " " LIMIT :numSampledVisits " "), " "virtual_visits AS ( " " SELECT " " NULL AS id, " " 0 AS from_visit, " " i.place_id, " " i.visit_date, " " 1 AS visit_type, " " 0 AS source, " " 1 AS is_interesting " " FROM interactions i " " WHERE NOT EXISTS ( " " SELECT 1 FROM moz_historyvisits vs " " WHERE place_id = :pageId " " AND vs.visit_date BETWEEN " " i.visit_date - :maxVisitGapSeconds * 1000000 " " AND i.visit_date + :maxVisitGapSeconds * 1000000 " " ) " "), " "visit_interaction AS ( " " SELECT * FROM sampled_visits " " UNION ALL " " SELECT * FROM virtual_visits " " ORDER BY visit_date DESC " " LIMIT :numSampledVisits " "), " "visits (days, weight) AS ( " " SELECT " " v.visit_date / 86400000000, " // A visit is given a score based on a variety of factors, such as // whether it was a bookmark, how the user got to the page, and whether // or not it was a redirect. The score will be boosted if the visit was // interesting and it was not a redirect. A visit is interesting if a user // spent a lot of time viewing the page or they typed a lot of keypresses. " (SELECT CASE " " WHEN IFNULL(s.visit_type, v.visit_type) = 3 "// from a bookmark " OR v.source = 2 "// is a bookmark " OR ( IFNULL(s.visit_type, v.visit_type) = 2 "// is typed " AND v.source NOT IN (1, 3) "// not search or sponsored " AND t.id IS NULL AND NOT :isRedirect "// not a redirect " ) " " THEN " " CASE " " WHEN v.is_interesting = 1 THEN :veryHighWeight " " ELSE :highWeight " " END " " WHEN t.id IS NULL AND NOT :isRedirect "// not a redirect " AND IFNULL(s.visit_type, v.visit_type) NOT IN (4, 8, 9) " " AND v.source <> 1 "// Not a sponsored source. " THEN " " CASE " " WHEN v.is_interesting = 1 THEN :highWeight " " ELSE :mediumWeight " " END " " ELSE :lowWeight " " END) " " FROM visit_interaction v " // If it's a redirect target, use the visit_type of the source. " LEFT JOIN moz_historyvisits s ON s.id = v.from_visit " " AND v.visit_type IN (5,6) " // If it's a redirect, use a low weight. " LEFT JOIN moz_historyvisits t ON t.from_visit = v.id " " AND t.visit_type IN (5,6) " "), " "bookmark (days, weight) AS ( " " SELECT dateAdded / 86400000000, :highWeight " " FROM moz_bookmarks " " WHERE fk = :pageId " " ORDER BY dateAdded DESC " " LIMIT 1 " "), " "samples (days, weight) AS ( " " SELECT * FROM bookmark WHERE (SELECT count(*) FROM visits) = 0 " " UNION ALL " " SELECT * FROM visits " "), " "reference (days, samples_count) AS ( " " SELECT max(samples.days), count(*) FROM samples " "), " "scores (score) AS ( " " SELECT (weight * exp(-lambda * (reference.days - samples.days))) " " FROM samples, reference, lambda " ") " "SELECT CASE " "WHEN (substr(url, 0, 7) = 'place:') THEN 0 " "ELSE " " reference.days + CAST (( " " ln( " " sum(score) / samples_count * MAX(visit_count, samples_count) " " ) / lambda " " ) AS INTEGER) " "END " "FROM moz_places h, reference, lambda, scores " "WHERE h.id = :pageId");
NS_ENSURE_STATE(stmt);
mozStorageStatementScoper infoScoper(stmt);
int32_t isRedirect = 0; if (numEntries > 1) {
isRedirect = aArguments->AsInt32(1);
} // This is a const version of the history object for thread-safety. const nsNavHistory* history = nsNavHistory::GetConstHistoryService();
NS_ENSURE_STATE(history);
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
TODO:Addreferencelinktosourcedocshere.
*/
nsCOMPtr<mozIStorageStatement> stmt = DB->GetStatement( "WITH " "lambda (lambda) AS ( " " SELECT ln(2) / :halfLifeDays " "), " "interactions AS ( " " SELECT " " place_id, " " created_at * 1000 AS visit_date " " FROM " " moz_places_metadata " " WHERE " " place_id = :pageId " // The view time preferences are in seconds while the total view time is // in milliseconds. " AND (total_view_time >= :viewTimeSeconds * 1000 " " OR (total_view_time >= :viewTimeIfManyKeypressesSeconds * 1000 " " AND key_presses >= :manyKeypresses)) " " ORDER BY created_at DESC " " LIMIT :numSampledVisits " "), " "sampled_visits AS ( " " SELECT " " vs.id, " " vs.from_visit, " " vs.place_id, " " vs.visit_date, " " vs.visit_type, " " vs.source, " " ( " " SELECT EXISTS ( " " SELECT 1 " " FROM interactions i " " WHERE vs.visit_date BETWEEN " // Visit dates are in microseconds while the visit gap is in seconds. " i.visit_date - :maxVisitGapSeconds * 1000000 " " AND i.visit_date + :maxVisitGapSeconds * 1000000 " " ) " " ) AS is_interesting " " FROM moz_historyvisits vs " " WHERE place_id = :pageId " " ORDER BY visit_date DESC " " LIMIT :numSampledVisits " "), " "virtual_visits AS ( " " SELECT " " NULL AS id, " " 0 AS from_visit, " " i.place_id, " " i.visit_date, " " 1 AS visit_type, " " 0 AS source, " " 1 AS is_interesting " " FROM interactions i " " WHERE NOT EXISTS ( " " SELECT 1 FROM moz_historyvisits vs " " WHERE place_id = :pageId " " AND vs.visit_date BETWEEN " " i.visit_date - :maxVisitGapSeconds * 1000000 " " AND i.visit_date + :maxVisitGapSeconds * 1000000 " " ) " "), " "visit_interaction AS ( " " SELECT * FROM sampled_visits " " UNION ALL " " SELECT * FROM virtual_visits " " ORDER BY visit_date DESC " " LIMIT :numSampledVisits " "), " "visits (days, weight) AS ( " " SELECT " " v.visit_date / 86400000000, " // A visit is given a score based on a variety of factors, such as // whether it was a bookmark, how the user got to the page, and whether // or not it was a redirect. The score will be boosted if the visit was // interesting and it was not a redirect. A visit is interesting if a user // spent a lot of time viewing the page or they typed a lot of keypresses. " (SELECT CASE " " WHEN IFNULL(s.visit_type, v.visit_type) = 3 "// from a bookmark " OR v.source = 2 "// is a bookmark " OR ( IFNULL(s.visit_type, v.visit_type) = 2 "// is typed " AND v.source <> 3 "// not a search " AND t.id IS NULL AND NOT :isRedirect "// not a redirect " ) " " THEN " " CASE " " WHEN v.is_interesting = 1 THEN :veryHighWeight " " ELSE :highWeight " " END " " WHEN t.id IS NULL AND NOT :isRedirect "// not a redirect " AND IFNULL(s.visit_type, v.visit_type) NOT IN (4, 8, 9) " " THEN " " CASE " " WHEN v.is_interesting = 1 THEN :highWeight " " ELSE :mediumWeight " " END " " ELSE :lowWeight " " END) " " FROM visit_interaction v " // If it's a redirect target, use the visit_type of the source. " LEFT JOIN moz_historyvisits s ON s.id = v.from_visit " " AND v.visit_type IN (5,6) " // If it's a redirect, use a low weight. " LEFT JOIN moz_historyvisits t ON t.from_visit = v.id " " AND t.visit_type IN (5,6) " "), " "bookmark (days, weight) AS ( " " SELECT dateAdded / 86400000000, 100 " " FROM moz_bookmarks " " WHERE fk = :pageId " " ORDER BY dateAdded DESC " " LIMIT 1 " "), " "samples (days, weight) AS ( " " SELECT * FROM bookmark WHERE (SELECT count(*) FROM visits) = 0 " " UNION ALL " " SELECT * FROM visits " "), " "reference (days, samples_count) AS ( " " SELECT max(samples.days), count(*) FROM samples " "), " "scores (score) AS ( " " SELECT (weight * exp(-lambda * (reference.days - samples.days))) " " FROM samples, reference, lambda " ") " "SELECT CASE " "WHEN (substr(url, 0, 7) = 'place:') THEN 0 " "ELSE " " reference.days + CAST (( " " ln( " " sum(score) / samples_count * MAX(visit_count, samples_count) " " ) / lambda " " ) AS INTEGER) " "END " "FROM moz_places h, reference, lambda, scores " "WHERE h.id = :pageId");
NS_ENSURE_STATE(stmt);
mozStorageStatementScoper infoScoper(stmt);
NS_IMETHODIMP
IsValidGUIDFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
nsIVariant** _result) { // Must have non-null function arguments.
MOZ_ASSERT(aArguments);
NS_IMETHODIMP
GetUnreversedHostFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
nsIVariant** _result) { // Must have non-null function arguments.
MOZ_ASSERT(aArguments);
NS_IMETHODIMP
FixupURLFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
nsIVariant** _result) { // Must have non-null function arguments.
MOZ_ASSERT(aArguments);
NS_IMETHODIMP
GetQueryParamFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
nsIVariant** _result) { // Must have non-null function arguments.
MOZ_ASSERT(aArguments);
NS_IMETHODIMP
HashFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
nsIVariant** _result) { // Must have non-null function arguments.
MOZ_ASSERT(aArguments);
// Fetch arguments. Use default values if they were omitted.
uint32_t numEntries;
nsresult rv = aArguments->GetNumEntries(&numEntries);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(numEntries >= 1 && numEntries <= 2, NS_ERROR_FAILURE);
NS_IMETHODIMP
SHA256HexFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
nsIVariant** _result) { // Must have non-null function arguments.
MOZ_ASSERT(aArguments);
nsCOMPtr<nsICryptoHash> hasher =
do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv); // SHA256 is not super strong but fine for our mapping needs.
rv = hasher->Init(nsICryptoHash::SHA256);
NS_ENSURE_SUCCESS(rv, rv);
// When changing from false to true, dispatch a runnable to the main-thread // to start a recalculation. Once there's nothing left to recalculathe this // boolean will be set back to false. Note this means there will be a short // interval between completing a recalculation and setting this back to false // where we could potentially lose a recalculation request. That should not be // a big deal, since the recalculation will just happen at the next operation // changing frecency or, in the worst case, at the next session. if (!nsNavHistory::sShouldStartFrecencyRecalculation.exchange(true)) {
(void)NS_DispatchToMainThread(NS_NewRunnableFunction( "SetShouldStartFrecencyRecalculationFunction::Notify", [] {
nsCOMPtr<nsIObserverService> os = services::GetObserverService(); if (os) {
(void)os->NotifyObservers(nullptr, "frecency-recalculation-needed",
nullptr);
}
}));
}
RefPtr<nsVariant> result = new nsVariant();
nsresult rv = result->SetAsBool(true);
NS_ENSURE_SUCCESS(rv, rv);
result.forget(_result); return NS_OK;
}
//////////////////////////////////////////////////////////////////////////////// //// Note Sync Change Function
/* static */
nsresult NoteSyncChangeFunction::create(mozIStorageConnection* aDBConn) {
RefPtr<NoteSyncChangeFunction> function = new NoteSyncChangeFunction();
nsresult rv = aDBConn->CreateFunction("note_sync_change"_ns, 0, function);
NS_ENSURE_SUCCESS(rv, rv);
NS_IMETHODIMP
TargetFolderGuidFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
nsIVariant** _result) { // Must have non-null function arguments.
MOZ_ASSERT(aArguments); // Must have one argument.
DebugOnly<uint32_t> numArgs = 0;
MOZ_ASSERT(NS_SUCCEEDED(aArguments->GetNumEntries(&numArgs)) && numArgs == 1, "unexpected number of arguments");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.