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

Side by Side Diff: chrome/browser/prerender/prerender_link_manager.cc

Issue 11316311: Make PrerenderHandle an observer of PrerenderContents. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: clear to land Created 8 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/prerender/prerender_link_manager.h" 5 #include "chrome/browser/prerender/prerender_link_manager.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <queue>
9 #include <utility> 8 #include <utility>
10 9
10 #include "base/memory/scoped_ptr.h"
11 #include "chrome/browser/prerender/prerender_contents.h" 11 #include "chrome/browser/prerender/prerender_contents.h"
12 #include "chrome/browser/prerender/prerender_handle.h" 12 #include "chrome/browser/prerender/prerender_handle.h"
13 #include "chrome/browser/prerender/prerender_manager.h" 13 #include "chrome/browser/prerender/prerender_manager.h"
14 #include "chrome/browser/prerender/prerender_manager_factory.h" 14 #include "chrome/browser/prerender/prerender_manager_factory.h"
15 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/prerender_messages.h"
17 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/render_view_host.h" 18 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/session_storage_namespace.h" 19 #include "content/public/browser/session_storage_namespace.h"
18 #include "content/public/common/referrer.h" 20 #include "content/public/common/referrer.h"
19 #include "googleurl/src/gurl.h" 21 #include "googleurl/src/gurl.h"
20 #include "ui/gfx/size.h" 22 #include "ui/gfx/size.h"
21 23
22 using content::RenderViewHost; 24 using content::RenderViewHost;
23 using content::SessionStorageNamespace; 25 using content::SessionStorageNamespace;
24 26
27 namespace {
28
29 void Send(int child_id, IPC::Message* raw_message) {
30 using content::RenderProcessHost;
31 scoped_ptr<IPC::Message> own_message(raw_message);
32
33 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id);
34 if (!render_process_host)
35 return;
36 render_process_host->Send(own_message.release());
37 }
38
39 } // namespace
40
25 namespace prerender { 41 namespace prerender {
26 42
27 PrerenderLinkManager::PrerenderLinkManager(PrerenderManager* manager) 43 PrerenderLinkManager::PrerenderLinkManager(PrerenderManager* manager)
28 : manager_(manager) { 44 : manager_(manager) {
29 } 45 }
30 46
31 PrerenderLinkManager::~PrerenderLinkManager() { 47 PrerenderLinkManager::~PrerenderLinkManager() {
32 for (IdPairToPrerenderHandleMap::iterator it = ids_to_handle_map_.begin(); 48 for (IdPairToPrerenderHandleMap::iterator it = ids_to_handle_map_.begin();
33 it != ids_to_handle_map_.end(); 49 it != ids_to_handle_map_.end();
34 ++it) { 50 ++it) {
35 PrerenderHandle* prerender_handle = it->second; 51 PrerenderHandle* prerender_handle = it->second;
36 prerender_handle->OnCancel(); 52 DCHECK(!prerender_handle->IsPrerendering())
53 << "All running prerenders should stop at the same time as the "
54 << "PrerenderManager.";
37 delete prerender_handle; 55 delete prerender_handle;
38 } 56 }
39 } 57 }
40 58
41 bool PrerenderLinkManager::OnAddPrerender(int child_id, 59 bool PrerenderLinkManager::OnAddPrerender(int child_id,
42 int prerender_id, 60 int prerender_id,
43 const GURL& url, 61 const GURL& url,
44 const content::Referrer& referrer, 62 const content::Referrer& referrer,
45 const gfx::Size& size, 63 const gfx::Size& size,
46 int render_view_route_id) { 64 int render_view_route_id) {
47 DVLOG(2) << "OnAddPrerender, child_id = " << child_id 65 DVLOG(2) << "OnAddPrerender, child_id = " << child_id
48 << ", prerender_id = " << prerender_id 66 << ", prerender_id = " << prerender_id
49 << ", url = " << url.spec(); 67 << ", url = " << url.spec();
50 DVLOG(3) << "... referrer url = " << referrer.url.spec() 68 DVLOG(3) << "... referrer url = " << referrer.url.spec()
51 << ", size = (" << size.width() << ", " << size.height() << ")" 69 << ", size = (" << size.width() << ", " << size.height() << ")"
52 << ", render_view_route_id = " << render_view_route_id; 70 << ", render_view_route_id = " << render_view_route_id;
53 71
72
73 PrerenderHandle* prerender_handle =
74 manager_->AddPrerenderFromLinkRelPrerender(
75 child_id, render_view_route_id, url, referrer, size);
76 if (!prerender_handle)
77 return false;
78
54 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); 79 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id);
55 DCHECK_EQ(0U, ids_to_handle_map_.count(child_and_prerender_id)); 80 DCHECK_EQ(0u, ids_to_handle_map_.count(child_and_prerender_id));
81 ids_to_handle_map_[child_and_prerender_id] = prerender_handle;
56 82
57 scoped_ptr<PrerenderHandle> prerender_handle( 83 // If we are given a prerender that is already prerendering, we have missed
58 manager_->AddPrerenderFromLinkRelPrerender( 84 // the start event.
59 child_id, render_view_route_id, url, referrer, size)); 85 if (prerender_handle->IsPrerendering())
60 if (prerender_handle.get()) { 86 OnPrerenderStart(prerender_handle);
61 std::pair<IdPairToPrerenderHandleMap::iterator, bool> insert_result = 87 prerender_handle->SetObserver(this);
62 ids_to_handle_map_.insert(std::make_pair( 88 return true;
63 child_and_prerender_id, static_cast<PrerenderHandle*>(NULL)));
64 DCHECK(insert_result.second);
65 delete insert_result.first->second;
66 insert_result.first->second = prerender_handle.release();
67 return true;
68 }
69 return false;
70 } 89 }
71 90
72 // TODO(gavinp): Once an observer interface is provided down to the WebKit
73 // layer, we should add DCHECK_NE(0L, ids_to_url_map_.count(...)) to both
74 // OnCancelPrerender and OnAbandonPrerender. We can't do this now, since
75 // the WebKit layer isn't even aware if we didn't add the prerender to the map
76 // in OnAddPrerender above.
77 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { 91 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) {
78 DVLOG(2) << "OnCancelPrerender, child_id = " << child_id 92 DVLOG(2) << "OnCancelPrerender, child_id = " << child_id
79 << ", prerender_id = " << prerender_id; 93 << ", prerender_id = " << prerender_id;
80 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); 94 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id);
81 IdPairToPrerenderHandleMap::iterator id_to_handle_iter = 95 IdPairToPrerenderHandleMap::iterator id_to_handle_iter =
82 ids_to_handle_map_.find(child_and_prerender_id); 96 ids_to_handle_map_.find(child_and_prerender_id);
83 if (id_to_handle_iter == ids_to_handle_map_.end()) { 97 if (id_to_handle_iter == ids_to_handle_map_.end()) {
84 DVLOG(5) << "... canceling a prerender that doesn't exist."; 98 DVLOG(5) << "... canceling a prerender that doesn't exist.";
85 return; 99 return;
86 } 100 }
87 PrerenderHandle* prerender_handle = id_to_handle_iter->second; 101 PrerenderHandle* prerender_handle = id_to_handle_iter->second;
88 prerender_handle->OnCancel(); 102 prerender_handle->OnCancel();
89 RemovePrerender(id_to_handle_iter); 103
104 // Because OnCancel() can remove the prerender from the map, we need to
105 // consider our iterator invalid.
106 id_to_handle_iter = ids_to_handle_map_.find(child_and_prerender_id);
107 if (id_to_handle_iter != ids_to_handle_map_.end())
108 RemovePrerender(id_to_handle_iter);
90 } 109 }
91 110
92 void PrerenderLinkManager::OnAbandonPrerender(int child_id, int prerender_id) { 111 void PrerenderLinkManager::OnAbandonPrerender(int child_id, int prerender_id) {
93 DVLOG(2) << "OnAbandonPrerender, child_id = " << child_id 112 DVLOG(2) << "OnAbandonPrerender, child_id = " << child_id
94 << ", prerender_id = " << prerender_id; 113 << ", prerender_id = " << prerender_id;
95 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); 114 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id);
96 IdPairToPrerenderHandleMap::iterator id_to_handle_iter = 115 IdPairToPrerenderHandleMap::iterator id_to_handle_iter =
97 ids_to_handle_map_.find(child_and_prerender_id); 116 ids_to_handle_map_.find(child_and_prerender_id);
98 if (id_to_handle_iter == ids_to_handle_map_.end()) 117 if (id_to_handle_iter == ids_to_handle_map_.end())
99 return; 118 return;
100 PrerenderHandle* prerender_handle = id_to_handle_iter->second; 119 PrerenderHandle* prerender_handle = id_to_handle_iter->second;
101 prerender_handle->OnNavigateAway(); 120 prerender_handle->OnNavigateAway();
102 RemovePrerender(id_to_handle_iter);
103 } 121 }
104 122
105 void PrerenderLinkManager::OnChannelClosing(int child_id) { 123 void PrerenderLinkManager::OnChannelClosing(int child_id) {
106 DVLOG(2) << "OnChannelClosing, child id = " << child_id; 124 DVLOG(2) << "OnChannelClosing, child id = " << child_id;
107 const ChildAndPrerenderIdPair child_and_minimum_prerender_id( 125 const ChildAndPrerenderIdPair child_and_minimum_prerender_id(
108 child_id, std::numeric_limits<int>::min()); 126 child_id, std::numeric_limits<int>::min());
109 const ChildAndPrerenderIdPair child_and_maximum_prerender_id( 127 const ChildAndPrerenderIdPair child_and_maximum_prerender_id(
110 child_id, std::numeric_limits<int>::max()); 128 child_id, std::numeric_limits<int>::max());
111 std::queue<int> prerender_ids_to_abandon; 129
112 for (IdPairToPrerenderHandleMap::iterator 130 IdPairToPrerenderHandleMap::iterator
113 i = ids_to_handle_map_.lower_bound(child_and_minimum_prerender_id), 131 it = ids_to_handle_map_.lower_bound(child_and_minimum_prerender_id);
114 e = ids_to_handle_map_.upper_bound(child_and_maximum_prerender_id); 132 IdPairToPrerenderHandleMap::iterator
115 i != e; ++i) { 133 end = ids_to_handle_map_.upper_bound(child_and_maximum_prerender_id);
116 prerender_ids_to_abandon.push(i->first.second); 134 while (it != end) {
117 } 135 IdPairToPrerenderHandleMap::iterator next = it;
118 while (!prerender_ids_to_abandon.empty()) { 136 ++next;
119 DVLOG(4) << "---> abandon prerender_id = " 137
120 << prerender_ids_to_abandon.front(); 138 size_t size_before_abandon = ids_to_handle_map_.size();
121 OnAbandonPrerender(child_id, prerender_ids_to_abandon.front()); 139 OnAbandonPrerender(child_id, it->first.second);
122 prerender_ids_to_abandon.pop(); 140 DCHECK_EQ(size_before_abandon, ids_to_handle_map_.size());
141 RemovePrerender(it);
142
143 it = next;
123 } 144 }
124 } 145 }
125 146
126 bool PrerenderLinkManager::IsEmpty() const { 147 bool PrerenderLinkManager::IsEmpty() const {
127 return ids_to_handle_map_.empty(); 148 return ids_to_handle_map_.empty();
128 } 149 }
129 150
130 void PrerenderLinkManager::RemovePrerender( 151 void PrerenderLinkManager::RemovePrerender(
131 const IdPairToPrerenderHandleMap::iterator& id_to_handle_iter) { 152 const IdPairToPrerenderHandleMap::iterator& id_to_handle_iter) {
132 PrerenderHandle* prerender_handle = id_to_handle_iter->second; 153 PrerenderHandle* prerender_handle = id_to_handle_iter->second;
133 delete prerender_handle; 154 delete prerender_handle;
134 ids_to_handle_map_.erase(id_to_handle_iter); 155 ids_to_handle_map_.erase(id_to_handle_iter);
135 } 156 }
136 157
158 PrerenderLinkManager::IdPairToPrerenderHandleMap::iterator
159 PrerenderLinkManager::FindPrerenderHandle(
160 PrerenderHandle* prerender_handle) {
161 for (IdPairToPrerenderHandleMap::iterator it = ids_to_handle_map_.begin();
162 it != ids_to_handle_map_.end(); ++it) {
163 if (it->second == prerender_handle)
164 return it;
165 }
166 return ids_to_handle_map_.end();
167 }
168
169 // In practice, this is always called from either
170 // PrerenderLinkManager::OnAddPrerender in the regular case, or in the pending
171 // prerender case, from PrerenderHandle::AdoptPrerenderDataFrom.
172 void PrerenderLinkManager::OnPrerenderStart(
173 PrerenderHandle* prerender_handle) {
174 IdPairToPrerenderHandleMap::iterator it =
175 FindPrerenderHandle(prerender_handle);
176 DCHECK(it != ids_to_handle_map_.end());
177 const int child_id = it->first.first;
178 const int prerender_id = it->first.second;
179
180 Send(child_id, new PrerenderMsg_OnPrerenderStart(prerender_id));
181 }
182
183 void PrerenderLinkManager::OnPrerenderAddAlias(
184 PrerenderHandle* prerender_handle,
185 const GURL& alias_url) {
186 IdPairToPrerenderHandleMap::iterator it =
187 FindPrerenderHandle(prerender_handle);
188 if (it == ids_to_handle_map_.end())
189 return;
190 const int child_id = it->first.first;
191 const int prerender_id = it->first.second;
192
193 Send(child_id, new PrerenderMsg_OnPrerenderAddAlias(prerender_id, alias_url));
194 }
195
196 void PrerenderLinkManager::OnPrerenderStop(
197 PrerenderHandle* prerender_handle) {
198 IdPairToPrerenderHandleMap::iterator it =
199 FindPrerenderHandle(prerender_handle);
200 if (it == ids_to_handle_map_.end())
201 return;
202 const int child_id = it->first.first;
203 const int prerender_id = it->first.second;
204
205 Send(child_id, new PrerenderMsg_OnPrerenderStop(prerender_id));
206 RemovePrerender(it);
207 }
208
137 } // namespace prerender 209 } // namespace prerender
OLDNEW
« no previous file with comments | « chrome/browser/prerender/prerender_link_manager.h ('k') | chrome/browser/prerender/prerender_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698