summaryrefslogtreecommitdiff
path: root/chromium/content/browser/appcache/appcache_interceptor.cc
blob: 95e24b01a877bf300a42f3a2e1f461b85cea1055 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// 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 "content/browser/appcache/appcache_interceptor.h"

#include <utility>

#include "base/debug/crash_logging.h"
#include "content/browser/appcache/appcache_backend_impl.h"
#include "content/browser/appcache/appcache_host.h"
#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/appcache/appcache_url_request.h"
#include "content/browser/appcache/appcache_url_request_job.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/bad_message.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_requester_info.h"
#include "content/common/appcache_interfaces.h"
#include "net/url_request/url_request.h"

static int kHandlerKey;  // Value is not used.

namespace content {

void AppCacheInterceptor::SetHandler(
    net::URLRequest* request,
    std::unique_ptr<AppCacheRequestHandler> handler) {
  request->SetUserData(&kHandlerKey, std::move(handler));
}

AppCacheRequestHandler* AppCacheInterceptor::GetHandler(
    net::URLRequest* request) {
  return static_cast<AppCacheRequestHandler*>(
      request->GetUserData(&kHandlerKey));
}

void AppCacheInterceptor::SetExtraRequestInfo(net::URLRequest* request,
                                              AppCacheServiceImpl* service,
                                              int process_id,
                                              int host_id,
                                              ResourceType resource_type,
                                              bool should_reset_appcache) {
  if (!service || (host_id == kAppCacheNoHostId))
    return;

  AppCacheBackendImpl* backend = service->GetBackend(process_id);
  if (!backend)
    return;

  // TODO(michaeln): An invalid host id is indicative of bad data
  // from a child process. How should we handle that here?
  AppCacheHost* host = backend->GetHost(host_id);
  if (!host)
    return;

  SetExtraRequestInfoForHost(request, host, resource_type,
                             should_reset_appcache);
}

void AppCacheInterceptor::SetExtraRequestInfoForHost(
    net::URLRequest* request,
    AppCacheHost* host,
    ResourceType resource_type,
    bool should_reset_appcache) {
  // Create a handler for this request and associate it with the request.
  std::unique_ptr<AppCacheRequestHandler> handler =
      host->CreateRequestHandler(AppCacheURLRequest::Create(request),
                                 resource_type, should_reset_appcache);
  if (handler)
    SetHandler(request, std::move(handler));
}

void AppCacheInterceptor::GetExtraResponseInfo(net::URLRequest* request,
                                               int64_t* cache_id,
                                               GURL* manifest_url) {
  DCHECK(*cache_id == kAppCacheNoCacheId);
  DCHECK(manifest_url->is_empty());
  AppCacheRequestHandler* handler = GetHandler(request);
  if (handler)
    handler->GetExtraResponseInfo(cache_id, manifest_url);
}

void AppCacheInterceptor::PrepareForCrossSiteTransfer(
    net::URLRequest* request,
    int old_process_id) {
  AppCacheRequestHandler* handler = GetHandler(request);
  if (!handler)
    return;
  handler->PrepareForCrossSiteTransfer(old_process_id);
}

void AppCacheInterceptor::CompleteCrossSiteTransfer(
    net::URLRequest* request,
    int new_process_id,
    int new_host_id,
    ResourceRequesterInfo* requester_info) {
  // AppCache is supported only for renderer initiated requests.
  DCHECK(requester_info->IsRenderer());
  AppCacheRequestHandler* handler = GetHandler(request);
  if (!handler)
    return;
  if (!handler->SanityCheckIsSameService(requester_info->appcache_service())) {
    // This can happen when V2 apps and web pages end up in the same storage
    // partition.
    const GURL& first_party_url_for_cookies = request->site_for_cookies();
    if (first_party_url_for_cookies.is_valid()) {
      // TODO(lazyboy): Remove this once we know which extensions run into this
      // issue. See https://crbug.com/612711#c25 for details.
      base::debug::SetCrashKeyValue("aci_wrong_sp_extension_id",
                                    first_party_url_for_cookies.host());
      // No need to explicitly call DumpWithoutCrashing(), since
      // bad_message::ReceivedBadMessage() below will do that.
    }
    bad_message::ReceivedBadMessage(requester_info->filter(),
                                    bad_message::ACI_WRONG_STORAGE_PARTITION);
    return;
  }
  DCHECK_NE(kAppCacheNoHostId, new_host_id);
  handler->CompleteCrossSiteTransfer(new_process_id, new_host_id);
}

void AppCacheInterceptor::MaybeCompleteCrossSiteTransferInOldProcess(
    net::URLRequest* request,
    int process_id) {
  AppCacheRequestHandler* handler = GetHandler(request);
  if (!handler)
    return;
  handler->MaybeCompleteCrossSiteTransferInOldProcess(process_id);
}

AppCacheInterceptor::AppCacheInterceptor() {
}

AppCacheInterceptor::~AppCacheInterceptor() {
}

net::URLRequestJob* AppCacheInterceptor::MaybeInterceptRequest(
    net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
  AppCacheRequestHandler* handler = GetHandler(request);
  if (!handler)
    return NULL;

  AppCacheJob* job = handler->MaybeLoadResource(network_delegate);
  return job ? job->AsURLRequestJob() : nullptr;
}

net::URLRequestJob* AppCacheInterceptor::MaybeInterceptRedirect(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate,
    const GURL& location) const {
  AppCacheRequestHandler* handler = GetHandler(request);
  if (!handler)
    return NULL;

  AppCacheJob* job =
      handler->MaybeLoadFallbackForRedirect(network_delegate, location);
  return job ? job->AsURLRequestJob() : nullptr;
}

net::URLRequestJob* AppCacheInterceptor::MaybeInterceptResponse(
    net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
  AppCacheRequestHandler* handler = GetHandler(request);
  if (!handler)
    return NULL;

  AppCacheJob* job = handler->MaybeLoadFallbackForResponse(network_delegate);
  return job ? job->AsURLRequestJob() : nullptr;
}

}  // namespace content