// Copyright 2014 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 "extensions/common/extension_messages.h"

#include <stddef.h>

#include <memory>

#include "base/memory/ptr_util.h"
#include "content/public/common/common_param_traits.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_handler.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/permissions/permissions_info.h"

using extensions::APIPermission;
using extensions::APIPermissionInfo;
using extensions::APIPermissionSet;
using extensions::Extension;
using extensions::Manifest;
using extensions::ManifestHandler;
using extensions::ManifestPermission;
using extensions::ManifestPermissionSet;
using extensions::PermissionSet;
using extensions::URLPatternSet;

ExtensionMsg_PermissionSetStruct::ExtensionMsg_PermissionSetStruct() {
}

ExtensionMsg_PermissionSetStruct::ExtensionMsg_PermissionSetStruct(
    const PermissionSet& permissions)
    : apis(permissions.apis()),
      manifest_permissions(permissions.manifest_permissions()),
      explicit_hosts(permissions.explicit_hosts()),
      scriptable_hosts(permissions.scriptable_hosts()) {
}

ExtensionMsg_PermissionSetStruct::ExtensionMsg_PermissionSetStruct(
    const ExtensionMsg_PermissionSetStruct& other) = default;

ExtensionMsg_PermissionSetStruct::~ExtensionMsg_PermissionSetStruct() {
}

std::unique_ptr<const PermissionSet>
ExtensionMsg_PermissionSetStruct::ToPermissionSet() const {
  return base::WrapUnique(new PermissionSet(apis, manifest_permissions,
                                            explicit_hosts, scriptable_hosts));
}

ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params()
    : location(Manifest::INVALID_LOCATION),
      creation_flags(Extension::NO_FLAGS) {}

ExtensionMsg_Loaded_Params::~ExtensionMsg_Loaded_Params() {}

ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params(
    const Extension* extension,
    bool include_tab_permissions)
    : manifest(extension->manifest()->value()->DeepCopy()),
      location(extension->location()),
      path(extension->path()),
      active_permissions(extension->permissions_data()->active_permissions()),
      withheld_permissions(
          extension->permissions_data()->withheld_permissions()),
      policy_blocked_hosts(
          extension->permissions_data()->policy_blocked_hosts()),
      policy_allowed_hosts(
          extension->permissions_data()->policy_allowed_hosts()),
      uses_default_policy_blocked_allowed_hosts(
          extension->permissions_data()->UsesDefaultPolicyHostRestrictions()),
      id(extension->id()),
      creation_flags(extension->creation_flags()) {
  if (include_tab_permissions) {
    for (const auto& pair :
         extension->permissions_data()->tab_specific_permissions()) {
      tab_specific_permissions[pair.first] =
          ExtensionMsg_PermissionSetStruct(*pair.second);
    }
  }
}

ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params(
    const ExtensionMsg_Loaded_Params& other) = default;

scoped_refptr<Extension> ExtensionMsg_Loaded_Params::ConvertToExtension(
    std::string* error) const {
  // We pass in the |id| to the create call because it will save work in the
  // normal case, and because in tests, extensions may not have paths or keys,
  // but it's important to retain the same id.
  scoped_refptr<Extension> extension =
      Extension::Create(path, location, *manifest, creation_flags, id, error);
  if (extension.get()) {
    const extensions::PermissionsData* permissions_data =
        extension->permissions_data();
    permissions_data->SetPermissions(active_permissions.ToPermissionSet(),
                                     withheld_permissions.ToPermissionSet());
    if (uses_default_policy_blocked_allowed_hosts) {
      permissions_data->SetUsesDefaultHostRestrictions();
    } else {
      permissions_data->SetPolicyHostRestrictions(policy_blocked_hosts,
                                                  policy_allowed_hosts);
    }
    for (const auto& pair : tab_specific_permissions) {
      permissions_data->UpdateTabSpecificPermissions(
          pair.first, *pair.second.ToPermissionSet());
    }
  }
  return extension;
}

