// Copyright (c) 2012 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_EXTENSIONS_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULES_REGISTRY_H_
#define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULES_REGISTRY_H_

#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/extensions/api/declarative/declarative_rule.h"
#include "chrome/browser/extensions/api/declarative/rules_registry.h"
#include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h"
#include "extensions/browser/info_map.h"
#include "extensions/common/matcher/url_matcher.h"

class Profile;
class WebRequestPermissions;

namespace extension_web_request_api_helpers {
struct EventResponseDelta;
}

namespace net {
class URLRequest;
}

namespace extensions {

class RulesRegistryService;

typedef linked_ptr<extension_web_request_api_helpers::EventResponseDelta>
    LinkedPtrEventResponseDelta;
typedef DeclarativeRule<WebRequestCondition, WebRequestAction> WebRequestRule;

// The WebRequestRulesRegistry is responsible for managing
// the internal representation of rules for the Declarative Web Request API.
//
// Here is the high level overview of this functionality:
//
// RulesRegistry::Rule consists of Conditions and Actions, these are
// represented as a WebRequestRule with WebRequestConditions and
// WebRequestRuleActions.
//
// WebRequestConditions represent JSON dictionaries as the following:
// {
//   'instanceType': 'URLMatcher',
//   'host_suffix': 'example.com',
//   'path_prefix': '/query',
//   'scheme': 'http'
// }
//
// The evaluation of URL related condition attributes (host_suffix, path_prefix)
// is delegated to a URLMatcher, because this is capable of evaluating many
// of such URL related condition attributes in parallel.
//
// For this, the URLRequestCondition has a URLMatcherConditionSet, which
// represents the {'host_suffix': 'example.com', 'path_prefix': '/query'} part.
// We will then ask the URLMatcher, whether a given URL
// "http://www.example.com/query/" has any matches, and the URLMatcher
// will respond with the URLMatcherConditionSet::ID. We can map this
// to the WebRequestRule and check whether also the other conditions (in this
// example 'scheme': 'http') are fulfilled.
class WebRequestRulesRegistry : public RulesRegistry {
 public:
  // |cache_delegate| can be NULL. In that case it constructs the registry with
  // storage functionality suspended.
  WebRequestRulesRegistry(Profile* profile,
                          RulesCacheDelegate* cache_delegate,
                          const WebViewKey& webview_key);

  // TODO(battre): This will become an implementation detail, because we need
  // a way to also execute the actions of the rules.
  std::set<const WebRequestRule*> GetMatches(
      const WebRequestData& request_data_without_ids) const;

  // Returns which modifications should be executed on the network request
  // according to the rules registered in this registry.
  std::list<LinkedPtrEventResponseDelta> CreateDeltas(
      const InfoMap* extension_info_map,
      const WebRequestData& request_data,
      bool crosses_incognito);

  // Implementation of RulesRegistry:
  virtual std::string AddRulesImpl(
      const std::string& extension_id,
      const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) OVERRIDE;
  virtual std::string RemoveRulesImpl(
      const std::string& extension_id,
      const std::vector<std::string>& rule_identifiers) OVERRIDE;
  virtual std::string RemoveAllRulesImpl(
      const std::string& extension_id) OVERRIDE;

  // Returns true if this object retains no allocated data. Only for debugging.
  bool IsEmpty() const;

 protected:
  virtual ~WebRequestRulesRegistry();

  // Virtual for testing:
  virtual base::Time GetExtensionInstallationTime(
      const std::string& extension_id) const;
  virtual void ClearCacheOnNavigation();

  void SetExtensionInfoMapForTesting(
      scoped_refptr<InfoMap> extension_info_map) {
    extension_info_map_ = extension_info_map;
  }

  const std::set<const WebRequestRule*>&
  rules_with_untriggered_conditions_for_test() const {
    return rules_with_untriggered_conditions_;
  }

 private:
  FRIEND_TEST_ALL_PREFIXES(WebRequestRulesRegistrySimpleTest, StageChecker);
  FRIEND_TEST_ALL_PREFIXES(WebRequestRulesRegistrySimpleTest,
                           HostPermissionsChecker);

  typedef std::map<URLMatcherConditionSet::ID, WebRequestRule*> RuleTriggers;
  typedef std::map<WebRequestRule::RuleId, linked_ptr<WebRequestRule> >
      RulesMap;
  typedef std::set<URLMatcherConditionSet::ID> URLMatches;
  typedef std::set<const WebRequestRule*> RuleSet;

  // This bundles all consistency checkers. Returns true in case of consistency
  // and MUST set |error| otherwise.
  static bool Checker(const Extension* extension,
                      const WebRequestConditionSet* conditions,
                      const WebRequestActionSet* actions,
                      std::string* error);

  // Check that the |extension| has host permissions for all URLs if actions
  // requiring them are present.
  static bool HostPermissionsChecker(const Extension* extension,
                                     const WebRequestActionSet* actions,
                                     std::string* error);

  // Check that every action is applicable in the same request stage as at
  // least one condition.
  static bool StageChecker(const WebRequestConditionSet* conditions,
                           const WebRequestActionSet* actions,
                           std::string* error);

  // Helper for RemoveRulesImpl and RemoveAllRulesImpl. Call this before
  // deleting |rule| from one of the maps in |webrequest_rules_|. It will erase
  // the rule from |rule_triggers_| and |rules_with_untriggered_conditions_|,
  // and add every of the rule's URLMatcherConditionSet to
  // |remove_from_url_matcher|, so that the caller can remove them from the
  // matcher later.
  void CleanUpAfterRule(
      const WebRequestRule* rule,
      std::vector<URLMatcherConditionSet::ID>* remove_from_url_matcher);

  // This is a helper function to GetMatches. Rules triggered by |url_matches|
  // get added to |result| if one of their conditions is fulfilled.
  // |request_data| gets passed to IsFulfilled of the rules' condition sets.
  void AddTriggeredRules(const URLMatches& url_matches,
                         const WebRequestCondition::MatchData& request_data,
                         RuleSet* result) const;

  // Map that tells us which WebRequestRule may match under the condition that
  // the URLMatcherConditionSet::ID was returned by the |url_matcher_|.
  RuleTriggers rule_triggers_;

  // These rules contain condition sets with conditions without URL attributes.
  // Such conditions are not triggered by URL matcher, so we need to test them
  // separately.
  std::set<const WebRequestRule*> rules_with_untriggered_conditions_;

  std::map<WebRequestRule::ExtensionId, RulesMap> webrequest_rules_;

  URLMatcher url_matcher_;

  void* profile_id_;
  scoped_refptr<InfoMap> extension_info_map_;

  DISALLOW_COPY_AND_ASSIGN(WebRequestRulesRegistry);
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULES_REGISTRY_H_
