// 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 #include #include #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::ActivationSequence; 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().Clone()), manifest_permissions(permissions.manifest_permissions().Clone()), explicit_hosts(permissions.explicit_hosts().Clone()), scriptable_hosts(permissions.scriptable_hosts().Clone()) {} ExtensionMsg_PermissionSetStruct::~ExtensionMsg_PermissionSetStruct() {} ExtensionMsg_PermissionSetStruct::ExtensionMsg_PermissionSetStruct( ExtensionMsg_PermissionSetStruct&& other) = default; ExtensionMsg_PermissionSetStruct& ExtensionMsg_PermissionSetStruct::operator=( ExtensionMsg_PermissionSetStruct&& other) = default; std::unique_ptr ExtensionMsg_PermissionSetStruct::ToPermissionSet() const { // TODO(devlin): Make this destructive so we can std::move() the members. return std::make_unique( apis.Clone(), manifest_permissions.Clone(), explicit_hosts.Clone(), scriptable_hosts.Clone()); } 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, base::Optional worker_activation_sequence) : manifest(static_cast( extension->manifest()->value()->Clone())), 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().Clone()), policy_allowed_hosts( extension->permissions_data()->policy_allowed_hosts().Clone()), uses_default_policy_blocked_allowed_hosts( extension->permissions_data()->UsesDefaultPolicyHostRestrictions()), id(extension->id()), worker_activation_sequence(worker_activation_sequence), 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( ExtensionMsg_Loaded_Params&& other) = default; ExtensionMsg_Loaded_Params& ExtensionMsg_Loaded_Params::operator=( ExtensionMsg_Loaded_Params&& other) = default; scoped_refptr ExtensionMsg_Loaded_Params::ConvertToExtension( const int context_id, 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::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(context_id); } 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::Write(base::Pickle* m, const param_type& p) { WriteParam(m, p.valid_schemes()); WriteParam(m, p.GetAsString()); } bool ParamTraits::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); URLPattern::ParseResult result = p->Parse(spec); p->SetValidSchemes(valid_schemes); return URLPattern::ParseResult::kSuccess == result; } void ParamTraits::Log(const param_type& p, std::string* l) { LogParam(p.GetAsString(), l); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { WriteParam(m, p.patterns()); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { std::set patterns; if (!ReadParam(m, iter, &patterns)) return false; for (auto i = patterns.begin(); i != patterns.end(); ++i) p->AddPattern(*i); return true; } void ParamTraits::Log(const param_type& p, std::string* l) { LogParam(p.patterns(), l); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { WriteParam(m, static_cast(p)); } bool ParamTraits::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(api_id); return true; } void ParamTraits::Log( const param_type& p, std::string* l) { LogParam(static_cast(p), l); } void ParamTraits::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(p.size())); for (; it != end; ++it) { WriteParam(m, it->id()); it->Write(m); } } bool ParamTraits::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 p(permission_info->CreateAPIPermission()); if (!p->Read(m, iter)) return false; r->insert(std::move(p)); } return true; } void ParamTraits::Log( const param_type& p, std::string* l) { LogParam(p.map(), l); } void ParamTraits::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(p.size())); for (; it != end; ++it) { WriteParam(m, it->name()); it->Write(m); } } bool ParamTraits::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 p( ManifestHandler::CreatePermission(name)); if (!p) return false; if (!p->Read(m, iter)) return false; r->insert(std::move(p)); } return true; } void ParamTraits::Log( const param_type& p, std::string* l) { LogParam(p.map(), l); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { WriteParam(m, p.type()); WriteParam(m, p.id()); } bool ParamTraits::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::Log( const param_type& p, std::string* l) { LogParam(p.type(), l); LogParam(p.id(), l); } void ParamTraits::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::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::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::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); WriteParam(m, p.worker_activation_sequence); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { p->manifest.Clear(); return ReadParam(m, iter, &p->location) && ReadParam(m, iter, &p->path) && ReadParam(m, iter, &p->manifest) && 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) && ReadParam(m, iter, &p->worker_activation_sequence); } void ParamTraits::Log(const param_type& p, std::string* l) { l->append(p.id); } } // namespace IPC