Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(998)

Side by Side Diff: chrome/browser/android/offline_pages/offline_page_request_handler.cc

Issue 2002433002: Handle online and offline redirects via interceptor and offline scheme (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "chrome/browser/android/offline_pages/offline_page_request_handler.h"
6
7 #include "base/macros.h"
8 #include "chrome/browser/android/offline_pages/offline_page_utils.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/profiles/profile_manager.h"
12 #include "chrome/common/url_constants.h"
13 #include "components/offline_pages/offline_page_feature.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "net/base/network_change_notifier.h"
16 #include "net/url_request/url_request.h"
17 #include "net/url_request/url_request_redirect_job.h"
18
19 namespace offline_pages {
20
21 namespace {
22
23 int kUserDataKey; // Only address is used.
24
25 // An interceptor to hijack requests and potentially service them based on
26 // their offline information.
27 class OfflinePageRequestInterceptor : public net::URLRequestInterceptor {
28 public:
29 explicit OfflinePageRequestInterceptor(void* profile_id)
30 : profile_id_(profile_id) { }
31 ~OfflinePageRequestInterceptor() override {}
32
33 private:
34 // Overrides from net::URLRequestInterceptor:
35 net::URLRequestJob* MaybeInterceptRequest(
36 net::URLRequest* request,
37 net::NetworkDelegate* network_delegate) const override {
38 OfflinePageRequestHandler* handler = OfflinePageRequestHandler::GetHandler(
39 request);
40 if (!handler)
41 return nullptr;
42 return handler->MaybeCreateJob(request, network_delegate, profile_id_);
43 }
44
45 // The profile for processing Drive accesses. Should not be NULL.
46 void* profile_id_;
47
48 DISALLOW_COPY_AND_ASSIGN(OfflinePageRequestInterceptor);
49 };
50
51 // Called on IO thread after a redirect URL is obtained.
52 void DidGetRedirectURL(const GURL& redirect_url,
53 base::WeakPtr<OfflinePageRequestRedirectJob> job) {
54 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
55
56 if (!job)
57 return;
58
59 if (redirect_url.is_valid())
60 job->SetRedirectURL(redirect_url);
61 else
62 job->FallbackToDefault();
63 }
64
65 // Called on UI thread after an offline URL is obtained.
66 void DidGetOfflineURL(base::WeakPtr<OfflinePageRequestRedirectJob> job,
67 const GURL& online_url,
68 const GURL& offline_file_url) {
69 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
70
71 // DidGetRedirectURL should always be called even when no offline URL is
72 // found.
73 GURL redirect_url;
74 if (offline_file_url.is_valid()) {
75 redirect_url =
76 GURL(chrome::kOfflinePageScheme + std::string(":") + online_url.spec());
77 }
78
79 content::BrowserThread::PostTask(
80 content::BrowserThread::IO,
81 FROM_HERE,
82 base::Bind(&DidGetRedirectURL, redirect_url, job));
83 }
84
85 } // namespace
86
87 // static
88 void OfflinePageRequestHandler::InitializeHandler(
89 net::URLRequest* request,
90 content::ResourceType resource_type) {
91 if (!IsOfflinePagesEnabled())
92 return;
93
94 // Ignore the request not for the main resource file.
95 if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME)
96 return;
97
98 // TODO(jianli): Ignore other requests that will not involve offline
99 // redirects.
100
101 // Any more precise checks to see if the request should be intercepted are
102 // asynchronous, so just create our handler in all cases.
103 std::unique_ptr<OfflinePageRequestHandler> handler(
104 new OfflinePageRequestHandler());
105 request->SetUserData(&kUserDataKey, handler.release());
106 }
107
108 // static
109 OfflinePageRequestHandler* OfflinePageRequestHandler::GetHandler(
110 net::URLRequest* request) {
111 return static_cast<OfflinePageRequestHandler*>(
112 request->GetUserData(&kUserDataKey));
113 }
114
115 // static
116 std::unique_ptr<net::URLRequestInterceptor>
117 OfflinePageRequestHandler::CreateInterceptor(void* profile_id) {
118 if (!IsOfflinePagesEnabled())
119 return nullptr;
120
121 return std::unique_ptr<net::URLRequestInterceptor>(
122 new OfflinePageRequestInterceptor(profile_id));
123 }
124
125 OfflinePageRequestHandler::OfflinePageRequestHandler()
126 : weak_ptr_factory_(this) {
127 }
128
129 OfflinePageRequestHandler::~OfflinePageRequestHandler() {
130 }
131
132 void OfflinePageRequestHandler::OnPrepareToRestart() {
133 use_default_ = true;
134 redirect_job_.reset();
135 }
136
137 net::URLRequestJob* OfflinePageRequestHandler::MaybeCreateJob(
138 net::URLRequest* request,
139 net::NetworkDelegate* network_delegate,
140 void* profile_id) {
141 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
142
143 if (use_default_)
144 return nullptr;
145
146 OfflinePageRequestRedirectJob* redirect_job =
147 new OfflinePageRequestRedirectJob(request, network_delegate, this);
148 redirect_job_ = redirect_job->GetWeakPtr();
149
150 content::BrowserThread::PostTask(
151 content::BrowserThread::UI,
152 FROM_HERE,
153 base::Bind(&OfflinePageRequestHandler::GetRedirectUrl,
154 weak_ptr_factory_.GetWeakPtr(),
155 request->url(),
156 profile_id));
157
158 return redirect_job_.get();
159 }
160
161 void OfflinePageRequestHandler::GetRedirectUrl(const GURL& url,
162 void* profile_id){
163 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
164
165 // |profile_id| needs to be checked with ProfileManager::IsValidProfile
166 // before using it.
167 if (!g_browser_process->profile_manager()->IsValidProfile(profile_id))
168 return;
169 Profile* profile = reinterpret_cast<Profile*>(profile_id);
170
171 if (net::NetworkChangeNotifier::IsOffline()) {
172 // TODO(jianli): Currently offline_url returned by GetOfflineURLForOnlineURL
173 // is the underlying file URL. We should change it to offline scheme URL and
174 // expose file path in another method.
175 OfflinePageUtils::GetOfflineURLForOnlineURL(
176 profile,
177 url,
178 base::Bind(&DidGetOfflineURL, redirect_job_, url));
179 return;
180 }
181
182 GURL redirect_url;
183 if (url.SchemeIs(chrome::kOfflinePageScheme)) {
184 GURL online_url = GURL(url.GetContent());
185 if (online_url.is_valid() && online_url.SchemeIsHTTPOrHTTPS())
186 redirect_url = online_url;
187 }
188
189 content::BrowserThread::PostTask(
190 content::BrowserThread::IO,
191 FROM_HERE,
192 base::Bind(&DidGetRedirectURL, redirect_url, redirect_job_));
193 }
194
195 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698