Commit 5e4ec248 authored by Patrick Noland's avatar Patrick Noland Committed by Commit Bot

[Chromeshine] Hook up in-memory components to persistence

This CL makes a large number changes to account for the
fact that UsageStatsService operations are now async. The major upshot
is that promises are used instead of actual values. If data has been loaded,
then promises are fulfilled immediately. Otherwise, they're fulfilled once
the database is loaded. There is a corresponding downstream change that
adjusts UsageStatsBrowserService to account for this.

There are also a couple bug fixes; usage stats database needs to split its
databases into different folders, so that is fixed.

Bug: 939456
Change-Id: I0869318b5733ea6cb496af31224c6e9c93030fb5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1509103
Commit-Queue: Patrick Noland <pnoland@chromium.org>
Reviewed-by: default avatarFilip Gorski <fgorski@chromium.org>
Cr-Commit-Position: refs/heads/master@{#641699}
parent 35d5999d
......@@ -14,8 +14,8 @@ import java.util.List;
public class EventTracker {
private final List<WebsiteEvent> mWebsiteList;
public EventTracker() {
mWebsiteList = new ArrayList<>();
public EventTracker(List<WebsiteEvent> websiteList) {
mWebsiteList = websiteList;
}
/** Query all events in the half-open range [start, end) */
......@@ -31,10 +31,8 @@ public class EventTracker {
* last event in the list is illegal.
*/
public void addWebsiteEvent(WebsiteEvent event) {
if (mWebsiteList.size() > 0) {
assert event.getTimestamp() >= mWebsiteList.get(mWebsiteList.size() - 1).getTimestamp();
}
assert mWebsiteList.size() == 0
|| event.getTimestamp() >= mWebsiteList.get(mWebsiteList.size() - 1).getTimestamp();
mWebsiteList.add(event);
}
......
......@@ -12,6 +12,7 @@ import android.net.Uri;
import android.webkit.URLUtil;
import org.chromium.base.Log;
import org.chromium.base.Promise;
import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.Tab.TabHidingType;
......@@ -35,21 +36,16 @@ public class PageViewObserver {
private final TabModelSelectorTabModelObserver mTabModelObserver;
private final TabModelSelector mTabModelSelector;
private final TabObserver mTabObserver;
private final EventTracker mEventTracker;
private final TokenTracker mTokenTracker;
private final SuspensionTracker mSuspensionTracker;
private final UsageStatsService mUsageStatsService;
private Tab mCurrentTab;
private String mLastFqdn;
public PageViewObserver(Activity activity, TabModelSelector tabModelSelector,
EventTracker eventTracker, TokenTracker tokenTracker,
SuspensionTracker suspensionTracker) {
UsageStatsService usageStatsService) {
mActivity = activity;
mTabModelSelector = tabModelSelector;
mEventTracker = eventTracker;
mTokenTracker = tokenTracker;
mSuspensionTracker = suspensionTracker;
mUsageStatsService = usageStatsService;
mTabObserver = new EmptyTabObserver() {
@Override
public void onShown(Tab tab, @TabSelectionType int type) {
......@@ -109,15 +105,22 @@ public class PageViewObserver {
String newFqdn = newUrl == null ? "" : Uri.parse(newUrl).getHost();
boolean didSuspend = false;
if (newFqdn != null && mSuspensionTracker.isWebsiteSuspended(newFqdn)) {
SuspendedTab.create(mCurrentTab).show();
didSuspend = true;
if (newFqdn != null) {
Promise<Boolean> isSuspendedPromise =
mUsageStatsService.isWebsiteSuspendedAsync(newFqdn);
// If the promise isn't immediately fulfilled, we won't wait for it; we'll just act as
// if the site isn't suspended. If it is actually suspended, the next navigation will be
// blocked.
if (isSuspendedPromise.isFulfilled() && isSuspendedPromise.getResult()) {
SuspendedTab.create(mCurrentTab).show();
didSuspend = true;
}
}
if (mLastFqdn != null && mLastFqdn.equals(newFqdn)) return;
if (mLastFqdn != null) {
mEventTracker.addWebsiteEvent(new WebsiteEvent(
mUsageStatsService.addWebsiteEventAsync(new WebsiteEvent(
System.currentTimeMillis(), mLastFqdn, WebsiteEvent.EventType.STOP));
reportToPlatformIfDomainIsTracked("reportUsageStop", mLastFqdn);
mLastFqdn = null;
......@@ -126,7 +129,7 @@ public class PageViewObserver {
if (!URLUtil.isHttpUrl(newUrl) && !URLUtil.isHttpsUrl(newUrl) || didSuspend) return;
mLastFqdn = newFqdn;
mEventTracker.addWebsiteEvent(new WebsiteEvent(
mUsageStatsService.addWebsiteEventAsync(new WebsiteEvent(
System.currentTimeMillis(), mLastFqdn, WebsiteEvent.EventType.START));
reportToPlatformIfDomainIsTracked("reportUsageStart", mLastFqdn);
}
......@@ -148,7 +151,7 @@ public class PageViewObserver {
}
private void reportToPlatformIfDomainIsTracked(String reportMethodName, String fqdn) {
String token = mTokenTracker.getTokenForFqdn(fqdn);
String token = mUsageStatsService.getTokenForFqdn(fqdn);
if (token == null) return;
try {
......
......@@ -15,8 +15,8 @@ import java.util.Set;
public class SuspensionTracker {
private Set<String> mSuspendedWebsites;
public SuspensionTracker() {
mSuspendedWebsites = new HashSet<String>();
public SuspensionTracker(List<String> suspendedSites) {
mSuspendedWebsites = new HashSet<String>(suspendedSites);
}
public void setWebsitesSuspended(List<String> fqdns, boolean suspended) {
......@@ -28,7 +28,7 @@ public class SuspensionTracker {
}
public List<String> getAllSuspendedWebsites() {
List<String> result = new ArrayList<>();
List<String> result = new ArrayList<>(mSuspendedWebsites.size());
result.addAll(mSuspendedWebsites);
return result;
}
......
......@@ -17,10 +17,17 @@ public class TokenTracker {
private Map<String, String> mTokenToFqdnMap;
private TokenGenerator mTokenGenerator;
public TokenTracker() {
public TokenTracker(Map<String, String> tokenToFqdnMap) {
mTokenToFqdnMap = new HashMap<>();
mFqdnToTokenMap = new HashMap<>();
mTokenGenerator = new TokenGenerator();
long maxTokenValue = 0;
for (Map.Entry<String, String> entry : tokenToFqdnMap.entrySet()) {
putMapping(entry.getKey(), entry.getValue());
long currentValue = Long.valueOf(entry.getKey());
maxTokenValue = maxTokenValue < currentValue ? currentValue : maxTokenValue;
}
mTokenGenerator = new TokenGenerator(maxTokenValue + 1);
}
/**
......@@ -57,6 +64,11 @@ public class TokenTracker {
return result;
}
/** Get a map of all tracked domains, keyed by token. */
public Map<String, String> getAllTokenMappings() {
return mTokenToFqdnMap;
}
private String getFqdnForToken(String token) {
return mTokenToFqdnMap.get(token);
}
......
......@@ -13,6 +13,7 @@ import org.robolectric.annotation.Config;
import org.chromium.base.test.BaseRobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
/**
......@@ -25,7 +26,7 @@ public class EventTrackerTest {
@Before
public void setUp() {
mEventTracker = new EventTracker();
mEventTracker = new EventTracker(new ArrayList<>());
}
@Test
......
......@@ -22,6 +22,9 @@ using leveldb_proto::ProtoDatabaseProvider;
using leveldb_proto::ProtoDatabaseProviderFactory;
const char kNamespace[] = "UsageStats";
const char kEventsDbName[] = "Events";
const char kSuspensionsDbName[] = "Suspensions";
const char kTokensDbName[] = "Tokens";
const char kKeySeparator[] = "_";
......@@ -45,16 +48,16 @@ UsageStatsDatabase::UsageStatsDatabase(Profile* profile)
{base::MayBlock(), base::TaskPriority::BEST_EFFORT});
website_event_db_ = db_provider->GetDB<WebsiteEvent>(
leveldb_proto::ProtoDbType::USAGE_STATS_WEBSITE_EVENT, usage_stats_dir,
db_task_runner);
leveldb_proto::ProtoDbType::USAGE_STATS_WEBSITE_EVENT,
usage_stats_dir.Append(kEventsDbName), db_task_runner);
suspension_db_ = db_provider->GetDB<Suspension>(
leveldb_proto::ProtoDbType::USAGE_STATS_SUSPENSION, usage_stats_dir,
db_task_runner);
leveldb_proto::ProtoDbType::USAGE_STATS_SUSPENSION,
usage_stats_dir.Append(kSuspensionsDbName), db_task_runner);
token_mapping_db_ = db_provider->GetDB<TokenMapping>(
leveldb_proto::ProtoDbType::USAGE_STATS_TOKEN_MAPPING, usage_stats_dir,
db_task_runner);
leveldb_proto::ProtoDbType::USAGE_STATS_TOKEN_MAPPING,
usage_stats_dir.Append(kTokensDbName), db_task_runner);
InitializeDBs();
}
......@@ -110,16 +113,15 @@ std::string CreateWebsiteEventKey(int64_t seconds, const std::string& fqdn) {
void UsageStatsDatabase::InitializeDBs() {
// Asynchronously initialize databases.
website_event_db_->Init(
kNamespace, base::BindOnce(&UsageStatsDatabase::OnWebsiteEventInitDone,
weak_ptr_factory_.GetWeakPtr(), true));
base::BindOnce(&UsageStatsDatabase::OnWebsiteEventInitDone,
weak_ptr_factory_.GetWeakPtr(), true));
suspension_db_->Init(kNamespace,
base::BindOnce(&UsageStatsDatabase::OnSuspensionInitDone,
suspension_db_->Init(base::BindOnce(&UsageStatsDatabase::OnSuspensionInitDone,
weak_ptr_factory_.GetWeakPtr(), true));
token_mapping_db_->Init(
kNamespace, base::BindOnce(&UsageStatsDatabase::OnTokenMappingInitDone,
weak_ptr_factory_.GetWeakPtr(), true));
base::BindOnce(&UsageStatsDatabase::OnTokenMappingInitDone,
weak_ptr_factory_.GetWeakPtr(), true));
}
void UsageStatsDatabase::GetAllEvents(EventsCallback callback) {
......@@ -355,7 +357,6 @@ void UsageStatsDatabase::OnWebsiteEventInitDone(
if (retry) {
// Retry unsuccessful initialization.
website_event_db_->Init(
kNamespace,
base::BindOnce(&UsageStatsDatabase::OnWebsiteEventInitDone,
weak_ptr_factory_.GetWeakPtr(), false));
}
......@@ -378,8 +379,8 @@ void UsageStatsDatabase::OnSuspensionInitDone(
if (retry) {
// Retry unsuccessful initialization.
suspension_db_->Init(
kNamespace, base::BindOnce(&UsageStatsDatabase::OnSuspensionInitDone,
weak_ptr_factory_.GetWeakPtr(), false));
base::BindOnce(&UsageStatsDatabase::OnSuspensionInitDone,
weak_ptr_factory_.GetWeakPtr(), false));
}
return;
}
......@@ -401,7 +402,6 @@ void UsageStatsDatabase::OnTokenMappingInitDone(
if (retry) {
// Retry unsuccessful initialization.
token_mapping_db_->Init(
kNamespace,
base::BindOnce(&UsageStatsDatabase::OnTokenMappingInitDone,
weak_ptr_factory_.GetWeakPtr(), false));
}
......
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