Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 "chrome/browser/prerender/prerender_link_manager.h" | |
| 6 | |
| 7 #include <limits> | |
| 8 #include <queue> | |
| 9 #include <utility> | |
| 10 | |
| 11 #include "chrome/browser/prerender/prerender_contents.h" | |
| 12 #include "chrome/browser/prerender/prerender_manager.h" | |
| 13 #include "chrome/browser/prerender/prerender_manager_factory.h" | |
| 14 #include "chrome/browser/profiles/profile.h" | |
| 15 #include "content/public/common/referrer.h" | |
| 16 #include "googleurl/src/gurl.h" | |
| 17 #include "googleurl/src/url_canon.h" | |
| 18 #include "ui/gfx/size.h" | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 template<typename MapForwards, typename MapBackwards> | |
| 23 bool MapsAreInverseOfEachOther(const MapForwards& map_forwards, | |
| 24 const MapBackwards& map_backwards) { | |
| 25 if (map_forwards.size() != map_backwards.size()) | |
| 26 return false; | |
| 27 for (typename MapForwards::const_iterator i = map_forwards.begin(), | |
| 28 e = map_forwards.end(); | |
| 29 i != e; ++i) { | |
|
dominich
2012/04/26 22:50:58
why do you need to declare e in the first part? ie
gavinp
2012/04/27 20:31:32
Pure superstition. The standard guarantees that t
| |
| 30 // Best to use std::count here both times, as | |
| 31 // AssociativeContainer::count returns size_t, vs. std::count | |
| 32 // returning iterator_traits<InputIterator>::difference_type | |
| 33 typedef typename std::iterator_traits< | |
| 34 typename MapForwards::iterator>::difference_type diff_type; | |
| 35 diff_type forwards_count = | |
| 36 std::count(map_forwards.begin(), map_forwards.end(), | |
| 37 typename MapForwards::value_type(i->first, i->second)); | |
| 38 diff_type backwards_count = | |
| 39 std::count(map_backwards.begin(), map_backwards.end(), | |
| 40 typename MapBackwards::value_type(i->second, i->first)); | |
| 41 if (forwards_count != backwards_count) { | |
|
dominich
2012/04/26 22:50:58
nit: {} not necessary here
gavinp
2012/04/27 20:31:32
Done.
| |
| 42 return false; | |
| 43 } | |
| 44 } | |
| 45 return true; | |
| 46 } | |
| 47 | |
| 48 } | |
| 49 | |
| 50 namespace prerender { | |
| 51 | |
| 52 PrerenderLinkManager::PrerenderLinkManager( | |
|
dominich
2012/04/26 22:50:58
nit: unnecessary to wrap this line
gavinp
2012/04/27 20:31:32
Done.
| |
| 53 PrerenderManager* manager) | |
| 54 : manager_(manager) { | |
| 55 } | |
| 56 | |
| 57 PrerenderLinkManager::~PrerenderLinkManager() { | |
| 58 } | |
| 59 | |
| 60 bool PrerenderLinkManager::OnAddPrerender(int child_id, | |
| 61 int prerender_id, | |
| 62 const GURL& orig_url, | |
| 63 const content::Referrer& referrer, | |
| 64 const gfx::Size& ALLOW_UNUSED size, | |
| 65 int render_view_route_id) { | |
| 66 DVLOG(2) << "OnAddPrerender, child_id = " << child_id | |
| 67 << ", prerender_id = " << prerender_id | |
| 68 << ", url = " << orig_url.spec(); | |
| 69 DVLOG(3) << "... render_view_route_id = " << render_view_route_id | |
| 70 << ", referrer url = " << referrer.url.spec(); | |
| 71 DCHECK(MapsAreInverseOfEachOther(ids_to_url_map_, urls_to_id_map_)); | |
| 72 // TODO(gavinp): Add tests to insure fragments work, then remove this fragment | |
| 73 // clearing code. | |
| 74 url_canon::Replacements<char> replacements; | |
| 75 replacements.ClearRef(); | |
| 76 const GURL url = orig_url.ReplaceComponents(replacements); | |
| 77 | |
| 78 // TODO(gavinp,dominich): After the Prerender API can send events back to | |
|
dominich
2012/04/26 22:50:58
From this code, I don't see why the urls_to_id_map
gavinp
2012/04/27 20:31:32
Two links prerender the same page from the same or
dominich
2012/04/27 21:52:01
So they'd have the same child_id but different pre
gavinp
2012/04/27 23:31:45
Yes. However, notice that OnCancelPrerender has d
| |
| 79 // their client links, revisit having both maps and all the trouble that | |
| 80 // causes. | |
| 81 const bool did_successfully_add = manager_->AddPrerenderFromLinkRelPrerender( | |
| 82 child_id, render_view_route_id, url, referrer); | |
| 83 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); | |
| 84 DCHECK(ids_to_url_map_.find(child_and_prerender_id) == ids_to_url_map_.end()); | |
| 85 ids_to_url_map_.insert(std::make_pair(child_and_prerender_id, url)); | |
|
dominich
2012/04/26 22:50:58
Why insert these if |did_successfully_add| is fals
gavinp
2012/04/27 20:31:32
Done. What I liked about the original approach wa
| |
| 86 urls_to_id_map_.insert(std::make_pair(url, child_and_prerender_id)); | |
| 87 DCHECK(MapsAreInverseOfEachOther(ids_to_url_map_, urls_to_id_map_)); | |
| 88 return did_successfully_add; | |
| 89 } | |
| 90 | |
| 91 void PrerenderLinkManager::OnCancelPrerender(int prerender_id, | |
| 92 int child_id) { | |
| 93 DVLOG(2) << "OnCancelPrerender, child_id = " << child_id | |
| 94 << ", prerender_id = " << prerender_id; | |
| 95 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); | |
| 96 IdPairToUrlMap::iterator id_url_iter = | |
| 97 ids_to_url_map_.find(child_and_prerender_id); | |
| 98 if (id_url_iter == ids_to_url_map_.end()) { | |
| 99 NOTREACHED() << "Canceling a prerender that doesn't exist."; | |
| 100 return; | |
| 101 } | |
| 102 const GURL url = id_url_iter->second; | |
| 103 RemovePrerender(id_url_iter); | |
| 104 | |
| 105 if (urls_to_id_map_.find(url) != urls_to_id_map_.end()) | |
| 106 return; | |
| 107 | |
| 108 // TODO(gavinp): Track down the correct prerender and stop it, rather than | |
| 109 // this nuclear option, which assumes that only one prerender at a time | |
| 110 // runs. | |
| 111 if (PrerenderContents* contents = manager_->GetEntry(url)) | |
| 112 contents->Destroy(FINAL_STATUS_CANCELLED); | |
| 113 } | |
| 114 | |
| 115 void PrerenderLinkManager::OnAbandonPrerender(int prerender_id, int child_id) { | |
| 116 DVLOG(2) << "OnAbandonPrerender, child_id = " << child_id | |
| 117 << ", prerender_id = " << prerender_id; | |
| 118 // TODO(gavinp,cbentzel): Implement reasonable behaviour for | |
| 119 // navigation away from launcher. | |
| 120 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); | |
| 121 IdPairToUrlMap::iterator id_url_iter = | |
| 122 ids_to_url_map_.find(child_and_prerender_id); | |
| 123 if (id_url_iter == ids_to_url_map_.end()) { | |
| 124 // FIXME(gavinp): Currently, canceled prerenders also get abandoned later. | |
| 125 // When the WebKit fix to stop this lands, add a NOTREACHED() here. | |
| 126 return; | |
| 127 } | |
| 128 RemovePrerender(id_url_iter); | |
| 129 } | |
| 130 | |
| 131 void PrerenderLinkManager::OnChannelClosing(int child_id) { | |
| 132 DVLOG(2) << "OnChannelClosing, child id = " << child_id; | |
| 133 const ChildAndPrerenderIdPair child_and_minimum_prerender_id( | |
| 134 child_id, std::numeric_limits<int>::min()); | |
| 135 const ChildAndPrerenderIdPair child_and_maximum_prerender_id( | |
| 136 child_id, std::numeric_limits<int>::max()); | |
| 137 std::queue<int> prerender_ids_to_abandon; | |
| 138 for (IdPairToUrlMap::iterator | |
| 139 i = ids_to_url_map_.lower_bound(child_and_minimum_prerender_id), | |
| 140 e = ids_to_url_map_.upper_bound(child_and_maximum_prerender_id); | |
| 141 i != e; ++i) { | |
| 142 prerender_ids_to_abandon.push(i->first.second); | |
| 143 } | |
| 144 while (!prerender_ids_to_abandon.empty()) { | |
| 145 DVLOG(4) << "---> abandon prerender_id = " | |
| 146 << prerender_ids_to_abandon.front(); | |
| 147 OnAbandonPrerender(prerender_ids_to_abandon.front(), child_id); | |
| 148 prerender_ids_to_abandon.pop(); | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 void PrerenderLinkManager::RemovePrerender( | |
| 153 const IdPairToUrlMap::iterator& id_url_iter) { | |
| 154 DCHECK(MapsAreInverseOfEachOther(ids_to_url_map_, urls_to_id_map_)); | |
| 155 const GURL url = id_url_iter->second; | |
| 156 const ChildAndPrerenderIdPair child_and_prerender_id = id_url_iter->first; | |
| 157 ids_to_url_map_.erase(id_url_iter); | |
| 158 | |
| 159 for (UrlToIdPairMap::iterator i = urls_to_id_map_.lower_bound(url), | |
| 160 e = urls_to_id_map_.upper_bound(url); | |
|
gavinp
2012/04/27 20:31:32
I'm leaving this one here, multimap::upper_bound()
| |
| 161 i != e; ++i) { | |
| 162 if (i->second == child_and_prerender_id) { | |
| 163 urls_to_id_map_.erase(i); | |
| 164 DCHECK(MapsAreInverseOfEachOther(ids_to_url_map_, urls_to_id_map_)); | |
| 165 return; | |
| 166 } | |
| 167 } | |
| 168 NOTREACHED(); | |
| 169 } | |
| 170 | |
| 171 bool PrerenderLinkManager::IsEmpty() const { | |
| 172 return ids_to_url_map_.empty(); | |
| 173 } | |
| 174 | |
| 175 } // namespace prerender | |
| 176 | |
| OLD | NEW |