// 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.

#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h"
#include "extensions/common/matcher/url_matcher_factory.h"
#include "net/url_request/url_request.h"

namespace keys = extensions::declarative_webrequest_constants;

namespace {
static extensions::URLMatcherConditionSet::ID g_next_id = 0;

// TODO(battre): improve error messaging to give more meaningful messages
// to the extension developer.
// Error messages:
const char kExpectedDictionary[] = "A condition has to be a dictionary.";
const char kConditionWithoutInstanceType[] = "A condition had no instanceType";
const char kExpectedOtherConditionType[] = "Expected a condition of type "
    "declarativeWebRequest.RequestMatcher";
const char kInvalidTypeOfParamter[] = "Attribute '%s' has an invalid type";
const char kConditionCannotBeFulfilled[] = "A condition can never be "
    "fulfilled because its attributes cannot all be tested at the "
    "same time in the request life-cycle.";
}  // namespace

namespace extensions {

namespace keys = declarative_webrequest_constants;

//
// WebRequestData
//

WebRequestData::WebRequestData(net::URLRequest* request, RequestStage stage)
    : request(request),
      stage(stage),
      original_response_headers(NULL) {}

WebRequestData::WebRequestData(
    net::URLRequest* request,
    RequestStage stage,
    const net::HttpResponseHeaders* original_response_headers)
    : request(request),
      stage(stage),
      original_response_headers(original_response_headers) {}

WebRequestData::~WebRequestData() {}

//
// WebRequestDataWithMatchIds
//

WebRequestDataWithMatchIds::WebRequestDataWithMatchIds(
    const WebRequestData* request_data)
    : data(request_data) {}

WebRequestDataWithMatchIds::~WebRequestDataWithMatchIds() {}

//
// WebRequestCondition
//

WebRequestCondition::WebRequestCondition(
    scoped_refptr<URLMatcherConditionSet> url_matcher_conditions,
    scoped_refptr<URLMatcherConditionSet> first_party_url_matcher_conditions,
    const WebRequestConditionAttributes& condition_attributes)
    : url_matcher_conditions_(url_matcher_conditions),
      first_party_url_matcher_conditions_(first_party_url_matcher_conditions),
      condition_attributes_(condition_attributes),
      applicable_request_stages_(~0) {
  for (WebRequestConditionAttributes::const_iterator i =
       condition_attributes_.begin(); i != condition_attributes_.end(); ++i) {
    applicable_request_stages_ &= (*i)->GetStages();
  }
}

WebRequestCondition::~WebRequestCondition() {}

bool WebRequestCondition::IsFulfilled(
    const MatchData& request_data) const {
  if (!(request_data.data->stage & applicable_request_stages_)) {
    // A condition that cannot be evaluated is considered as violated.
    return false;
  }

  // Check URL attributes if present.
  if (url_matcher_conditions_.get() &&
      !ContainsKey(request_data.url_match_ids, url_matcher_conditions_->id()))
    return false;
  if (first_party_url_matcher_conditions_.get() &&
      !ContainsKey(request_data.first_party_url_match_ids,
                   first_party_url_matcher_conditions_->id()))
    return false;

  // All condition attributes must be fulfilled for a fulfilled condition.
  for (WebRequestConditionAttributes::const_iterator i =
           condition_attributes_.begin();
       i != condition_attributes_.end(); ++i) {
    if (!(*i)->IsFulfilled(*(request_data.data)))
      return false;
  }
  return true;
}

void WebRequestCondition::GetURLMatcherConditionSets(
    URLMatcherConditionSet::Vector* condition_sets) const {
  if (url_matcher_conditions_.get())
    condition_sets->push_back(url_matcher_conditions_);
  if (first_party_url_matcher_conditions_.get())
    condition_sets->push_back(first_party_url_matcher_conditions_);
}

// static
scoped_ptr<WebRequestCondition> WebRequestCondition::Create(
    const Extension* extension,
    URLMatcherConditionFactory* url_matcher_condition_factory,
    const base::Value& condition,
    std::string* error) {
  const base::DictionaryValue* condition_dict = NULL;
  if (!condition.GetAsDictionary(&condition_dict)) {
    *error = kExpectedDictionary;
    return scoped_ptr<WebRequestCondition>();
  }

  // Verify that we are dealing with a Condition whose type we understand.
  std::string instance_type;
  if (!condition_dict->GetString(keys::kInstanceTypeKey, &instance_type)) {
    *error = kConditionWithoutInstanceType;
    return scoped_ptr<WebRequestCondition>();
  }
  if (instance_type != keys::kRequestMatcherType) {
    *error = kExpectedOtherConditionType;
    return scoped_ptr<WebRequestCondition>();
  }

  WebRequestConditionAttributes attributes;
  scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set;
  scoped_refptr<URLMatcherConditionSet> first_party_url_matcher_condition_set;

  for (base::DictionaryValue::Iterator iter(*condition_dict);
       !iter.IsAtEnd(); iter.Advance()) {
    const std::string& condition_attribute_name = iter.key();
    const Value& condition_attribute_value = iter.value();
    const bool name_is_url = condition_attribute_name == keys::kUrlKey;
    if (condition_attribute_name == keys::kInstanceTypeKey) {
      // Skip this.
    } else if (name_is_url ||
               condition_attribute_name == keys::kFirstPartyForCookiesUrlKey) {
      const base::DictionaryValue* dict = NULL;
      if (!condition_attribute_value.GetAsDictionary(&dict)) {
        *error = base::StringPrintf(kInvalidTypeOfParamter,
                                    condition_attribute_name.c_str());
      } else {
        if (name_is_url) {
          url_matcher_condition_set =
              URLMatcherFactory::CreateFromURLFilterDictionary(
                  url_matcher_condition_factory, dict, ++g_next_id, error);
        } else {
          first_party_url_matcher_condition_set =
              URLMatcherFactory::CreateFromURLFilterDictionary(
                  url_matcher_condition_factory, dict, ++g_next_id, error);
        }
      }
    } else {
      scoped_refptr<const WebRequestConditionAttribute> attribute =
          WebRequestConditionAttribute::Create(
              condition_attribute_name,
              &condition_attribute_value,
              error);
      if (attribute.get())
        attributes.push_back(attribute);
    }
    if (!error->empty())
      return scoped_ptr<WebRequestCondition>();
  }

  scoped_ptr<WebRequestCondition> result(
      new WebRequestCondition(url_matcher_condition_set,
                              first_party_url_matcher_condition_set,
                              attributes));

  if (!result->stages()) {
    *error = kConditionCannotBeFulfilled;
    return scoped_ptr<WebRequestCondition>();
  }

  return result.Pass();
}

}  // namespace extensions
