blob: 9d1a12c9971404bc6ea5dd7924be12edd8a46303 [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 <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "chrome/browser/android/data_usage/data_use_tab_model.h"
namespace base {
class SingleThreadTaskRunner;
class TickClock;
}
namespace re2 {
class RE2;
}
class GURL;
namespace chrome {
namespace android {
class ExternalDataUseObserver;
// 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.
class DataUseMatcher {
public:
DataUseMatcher(
const base::WeakPtr<DataUseTabModel>& data_use_tab_model,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
const base::WeakPtr<ExternalDataUseObserver>& external_data_use_observer,
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;
// Fetches the matching rules asynchronously from
// |external_data_use_observer_|.
void FetchMatchingRules();
// Returns true if there is any valid matching rule.
bool HasValidRules() 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,
scoped_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.
scoped_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<scoped_ptr<MatchingRule>> matching_rules_;
// |data_use_tab_model_| is notified if a label is removed from the set of
// matching labels.
base::WeakPtr<DataUseTabModel> data_use_tab_model_;
// 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.
scoped_ptr<base::TickClock> tick_clock_;
// |io_task_runner_| is used to call ExternalDataUseObserver methods on
// IO thread.
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// |external_data_use_observer_| is notified when matching rules are fetched.
base::WeakPtr<ExternalDataUseObserver> external_data_use_observer_;
DISALLOW_COPY_AND_ASSIGN(DataUseMatcher);
};
} // namespace android
} // namespace chrome
#endif // CHROME_BROWSER_ANDROID_DATA_USAGE_DATA_USE_MATCHER_H_