blob: 557e7f3a37fce54a090c3b59c9523f0621a9ce18 [file] [log] [blame]
// 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_DATA_USAGE_DATA_USE_MATCHER_H_
#define CHROME_BROWSER_ANDROID_DATA_USAGE_DATA_USE_MATCHER_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
namespace base {
class TickClock;
}
namespace re2 {
class RE2;
}
class GURL;
namespace chrome {
namespace android {
// DataUseMatcher stores the matching URL patterns and package names along with
// the labels. It also provides functionality to get the matching label for a
// given URL or package. DataUseMatcher is not thread safe. It is created on IO
// thread, but immediately moved to the UI thread, and afterwards accessible
// only on the UI thread.
class DataUseMatcher {
public:
// |on_tracking_label_removed_callback| is the callback to be run when a
// tracking label is removed from the list of matching rules.
// |on_matching_rules_fetched_callback| is the callback to be run after
// matching rules are fetched, indicating if at least one valid matching rule
// is available.
DataUseMatcher(
const base::Callback<void(const std::string&)>&
on_tracking_label_removed_callback,
const base::Callback<void(bool)>& on_matching_rules_fetched_callback,
const base::TimeDelta& default_matching_rule_expiration_duration);
~DataUseMatcher();
// Called by FetchMatchingRulesDoneOnIOThread 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>& app_package_names,
const std::vector<std::string>& domain_path_regexes,
const std::vector<std::string>& labels);
// Returns true if the |url| matches the registered regular expressions.
// |label| must not be null. If a match is found, the |label| is set to the
// matching rule's label.
bool MatchesURL(const GURL& url, std::string* label) const WARN_UNUSED_RESULT;
// Returns true if the |app_package_name| matches the registered package
// names. |label| must not be null. If a match is found, the |label| is set
// to the matching rule's label.
bool MatchesAppPackageName(const std::string& app_package_name,
std::string* label) const WARN_UNUSED_RESULT;
// Returns true if there is any matching rule. HasRules may return true even
// if all rules are expired.
bool HasRules() const;
// Returns true if there is any valid matching rule with label |label|.
bool HasValidRuleWithLabel(const std::string& label) const;
private:
friend class DataUseMatcherTest;
FRIEND_TEST_ALL_PREFIXES(DataUseMatcherTest,
EncodeExpirationTimeInPackageName);
FRIEND_TEST_ALL_PREFIXES(DataUseMatcherTest,
EncodeJavaExpirationTimeInPackageName);
FRIEND_TEST_ALL_PREFIXES(DataUseMatcherTest, MatchesIgnoresExpiredRules);
FRIEND_TEST_ALL_PREFIXES(DataUseMatcherTest, ParsePackageField);
// Stores the matching rules.
class MatchingRule {
public:
MatchingRule(const std::string& app_package_name,
std::unique_ptr<re2::RE2> pattern,
const std::string& label,
const base::TimeTicks& expiration);
~MatchingRule();
const re2::RE2* pattern() const;
const std::string& app_package_name() const;
const std::string& label() const;
const base::TimeTicks& expiration() const;
private:
// Package name of the app that should be matched.
const std::string app_package_name_;
// RE2 pattern to match against URLs.
std::unique_ptr<re2::RE2> pattern_;
// Opaque label that uniquely identifies this matching rule.
const std::string label_;
// Expiration time of this matching rule.
const base::TimeTicks expiration_;
DISALLOW_COPY_AND_ASSIGN(MatchingRule);
};
// Parses the app package name and expiration time of the matching rule
// encoded in the format "app_package_name|milliseconds_since_epoch" in
// |app_package_name|. |new_app_package_name| and |expiration| should not be
// null. Parsed expiration time is set in |expiration| and app package name
// is set in |new_app_package_name|. If |app_package_name| is not in the
// expected format, |expiration| will be set to default expiration duration
// from now, and |new_app_package_name| will be set to the |app_package_name|.
void ParsePackageField(const std::string& app_package_name,
std::string* new_app_package_name,
base::TimeTicks* expiration) const;
base::ThreadChecker thread_checker_;
std::vector<std::unique_ptr<MatchingRule>> matching_rules_;
// Default expiration duration of a matching rule, if expiration is not
// specified in the rule.
const base::TimeDelta default_matching_rule_expiration_duration_;
// TickClock used for obtaining the current time.
std::unique_ptr<base::TickClock> tick_clock_;
// Callback to be run when a label is removed from the set of matching labels.
const base::Callback<void(const std::string&)>
on_tracking_label_removed_callback_;
// Callback to be run when matching rules are fetched.
const base::Callback<void(bool)> on_matching_rules_fetched_callback_;
DISALLOW_COPY_AND_ASSIGN(DataUseMatcher);
};
} // namespace android
} // namespace chrome
#endif // CHROME_BROWSER_ANDROID_DATA_USAGE_DATA_USE_MATCHER_H_