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