| Index: content/browser/loader/resource_dispatcher_host_impl.cc
|
| diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
|
| index 981c71ba454f337c573f6c9b64805d7934a13ce5..7b9d1cc5e25bfc3aa4b17d0e4893540d70d36252 100644
|
| --- a/content/browser/loader/resource_dispatcher_host_impl.cc
|
| +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
|
| @@ -295,7 +295,8 @@ bool ShouldServiceRequest(int process_type,
|
| const ResourceRequest& request_data,
|
| const net::HttpRequestHeaders& headers,
|
| ResourceMessageFilter* filter,
|
| - ResourceContext* resource_context) {
|
| + ResourceContext* resource_context,
|
| + ResourceDispatcherHostImpl* host) {
|
| ChildProcessSecurityPolicyImpl* policy =
|
| ChildProcessSecurityPolicyImpl::GetInstance();
|
|
|
| @@ -313,8 +314,7 @@ bool ShouldServiceRequest(int process_type,
|
| if (has_origin) {
|
| GURL origin(origin_string);
|
| if (!policy->CanCommitURL(child_id, origin) ||
|
| - GetContentClient()->browser()->IsIllegalOrigin(resource_context,
|
| - child_id, origin)) {
|
| + host->IsIllegalOrigin(resource_context, origin, child_id)) {
|
| VLOG(1) << "Killed renderer for illegal origin: " << origin_string;
|
| bad_message::ReceivedBadMessage(filter, bad_message::RDH_ILLEGAL_ORIGIN);
|
| return false;
|
| @@ -493,6 +493,16 @@ void NotifyForEachFrameFromUI(
|
|
|
| } // namespace
|
|
|
| +ResourceDispatcherHostImpl::OriginAccessInfo::OriginAccessInfo() {
|
| +}
|
| +
|
| +ResourceDispatcherHostImpl::OriginAccessInfo::~OriginAccessInfo() {
|
| +}
|
| +
|
| +ResourceDispatcherHostImpl::OriginAccessInfo::OriginAccessInfo(
|
| + const OriginAccessInfo& other) {
|
| +}
|
| +
|
| // static
|
| ResourceDispatcherHost* ResourceDispatcherHost::Get() {
|
| return g_resource_dispatcher_host;
|
| @@ -751,6 +761,145 @@ void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest(
|
| }
|
| }
|
|
|
| +void ResourceDispatcherHostImpl::AddSchemeForAccessCheck(
|
| + const std::string& scheme) {
|
| + origins_for_access_check_.insert(scheme);
|
| +}
|
| +
|
| +void ResourceDispatcherHostImpl::RegisterOriginForAccessChecks(
|
| + const ResourceContext* context,
|
| + const std::string& origin,
|
| + OriginAccessCheckMask access_check_mask) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + GURL url(origin);
|
| + // The following conditions need to apply before we can add access
|
| + // information for an origin.
|
| + // 1. The URL has to be valid.
|
| + // 2. It has to have a valid host.
|
| + // 3. The scheme has to be registered in the list of schemes being access
|
| + // checked.
|
| + if (!url.is_valid() || !url.has_host() ||
|
| + origins_for_access_check_.find(url.scheme()) ==
|
| + origins_for_access_check_.end()) {
|
| + NOTREACHED() << "Invalid URL or unregistered scheme.";
|
| + return;
|
| + }
|
| +
|
| + OriginAccessInfoMap* origin_access_info_map =
|
| + GetOriginAccessMapForResourceContext(context);
|
| + DCHECK(origin_access_info_map->find(url.host()) ==
|
| + origin_access_info_map->end());
|
| +
|
| + OriginAccessInfo access_info;
|
| + access_info.access_check_mask = access_check_mask;
|
| +
|
| + (*origin_access_info_map)[url.host()] = access_info;
|
| +}
|
| +
|
| +void ResourceDispatcherHostImpl::UnregisterOriginForAccessChecks(
|
| + const ResourceContext* context,
|
| + const std::string& origin) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + GURL url(origin);
|
| + // The scheme has to be registered in the list of schemes being access
|
| + // checked.
|
| + if (origins_for_access_check_.find(url.scheme()) ==
|
| + origins_for_access_check_.end()) {
|
| + NOTREACHED() << "Unregistered scheme for access check";
|
| + return;
|
| + }
|
| + OriginAccessInfoMap* origin_access_info_map =
|
| + GetOriginAccessMapForResourceContext(context);
|
| + OriginAccessInfoMap::iterator index = origin_access_info_map->find(
|
| + url.host());
|
| + if (index != origin_access_info_map->end())
|
| + origin_access_info_map->erase(index);
|
| +}
|
| +
|
| +void ResourceDispatcherHostImpl::AddProcessForOrigin(
|
| + const ResourceContext* context,
|
| + const std::string& origin,
|
| + int process_id,
|
| + bool owner_process) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + GURL url(origin);
|
| + // The following conditions need to apply before we can add the process to
|
| + // the list of allowed processes for an origin.
|
| + // 1. The URL has to be valid.
|
| + // 2. It has to have a valid host.
|
| + // 3. The scheme has to be registered in the list of schemes being access
|
| + // checked.
|
| + if (!url.is_valid() || !url.has_host() ||
|
| + origins_for_access_check_.find(url.scheme()) ==
|
| + origins_for_access_check_.end()) {
|
| + NOTREACHED() << "Invalid URL or unregistered scheme.";
|
| + return;
|
| + }
|
| +
|
| + OriginAccessInfoMap* origin_access_info_map =
|
| + GetOriginAccessMapForResourceContext(context);
|
| + DCHECK(origin_access_info_map);
|
| +
|
| + OriginAccessInfoMap::iterator index = origin_access_info_map->find(
|
| + url.host());
|
| + // No need to add access information for an unregistered host.
|
| + if (index == origin_access_info_map->end())
|
| + return;
|
| +
|
| + OriginAccessInfo& access_info = index->second;
|
| + if (owner_process) {
|
| + access_info.owner_processes[process_id]++;
|
| + } else {
|
| + access_info.other_processes[process_id]++;
|
| + }
|
| +}
|
| +
|
| +void ResourceDispatcherHostImpl::RemoveProcessForOrigin(
|
| + const ResourceContext* context,
|
| + const std::string& origin,
|
| + int process_id,
|
| + bool owner_process) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + GURL url(origin);
|
| + // The scheme has to be registered in the list of schemes being access
|
| + // checked.
|
| + if (origins_for_access_check_.find(url.scheme()) ==
|
| + origins_for_access_check_.end()) {
|
| + DCHECK(false);
|
| + return;
|
| + }
|
| +
|
| + OriginAccessInfoMap* origin_access_info_map =
|
| + GetOriginAccessMapForResourceContext(context);
|
| + DCHECK(origin_access_info_map);
|
| +
|
| + OriginAccessInfoMap::iterator index = origin_access_info_map->find(
|
| + url.host());
|
| + // No need to add access information for an unregistered host.
|
| + if (index == origin_access_info_map->end())
|
| + return;
|
| +
|
| + OriginAccessInfo& access_info = index->second;
|
| +
|
| + std::map<int, int>::iterator process_index;
|
| + std::map<int, int>* process_map = nullptr;
|
| + if (owner_process) {
|
| + process_map = &access_info.owner_processes;
|
| + } else {
|
| + process_map = &access_info.other_processes;
|
| + }
|
| + process_index = process_map->find(process_id);
|
| + // The process has to be there in the list.
|
| + DCHECK(process_index != process_map->end());
|
| + process_index->second--;
|
| + if (process_index->second == 0)
|
| + process_map->erase(process_index);
|
| +}
|
| +
|
| void ResourceDispatcherHostImpl::Shutdown() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| BrowserThread::PostTask(BrowserThread::IO,
|
| @@ -1361,7 +1510,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
|
|
|
| if (is_shutdown_ ||
|
| !ShouldServiceRequest(process_type, child_id, request_data, headers,
|
| - filter_, resource_context)) {
|
| + filter_, resource_context, this)) {
|
| AbortRequestBeforeItStarts(filter_, sync_result, request_id);
|
| return;
|
| }
|
| @@ -2607,4 +2756,61 @@ CertStore* ResourceDispatcherHostImpl::GetCertStore() {
|
| : CertStore::GetInstance();
|
| }
|
|
|
| +ResourceDispatcherHostImpl::OriginAccessInfoMap*
|
| +ResourceDispatcherHostImpl::GetOriginAccessMapForResourceContext(
|
| + const ResourceContext* context) {
|
| + ResourceContextOriginMap::iterator context_index =
|
| + context_origin_access_info_map_.find(context);
|
| + if (context_index != context_origin_access_info_map_.end())
|
| + return context_index->second.get();
|
| +
|
| + context_origin_access_info_map_[context].reset(new OriginAccessInfoMap);
|
| + return context_origin_access_info_map_[context].get();
|
| +}
|
| +
|
| +bool ResourceDispatcherHostImpl::IsIllegalOrigin(ResourceContext* context,
|
| + const GURL& origin,
|
| + int child_process_id) {
|
| + if (origins_for_access_check_.find(origin.scheme()) ==
|
| + origins_for_access_check_.end()) {
|
| + return false;
|
| + }
|
| +
|
| + OriginAccessInfoMap* origin_access_info_map =
|
| + GetOriginAccessMapForResourceContext(
|
| + const_cast<const ResourceContext*>(context));
|
| + DCHECK(origin_access_info_map);
|
| +
|
| + // If the origin is not found then this URL cannot be committed.
|
| + OriginAccessInfoMap::iterator index =
|
| + origin_access_info_map->find(origin.host());
|
| + if (index == origin_access_info_map->end())
|
| + return false;
|
| +
|
| + OriginAccessInfo& access_info = index->second;
|
| + // Owner processes are allowed access by default.
|
| + if (access_info.owner_processes.find(child_process_id) !=
|
| + access_info.owner_processes.end()) {
|
| + return false;
|
| + }
|
| +
|
| + DCHECK(access_info.access_check_mask >= DENY_FOR_NON_OWNERS &&
|
| + access_info.access_check_mask <= ACCESS_CHECK_MASK_LAST);
|
| +
|
| + if (access_info.access_check_mask == DENY_FOR_NON_OWNERS)
|
| + return true;
|
| +
|
| + // No need to check for other processes here.
|
| + if (access_info.access_check_mask == ALLOW_EVERYTHING)
|
| + return false;
|
| +
|
| + // Processes in the other_processes list are allowed.
|
| + if (access_info.other_processes.find(child_process_id) !=
|
| + access_info.other_processes.end()) {
|
| + return false;
|
| + }
|
| + // The origin being accessed is not allowed for the |child_process_id|.
|
| + return true;
|
| +}
|
| +
|
| } // namespace content
|
|
|