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* kRequestAlreadyQueriedDataKey = &kRequestAlreadyQueriedDataKey;
28
29} // namespace
30
31AwRequestInterceptor::AwRequestInterceptor() {
32}
33
34AwRequestInterceptor::~AwRequestInterceptor() {
35}
36
37scoped_ptr<InterceptedRequestData>
38AwRequestInterceptor::QueryForInterceptedRequestData(
39    const GURL& location,
40    net::URLRequest* request) const {
41  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
42  int render_process_id, render_view_id;
43  if (!ResourceRequestInfo::GetRenderViewForRequest(
44      request, &render_process_id, &render_view_id))
45    return scoped_ptr<InterceptedRequestData>();
46
47  scoped_ptr<AwContentsIoThreadClient> io_thread_client =
48    AwContentsIoThreadClient::FromID(render_process_id, render_view_id);
49
50  if (!io_thread_client.get())
51    return scoped_ptr<InterceptedRequestData>();
52
53  return io_thread_client->ShouldInterceptRequest(location, request).Pass();
54}
55
56net::URLRequestJob* AwRequestInterceptor::MaybeCreateJob(
57    net::URLRequest* request,
58    net::NetworkDelegate* network_delegate) const {
59  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
60
61  // See if we've already found out the intercepted_request_data for this
62  // request.
63  // This is done not only for efficiency reasons, but also for correctness
64  // as it is possible for the Interceptor chain to be invoked more than once
65  // in which case we don't want to query the embedder multiple times.
66  // Note: The Interceptor chain is not invoked more than once if we create a
67  // URLRequestJob in this method, so this is only caching negative hits.
68  if (request->GetUserData(kRequestAlreadyQueriedDataKey))
69    return NULL;
70  request->SetUserData(kRequestAlreadyQueriedDataKey,
71                       new base::SupportsUserData::Data());
72
73  scoped_ptr<InterceptedRequestData> intercepted_request_data =
74      QueryForInterceptedRequestData(request->url(), request);
75
76  if (!intercepted_request_data)
77    return NULL;
78
79  // The newly created job will own the InterceptedRequestData.
80  return InterceptedRequestData::CreateJobFor(
81      intercepted_request_data.Pass(), request, network_delegate);
82}
83
84} // namespace android_webview
85