--- a/netwerk/base/nsIBrowserSearchService.idl
+++ b/netwerk/base/nsIBrowserSearchService.idl
@@ -150,19 +150,19 @@ interface nsISearchEngine : nsISupports
/**
* An optional unique identifier for this search engine within the context of
* the distribution, as provided by the distributing entity.
*/
readonly attribute AString identifier;
/**
* Gets a string representing the hostname from which search results for a
- * given responseType are returned, minus the leading "www." (if present).
- * This can be specified as an url attribute in the engine description file,
- * but will default to host from the <Url>'s template otherwise.
+ * given responseType are returned. This can be specified as an url attribute
+ * in the engine description file, but will default to host from the <Url>'s
+ * template otherwise.
*
* @param responseType [optional]
* The MIME type to get resultDomain for. Defaults to "text/html".
*
* @return the resultDomain for the given responseType.
*/
AString getResultDomain([optional] in AString responseType);
};
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -73,16 +73,18 @@
// * IE didn't support urls longer than 2083 chars
// * Sitemaps protocol used to support a maximum of 2048 chars
// * Various SEO guides suggest to not go over 2000 chars
// * Various apps/services are known to have issues over 2000 chars
// * RFC 2616 - HTTP/1.1 suggests being cautious about depending
// on URI lengths above 255 bytes
#define PREF_HISTORY_MAXURLLEN_DEFAULT 2000
+#define PREF_MIGRATE_V48_FRECENCIES "places.database.migrateV48Frecencies"
+
// Maximum size for the WAL file.
// For performance reasons this should be as large as possible, so that more
// transactions can fit into it, and the checkpoint cost is paid less often.
// At the same time, since we use synchronous = NORMAL, an fsync happens only
// at checkpoint time, so we don't want the WAL to grow too much and risk to
// lose all the contained transactions on a crash.
#define DATABASE_MAX_WAL_BYTES 2048000
@@ -1115,16 +1117,17 @@ Database::InitSchema(bool* aDatabaseMigr
MOZ_ALWAYS_SUCCEEDS(mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"VACUUM favicons"
)));
}
if (mShouldConvertIconPayloads) {
mShouldConvertIconPayloads = false;
nsFaviconService::ConvertUnsupportedPayloads(mMainConn);
}
+ MigrateV48Frecencies();
});
// We are going to update the database, so everything from now on should be in
// a transaction for performances.
mozStorageTransaction transaction(mMainConn, false);
if (databaseInitialized) {
// Migration How-to:
@@ -1254,61 +1257,70 @@ Database::InitSchema(bool* aDatabaseMigr
if (currentSchemaVersion < 47) {
rv = MigrateV47Up();
NS_ENSURE_SUCCESS(rv, rv);
}
// Firefox 61 uses schema version 47.
+ if (currentSchemaVersion < 48) {
+ rv = MigrateV48Up();
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // Firefox 62 uses schema version 48.
+
// Schema Upgrades must add migration code here.
// >>> IMPORTANT! <<<
// NEVER MIX UP SYNC AND ASYNC EXECUTION IN MIGRATORS, YOU MAY LOCK THE
// CONNECTION AND CAUSE FURTHER STEPS TO FAIL.
// In case, set a bool and do the async work in the ScopeExit guard just
// before the migration steps.
}
}
else {
// This is a new database, so we have to create all the tables and indices.
+ // moz_origins.
+ rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_ORIGINS);
+ NS_ENSURE_SUCCESS(rv, rv);
+
// moz_places.
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_PLACES);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_URL_HASH);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_REVHOST);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_VISITCOUNT);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_FRECENCY);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_LASTVISITDATE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_GUID);
NS_ENSURE_SUCCESS(rv, rv);
+ rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_ORIGIN_ID);
+ NS_ENSURE_SUCCESS(rv, rv);
// moz_historyvisits.
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_HISTORYVISITS);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_HISTORYVISITS_PLACEDATE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_HISTORYVISITS_FROMVISIT);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_HISTORYVISITS_VISITDATE);
NS_ENSURE_SUCCESS(rv, rv);
// moz_inputhistory.
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_INPUTHISTORY);
NS_ENSURE_SUCCESS(rv, rv);
- // moz_hosts.
- rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_HOSTS);
- NS_ENSURE_SUCCESS(rv, rv);
-
// moz_bookmarks.
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_BOOKMARKS);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_BOOKMARKS_DELETED);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_BOOKMARKS_PLACETYPE);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_BOOKMARKS_PARENTPOSITION);
@@ -1528,47 +1540,53 @@ Database::InitFunctions()
rv = FrecencyNotificationFunction::create(mMainConn);
NS_ENSURE_SUCCESS(rv, rv);
rv = StoreLastInsertedIdFunction::create(mMainConn);
NS_ENSURE_SUCCESS(rv, rv);
rv = HashFunction::create(mMainConn);
NS_ENSURE_SUCCESS(rv, rv);
rv = GetQueryParamFunction::create(mMainConn);
NS_ENSURE_SUCCESS(rv, rv);
+ rv = GetPrefixFunction::create(mMainConn);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = GetHostAndPortFunction::create(mMainConn);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = StripPrefixAndUserinfoFunction::create(mMainConn);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = IsFrecencyDecayingFunction::create(mMainConn);
+ NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
Database::InitTempEntities()
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = mMainConn->ExecuteSimpleSQL(CREATE_HISTORYVISITS_AFTERINSERT_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_HISTORYVISITS_AFTERDELETE_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
- // Add the triggers that update the moz_hosts table as necessary.
- rv = mMainConn->ExecuteSimpleSQL(CREATE_UPDATEHOSTSINSERT_TEMP);
+ // Add the triggers that update the moz_origins table as necessary.
+ rv = mMainConn->ExecuteSimpleSQL(CREATE_UPDATEORIGINSINSERT_TEMP);
NS_ENSURE_SUCCESS(rv, rv);
- rv = mMainConn->ExecuteSimpleSQL(CREATE_UPDATEHOSTSINSERT_AFTERDELETE_TRIGGER);
+ rv = mMainConn->ExecuteSimpleSQL(CREATE_UPDATEORIGINSINSERT_AFTERDELETE_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_PLACES_AFTERINSERT_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
- rv = mMainConn->ExecuteSimpleSQL(CREATE_UPDATEHOSTSDELETE_TEMP);
+ rv = mMainConn->ExecuteSimpleSQL(CREATE_UPDATEORIGINSDELETE_TEMP);
NS_ENSURE_SUCCESS(rv, rv);
- rv = mMainConn->ExecuteSimpleSQL(CREATE_UPDATEHOSTSDELETE_AFTERDELETE_TRIGGER);
+ rv = mMainConn->ExecuteSimpleSQL(CREATE_UPDATEORIGINSDELETE_AFTERDELETE_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_PLACES_AFTERDELETE_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_PLACES_AFTERUPDATE_FRECENCY_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
- rv = mMainConn->ExecuteSimpleSQL(CREATE_PLACES_AFTERUPDATE_TYPED_TRIGGER);
- NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_BOOKMARKS_FOREIGNCOUNT_AFTERDELETE_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_BOOKMARKS_FOREIGNCOUNT_AFTERINSERT_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
rv = mMainConn->ExecuteSimpleSQL(CREATE_BOOKMARKS_FOREIGNCOUNT_AFTERUPDATE_TRIGGER);
NS_ENSURE_SUCCESS(rv, rv);
@@ -1655,23 +1673,51 @@ Database::MigrateV32Up() {
"WHERE host IN (SELECT host FROM moz_migrate_v32_temp) "
"AND NOT EXISTS("
"SELECT 1 FROM moz_places "
"WHERE rev_host = get_unreversed_host(host || '.') || '.' "
"OR rev_host = get_unreversed_host(host || '.') || '.www.' "
"); "
), getter_AddRefs(deleteHostsStmt));
NS_ENSURE_SUCCESS(rv, rv);
+
+#define HOST_TO_REVHOST_PREDICATE \
+ "rev_host = get_unreversed_host(host || '.') || '.' " \
+ "OR rev_host = get_unreversed_host(host || '.') || '.www.'"
+#define HOSTS_PREFIX_PRIORITY_FRAGMENT \
+ "SELECT CASE " \
+ "WHEN ( " \
+ "SELECT round(avg(substr(url,1,12) = 'https://www.')) FROM moz_places h " \
+ "WHERE (" HOST_TO_REVHOST_PREDICATE ") AND +h.typed = 1 " \
+ ") THEN 'https://www.' " \
+ "WHEN ( " \
+ "SELECT round(avg(substr(url,1,8) = 'https://')) FROM moz_places h " \
+ "WHERE (" HOST_TO_REVHOST_PREDICATE ") AND +h.typed = 1 " \
+ ") THEN 'https://' " \
+ "WHEN 1 = ( " \
+ "SELECT min(substr(url,1,4) = 'ftp:') FROM moz_places h " \
+ "WHERE (" HOST_TO_REVHOST_PREDICATE ") AND +h.typed = 1 " \
+ ") THEN 'ftp://' " \
+ "WHEN ( " \
+ "SELECT round(avg(substr(url,1,11) = 'http://www.')) FROM moz_places h " \
+ "WHERE (" HOST_TO_REVHOST_PREDICATE ") AND +h.typed = 1 " \
+ ") THEN 'www.' " \
+ "END "
+
nsCOMPtr<mozIStorageAsyncStatement> updateHostsStmt;
rv = mMainConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
"UPDATE moz_hosts "
"SET prefix = (" HOSTS_PREFIX_PRIORITY_FRAGMENT ") "
"WHERE host IN (SELECT host FROM moz_migrate_v32_temp) "
), getter_AddRefs(updateHostsStmt));
NS_ENSURE_SUCCESS(rv, rv);
+
+#undef HOST_TO_REVHOST_PREDICATE
+#undef HOSTS_PREFIX_PRIORITY_FRAGMENT
+
nsCOMPtr<mozIStorageAsyncStatement> dropTableStmt;
rv = mMainConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
"DROP TABLE IF EXISTS moz_migrate_v32_temp"
), getter_AddRefs(dropTableStmt));
NS_ENSURE_SUCCESS(rv, rv);
mozIStorageBaseStatement *stmts[] = {
expireOrphansStmt,
@@ -2245,16 +2291,162 @@ Database::MigrateV47Up() {
"AND url = 'place:excludeItems=1' "
") "
));
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
+Database::MigrateV48Up() {
+ // Create and populate moz_origins.
+ nsCOMPtr<mozIStorageStatement> stmt;
+ nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
+ "SELECT * FROM moz_origins; "
+ ), getter_AddRefs(stmt));
+ if (NS_FAILED(rv)) {
+ rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_ORIGINS);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+ "INSERT OR IGNORE INTO moz_origins (prefix, host, frecency) " \
+ "SELECT get_prefix(url), get_host_and_port(url), -1 " \
+ "FROM moz_places; "
+ ));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Add and populate moz_places.origin_id.
+ rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
+ "SELECT origin_id FROM moz_places; "
+ ), getter_AddRefs(stmt));
+ if (NS_FAILED(rv)) {
+ rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+ "ALTER TABLE moz_places " \
+ "ADD COLUMN origin_id INTEGER REFERENCES moz_origins(id); "
+ ));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_ORIGIN_ID);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+ "UPDATE moz_places " \
+ "SET origin_id = ( "
+ "SELECT id FROM moz_origins " \
+ "WHERE prefix = get_prefix(url) AND host = get_host_and_port(url) " \
+ "); "
+ ));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Setting this pref will cause InitSchema to begin async migration of
+ // frecencies to moz_origins. The reason we don't defer the other steps
+ // above, like we do this one here, is because we want to make sure that the
+ // main data in moz_origins, prefix and host, are coherent in relation to
+ // moz_places.
+ Unused << Preferences::SetBool(PREF_MIGRATE_V48_FRECENCIES, true);
+
+ // From this point on, nobody should use moz_hosts again. Empty it so that we
+ // don't leak the user's history, but don't remove it yet so that the user can
+ // downgrade.
+ rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+ "DELETE FROM moz_hosts; "
+ ));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+namespace {
+
+class MigrateV48FrecenciesRunnable final : public Runnable
+{
+public:
+ NS_DECL_NSIRUNNABLE
+ explicit MigrateV48FrecenciesRunnable(mozIStorageConnection* aDBConn);
+private:
+ nsCOMPtr<mozIStorageConnection> mDBConn;
+};
+
+MigrateV48FrecenciesRunnable::MigrateV48FrecenciesRunnable(mozIStorageConnection* aDBConn)
+ : Runnable("places::MigrateV48FrecenciesRunnable")
+ , mDBConn(aDBConn)
+{
+}
+
+NS_IMETHODIMP
+MigrateV48FrecenciesRunnable::Run()
+{
+ if (NS_IsMainThread()) {
+ // Migration done. Clear the pref.
+ Unused << Preferences::ClearUser(PREF_MIGRATE_V48_FRECENCIES);
+ return NS_OK;
+ }
+
+ nsCOMPtr<mozIStorageStatement> selectStmt;
+ nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
+ "SELECT id FROM moz_origins " \
+ "WHERE frecency = -1 " \
+ "ORDER BY id ASC " \
+ "LIMIT 200; "
+ ), getter_AddRefs(selectStmt));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<mozIStorageStatement> updateStmt;
+ rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
+ "UPDATE moz_origins " \
+ "SET frecency = ( " \
+ "SELECT MAX(frecency) " \
+ "FROM moz_places " \
+ "WHERE moz_places.origin_id = moz_origins.id " \
+ ") " \
+ "WHERE id = :id; "
+ ), getter_AddRefs(updateStmt));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mozStorageStatementScoper updateScoper(updateStmt);
+
+ // We should do the work in chunks, or the wal journal may grow too much.
+ bool hasResult;
+ uint8_t count = 0;
+ for (; NS_SUCCEEDED(selectStmt->ExecuteStep(&hasResult)) && hasResult; ++count) {
+ int64_t id = selectStmt->AsInt64(0);
+ rv = updateStmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), id);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = updateStmt->Execute();
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ if (count == 200) {
+ // There are more results to handle. Re-dispatch to the same thread for the
+ // next chunk.
+ return NS_DispatchToCurrentThread(this);
+ }
+
+ // Re-dispatch to the main-thread to flip the migration pref.
+ return NS_DispatchToMainThread(this);
+}
+
+} // namespace
+
+void
+Database::MigrateV48Frecencies()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ if (!Preferences::GetBool(PREF_MIGRATE_V48_FRECENCIES)) {
+ return;
+ }
+
+ RefPtr<MigrateV48FrecenciesRunnable> runnable =
+ new MigrateV48FrecenciesRunnable(mMainConn);
+ nsCOMPtr<nsIEventTarget> target = do_GetInterface(mMainConn);
+ MOZ_ASSERT(target);
+ Unused << target->Dispatch(runnable, NS_DISPATCH_NORMAL);
+}
+
+nsresult
Database::GetItemsWithAnno(const nsACString& aAnnoName, int32_t aItemType,
nsTArray<int64_t>& aItemIds)
{
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT b.id FROM moz_items_annos a "
"JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id "
"JOIN moz_bookmarks b ON b.id = a.item_id "
--- a/toolkit/components/places/Database.h
+++ b/toolkit/components/places/Database.h
@@ -14,17 +14,17 @@
#include "mozilla/storage/StatementCache.h"
#include "mozilla/Attributes.h"
#include "nsIEventTarget.h"
#include "Shutdown.h"
#include "nsCategoryCache.h"
// This is the schema version. Update it at any schema change and add a
// corresponding migrateVxx method below.
-#define DATABASE_SCHEMA_VERSION 47
+#define DATABASE_SCHEMA_VERSION 48
// Fired after Places inited.
#define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
// This topic is received when the profile is about to be lost. Places does
// initial shutdown work and notifies TOPIC_PLACES_SHUTDOWN to all listeners.
// Any shutdown work that requires the Places APIs should happen here.
#define TOPIC_PROFILE_CHANGE_TEARDOWN "profile-change-teardown"
// Fired when Places is shutting down. Any code should stop accessing Places
@@ -333,16 +333,19 @@ protected:
nsresult MigrateV40Up();
nsresult MigrateV41Up();
nsresult MigrateV42Up();
nsresult MigrateV43Up();
nsresult MigrateV44Up();
nsresult MigrateV45Up();
nsresult MigrateV46Up();
nsresult MigrateV47Up();
+ nsresult MigrateV48Up();
+
+ void MigrateV48Frecencies();
nsresult UpdateBookmarkRootTitles();
friend class ConnectionShutdownBlocker;
int64_t CreateMobileRoot();
nsresult GetItemsWithAnno(const nsACString& aAnnoName, int32_t aItemType,
nsTArray<int64_t>& aItemIds);
--- a/toolkit/components/places/PlacesSearchAutocompleteProvider.jsm
+++ b/toolkit/components/places/PlacesSearchAutocompleteProvider.jsm
@@ -226,18 +226,20 @@ var PlacesSearchAutocompleteProvider = O
* iconUrl: Icon associated to the match, or null if not available.
* }
*/
async findMatchByToken(searchToken) {
await this.ensureInitialized();
// Match at the beginning for now. In the future, an "options" argument may
// allow the matching behavior to be tuned.
- return SearchAutocompleteProviderInternal.priorityMatches
- .find(m => m.token.startsWith(searchToken));
+ return SearchAutocompleteProviderInternal.priorityMatches.find(m => {
+ return m.token.startsWith(searchToken) ||
+ m.token.startsWith("www." + searchToken);
+ });
},
/**
* Matches a given search string to an item that should be included by
* components wishing to search using search engine aliases, like
* autocomple.
*
* @param searchToken
--- a/toolkit/components/places/SQLFunctions.cpp
+++ b/toolkit/components/places/SQLFunctions.cpp
@@ -27,16 +27,18 @@
using namespace mozilla::storage;
////////////////////////////////////////////////////////////////////////////////
//// Anonymous Helpers
namespace {
typedef nsACString::const_char_iterator const_char_iterator;
+ typedef nsACString::size_type size_type;
+ typedef nsACString::char_type char_type;
/**
* Scan forward through UTF-8 text until the next potential character that
* could match a given codepoint when lower-cased (false positives are okay).
* This avoids having to actually parse the UTF-8 text, which is slow.
*
* @param aStart
* An iterator pointing to the first character position considered.
@@ -267,16 +269,121 @@ namespace {
mResult->SetAsAString(aValue);
return false;
}
private:
const nsCString& mParamName;
nsVariant* mResult;
};
+ /**
+ * Gets the length of the prefix in a URI spec. "Prefix" is defined to be the
+ * scheme, colon, and, if present, two slashes.
+ *
+ * Examples:
+ *
+ * http://example.com
+ * ~~~~~~~
+ * => length == 7
+ *
+ * foo:example
+ * ~~~~
+ * => length == 4
+ *
+ * not a spec
+ * => length == 0
+ *
+ * @param aSpec
+ * A URI spec, or a string that may be a URI spec.
+ * @return The length of the prefix in the spec. If there isn't a prefix,
+ * returns 0.
+ */
+ 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;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Gets the index in a URI spec of the host and port substring and optionally
+ * its length.
+ *
+ * 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
+ *
+ * not a spec
+ * ~~~~~~~~~~
+ * => index == 0, length == 10
+ *
+ * @param aSpec
+ * A URI spec, or a string that may be a URI spec.
+ * @param _hostAndPortLength
+ * The length of the host and port substring is returned through this
+ * param. Pass null if you don't care.
+ * @return The length of the host and port substring in the spec. If aSpec
+ * doesn't look like a URI, then the entire aSpec is assumed to be a
+ * "host and port", and this returns 0, and _hostAndPortLength will be
+ * the length of aSpec.
+ */
+ 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 {
namespace places {
////////////////////////////////////////////////////////////////////////////////
//// AutoComplete Matching Function
@@ -320,20 +427,16 @@ namespace places {
if (StringBeginsWith(fixedSpec, NS_LITERAL_CSTRING("http://"))) {
fixedSpec.Rebind(fixedSpec, 7);
} else if (StringBeginsWith(fixedSpec, NS_LITERAL_CSTRING("https://"))) {
fixedSpec.Rebind(fixedSpec, 8);
} else if (StringBeginsWith(fixedSpec, NS_LITERAL_CSTRING("ftp://"))) {
fixedSpec.Rebind(fixedSpec, 6);
}
- if (StringBeginsWith(fixedSpec, NS_LITERAL_CSTRING("www."))) {
- fixedSpec.Rebind(fixedSpec, 4);
- }
-
return fixedSpec;
}
/* static */
bool
MatchAutoCompleteFunction::findAnywhere(const nsDependentCSubstring &aToken,
const nsACString &aSourceString)
{
@@ -1113,10 +1216,179 @@ namespace places {
NS_ENSURE_SUCCESS(rv, rv);
rv = result->SetAsInt64(hash);
NS_ENSURE_SUCCESS(rv, rv);
result.forget(_result);
return NS_OK;
}
+////////////////////////////////////////////////////////////////////////////////
+//// Get prefix function
+
+ /* static */
+ nsresult
+ GetPrefixFunction::create(mozIStorageConnection *aDBConn)
+ {
+ RefPtr<GetPrefixFunction> function = new GetPrefixFunction();
+ nsresult rv = aDBConn->CreateFunction(
+ NS_LITERAL_CSTRING("get_prefix"), 1, function
+ );
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+ }
+
+ NS_IMPL_ISUPPORTS(
+ GetPrefixFunction,
+ mozIStorageFunction
+ )
+
+ NS_IMETHODIMP
+ GetPrefixFunction::OnFunctionCall(mozIStorageValueArray *aArgs,
+ nsIVariant **_result)
+ {
+ MOZ_ASSERT(aArgs);
+
+ uint32_t numArgs;
+ nsresult rv = aArgs->GetNumEntries(&numArgs);
+ NS_ENSURE_SUCCESS(rv, rv);
+ MOZ_ASSERT(numArgs == 1);
+
+ nsDependentCString spec(getSharedUTF8String(aArgs, 0));
+
+ RefPtr<nsVariant> result = new nsVariant();
+ result->SetAsACString(Substring(spec, 0, getPrefixLength(spec)));
+ result.forget(_result);
+ return NS_OK;
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+//// Get host and port function
+
+ /* static */
+ nsresult
+ GetHostAndPortFunction::create(mozIStorageConnection *aDBConn)
+ {
+ RefPtr<GetHostAndPortFunction> function = new GetHostAndPortFunction();
+ nsresult rv = aDBConn->CreateFunction(
+ NS_LITERAL_CSTRING("get_host_and_port"), 1, function
+ );
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+ }
+
+ NS_IMPL_ISUPPORTS(
+ GetHostAndPortFunction,
+ mozIStorageFunction
+ )
+
+ NS_IMETHODIMP
+ GetHostAndPortFunction::OnFunctionCall(mozIStorageValueArray *aArgs,
+ nsIVariant **_result)
+ {
+ MOZ_ASSERT(aArgs);
+
+ uint32_t numArgs;
+ nsresult rv = aArgs->GetNumEntries(&numArgs);
+ NS_ENSURE_SUCCESS(rv, rv);
+ MOZ_ASSERT(numArgs == 1);
+
+ nsDependentCString spec(getSharedUTF8String(aArgs, 0));
+
+ RefPtr<nsVariant> result = new nsVariant();
+
+ size_type length;
+ size_type index = indexOfHostAndPort(spec, &length);
+ result->SetAsACString(Substring(spec, index, length));
+ result.forget(_result);
+ return NS_OK;
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+//// Strip prefix and userinfo function
+
+ /* static */
+ nsresult
+ StripPrefixAndUserinfoFunction::create(mozIStorageConnection *aDBConn)
+ {
+ RefPtr<StripPrefixAndUserinfoFunction> function =
+ new StripPrefixAndUserinfoFunction();
+ nsresult rv = aDBConn->CreateFunction(
+ NS_LITERAL_CSTRING("strip_prefix_and_userinfo"), 1, function
+ );
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+ }
+
+ NS_IMPL_ISUPPORTS(
+ StripPrefixAndUserinfoFunction,
+ mozIStorageFunction
+ )
+
+ NS_IMETHODIMP
+ StripPrefixAndUserinfoFunction::OnFunctionCall(mozIStorageValueArray *aArgs,
+ nsIVariant **_result)
+ {
+ MOZ_ASSERT(aArgs);
+
+ uint32_t numArgs;
+ nsresult rv = aArgs->GetNumEntries(&numArgs);
+ NS_ENSURE_SUCCESS(rv, rv);
+ MOZ_ASSERT(numArgs == 1);
+
+ nsDependentCString spec(getSharedUTF8String(aArgs, 0));
+
+ RefPtr<nsVariant> result = new nsVariant();
+
+ size_type index = indexOfHostAndPort(spec, NULL);
+ result->SetAsACString(Substring(spec, index, spec.Length() - index));
+ result.forget(_result);
+ return NS_OK;
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+//// Is frecency decaying function
+
+ /* static */
+ nsresult
+ IsFrecencyDecayingFunction::create(mozIStorageConnection *aDBConn)
+ {
+ RefPtr<IsFrecencyDecayingFunction> function =
+ new IsFrecencyDecayingFunction();
+ nsresult rv = aDBConn->CreateFunction(
+ NS_LITERAL_CSTRING("is_frecency_decaying"), 0, function
+ );
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+ }
+
+ NS_IMPL_ISUPPORTS(
+ IsFrecencyDecayingFunction,
+ mozIStorageFunction
+ )
+
+ NS_IMETHODIMP
+ IsFrecencyDecayingFunction::OnFunctionCall(mozIStorageValueArray *aArgs,
+ nsIVariant **_result)
+ {
+ MOZ_ASSERT(aArgs);
+
+ uint32_t numArgs;
+ nsresult rv = aArgs->GetNumEntries(&numArgs);
+ NS_ENSURE_SUCCESS(rv, rv);
+ MOZ_ASSERT(numArgs == 0);
+
+ const nsNavHistory *navHistory = nsNavHistory::GetConstHistoryService();
+ NS_ENSURE_STATE(navHistory);
+
+ RefPtr<nsVariant> result = new nsVariant();
+ rv = result->SetAsBool(navHistory->IsFrecencyDecaying());
+ NS_ENSURE_SUCCESS(rv, rv);
+ result.forget(_result);
+ return NS_OK;
+ }
+
} // namespace places
} // namespace mozilla
--- a/toolkit/components/places/SQLFunctions.h
+++ b/toolkit/components/places/SQLFunctions.h
@@ -440,12 +440,133 @@ public:
* The database connection to register with.
*/
static nsresult create(mozIStorageConnection *aDBConn);
private:
~GetQueryParamFunction() {}
};
+////////////////////////////////////////////////////////////////////////////////
+//// Get prefix function
+
+/**
+ * Gets the length of the prefix in a URL. "Prefix" is defined to be the
+ * scheme, colon, and, if present, two slashes.
+ *
+ * @param url
+ * A URL, or a string that may be a URL.
+ * @return
+ * If `url` is actually a URL and has a prefix, then this returns the
+ * prefix. Otherwise this returns an empty string.
+ */
+class GetPrefixFunction final : public mozIStorageFunction
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_MOZISTORAGEFUNCTION
+
+ /**
+ * Registers the function with the specified database connection.
+ *
+ * @param aDBConn
+ * The database connection to register with.
+ */
+ static nsresult create(mozIStorageConnection *aDBConn);
+private:
+ ~GetPrefixFunction() {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+//// Get host and port function
+
+/**
+ * Gets the host and port substring of a URL.
+ *
+ * @param url
+ * A URL, or a string that may be a URL.
+ * @return
+ * If `url` is actually a URL, or if it's a URL without the prefix, then
+ * this returns the host and port substring of the URL. Otherwise, this
+ * returns `url` itself.
+ */
+class GetHostAndPortFunction final : public mozIStorageFunction
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_MOZISTORAGEFUNCTION
+
+ /**
+ * Registers the function with the specified database connection.
+ *
+ * @param aDBConn
+ * The database connection to register with.
+ */
+ static nsresult create(mozIStorageConnection *aDBConn);
+private:
+ ~GetHostAndPortFunction() {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+//// Strip prefix function
+
+/**
+ * Gets the part of a URL after its prefix and userinfo; i.e., the substring
+ * starting at the host.
+ *
+ * @param url
+ * A URL, or a string that may be a URL.
+ * @return
+ * If `url` is actually a URL, or if it's a URL without the prefix, then
+ * this returns the substring starting at the host. Otherwise, this
+ * returns `url` itself.
+ */
+class StripPrefixAndUserinfoFunction final : public mozIStorageFunction
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_MOZISTORAGEFUNCTION
+
+ /**
+ * Registers the function with the specified database connection.
+ *
+ * @param aDBConn
+ * The database connection to register with.
+ */
+ static nsresult create(mozIStorageConnection *aDBConn);
+private:
+ ~StripPrefixAndUserinfoFunction() {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+//// Is frecency decaying function
+
+/**
+ * Returns nsNavHistory::IsFrecencyDecaying().
+ *
+ * @return
+ * True if frecency is currently decaying and false otherwise.
+ */
+class IsFrecencyDecayingFunction final : public mozIStorageFunction
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_MOZISTORAGEFUNCTION
+
+ /**
+ * Registers the function with the specified database connection.
+ *
+ * @param aDBConn
+ * The database connection to register with.
+ */
+ static nsresult create(mozIStorageConnection *aDBConn);
+private:
+ ~IsFrecencyDecayingFunction() {}
+};
+
+
} // namespace places
} // namespace mozilla
#endif // mozilla_places_SQLFunctions_h_
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -11,16 +11,17 @@
#include "nsNavHistory.h"
#include "mozIPlacesAutoComplete.h"
#include "nsNavBookmarks.h"
#include "nsAnnotationService.h"
#include "nsFaviconService.h"
#include "nsPlacesMacros.h"
+#include "nsPlacesTriggers.h"
#include "DateTimeFormat.h"
#include "History.h"
#include "Helpers.h"
#include "nsTArray.h"
#include "nsCollationCID.h"
#include "nsNetUtil.h"
#include "nsPrintfCString.h"
@@ -103,17 +104,16 @@ using namespace mozilla::places;
#define PREF_FREC_UNVISITED_BOOKMARK_BONUS_DEF 140
#define PREF_FREC_UNVISITED_TYPED_BONUS "places.frecency.unvisitedTypedBonus"
#define PREF_FREC_UNVISITED_TYPED_BONUS_DEF 200
#define PREF_FREC_RELOAD_VISIT_BONUS "places.frecency.reloadVisitBonus"
#define PREF_FREC_RELOAD_VISIT_BONUS_DEF 0
// This is a 'hidden' pref for the purposes of unit tests.
#define PREF_FREC_DECAY_RATE "places.frecency.decayRate"
-#define PREF_FREC_DECAY_RATE_DEF 0.975f
// In order to avoid calling PR_now() too often we use a cached "now" value
// for repeating stuff. These are milliseconds between "now" cache refreshes.
#define RENEW_CACHED_NOW_TIMEOUT ((int32_t)3 * PR_MSEC_PER_SEC)
// character-set annotation
#define CHARSET_ANNO NS_LITERAL_CSTRING("URIProperties/characterSet")
@@ -273,16 +273,17 @@ nsNavHistory::nsNavHistory()
, mBatchDBTransaction(nullptr)
, mCachedNow(0)
, mRecentTyped(RECENT_EVENTS_INITIAL_CACHE_LENGTH)
, mRecentLink(RECENT_EVENTS_INITIAL_CACHE_LENGTH)
, mRecentBookmark(RECENT_EVENTS_INITIAL_CACHE_LENGTH)
, mEmbedVisits(EMBED_VISITS_INITIAL_CACHE_LENGTH)
, mHistoryEnabled(true)
, mNumVisitsForFrecency(10)
+ , mDecayFrecencyPendingCount(0)
, mTagsFolder(-1)
, mDaysOfHistory(-1)
, mLastCachedStartOfDay(INT64_MAX)
, mLastCachedEndOfDay(0)
, mCanNotify(true)
#ifdef XP_WIN
, mCryptoProviderInitialized(false)
#endif
@@ -2460,47 +2461,41 @@ nsNavHistory::Observe(nsISupports *aSubj
else if (strcmp(aTopic, TOPIC_IDLE_DAILY) == 0) {
(void)DecayFrecency();
}
return NS_OK;
}
-namespace {
-
-class DecayFrecencyCallback : public AsyncStatementTelemetryTimer
+class PlacesDecayFrecencyCallback : public AsyncStatementTelemetryTimer
{
public:
- DecayFrecencyCallback()
+ PlacesDecayFrecencyCallback()
: AsyncStatementTelemetryTimer(Telemetry::PLACES_IDLE_FRECENCY_DECAY_TIME_MS)
{
}
NS_IMETHOD HandleCompletion(uint16_t aReason) override
{
(void)AsyncStatementTelemetryTimer::HandleCompletion(aReason);
- if (aReason == REASON_FINISHED) {
- nsNavHistory *navHistory = nsNavHistory::GetHistoryService();
- NS_ENSURE_STATE(navHistory);
- navHistory->NotifyManyFrecenciesChanged();
- }
+ nsNavHistory *navHistory = nsNavHistory::GetHistoryService();
+ NS_ENSURE_STATE(navHistory);
+ navHistory->DecayFrecencyCompleted(aReason);
return NS_OK;
}
};
-} // namespace
-
nsresult
nsNavHistory::DecayFrecency()
{
nsresult rv = FixInvalidFrecencies();
NS_ENSURE_SUCCESS(rv, rv);
- float decayRate = Preferences::GetFloat(PREF_FREC_DECAY_RATE, PREF_FREC_DECAY_RATE_DEF);
+ float decayRate = Preferences::GetFloat(PREF_FREC_DECAY_RATE, FRECENCY_DECAY_RATE);
// Globally decay places frecency rankings to estimate reduced frecency
// values of pages that haven't been visited for a while, i.e., they do
// not get an updated frecency. A scaling factor of .975 results in .5 the
// original value after 28 days.
// When changing the scaling factor, ensure that the barrier in
// moz_places_afterupdate_frecency_trigger still ignores these changes.
nsCOMPtr<mozIStorageAsyncStatement> decayFrecency = mDB->GetAsyncStatement(
@@ -2531,24 +2526,42 @@ nsNavHistory::DecayFrecency()
return NS_ERROR_UNEXPECTED;
}
mozIStorageBaseStatement *stmts[] = {
decayFrecency.get(),
decayAdaptive.get(),
deleteAdaptive.get()
};
nsCOMPtr<mozIStoragePendingStatement> ps;
- RefPtr<DecayFrecencyCallback> cb = new DecayFrecencyCallback();
+ RefPtr<PlacesDecayFrecencyCallback> cb = new PlacesDecayFrecencyCallback();
rv = conn->ExecuteAsync(stmts, ArrayLength(stmts), cb,
getter_AddRefs(ps));
NS_ENSURE_SUCCESS(rv, rv);
+ mDecayFrecencyPendingCount++;
+
return NS_OK;
}
+void
+nsNavHistory::DecayFrecencyCompleted(uint16_t reason)
+{
+ MOZ_ASSERT(mDecayFrecencyPendingCount > 0);
+ mDecayFrecencyPendingCount--;
+ if (mozIStorageStatementCallback::REASON_FINISHED == reason) {
+ NotifyManyFrecenciesChanged();
+ }
+}
+
+bool
+nsNavHistory::IsFrecencyDecaying() const
+{
+ return mDecayFrecencyPendingCount > 0;
+}
+
// Query stuff *****************************************************************
// Helper class for QueryToSelectClause
//
// This class helps to build part of the WHERE clause.
class ConditionBuilder
--- a/toolkit/components/places/nsNavHistory.h
+++ b/toolkit/components/places/nsNavHistory.h
@@ -60,30 +60,32 @@
// The preference we watch to know when the mobile bookmarks folder is filled by
// sync.
#define MOBILE_BOOKMARKS_PREF "browser.bookmarks.showMobileBookmarks"
// The guid of the mobile bookmarks virtual query.
#define MOBILE_BOOKMARKS_VIRTUAL_GUID "mobile____v"
-class nsNavHistory;
-class QueryKeyValuePair;
+class nsIAutoCompleteController;
class nsIEffectiveTLDService;
class nsIIDNService;
+class nsNavHistory;
+class PlacesDecayFrecencyCallback;
class PlacesSQLQueryBuilder;
-class nsIAutoCompleteController;
+class QueryKeyValuePair;
// nsNavHistory
class nsNavHistory final : public nsSupportsWeakReference
, public nsINavHistoryService
, public nsIObserver
, public mozIStorageVacuumParticipant
{
+ friend class PlacesDecayFrecencyCallback;
friend class PlacesSQLQueryBuilder;
public:
nsNavHistory();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSINAVHISTORYSERVICE
NS_DECL_NSIOBSERVER
@@ -457,16 +459,23 @@ public:
*/
void DispatchFrecencyChangedNotification(const nsACString& aSpec,
int32_t aNewFrecency,
const nsACString& aGUID,
bool aHidden,
PRTime aLastVisitDate) const;
/**
+ * Returns true if frecency is currently being decayed.
+ *
+ * @return True if frecency is being decayed, false if not.
+ */
+ bool IsFrecencyDecaying() const;
+
+ /**
* Store last insterted id for a table.
*/
static mozilla::Atomic<int64_t> sLastInsertedPlaceId;
static mozilla::Atomic<int64_t> sLastInsertedVisitId;
static void StoreLastInsertedId(const nsACString& aTable,
const int64_t aLastInsertedId);
@@ -614,16 +623,19 @@ protected:
int32_t mPermRedirectVisitBonus;
int32_t mTempRedirectVisitBonus;
int32_t mRedirectSourceVisitBonus;
int32_t mDefaultVisitBonus;
int32_t mUnvisitedBookmarkBonus;
int32_t mUnvisitedTypedBonus;
int32_t mReloadVisitBonus;
+ void DecayFrecencyCompleted(uint16_t reason);
+ uint32_t mDecayFrecencyPendingCount;
+
// in nsNavHistoryQuery.cpp
nsresult TokensToQuery(const nsTArray<QueryKeyValuePair>& aTokens,
nsNavHistoryQuery* aQuery,
nsNavHistoryQueryOptions* aOptions);
int64_t mTagsFolder;
int32_t mDaysOfHistory;
--- a/toolkit/components/places/nsPlacesTriggers.h
+++ b/toolkit/components/places/nsPlacesTriggers.h
@@ -116,30 +116,33 @@
"DELETE FROM moz_icons " \
"WHERE fixed_icon_url_hash = hash(fixup_url(OLD.host || '/favicon.ico')) " \
"AND fixup_url(icon_url) = fixup_url(OLD.host || '/favicon.ico') "\
"AND NOT EXISTS (SELECT 1 FROM moz_origins WHERE host = OLD.host " \
"OR host = fixup_url(OLD.host)); " \
"END" \
)
+#define FRECENCY_DECAY_RATE 0.975f
+#define FRECENCY_DECAY_RATE_STR "0.975"
+
// This trigger keeps frecencies in the moz_origins table in sync with
// frecencies in moz_places. However, we skip this when frecency changes are
// due to frecency decay since (1) decay updates all frecencies at once, so this
// trigger would run for each moz_place, which would be expensive; and (2) decay
// does not change the ordering of frecencies since all frecencies decay by the
// same percentage.
#define CREATE_PLACES_AFTERUPDATE_FRECENCY_TRIGGER NS_LITERAL_CSTRING( \
"CREATE TEMP TRIGGER moz_places_afterupdate_frecency_trigger " \
"AFTER UPDATE OF frecency ON moz_places FOR EACH ROW " \
"WHEN NEW.frecency >= 0 AND NOT ( " \
"OLD.frecency > 0 " \
"AND is_frecency_decaying() " \
"AND NEW.frecency < OLD.frecency " \
- "AND (OLD.frecency - NEW.frecency) / OLD.frecency <= 0.975 " \
+ "AND (OLD.frecency - NEW.frecency) / OLD.frecency <= " FRECENCY_DECAY_RATE_STR \
") " \
"BEGIN " \
"UPDATE moz_origins " \
"SET frecency = ( " \
"SELECT IFNULL(MAX(frecency), 0) " \
"FROM moz_places " \
"WHERE moz_places.origin_id = moz_origins.id " \
") " \
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -1071,20 +1071,16 @@ function EngineURL(aType, aMethod, aTemp
break;
default:
FAIL("new EngineURL: template uses invalid scheme!", Cr.NS_ERROR_FAILURE);
}
// If no resultDomain was specified in the engine definition file, use the
// host from the template.
this.resultDomain = aResultDomain || templateURI.host;
- // We never want to return a "www." prefix, so eventually strip it.
- if (this.resultDomain.startsWith("www.")) {
- this.resultDomain = this.resultDomain.substr(4);
- }
}
EngineURL.prototype = {
addParam: function SRCH_EURL_addParam(aName, aValue, aPurpose) {
this.params.push(new QueryParameter(aName, aValue, aPurpose));
},
// Note: This method requires that aObj has a unique name or the previous MozParams entry with