| Index: content/browser/webui/url_data_manager_backend.cc
 | 
| diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc
 | 
| index ff7a79a29821a581465d9c0104037aadf3b93f3f..fe1015f87e445c77ae396386df9182b94fc81cd0 100644
 | 
| --- a/content/browser/webui/url_data_manager_backend.cc
 | 
| +++ b/content/browser/webui/url_data_manager_backend.cc
 | 
| @@ -180,7 +180,13 @@
 | 
|  
 | 
|    // Helper for Start(), to let us start asynchronously.
 | 
|    // (This pattern is shared by most net::URLRequestJob implementations.)
 | 
| -  void StartAsync();
 | 
| +  void StartAsync(bool allowed);
 | 
| +
 | 
| +  // Called on the UI thread to check if this request is allowed.
 | 
| +  static void CheckStoragePartitionMatches(
 | 
| +      int render_process_id,
 | 
| +      const GURL& url,
 | 
| +      const base::WeakPtr<URLRequestChromeJob>& job);
 | 
|  
 | 
|    // Specific resources require unsafe-eval in the Content Security Policy.
 | 
|    bool RequiresUnsafeEval() const;
 | 
| @@ -257,14 +263,40 @@
 | 
|  }
 | 
|  
 | 
|  void URLRequestChromeJob::Start() {
 | 
| -  // Start reading asynchronously so that all error reporting and data
 | 
| -  // callbacks happen as they would for network requests.
 | 
| -  base::MessageLoop::current()->PostTask(
 | 
| +  const GURL url = request_->url();
 | 
| +
 | 
| +  TRACE_EVENT_ASYNC_BEGIN1("browser", "DataManager:Request", this, "URL",
 | 
| +      url.possibly_invalid_spec());
 | 
| +
 | 
| +  int render_process_id, unused;
 | 
| +  bool is_renderer_request = ResourceRequestInfo::GetRenderFrameForRequest(
 | 
| +      request_, &render_process_id, &unused);
 | 
| +
 | 
| +  if (!is_renderer_request) {
 | 
| +    StartAsync(true);
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  if (url.SchemeIs(kChromeUIScheme)) {
 | 
| +    // TODO(dbeam): it's not clear that partition checking is needed or used. It
 | 
| +    // was added for iframe-based signin (http://crbug.com/338127), which has
 | 
| +    // since changed. We should remove if no longer necessary.
 | 
| +    std::vector<std::string> hosts;
 | 
| +    hosts.push_back(content::kChromeUIResourcesHost);
 | 
| +    GetContentClient()->
 | 
| +        browser()->GetAdditionalWebUIHostsToIgnoreParititionCheck(&hosts);
 | 
| +    if (std::find(hosts.begin(), hosts.end(), url.host()) != hosts.end()) {
 | 
| +      StartAsync(true);
 | 
| +      return;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  BrowserThread::PostTask(
 | 
| +      BrowserThread::UI,
 | 
|        FROM_HERE,
 | 
| -      base::Bind(&URLRequestChromeJob::StartAsync, weak_factory_.GetWeakPtr()));
 | 
| -
 | 
| -  TRACE_EVENT_ASYNC_BEGIN1("browser", "DataManager:Request", this, "URL",
 | 
| -      request_->url().possibly_invalid_spec());
 | 
| +      base::Bind(&URLRequestChromeJob::CheckStoragePartitionMatches,
 | 
| +                 render_process_id, url,
 | 
| +                 weak_factory_.GetWeakPtr()));
 | 
|  }
 | 
|  
 | 
|  void URLRequestChromeJob::Kill() {
 | 
| @@ -374,11 +406,33 @@
 | 
|    return buf_size;
 | 
|  }
 | 
|  
 | 
| -void URLRequestChromeJob::StartAsync() {
 | 
| +void URLRequestChromeJob::CheckStoragePartitionMatches(
 | 
| +    int render_process_id,
 | 
| +    const GURL& url,
 | 
| +    const base::WeakPtr<URLRequestChromeJob>& job) {
 | 
| +  // The embedder could put some webui pages in separate storage partition.
 | 
| +  // RenderProcessHostImpl::IsSuitableHost would guard against top level pages
 | 
| +  // being in the same process. We do an extra check to guard against an
 | 
| +  // exploited renderer pretending to add them as a subframe. We skip this check
 | 
| +  // for resources.
 | 
| +  bool allowed = false;
 | 
| +  RenderProcessHost* process = RenderProcessHost::FromID(render_process_id);
 | 
| +  if (process) {
 | 
| +    StoragePartition* partition = BrowserContext::GetStoragePartitionForSite(
 | 
| +        process->GetBrowserContext(), url);
 | 
| +    allowed = partition == process->GetStoragePartition();
 | 
| +  }
 | 
| +  BrowserThread::PostTask(
 | 
| +      BrowserThread::IO,
 | 
| +      FROM_HERE,
 | 
| +      base::Bind(&URLRequestChromeJob::StartAsync, job, allowed));
 | 
| +}
 | 
| +
 | 
| +void URLRequestChromeJob::StartAsync(bool allowed) {
 | 
|    if (!request_)
 | 
|      return;
 | 
|  
 | 
| -  if (!backend_->StartRequest(request_, this)) {
 | 
| +  if (!allowed || !backend_->StartRequest(request_, this)) {
 | 
|      NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
 | 
|                                             net::ERR_INVALID_URL));
 | 
|    }
 | 
| 
 |