Commit 87303639 authored by manukh's avatar manukh Committed by Commit Bot

[omnibox] Expire search session token on cookie or cache deletion.

Moves session token management from the SearchProvider to
TemplateURLService.

Bug: 10664653
Change-Id: I48be94dbed74b7a3ca4e8c45a0d81687c2a2dea0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2519837Reviewed-by: default avatarChristian Dullweber <dullweber@chromium.org>
Reviewed-by: default avatarJustin Donnelly <jdonnelly@chromium.org>
Commit-Queue: manuk hovanesian <manukh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825363}
parent 9d2e4b70
......@@ -3670,7 +3670,8 @@ TEST_F(SearchProviderTest, SuggestQueryUsesToken) {
// And the URL matches what we expected.
TemplateURLRef::SearchTermsArgs search_terms_args(term);
search_terms_args.session_token = provider_->current_token_;
search_terms_args.session_token =
provider_->client()->GetTemplateURLService()->GetSessionToken();
std::string expected_url(
default_t_url_->suggestions_url_ref().ReplaceSearchTerms(
search_terms_args, turl_model->search_terms_data()));
......@@ -3683,36 +3684,6 @@ TEST_F(SearchProviderTest, SuggestQueryUsesToken) {
RunTillProviderDone();
}
TEST_F(SearchProviderTest, SessionToken) {
// Subsequent calls always get the same token.
std::string token = provider_->GetSessionToken();
std::string token2 = provider_->GetSessionToken();
EXPECT_EQ(token, token2);
EXPECT_FALSE(token.empty());
// Calls do not regenerate a token.
provider_->current_token_ = "PRE-EXISTING TOKEN";
token = provider_->GetSessionToken();
EXPECT_EQ(token, "PRE-EXISTING TOKEN");
// ... unless the token has expired.
provider_->current_token_.clear();
const base::TimeDelta kSmallDelta = base::TimeDelta::FromMilliseconds(1);
provider_->token_expiration_time_ = base::TimeTicks::Now() - kSmallDelta;
token = provider_->GetSessionToken();
EXPECT_FALSE(token.empty());
EXPECT_EQ(token, provider_->current_token_);
// The expiration time is always updated.
provider_->GetSessionToken();
base::TimeTicks expiration_time_1 = provider_->token_expiration_time_;
base::PlatformThread::Sleep(kSmallDelta);
provider_->GetSessionToken();
base::TimeTicks expiration_time_2 = provider_->token_expiration_time_;
EXPECT_GT(expiration_time_2, expiration_time_1);
EXPECT_GE(expiration_time_2, expiration_time_1 + kSmallDelta);
}
TEST_F(SearchProviderTest, AnswersCache) {
AutocompleteResult result;
ACMatches matches;
......
......@@ -1104,13 +1104,13 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData(
}
//////////////////////////////////////////////////////////////////////////////
// Zero suggest and Search prefetch.
// Zero suggest, Search prefetch, and search session token.
// Remove omnibox zero-suggest cache results and Search Prefetch cached
// results, we only delete when the default search engine is in the filter.
// results only when their respective URLs are in the filter.
if ((remove_mask & (content::BrowsingDataRemover::DATA_TYPE_CACHE |
content::BrowsingDataRemover::DATA_TYPE_COOKIES))) {
// If there is no template service or DSE, clear the caches.
bool should_clear_zero_suggest = true;
bool should_clear_zero_suggest_and_session_token = true;
bool should_clear_search_prefetch = true;
auto* template_url_service =
......@@ -1122,7 +1122,7 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData(
// The suggest URL is used for zero suggest.
GURL suggest_url(
template_url_service->GetDefaultSearchProvider()->suggestions_url());
should_clear_zero_suggest =
should_clear_zero_suggest_and_session_token =
nullable_filter.is_null() || nullable_filter.Run(suggest_url);
// The search URL is used for search prefetch.
......@@ -1131,7 +1131,7 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData(
nullable_filter.is_null() || nullable_filter.Run(search_url);
}
if (should_clear_zero_suggest)
if (should_clear_zero_suggest_and_session_token)
prefs->SetString(omnibox::kZeroSuggestCachedResults, std::string());
// |search_prefetch_service| is null if |profile_| is off the record.
......@@ -1139,6 +1139,9 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData(
SearchPrefetchServiceFactory::GetForProfile(profile_);
if (should_clear_search_prefetch && search_prefetch_service)
search_prefetch_service->ClearPrefetches();
if (should_clear_zero_suggest_and_session_token && template_url_service)
template_url_service->ClearSessionToken();
}
//////////////////////////////////////////////////////////////////////////////
......
......@@ -900,7 +900,8 @@ std::unique_ptr<network::SimpleURLLoader> SearchProvider::CreateSuggestLoader(
search_term_args.cursor_position = input.cursor_position();
search_term_args.page_classification = input.current_page_classification();
// Session token and prefetch data required for answers.
search_term_args.session_token = GetSessionToken();
search_term_args.session_token =
client()->GetTemplateURLService()->GetSessionToken();
if (!prefetch_data_.full_query_text.empty()) {
search_term_args.prefetch_query =
base::UTF16ToUTF8(prefetch_data_.full_query_text);
......@@ -931,14 +932,13 @@ std::unique_ptr<network::SimpleURLLoader> SearchProvider::CreateSuggestLoader(
return nullptr;
// Send the current page URL if user setting and URL requirements are met.
TemplateURLService* template_url_service = client()->GetTemplateURLService();
if (CanSendURL(input.current_url(), suggest_url, template_url,
input.current_page_classification(),
template_url_service->search_terms_data(), client(), true)) {
input.current_page_classification(), search_terms_data,
client(), true)) {
search_term_args.current_page_url = input.current_url().spec();
// Create the suggest URL again with the current page URL.
suggest_url = GURL(template_url->suggestions_url_ref().ReplaceSearchTerms(
search_term_args, template_url_service->search_terms_data()));
search_term_args, search_terms_data));
}
LogOmniboxSuggestRequest(REQUEST_SENT);
......@@ -1556,26 +1556,6 @@ void SearchProvider::UpdateDone() {
done_ = !timer_.IsRunning() && !default_loader_ && !keyword_loader_;
}
std::string SearchProvider::GetSessionToken() {
base::TimeTicks current_time(base::TimeTicks::Now());
// Renew token if it expired.
if (current_time > token_expiration_time_) {
const size_t kTokenBytes = 12;
std::string raw_data;
base::RandBytes(base::WriteInto(&raw_data, kTokenBytes + 1), kTokenBytes);
base::Base64Encode(raw_data, &current_token_);
// Make the base64 encoded value URL and filename safe(see RFC 3548).
std::replace(current_token_.begin(), current_token_.end(), '+', '-');
std::replace(current_token_.begin(), current_token_.end(), '/', '_');
}
// Extend expiration time another 60 seconds.
token_expiration_time_ = current_time + base::TimeDelta::FromSeconds(60);
return current_token_;
}
AnswersQueryData SearchProvider::FindAnswersPrefetchData() {
// Retrieve the top entry from scored history results.
MatchMap map;
......
......@@ -99,7 +99,6 @@ class SearchProvider : public BaseSearchProvider,
FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SuggestRelevanceExperiment);
FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, TestDeleteMatch);
FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SuggestQueryUsesToken);
FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SessionToken);
FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, AnswersCache);
FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, RemoveExtraAnswers);
FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, DoesNotProvideOnFocus);
......@@ -374,9 +373,6 @@ class SearchProvider : public BaseSearchProvider,
// Updates the value of |done_| from the internal state.
void UpdateDone();
// Obtains a session token, regenerating if necessary.
std::string GetSessionToken();
// Answers prefetch handling - finds the previously displayed answer matching
// the current top-scoring history result. If there is a previous answer,
// returns the query data associated with it. Otherwise, returns an empty
......@@ -428,10 +424,6 @@ class SearchProvider : public BaseSearchProvider,
// The top navigation suggestion, left blank/invalid if none.
GURL top_navigation_suggestion_;
// Session token management.
std::string current_token_;
base::TimeTicks token_expiration_time_;
// Answers prefetch management.
AnswersCache answers_cache_; // Cache for last answers seen.
AnswersQueryData prefetch_data_; // Data to use for query prefetching.
......
......@@ -152,6 +152,7 @@ source_set("unit_tests") {
"search_host_to_urls_map_unittest.cc",
"template_url_data_unittest.cc",
"template_url_prepopulate_data_unittest.cc",
"template_url_service_unittest.cc",
"template_url_service_util_unittest.cc",
"template_url_unittest.cc",
]
......
......@@ -7,11 +7,14 @@
#include <algorithm>
#include "base/auto_reset.h"
#include "base/base64.h"
#include "base/base64url.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/debug/crash_logging.h"
#include "base/format_macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
......@@ -1260,6 +1263,27 @@ void TemplateURLService::ProcessTemplateURLChange(
sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
}
std::string TemplateURLService::GetSessionToken() {
base::TimeTicks current_time(base::TimeTicks::Now());
// Renew token if it expired.
if (current_time > token_expiration_time_) {
const size_t kTokenBytes = 12;
std::string raw_data;
base::RandBytes(base::WriteInto(&raw_data, kTokenBytes + 1), kTokenBytes);
base::Base64UrlEncode(raw_data,
base::Base64UrlEncodePolicy::INCLUDE_PADDING,
&current_token_);
}
// Extend expiration time another 60 seconds.
token_expiration_time_ = current_time + base::TimeDelta::FromSeconds(60);
return current_token_;
}
void TemplateURLService::ClearSessionToken() {
token_expiration_time_ = base::TimeTicks();
}
// static
syncer::SyncData TemplateURLService::CreateSyncDataFromTemplateURL(
const TemplateURL& turl) {
......
......@@ -400,6 +400,13 @@ class TemplateURLService : public WebDataServiceConsumer,
return *search_terms_data_;
}
// Obtains a session token, regenerating if necessary.
std::string GetSessionToken();
// Clears the session token. Should be called when the user clears browsing
// data.
void ClearSessionToken();
// Returns a SyncData with a sync representation of the search engine data
// from |turl|.
static syncer::SyncData CreateSyncDataFromTemplateURL(
......@@ -455,6 +462,7 @@ class TemplateURLService : public WebDataServiceConsumer,
FRIEND_TEST_ALL_PREFIXES(TemplateURLServiceSyncTest, PreSyncDeletes);
FRIEND_TEST_ALL_PREFIXES(TemplateURLServiceSyncTest, MergeInSyncTemplateURL);
FRIEND_TEST_ALL_PREFIXES(LocationBarModelTest, GoogleBaseURL);
FRIEND_TEST_ALL_PREFIXES(TemplateURLServiceUnitTest, SessionToken);
friend class InstantUnitTestBase;
friend class Scoper;
......@@ -847,6 +855,10 @@ class TemplateURLService : public WebDataServiceConsumer,
// but if no model mutation occurs, the deferred notification can be skipped.
bool model_mutated_notification_pending_ = false;
// Session token management.
std::string current_token_;
base::TimeTicks token_expiration_time_;
#if defined(OS_ANDROID)
// Manage and fetch the java object that wraps this TemplateURLService on
// android.
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <memory>
#include "components/search_engines/template_url_service.h"
#include "testing/gtest/include/gtest/gtest.h"
class TemplateURLServiceUnitTest : public testing::Test {
public:
TemplateURLServiceUnitTest()
: template_url_service_(/*initializers=*/nullptr, /*count=*/0) {}
TemplateURLService& template_url_service() { return template_url_service_; }
private:
TemplateURLService template_url_service_;
};
TEST_F(TemplateURLServiceUnitTest, SessionToken) {
// Subsequent calls always get the same token.
std::string token = template_url_service().GetSessionToken();
std::string token2 = template_url_service().GetSessionToken();
EXPECT_EQ(token, token2);
EXPECT_FALSE(token.empty());
// Calls do not regenerate a token.
template_url_service().current_token_ = "PRE-EXISTING TOKEN";
token = template_url_service().GetSessionToken();
EXPECT_EQ(token, "PRE-EXISTING TOKEN");
// ... unless the token has expired.
template_url_service().current_token_.clear();
const base::TimeDelta kSmallDelta = base::TimeDelta::FromMilliseconds(1);
template_url_service().token_expiration_time_ =
base::TimeTicks::Now() - kSmallDelta;
token = template_url_service().GetSessionToken();
EXPECT_FALSE(token.empty());
EXPECT_EQ(token, template_url_service().current_token_);
// ... or cleared.
template_url_service().current_token_.clear();
template_url_service().ClearSessionToken();
token = template_url_service().GetSessionToken();
EXPECT_FALSE(token.empty());
EXPECT_EQ(token, template_url_service().current_token_);
// The expiration time is always updated.
template_url_service().GetSessionToken();
base::TimeTicks expiration_time_1 =
template_url_service().token_expiration_time_;
base::PlatformThread::Sleep(kSmallDelta);
template_url_service().GetSessionToken();
base::TimeTicks expiration_time_2 =
template_url_service().token_expiration_time_;
EXPECT_GT(expiration_time_2, expiration_time_1);
EXPECT_GE(expiration_time_2, expiration_time_1 + kSmallDelta);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment