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

Side by Side Diff: content/browser/appcache/appcache_frame_node_navigation.cc

Issue 2501343003: PlzNavigate: AppCache support. (Closed)
Patch Set: Add DCHECKs for PlzNavigate and fix a double Release problem which caused one unit_test to fail wit… Created 4 years, 1 month 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 "content/browser/appcache/appcache_frame_node_navigation.h"
6
7 #include <map>
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/lazy_instance.h"
11 #include "content/browser/appcache/appcache_dispatcher_host.h"
12 #include "content/browser/appcache/chrome_appcache_service.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/common/browser_side_navigation_policy.h"
15
16 namespace {
17
18 typedef std::map<int, content::AppCacheFrameNavigationHandler*>
19 FrameToNavigationHandlerMap;
20 base::LazyInstance<FrameToNavigationHandlerMap> g_frame_navigation_handler_map;
21
22 // PlzNavigate: Used to generate the host id for a navigation initiated by the
23 // browser. Starts at -2 and keeps going down.
24 static int g_next_appcache_host_id = -2;
25
26 } // namespace
27
28 namespace content {
29
30 AppCacheFrameNavigationHandler::AppCacheFrameNavigationHandler(
31 ChromeAppCacheService* appcache_service,
32 int frame_node_id)
33 : frame_node_id_(frame_node_id),
34 appcache_service_(appcache_service),
35 frontend_proxy_(this),
36 commit_received_(false),
37 weak_factory_(this) {
38 DCHECK_CURRENTLY_ON(BrowserThread::UI);
39 AddRef();
40 g_frame_navigation_handler_map.Get()[frame_node_id] = this;
41 }
42
43 AppCacheFrameNavigationHandler::~AppCacheFrameNavigationHandler() {
44 DCHECK_CURRENTLY_ON(BrowserThread::IO);
45 }
46
47 // static
48 int AppCacheFrameNavigationHandler::BeginNavigation(
49 AppCacheServiceImpl* appcache_service,
50 int frame_node_id) {
51 DCHECK(IsBrowserSideNavigationEnabled());
52 DCHECK_CURRENTLY_ON(BrowserThread::UI);
53
54 if (!appcache_service)
55 return kAppCacheNoHostId;
56
57 // If we have an existing AppCacheFrameNavigationHandler for the
58 // |frame_node_id| passed in, we have no choice at this point but to
59 // release that instance.
60 // Please note this only happens if the tasks we posted below never
61 // ran.
62 FrameToNavigationHandlerMap::iterator index =
63 g_frame_navigation_handler_map.Get().find(frame_node_id);
64 if (index != g_frame_navigation_handler_map.Get().end()) {
65 if (!index->second->commit_received_)
66 index->second->Release();
67 }
68
69 AppCacheFrameNavigationHandler* navigation_handler =
70 new AppCacheFrameNavigationHandler(
71 static_cast<ChromeAppCacheService*>(appcache_service), frame_node_id);
72 g_frame_navigation_handler_map.Get()[frame_node_id] = navigation_handler;
73
74 int host_id = g_next_appcache_host_id--;
75
76 BrowserThread::PostTask(
77 BrowserThread::IO, FROM_HERE,
78 base::Bind(&AppCacheFrameNavigationHandler::RegisterPendingHostHelper,
79 navigation_handler->weak_factory_.GetWeakPtr(), host_id));
80
81 return host_id;
82 }
83
84 // static
85 void AppCacheFrameNavigationHandler::CommitNavigation(int frame_node_id,
86 int process_id) {
87 DCHECK(IsBrowserSideNavigationEnabled());
88 DCHECK_CURRENTLY_ON(BrowserThread::UI);
89
90 DCHECK(g_frame_navigation_handler_map.Get().find(frame_node_id) !=
91 g_frame_navigation_handler_map.Get().end());
92
93 g_frame_navigation_handler_map.Get()[frame_node_id]->commit_received_ = true;
94
95 BrowserThread::PostTask(
96 BrowserThread::IO, FROM_HERE,
97 base::Bind(&AppCacheFrameNavigationHandler::CommitNavigationHelper,
98 g_frame_navigation_handler_map.Get()[frame_node_id]
99 ->weak_factory_.GetWeakPtr(),
100 process_id));
101 }
102
103 void AppCacheFrameNavigationHandler::FailedNavigation(int frame_node_id) {
104 DCHECK(IsBrowserSideNavigationEnabled());
105 DCHECK_CURRENTLY_ON(BrowserThread::UI);
106
107 FrameToNavigationHandlerMap::iterator index =
108 g_frame_navigation_handler_map.Get().find(frame_node_id);
109
110 DCHECK(index != g_frame_navigation_handler_map.Get().end());
111
112 index->second->Release();
113 }
114
115 bool AppCacheFrameNavigationHandler::Send(IPC::Message* msg) {
116 DCHECK(false);
117 return false;
118 }
119
120 void AppCacheFrameNavigationHandler::RegisterPendingHostHelper(int host_id) {
121 DCHECK(IsBrowserSideNavigationEnabled());
122 DCHECK_CURRENTLY_ON(BrowserThread::IO);
123 DCHECK(!backend_impl_.get());
124 backend_impl_.reset(new AppCacheBackendImpl);
125 backend_impl_->Initialize(appcache_service_.get(), &frontend_proxy_, -1,
126 frame_node_id_);
127 backend_impl_->RegisterHost(host_id);
128 }
129
130 void AppCacheFrameNavigationHandler::CommitNavigationHelper(int process_id) {
131 DCHECK(IsBrowserSideNavigationEnabled());
132 DCHECK_CURRENTLY_ON(BrowserThread::IO);
133 DCHECK(backend_impl_.get());
134
135 // When the navigation for a frame tree node commits, we need to switch the
136 // AppCacheBackendImpl instance from a frame based navigation to a process
137 // based navigation. For this we unregister the AppCacheBackendImpl instance
138 // from the AppCache service. We then set the process id in the
139 // AppCacheBackendImpl instance. This ensures that it is registered using
140 // the process id in the AppCacheDispatcherHost::FrameNavigationCommitted()
141 // function.
142 appcache_service_->UnregisterBackendForFrame(backend_impl_.get());
143
144 scoped_refptr<AppCacheDispatcherHost> dispatcher_host =
145 AppCacheDispatcherHost::GetHostForProcess(process_id);
146 if (dispatcher_host.get()) {
147 backend_impl_->set_process_id(process_id);
148 backend_impl_->set_frame_id(-1);
149 dispatcher_host->FrameNavigationCommitted(std::move(backend_impl_));
150 }
151
152 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
153 base::Bind(&AppCacheFrameNavigationHandler::Release,
154 base::Unretained(this)));
155 // Don't access any member from here on.
156 }
157
158 void AppCacheFrameNavigationHandler::DeleteOnCorrectThread() const {
159 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
160 // The reference to us in the global map needs to be remove in the UI
161 // thread.
162 FrameToNavigationHandlerMap::iterator index =
163 g_frame_navigation_handler_map.Get().find(frame_node_id_);
164 if ((index != g_frame_navigation_handler_map.Get().end()) &&
165 index->second == this) {
166 g_frame_navigation_handler_map.Get().erase(index);
167 }
168 }
169
170 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
michaeln 2016/11/22 00:17:27 if we go thru this code path, we do we leave a dan
ananta 2016/11/23 04:05:14 This file has gone
171 delete this;
172 return;
173 }
174
175 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
176 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this);
177 return;
178 }
179
180 // Better to leak than crash on shutdown.
181 }
182
183 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698