namespace IPC {

void ParamTraits<URLPattern>::GetSize(base::PickleSizer* s,
                                      const param_type& p) {
  GetParamSize(s, p.valid_schemes());
  GetParamSize(s, p.GetAsString());
}

void ParamTraits<URLPattern>::Write(base::Pickle* m, const param_type& p) {
  WriteParam(m, p.valid_schemes());
  WriteParam(m, p.GetAsString());
}

bool ParamTraits<URLPattern>::Read(const base::Pickle* m,
                                   base::PickleIterator* iter,
                                   param_type* p) {
  int valid_schemes;
  std::string spec;
  if (!ReadParam(m, iter, &valid_schemes) ||
      !ReadParam(m, iter, &spec))
    return false;

  // TODO(jstritar): We don't want the URLPattern to fail parsing when the
  // scheme is invalid. Instead, the pattern should parse but it should not
  // match the invalid patterns. We get around this by setting the valid
  // schemes after parsing the pattern. Update these method calls once we can
  // ignore scheme validation with URLPattern parse options. crbug.com/90544
  p->SetValidSchemes(URLPattern::SCHEME_ALL);
  // Allow effective TLD wildcarding since this check is only needed on initial
  // creation of URLPattern and not as part of deserialization.
  URLPattern::ParseResult result =
      p->Parse(spec, URLPattern::ALLOW_WILDCARD_FOR_EFFECTIVE_TLD);
  p->SetValidSchemes(valid_schemes);
  return URLPattern::PARSE_SUCCESS == result;
}

void ParamTraits<URLPattern>::Log(const param_type& p, std::string* l) {
  LogParam(p.GetAsString(), l);
}

void ParamTraits<URLPatternSet>::GetSize(base::PickleSizer* s,
                                         const param_type& p) {
  GetParamSize(s, p.patterns());
}

void ParamTraits<URLPatternSet>::Write(base::Pickle* m, const param_type& p) {
  WriteParam(m, p.patterns());
}

bool ParamTraits<URLPatternSet>::Read(const base::Pickle* m,
                                      base::PickleIterator* iter,
                                      param_type* p) {
  std::set<URLPattern> patterns;
  if (!ReadParam(m, iter, &patterns))
    return false;

  for (std::set<URLPattern>::iterator i = patterns.begin();
       i != patterns.end(); ++i)
    p->AddPattern(*i);
  return true;
}

void ParamTraits<URLPatternSet>::Log(const param_type& p, std::string* l) {
  LogParam(p.patterns(), l);
}

void ParamTraits<APIPermission::ID>::GetSize(base::PickleSizer* s,
                                             const param_type& p) {
  GetParamSize(s, static_cast<int>(p));
}

void ParamTraits<APIPermission::ID>::Write(base::Pickle* m,
                                           const param_type& p) {
  WriteParam(m, static_cast<int>(p));
}

bool ParamTraits<APIPermission::ID>::Read(const base::Pickle* m,
                                          base::PickleIterator* iter,
                                          param_type* p) {
  int api_id = -2;
  if (!ReadParam(m, iter, &api_id))
    return false;

  *p = static_cast<APIPermission::ID>(api_id);
  return true;
}

void ParamTraits<APIPermission::ID>::Log(
    const param_type& p, std::string* l) {
  LogParam(static_cast<int>(p), l);
}

void ParamTraits<APIPermissionSet>::GetSize(base::PickleSizer* s,
                                            const param_type& p) {
  APIPermissionSet::const_iterator it = p.begin();
  const APIPermissionSet::const_iterator end = p.end();
  GetParamSize(s, static_cast<uint32_t>(p.size()));
  for (; it != end; ++it) {
    GetParamSize(s, it->id());
    it->GetSize(s);
  }
}

void ParamTraits<APIPermissionSet>::Write(base::Pickle* m,
                                          const param_type& p) {
  APIPermissionSet::const_iterator it = p.begin();
  const APIPermissionSet::const_iterator end = p.end();
  WriteParam(m, static_cast<uint32_t>(p.size()));
  for (; it != end; ++it) {
    WriteParam(m, it->id());
    it->Write(m);
  }
}

bool ParamTraits<APIPermissionSet>::Read(const base::Pickle* m,
                                         base::PickleIterator* iter,
                                         param_type* r) {
  uint32_t size;
  if (!ReadParam(m, iter, &size))
    return false;
  for (uint32_t i = 0; i < size; ++i) {
    APIPermission::ID id;
    if (!ReadParam(m, iter, &id))
      return false;
    const APIPermissionInfo* permission_info =
      extensions::PermissionsInfo::GetInstance()->GetByID(id);
    if (!permission_info)
      return false;
    std::unique_ptr<APIPermission> p(permission_info->CreateAPIPermission());
    if (!p->Read(m, iter))
      return false;
    r->insert(p.release());
  }
  return true;
}

void ParamTraits<APIPermissionSet>::Log(
    const param_type& p, std::string* l) {
  LogParam(p.map(), l);
}

void ParamTraits<ManifestPermissionSet>::GetSize(base::PickleSizer* s,
                                                 const param_type& p) {
  ManifestPermissionSet::const_iterator it = p.begin();
  const ManifestPermissionSet::const_iterator end = p.end();
  GetParamSize(s, static_cast<uint32_t>(p.size()));
  for (; it != end; ++it) {
    GetParamSize(s, it->name());
    it->GetSize(s);
  }
}

void ParamTraits<ManifestPermissionSet>::Write(base::Pickle* m,
                                               const param_type& p) {
  ManifestPermissionSet::const_iterator it = p.begin();
  const ManifestPermissionSet::const_iterator end = p.end();
  WriteParam(m, static_cast<uint32_t>(p.size()));
  for (; it != end; ++it) {
    WriteParam(m, it->name());
    it->Write(m);
  }
}

bool ParamTraits<ManifestPermissionSet>::Read(const base::Pickle* m,
                                              base::PickleIterator* iter,
                                              param_type* r) {
  uint32_t size;
  if (!ReadParam(m, iter, &size))
    return false;
  for (uint32_t i = 0; i < size; ++i) {
    std::string name;
    if (!ReadParam(m, iter, &name))
      return false;
    std::unique_ptr<ManifestPermission> p(
        ManifestHandler::CreatePermission(name));
    if (!p)
      return false;
    if (!p->Read(m, iter))
      return false;
    r->insert(p.release());
  }
  return true;
}

void ParamTraits<ManifestPermissionSet>::Log(
    const param_type& p, std::string* l) {
  LogParam(p.map(), l);
}

void ParamTraits<HostID>::GetSize(base::PickleSizer* s, const param_type& p) {
  GetParamSize(s, p.type());
  GetParamSize(s, p.id());
}

void ParamTraits<HostID>::Write(base::Pickle* m, const param_type& p) {
  WriteParam(m, p.type());
  WriteParam(m, p.id());
}

bool ParamTraits<HostID>::Read(const base::Pickle* m,
                               base::PickleIterator* iter,
                               param_type* r) {
  HostID::HostType type;
  std::string id;
  if (!ReadParam(m, iter, &type))
    return false;
  if (!ReadParam(m, iter, &id))
    return false;
  *r = HostID(type, id);
  return true;
}

void ParamTraits<HostID>::Log(
    const param_type& p, std::string* l) {
  LogParam(p.type(), l);
  LogParam(p.id(), l);
}

void ParamTraits<ExtensionMsg_PermissionSetStruct>::GetSize(
    base::PickleSizer* s, const param_type& p) {
  GetParamSize(s, p.apis);
  GetParamSize(s, p.manifest_permissions);
  GetParamSize(s, p.explicit_hosts);
  GetParamSize(s, p.scriptable_hosts);
}

void ParamTraits<ExtensionMsg_PermissionSetStruct>::Write(base::Pickle* m,
                                                          const param_type& p) {
  WriteParam(m, p.apis);
  WriteParam(m, p.manifest_permissions);
  WriteParam(m, p.explicit_hosts);
  WriteParam(m, p.scriptable_hosts);
}

bool ParamTraits<ExtensionMsg_PermissionSetStruct>::Read(
    const base::Pickle* m,
    base::PickleIterator* iter,
    param_type* p) {
  return ReadParam(m, iter, &p->apis) &&
         ReadParam(m, iter, &p->manifest_permissions) &&
         ReadParam(m, iter, &p->explicit_hosts) &&
         ReadParam(m, iter, &p->scriptable_hosts);
}

void ParamTraits<ExtensionMsg_PermissionSetStruct>::Log(const param_type& p,
                                                        std::string* l) {
  LogParam(p.apis, l);
  LogParam(p.manifest_permissions, l);
  LogParam(p.explicit_hosts, l);
  LogParam(p.scriptable_hosts, l);
}

void ParamTraits<ExtensionMsg_Loaded_Params>::Write(base::Pickle* m,
                                                    const param_type& p) {
  WriteParam(m, p.location);
  WriteParam(m, p.path);
  WriteParam(m, *(p.manifest));
  WriteParam(m, p.creation_flags);
  WriteParam(m, p.id);
  WriteParam(m, p.active_permissions);
  WriteParam(m, p.withheld_permissions);
  WriteParam(m, p.tab_specific_permissions);
  WriteParam(m, p.policy_blocked_hosts);
  WriteParam(m, p.policy_allowed_hosts);
  WriteParam(m, p.uses_default_policy_blocked_allowed_hosts);
}

bool ParamTraits<ExtensionMsg_Loaded_Params>::Read(const base::Pickle* m,
                                                   base::PickleIterator* iter,
                                                   param_type* p) {
  p->manifest.reset(new base::DictionaryValue());
  return ReadParam(m, iter, &p->location) && ReadParam(m, iter, &p->path) &&
         ReadParam(m, iter, p->manifest.get()) &&
         ReadParam(m, iter, &p->creation_flags) && ReadParam(m, iter, &p->id) &&
         ReadParam(m, iter, &p->active_permissions) &&
         ReadParam(m, iter, &p->withheld_permissions) &&
         ReadParam(m, iter, &p->tab_specific_permissions) &&
         ReadParam(m, iter, &p->policy_blocked_hosts) &&
         ReadParam(m, iter, &p->policy_allowed_hosts) &&
         ReadParam(m, iter, &p->uses_default_policy_blocked_allowed_hosts);
}

void ParamTraits<ExtensionMsg_Loaded_Params>::Log(const param_type& p,
                                                  std::string* l) {
  l->append(p.id);
}

}  // namespace IPC
