Commit 796988c4 authored by tbansal's avatar tbansal Committed by Commit bot

Add external data use observer that will listen to data use

observations and pass them to Java over JNI.

ExternalDataUseObserver is created and owned by IOThread.
ExternalDataUseObserver listens to data use observations,
matches them with the regexes and passes them over to a
Java object over JNI. The Java object is of type
ExternalDataUseObserverAndroid.

For design doc, please see the bug.

This CL only has upstream implementation of
ExternalDataUseObserverAndroid.java which really does not
do much. Downstream implementation of
ExternalDataUseObserverAndroid.java will come in a separate
downstream CL. That would do the heavylifting of talking
with external entities as per the design doc.

BUG=540061

Review URL: https://codereview.chromium.org/1393073002

Cr-Commit-Position: refs/heads/master@{#353950}
parent f52ceea6
......@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.accessibility.FontSizePrefs;
import org.chromium.chrome.browser.banners.AppBannerManager;
import org.chromium.chrome.browser.banners.AppDetailsDelegate;
import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
import org.chromium.chrome.browser.datausage.ExternalDataUseObserver;
import org.chromium.chrome.browser.document.DocumentActivity;
import org.chromium.chrome.browser.document.IncognitoDocumentActivity;
import org.chromium.chrome.browser.download.DownloadManagerService;
......@@ -609,6 +610,14 @@ public class ChromeApplication extends ContentApplication {
return new ExternalEstimateProviderAndroid();
}
/**
* @return An external observer of data use.
* @param nativePtr Pointer to the native ExternalDataUseObserver object.
*/
public ExternalDataUseObserver createExternalDataUseObserver(long nativePtr) {
return new ExternalDataUseObserver(nativePtr);
}
/**
* @return The user agent string of Chrome.
*/
......
// Copyright 2015 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.
package org.chromium.chrome.browser.datausage;
import android.content.Context;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.chrome.browser.ChromeApplication;
/**
* This class provides a base class implementation of a data use observer that is external to
* Chromium. This class should be accessed only on IO thread.
*/
@JNINamespace("chrome::android")
public class ExternalDataUseObserver {
/**
* Pointer to the native ExternalDataUseObserver object.
*/
private long mNativeExternalDataUseObserver;
@CalledByNative
private static ExternalDataUseObserver create(Context context, long nativePtr) {
return ((ChromeApplication) context).createExternalDataUseObserver(nativePtr);
}
/**
* Notification that the native object has been destroyed.
*/
@CalledByNative
private void onDestroy() {
mNativeExternalDataUseObserver = 0;
}
@CalledByNative
private void onDataUse(String tag, long bytesDownloaded, long bytesUploaded) {}
/**
* Creates an instance of {@link #ExternalDataUseObserver}.
*/
public ExternalDataUseObserver(long nativePtr) {
mNativeExternalDataUseObserver = nativePtr;
assert mNativeExternalDataUseObserver != 0;
}
}
bengr@chromium.org
sclittle@chromium.org
\ No newline at end of file
......@@ -30,6 +30,7 @@
#include "chrome/browser/android/contextualsearch/contextual_search_manager.h"
#include "chrome/browser/android/contextualsearch/contextual_search_tab_helper.h"
#include "chrome/browser/android/cookies/cookies_fetcher.h"
#include "chrome/browser/android/datausage/external_data_use_observer.h"
#include "chrome/browser/android/dev_tools_server.h"
#include "chrome/browser/android/document/document_web_contents_delegate.h"
#include "chrome/browser/android/dom_distiller/external_feedback_reporter_android.h"
......@@ -240,6 +241,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = {
{"DownloadOverwriteInfoBarDelegate",
RegisterDownloadOverwriteInfoBarDelegate},
{"EditBookmarkHelper", RegisterEditBookmarkHelper},
{"ExternalDataUseObserver", RegisterExternalDataUseObserver},
{"ExternalPrerenderRequestHandler",
prerender::ExternalPrerenderHandlerAndroid::
RegisterExternalPrerenderHandlerAndroid},
......@@ -324,8 +326,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = {
{"TabModelJniBridge", TabModelJniBridge::Register},
{"TabState", RegisterTabState},
{"TabStripSceneLayer", RegisterTabStripSceneLayer},
{"TabWebContentsDelegateAndroid",
RegisterTabWebContentsDelegateAndroid},
{"TabWebContentsDelegateAndroid", RegisterTabWebContentsDelegateAndroid},
{"TemplateUrlServiceAndroid", TemplateUrlServiceAndroid::Register},
{"ThumbnailTabHelperAndroid", RegisterThumbnailTabHelperAndroid},
{"ToolbarModelAndroid", ToolbarModelAndroid::RegisterToolbarModelAndroid},
......
bengr@chromium.org
sclittle@chromium.org
\ No newline at end of file
// Copyright 2015 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 "chrome/browser/android/datausage/external_data_use_observer.h"
#include "base/android/jni_string.h"
#include "jni/ExternalDataUseObserver_jni.h"
#include "third_party/re2/re2/re2.h"
#include "url/gurl.h"
using base::android::ConvertUTF8ToJavaString;
namespace chrome {
namespace android {
ExternalDataUseObserver::ExternalDataUseObserver(
data_usage::DataUseAggregator* data_use_aggregator)
: data_use_aggregator_(data_use_aggregator) {
DCHECK(data_use_aggregator_);
JNIEnv* env = base::android::AttachCurrentThread();
j_external_data_use_observer_.Reset(Java_ExternalDataUseObserver_create(
env, base::android::GetApplicationContext(),
reinterpret_cast<intptr_t>(this)));
DCHECK(!j_external_data_use_observer_.is_null());
}
ExternalDataUseObserver::~ExternalDataUseObserver() {
DCHECK(thread_checker_.CalledOnValidThread());
JNIEnv* env = base::android::AttachCurrentThread();
Java_ExternalDataUseObserver_onDestroy(env,
j_external_data_use_observer_.obj());
if (url_patterns_.size() > 0)
data_use_aggregator_->RemoveObserver(this);
}
bool ExternalDataUseObserver::Matches(const GURL& gurl) const {
if (!gurl.is_valid() || gurl.is_empty())
return false;
for (const re2::RE2* pattern : url_patterns_) {
if (re2::RE2::FullMatch(gurl.spec(), *pattern))
return true;
}
return false;
}
void ExternalDataUseObserver::OnDataUse(
const std::vector<data_usage::DataUse>& data_use_sequence) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!j_external_data_use_observer_.is_null());
JNIEnv* env = base::android::AttachCurrentThread();
for (const auto& data_use : data_use_sequence) {
if (!Matches(data_use.url))
continue;
// TODO(tbansal): Use buffering to avoid frequent JNI calls.
std::string tag = ""; // data_use.tab_id;
int64_t bytes_downloaded = data_use.rx_bytes;
int64_t bytes_uploaded = data_use.tx_bytes;
Java_ExternalDataUseObserver_onDataUse(
env, j_external_data_use_observer_.obj(),
ConvertUTF8ToJavaString(env, tag).obj(), bytes_downloaded,
bytes_uploaded);
}
}
void ExternalDataUseObserver::RegisterURLRegexes(
const std::vector<std::string>& url_regexes) {
DCHECK(thread_checker_.CalledOnValidThread());
bool registered_as_observer = url_patterns_.size() > 0;
if (!registered_as_observer && url_regexes.size() > 0) {
registered_as_observer = true;
data_use_aggregator_->AddObserver(this);
}
url_patterns_.clear();
re2::RE2::Options options(re2::RE2::DefaultOptions);
options.set_case_sensitive(false);
for (const std::string& url_regex : url_regexes) {
if (url_regex.empty())
continue;
scoped_ptr<re2::RE2> pattern(new re2::RE2(url_regex, options));
if (!pattern->ok())
continue;
url_patterns_.push_back(pattern.Pass());
}
// Unregister as an observer if no regular expressions were received.
if (url_patterns_.size() == 0 && registered_as_observer)
data_use_aggregator_->RemoveObserver(this);
}
bool RegisterExternalDataUseObserver(JNIEnv* env) {
return RegisterNativesImpl(env);
}
} // namespace android
} // namespace chrome
// Copyright 2015 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.
#ifndef CHROME_BROWSER_ANDROID_DATAUSAGE_EXTERNAL_DATA_USE_OBSERVER_H_
#define CHROME_BROWSER_ANDROID_DATAUSAGE_EXTERNAL_DATA_USE_OBSERVER_H_
#include <jni.h>
#include <string>
#include <vector>
#include "base/android/scoped_java_ref.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "base/threading/thread_checker.h"
#include "components/data_usage/core/data_use.h"
#include "components/data_usage/core/data_use_aggregator.h"
namespace re2 {
class RE2;
}
namespace chrome {
namespace android {
// This class allows platform APIs that are external to Chromium to observe how
// much data is used by Chromium on the current Android device. It creates and
// owns a Java listener object that is notified of the data usage observations
// of Chromium. This class receives regular expressions from the Java listener
// object. It also registers as a data use observer with DataUseAggregator,
// filters the received observations by applying the regex matching to the URLs
// of the requests, and notifies the filtered data use to the Java listener. The
// Java object in turn may notify the platform APIs of the data usage
// observations.
class ExternalDataUseObserver : public data_usage::DataUseAggregator::Observer {
public:
explicit ExternalDataUseObserver(
data_usage::DataUseAggregator* data_use_aggregator);
~ExternalDataUseObserver() override;
private:
FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, SingleRegex);
FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, TwoRegex);
FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, MultipleRegex);
FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, ChangeRegex);
// data_usage::DataUseAggregator::Observer implementation:
void OnDataUse(
const std::vector<data_usage::DataUse>& data_use_sequence) override;
// Called by |j_external_data_use_observer_| to register multiple
// case-insensitive regular expressions. If the url of the data use request
// matches any of the regular expression, the observation is passed to the
// Java listener.
void RegisterURLRegexes(const std::vector<std::string>& url_regexes);
// Returns true if the |gurl| matches the registered regular expressions.
bool Matches(const GURL& gurl) const;
// Aggregator that sends data use observations.
data_usage::DataUseAggregator* data_use_aggregator_;
// Java listener that provides regular expressions to this class. The
// regular expressions are applied to the request URLs, and filtered
// data use is notified to |j_external_data_use_observer_|.
base::android::ScopedJavaGlobalRef<jobject> j_external_data_use_observer_;
// Registered RE2 patterns that are matched against the URLs.
ScopedVector<re2::RE2> url_patterns_;
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(ExternalDataUseObserver);
};
bool RegisterExternalDataUseObserver(JNIEnv* env);
} // namespace android
} // namespace chrome
#endif // CHROME_BROWSER_ANDROID_DATAUSAGE_EXTERNAL_DATA_USE_OBSERVER_H_
// Copyright 2015 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 "chrome/browser/android/datausage/external_data_use_observer.h"
#include <string>
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "components/data_usage/core/data_use.h"
#include "components/data_usage/core/data_use_aggregator.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace chrome {
namespace android {
TEST(ExternalDataUseObserverTest, SingleRegex) {
scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator(
new data_usage::DataUseAggregator());
scoped_ptr<ExternalDataUseObserver> external_data_use_observer(
new ExternalDataUseObserver(data_use_aggregator.get()));
const struct {
std::string url;
std::string regex;
bool expect_match;
} tests[] = {
{"http://www.google.com", "http://www.google.com/", true},
{"http://www.Google.com", "http://www.google.com/", true},
{"http://www.googleacom", "http://www.google.com/", true},
{"http://www.googleaacom", "http://www.google.com/", false},
{"http://www.google.com", "https://www.google.com/", false},
{"http://www.google.com", "{http|https}://www\\.google\\.com/search.*",
false},
{"https://www.google.com/search=test",
"https://www\\.google\\.com/search.*", true},
{"https://www.googleacom/search=test",
"https://www\\.google\\.com/search.*", false},
{"https://www.google.com/Search=test",
"https://www\\.google\\.com/search.*", true},
{"www.google.com", "http://www.google.com", false},
{"www.google.com:80", "http://www.google.com", false},
{"http://www.google.com:80", "http://www.google.com", false},
{"http://www.google.com:80/", "http://www.google.com/", true},
{"", "http://www.google.com", false},
{"", "", false},
{"https://www.google.com", "http://www.google.com", false},
};
for (size_t i = 0; i < arraysize(tests); ++i) {
external_data_use_observer->RegisterURLRegexes(
std::vector<std::string>(1, tests[i].regex));
EXPECT_EQ(tests[i].expect_match,
external_data_use_observer->Matches(GURL(tests[i].url)))
<< i;
}
}
TEST(ExternalDataUseObserverTest, TwoRegex) {
scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator(
new data_usage::DataUseAggregator());
scoped_ptr<ExternalDataUseObserver> external_data_use_observer(
new ExternalDataUseObserver(data_use_aggregator.get()));
const struct {
std::string url;
std::string regex1;
std::string regex2;
bool expect_match;
} tests[] = {
{"http://www.google.com", "http://www.google.com/",
"https://www.google.com/", true},
{"http://www.googleacom", "http://www.google.com/",
"http://www.google.com/", true},
{"https://www.google.com", "http://www.google.com/",
"https://www.google.com/", true},
{"https://www.googleacom", "http://www.google.com/",
"https://www.google.com/", true},
{"http://www.google.com", "{http|https}://www\\.google\\.com/search.*",
"", false},
{"http://www.google.com/search=test",
"http://www\\.google\\.com/search.*",
"https://www\\.google\\.com/search.*", true},
{"https://www.google.com/search=test",
"http://www\\.google\\.com/search.*",
"https://www\\.google\\.com/search.*", true},
{"http://google.com/search=test", "http://www\\.google\\.com/search.*",
"https://www\\.google\\.com/search.*", false},
{"https://www.googleacom/search=test", "",
"https://www\\.google\\.com/search.*", false},
{"https://www.google.com/Search=test", "",
"https://www\\.google\\.com/search.*", true},
{"www.google.com", "http://www.google.com", "", false},
{"www.google.com:80", "http://www.google.com", "", false},
{"http://www.google.com:80", "http://www.google.com", "", false},
{"", "http://www.google.com", "", false},
{"https://www.google.com", "http://www.google.com", "", false},
};
for (size_t i = 0; i < arraysize(tests); ++i) {
std::vector<std::string> url_regexes;
url_regexes.push_back(tests[i].regex1);
url_regexes.push_back(tests[i].regex2);
external_data_use_observer->RegisterURLRegexes(url_regexes);
EXPECT_EQ(tests[i].expect_match,
external_data_use_observer->Matches(GURL(tests[i].url)))
<< i;
}
}
TEST(ExternalDataUseObserverTest, MultipleRegex) {
scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator(
new data_usage::DataUseAggregator());
scoped_ptr<ExternalDataUseObserver> external_data_use_observer(
new ExternalDataUseObserver(data_use_aggregator.get()));
std::vector<std::string> url_regexes;
url_regexes.push_back("http://www\\.google\\.com/#q=.*");
url_regexes.push_back("https://www\\.google\\.com/#q=.*");
url_regexes.push_back("http://www\\.google\\.co\\.in/#q=.*");
url_regexes.push_back("https://www\\.google\\.co\\.in/#q=.*");
external_data_use_observer->RegisterURLRegexes(url_regexes);
const struct {
std::string url;
bool expect_match;
} tests[] = {
{"", false},
{"http://www.google.com", false},
{"http://www.googleacom", false},
{"https://www.google.com", false},
{"https://www.googleacom", false},
{"http://www.google.com", false},
{"quic://www.google.com/q=test", false},
{"http://www.google.com/q=test", false},
{"http://www.google.com/.q=test", false},
{"http://www.google.com/#q=test", true},
{"https://www.google.com/#q=test", true},
{"http://www.google.co.in/#q=test", true},
{"https://www.google.co.in/#q=test", true},
{"http://www.google.co.br/#q=test", false},
{"http://google.com/#q=test", false},
{"https://www.googleacom/#q=test", false},
{"https://www.google.com/#Q=test", true}, // case in-sensitive
{"www.google.com/#q=test", false},
{"www.google.com:80/#q=test", false},
{"http://www.google.com:80/#q=test", true},
};
for (size_t i = 0; i < arraysize(tests); ++i) {
EXPECT_EQ(tests[i].expect_match,
external_data_use_observer->Matches(GURL(tests[i].url)))
<< i << tests[i].url;
}
}
TEST(ExternalDataUseObserverTest, ChangeRegex) {
scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator(
new data_usage::DataUseAggregator());
scoped_ptr<ExternalDataUseObserver> external_data_use_observer(
new ExternalDataUseObserver(data_use_aggregator.get()));
// When no regex is specified, the URL match should fail.
EXPECT_FALSE(external_data_use_observer->Matches(GURL("")));
EXPECT_FALSE(
external_data_use_observer->Matches(GURL("http://www.google.com")));
std::vector<std::string> url_regexes;
url_regexes.push_back("http://www\\.google\\.com/#q=.*");
url_regexes.push_back("https://www\\.google\\.com/#q=.*");
external_data_use_observer->RegisterURLRegexes(url_regexes);
EXPECT_FALSE(external_data_use_observer->Matches(GURL("")));
EXPECT_TRUE(
external_data_use_observer->Matches(GURL("http://www.google.com#q=abc")));
EXPECT_FALSE(external_data_use_observer->Matches(
GURL("http://www.google.co.in#q=abc")));
// Change the regular expressions to verify that the new regexes replace
// the ones specified before.
url_regexes.clear();
url_regexes.push_back("http://www\\.google\\.co\\.in/#q=.*");
url_regexes.push_back("https://www\\.google\\.co\\.in/#q=.*");
external_data_use_observer->RegisterURLRegexes(url_regexes);
EXPECT_FALSE(external_data_use_observer->Matches(GURL("")));
EXPECT_FALSE(
external_data_use_observer->Matches(GURL("http://www.google.com#q=abc")));
EXPECT_TRUE(external_data_use_observer->Matches(
GURL("http://www.google.co.in#q=abc")));
}
} // namespace android
} // namespace chrome
......@@ -41,7 +41,6 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/data_usage/core/data_use_aggregator.h"
#include "components/net_log/chrome_net_log.h"
#include "components/policy/core/common/policy_service.h"
#include "components/proxy_config/pref_proxy_config_tracker.h"
......@@ -111,6 +110,7 @@
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
#include "chrome/browser/android/datausage/external_data_use_observer.h"
#include "chrome/browser/android/net/external_estimate_provider_android.h"
#endif
......@@ -571,7 +571,7 @@ void IOThread::Init() {
extension_event_router_forwarder_;
#endif
globals_->data_use_aggregator.reset(new data_usage::DataUseAggregator());
data_use_aggregator_.reset(new data_usage::DataUseAggregator());
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432
// is fixed.
......@@ -583,8 +583,12 @@ void IOThread::Init() {
&system_enable_referrers_));
// By default, data usage is considered off the record.
chrome_network_delegate->set_data_use_aggregator(
globals_->data_use_aggregator.get(),
true /* is_data_usage_off_the_record */);
data_use_aggregator(), true /* is_data_usage_off_the_record */);
#if defined(OS_ANDROID)
external_data_use_observer_.reset(
new chrome::android::ExternalDataUseObserver(data_use_aggregator()));
#endif
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432
// is fixed.
......@@ -1060,6 +1064,10 @@ base::TimeTicks IOThread::creation_time() const {
return creation_time_;
}
data_usage::DataUseAggregator* IOThread::data_use_aggregator() const {
return data_use_aggregator_.get();
}
net::SSLConfigService* IOThread::GetSSLConfigService() {
return ssl_config_service_manager_->Get();
}
......
......@@ -20,6 +20,7 @@
#include "base/time/time.h"
#include "chrome/browser/net/chrome_network_delegate.h"
#include "chrome/browser/net/ssl_config_service_manager.h"
#include "components/data_usage/core/data_use_aggregator.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browser_thread_delegate.h"
#include "net/base/network_change_notifier.h"
......@@ -43,10 +44,6 @@ namespace extensions {
class EventRouterForwarder;
}
namespace data_usage {
class DataUseAggregator;
}
namespace net {
class CertPolicyEnforcer;
class CertVerifier;
......@@ -127,9 +124,6 @@ class IOThread : public content::BrowserThreadDelegate {
Globals();
~Globals();
// Global aggregator of data use. It must outlive the
// |system_network_delegate|.
scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator;
// The "system" NetworkDelegate, used for Profile-agnostic network events.
scoped_ptr<net::NetworkDelegate> system_network_delegate;
scoped_ptr<net::HostResolver> host_resolver;
......@@ -256,6 +250,8 @@ class IOThread : public content::BrowserThreadDelegate {
base::TimeTicks creation_time() const;
data_usage::DataUseAggregator* data_use_aggregator() const;
// Returns true if QUIC should be enabled for data reduction proxy, either as
// a result of a field trial or a command line flag.
static bool ShouldEnableQuicForDataReductionProxy();
......@@ -517,6 +513,13 @@ class IOThread : public content::BrowserThreadDelegate {
// True if QUIC is allowed by policy.
bool is_quic_allowed_by_policy_;
// Global aggregator of data use. It must outlive the
// |system_network_delegate|.
scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator_;
// An external observer of data use.
scoped_ptr<data_usage::DataUseAggregator::Observer>
external_data_use_observer_;
const base::TimeTicks creation_time_;
base::WeakPtrFactory<IOThread> weak_factory_;
......
......@@ -1069,8 +1069,8 @@ void ProfileIOData::Init(
network_delegate->set_enable_do_not_track(&enable_do_not_track_);
network_delegate->set_force_google_safe_search(&force_google_safesearch_);
network_delegate->set_force_youtube_safety_mode(&force_youtube_safety_mode_);
network_delegate->set_data_use_aggregator(
io_thread_globals->data_use_aggregator.get(), IsOffTheRecord());
network_delegate->set_data_use_aggregator(io_thread->data_use_aggregator(),
IsOffTheRecord());
// NOTE: Proxy service uses the default io thread network delegate, not the
// delegate just created.
......
......@@ -102,6 +102,8 @@
'browser/android/contextualsearch/contextual_search_tab_helper.h',
'browser/android/cookies/cookies_fetcher.cc',
'browser/android/cookies/cookies_fetcher.h',
'browser/android/datausage/external_data_use_observer.cc',
'browser/android/datausage/external_data_use_observer.h',
'browser/android/dev_tools_discovery_provider_android.cc',
'browser/android/dev_tools_discovery_provider_android.h',
'browser/android/dev_tools_server.cc',
......@@ -1759,6 +1761,7 @@
'android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java',
'android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java',
'android/java/src/org/chromium/chrome/browser/cookies/CookiesFetcher.java',
'android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java',
'android/java/src/org/chromium/chrome/browser/DevToolsServer.java',
'android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java',
'android/java/src/org/chromium/chrome/browser/document/DocumentWebContentsDelegate.java',
......
......@@ -13,6 +13,7 @@
'browser/after_startup_task_utils_unittest.cc',
'browser/android/bookmarks/partner_bookmarks_shim_unittest.cc',
'browser/android/contextualsearch/contextual_search_delegate_unittest.cc',
'browser/android/datausage/external_data_use_observer_unittest.cc',
'browser/android/history_report/delta_file_backend_leveldb_unittest.cc',
'browser/android/history_report/delta_file_commons_unittest.cc',
'browser/android/history_report/usage_reports_buffer_backend_unittest.cc',
......
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