1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "android_webview/browser/aw_request_interceptor.h" 6 7#include "android_webview/browser/aw_contents_io_thread_client.h" 8#include "android_webview/browser/intercepted_request_data.h" 9#include "base/android/jni_string.h" 10#include "base/memory/scoped_ptr.h" 11#include "content/public/browser/browser_thread.h" 12#include "content/public/browser/render_view_host.h" 13#include "content/public/browser/resource_request_info.h" 14#include "net/url_request/url_request.h" 15#include "net/url_request/url_request_context.h" 16#include "net/url_request/url_request_context_getter.h" 17#include "net/url_request/url_request_job.h" 18 19using content::BrowserThread; 20using content::RenderViewHost; 21using content::ResourceRequestInfo; 22 23namespace android_webview { 24 25namespace { 26 27const void* kURLRequestUserDataKey = &kURLRequestUserDataKey; 28 29class URLRequestUserData : public base::SupportsUserData::Data { 30 public: 31 URLRequestUserData( 32 scoped_ptr<InterceptedRequestData> intercepted_request_data) 33 : intercepted_request_data_(intercepted_request_data.Pass()) { 34 } 35 36 static URLRequestUserData* Get(net::URLRequest* request) { 37 return reinterpret_cast<URLRequestUserData*>( 38 request->GetUserData(kURLRequestUserDataKey)); 39 } 40 41 const InterceptedRequestData* intercepted_request_data() const { 42 return intercepted_request_data_.get(); 43 } 44 45 private: 46 scoped_ptr<InterceptedRequestData> intercepted_request_data_; 47}; 48 49} // namespace 50 51AwRequestInterceptor::AwRequestInterceptor() { 52} 53 54AwRequestInterceptor::~AwRequestInterceptor() { 55} 56 57scoped_ptr<InterceptedRequestData> 58AwRequestInterceptor::QueryForInterceptedRequestData( 59 const GURL& location, 60 net::URLRequest* request) const { 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 62 int render_process_id, render_view_id; 63 if (!ResourceRequestInfo::GetRenderViewForRequest( 64 request, &render_process_id, &render_view_id)) 65 return scoped_ptr<InterceptedRequestData>(); 66 67 scoped_ptr<AwContentsIoThreadClient> io_thread_client = 68 AwContentsIoThreadClient::FromID(render_process_id, render_view_id); 69 70 if (!io_thread_client.get()) 71 return scoped_ptr<InterceptedRequestData>(); 72 73 return io_thread_client->ShouldInterceptRequest(location, request).Pass(); 74} 75 76net::URLRequestJob* AwRequestInterceptor::MaybeCreateJob( 77 net::URLRequest* request, 78 net::NetworkDelegate* network_delegate) const { 79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 80 81 // See if we've already found out the intercepted_request_data for this 82 // request. 83 // This is done not only for efficiency reasons, but also for correctness 84 // as it is possible for the Interceptor chain to be invoked more than once 85 // (in which case we don't want to query the embedder multiple times). 86 URLRequestUserData* user_data = URLRequestUserData::Get(request); 87 88 if (!user_data) { 89 // To ensure we only query the embedder once, we rely on the fact that the 90 // user_data object will be created and attached to the URLRequest after a 91 // call to QueryForInterceptedRequestData is made (regardless of whether 92 // the result of that call is a valid InterceptedRequestData* pointer or 93 // NULL. 94 user_data = new URLRequestUserData( 95 QueryForInterceptedRequestData(request->url(), request)); 96 request->SetUserData(kURLRequestUserDataKey, user_data); 97 } 98 99 const InterceptedRequestData* intercepted_request_data = 100 user_data->intercepted_request_data(); 101 102 if (!intercepted_request_data) 103 return NULL; 104 return intercepted_request_data->CreateJobFor(request, network_delegate); 105} 106 107} // namespace android_webview 108