| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "extensions/browser/extension_api_frame_id_map.h" | 5 #include "extensions/browser/extension_api_frame_id_map.h" |
| 6 | 6 |
| 7 #include <tuple> | 7 #include <tuple> |
| 8 | 8 |
| 9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
| 10 #include "content/public/browser/browser_thread.h" | 10 #include "content/public/browser/browser_thread.h" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 return kInvalidFrameId; | 103 return kInvalidFrameId; |
| 104 if (rfh->GetParent()) | 104 if (rfh->GetParent()) |
| 105 return rfh->GetFrameTreeNodeId(); | 105 return rfh->GetFrameTreeNodeId(); |
| 106 return kTopFrameId; | 106 return kTopFrameId; |
| 107 } | 107 } |
| 108 | 108 |
| 109 // static | 109 // static |
| 110 int ExtensionApiFrameIdMap::GetFrameId( | 110 int ExtensionApiFrameIdMap::GetFrameId( |
| 111 content::NavigationHandle* navigation_handle) { | 111 content::NavigationHandle* navigation_handle) { |
| 112 return navigation_handle->IsInMainFrame() | 112 return navigation_handle->IsInMainFrame() |
| 113 ? 0 | 113 ? kTopFrameId |
| 114 : navigation_handle->GetFrameTreeNodeId(); | 114 : navigation_handle->GetFrameTreeNodeId(); |
| 115 } | 115 } |
| 116 | 116 |
| 117 // static | 117 // static |
| 118 int ExtensionApiFrameIdMap::GetParentFrameId(content::RenderFrameHost* rfh) { | 118 int ExtensionApiFrameIdMap::GetParentFrameId(content::RenderFrameHost* rfh) { |
| 119 return rfh ? GetFrameId(rfh->GetParent()) : kInvalidFrameId; | 119 return rfh ? GetFrameId(rfh->GetParent()) : kInvalidFrameId; |
| 120 } | 120 } |
| 121 | 121 |
| 122 // static | 122 // static |
| 123 int ExtensionApiFrameIdMap::GetParentFrameId( | 123 int ExtensionApiFrameIdMap::GetParentFrameId( |
| 124 content::NavigationHandle* navigation_handle) { | 124 content::NavigationHandle* navigation_handle) { |
| 125 if (navigation_handle->IsInMainFrame()) | 125 if (navigation_handle->IsInMainFrame()) |
| 126 return -1; | 126 return kInvalidFrameId; |
| 127 | 127 |
| 128 if (navigation_handle->IsParentMainFrame()) | 128 if (navigation_handle->IsParentMainFrame()) |
| 129 return 0; | 129 return kTopFrameId; |
| 130 | 130 |
| 131 return navigation_handle->GetParentFrameTreeNodeId(); | 131 return navigation_handle->GetParentFrameTreeNodeId(); |
| 132 } | 132 } |
| 133 | 133 |
| 134 // static | 134 // static |
| 135 content::RenderFrameHost* ExtensionApiFrameIdMap::GetRenderFrameHostById( | 135 content::RenderFrameHost* ExtensionApiFrameIdMap::GetRenderFrameHostById( |
| 136 content::WebContents* web_contents, | 136 content::WebContents* web_contents, |
| 137 int frame_id) { | 137 int frame_id) { |
| 138 // Although it is technically possible to map |frame_id| to a RenderFrameHost | 138 // Although it is technically possible to map |frame_id| to a RenderFrameHost |
| 139 // without WebContents, we choose to not do that because in the extension API | 139 // without WebContents, we choose to not do that because in the extension API |
| (...skipping 17 matching lines...) Expand all Loading... |
| 157 key.render_process_id, key.frame_routing_id); | 157 key.render_process_id, key.frame_routing_id); |
| 158 int tab_id = -1; | 158 int tab_id = -1; |
| 159 int window_id = -1; | 159 int window_id = -1; |
| 160 if (helper_) | 160 if (helper_) |
| 161 helper_->GetTabAndWindowId(rfh, &tab_id, &window_id); | 161 helper_->GetTabAndWindowId(rfh, &tab_id, &window_id); |
| 162 return FrameData(GetFrameId(rfh), GetParentFrameId(rfh), tab_id, window_id); | 162 return FrameData(GetFrameId(rfh), GetParentFrameId(rfh), tab_id, window_id); |
| 163 } | 163 } |
| 164 | 164 |
| 165 ExtensionApiFrameIdMap::FrameData ExtensionApiFrameIdMap::LookupFrameDataOnUI( | 165 ExtensionApiFrameIdMap::FrameData ExtensionApiFrameIdMap::LookupFrameDataOnUI( |
| 166 const RenderFrameIdKey& key, | 166 const RenderFrameIdKey& key, |
| 167 bool for_lookup) { | 167 bool is_from_io) { |
| 168 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 168 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 169 | 169 |
| 170 bool lookup_successful = false; | 170 bool lookup_successful = false; |
| 171 FrameData data; | 171 FrameData data; |
| 172 FrameDataMap::const_iterator frame_id_iter = frame_data_map_.find(key); | 172 FrameDataMap::const_iterator frame_id_iter = frame_data_map_.find(key); |
| 173 if (frame_id_iter != frame_data_map_.end()) { | 173 if (frame_id_iter != frame_data_map_.end()) { |
| 174 lookup_successful = true; | 174 lookup_successful = true; |
| 175 data = frame_id_iter->second; | 175 data = frame_id_iter->second; |
| 176 } else { | 176 } else { |
| 177 data = KeyToValue(key); | 177 data = KeyToValue(key); |
| 178 // Don't save invalid values in the map. | 178 // Don't save invalid values in the map. |
| 179 if (data.frame_id != kInvalidFrameId) { | 179 if (data.frame_id != kInvalidFrameId) { |
| 180 lookup_successful = true; | 180 lookup_successful = true; |
| 181 auto kvpair = FrameDataMap::value_type(key, data); | 181 auto kvpair = FrameDataMap::value_type(key, data); |
| 182 base::AutoLock lock(frame_data_map_lock_); | 182 base::AutoLock lock(frame_data_map_lock_); |
| 183 frame_data_map_.insert(kvpair); | 183 frame_data_map_.insert(kvpair); |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 // TODO(devlin): Depending on how the data looks, this may be removable after | 187 // TODO(devlin): Depending on how the data looks, this may be removable after |
| 188 // a few cycles. Check back in M52 to see if it's still needed. | 188 // a few cycles. Check back in M52 to see if it's still needed. |
| 189 if (for_lookup) { | 189 if (is_from_io) { |
| 190 UMA_HISTOGRAM_BOOLEAN("Extensions.ExtensionFrameMapLookupSuccessful", | 190 UMA_HISTOGRAM_BOOLEAN("Extensions.ExtensionFrameMapLookupSuccessful", |
| 191 lookup_successful); | 191 lookup_successful); |
| 192 } | 192 } |
| 193 | 193 |
| 194 return data; | 194 return data; |
| 195 } | 195 } |
| 196 | 196 |
| 197 void ExtensionApiFrameIdMap::ReceivedFrameDataOnIO( | 197 void ExtensionApiFrameIdMap::ReceivedFrameDataOnIO( |
| 198 const RenderFrameIdKey& key, | 198 const RenderFrameIdKey& key, |
| 199 const FrameData& cached_frame_data) { | 199 const FrameData& cached_frame_data) { |
| 200 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 200 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 201 | 201 |
| 202 FrameDataCallbacksMap::iterator map_iter = callbacks_map_.find(key); | 202 FrameDataCallbacksMap::iterator map_iter = callbacks_map_.find(key); |
| 203 if (map_iter == callbacks_map_.end()) { | 203 if (map_iter == callbacks_map_.end()) { |
| 204 // Can happen if ReceivedFrameIdOnIO was called after the frame ID was | 204 // Can happen if ReceivedFrameDataOnIO was called after the frame ID was |
| 205 // resolved (e.g. via GetFrameDataOnIO), but before PostTaskAndReply | 205 // resolved (e.g. via GetFrameDataOnIO), but before PostTaskAndReply |
| 206 // replied. | 206 // replied. |
| 207 return; | 207 return; |
| 208 } | 208 } |
| 209 | 209 |
| 210 FrameDataCallbacks& callbacks = map_iter->second; | 210 FrameDataCallbacks& callbacks = map_iter->second; |
| 211 | 211 |
| 212 if (callbacks.is_iterating) | 212 if (callbacks.is_iterating) |
| 213 return; | 213 return; |
| 214 callbacks.is_iterating = true; | 214 callbacks.is_iterating = true; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 } | 262 } |
| 263 return; | 263 return; |
| 264 } | 264 } |
| 265 | 265 |
| 266 // The key was seen for the first time (or the frame has been removed). | 266 // The key was seen for the first time (or the frame has been removed). |
| 267 // Hop to the UI thread to look up the extension API frame ID. | 267 // Hop to the UI thread to look up the extension API frame ID. |
| 268 callbacks_map_[key].callbacks.push_back(callback); | 268 callbacks_map_[key].callbacks.push_back(callback); |
| 269 content::BrowserThread::PostTaskAndReplyWithResult( | 269 content::BrowserThread::PostTaskAndReplyWithResult( |
| 270 content::BrowserThread::UI, FROM_HERE, | 270 content::BrowserThread::UI, FROM_HERE, |
| 271 base::Bind(&ExtensionApiFrameIdMap::LookupFrameDataOnUI, | 271 base::Bind(&ExtensionApiFrameIdMap::LookupFrameDataOnUI, |
| 272 base::Unretained(this), key, true /* for lookup */), | 272 base::Unretained(this), key, true /* is_from_io */), |
| 273 base::Bind(&ExtensionApiFrameIdMap::ReceivedFrameDataOnIO, | 273 base::Bind(&ExtensionApiFrameIdMap::ReceivedFrameDataOnIO, |
| 274 base::Unretained(this), key)); | 274 base::Unretained(this), key)); |
| 275 } | 275 } |
| 276 | 276 |
| 277 bool ExtensionApiFrameIdMap::GetCachedFrameDataOnIO(int render_process_id, | 277 bool ExtensionApiFrameIdMap::GetCachedFrameDataOnIO(int render_process_id, |
| 278 int frame_routing_id, | 278 int frame_routing_id, |
| 279 FrameData* frame_data_out) { | 279 FrameData* frame_data_out) { |
| 280 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 280 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 281 | 281 |
| 282 // TODO(robwu): Enable assertion when all callers have been fixed. | 282 // TODO(robwu): Enable assertion when all callers have been fixed. |
| 283 // DCHECK_EQ(MSG_ROUTING_NONE, -1); | 283 // DCHECK_EQ(MSG_ROUTING_NONE, -1); |
| 284 if (!IsFrameRoutingIdValid(frame_routing_id)) | 284 if (!IsFrameRoutingIdValid(frame_routing_id)) |
| 285 return false; | 285 return false; |
| 286 | 286 |
| 287 // A valid routing ID is only meaningful with a valid process ID. | 287 // A valid routing ID is only meaningful with a valid process ID. |
| 288 DCHECK_GE(render_process_id, 0); | 288 DCHECK_GE(render_process_id, 0); |
| 289 | 289 |
| 290 bool found = false; | 290 bool found = false; |
| 291 { | 291 { |
| 292 base::AutoLock lock(frame_data_map_lock_); | 292 base::AutoLock lock(frame_data_map_lock_); |
| 293 FrameDataMap::const_iterator frame_id_iter = frame_data_map_.find( | 293 FrameDataMap::const_iterator frame_id_iter = frame_data_map_.find( |
| 294 RenderFrameIdKey(render_process_id, frame_routing_id)); | 294 RenderFrameIdKey(render_process_id, frame_routing_id)); |
| 295 if (frame_id_iter != frame_data_map_.end()) { | 295 if (frame_id_iter != frame_data_map_.end()) { |
| 296 // This is very likely to happen because CacheFrameId() is called as soon | 296 // This is very likely to happen because CacheFrameData() is called as |
| 297 // as the frame is created. | 297 // soon as the frame is created. |
| 298 *frame_data_out = frame_id_iter->second; | 298 *frame_data_out = frame_id_iter->second; |
| 299 found = true; | 299 found = true; |
| 300 } | 300 } |
| 301 } | 301 } |
| 302 | 302 |
| 303 // TODO(devlin): Depending on how the data looks, this may be removable after | 303 // TODO(devlin): Depending on how the data looks, this may be removable after |
| 304 // a few cycles. Check back in M52 to see if it's still needed. | 304 // a few cycles. Check back in M52 to see if it's still needed. |
| 305 UMA_HISTOGRAM_BOOLEAN("Extensions.ExtensionFrameMapCacheHit", found); | 305 UMA_HISTOGRAM_BOOLEAN("Extensions.ExtensionFrameMapCacheHit", found); |
| 306 return found; | 306 return found; |
| 307 } | 307 } |
| 308 | 308 |
| 309 ExtensionApiFrameIdMap::FrameData ExtensionApiFrameIdMap::GetFrameData( |
| 310 content::RenderFrameHost* rfh) { |
| 311 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 312 |
| 313 const RenderFrameIdKey key(rfh->GetProcess()->GetID(), rfh->GetRoutingID()); |
| 314 return LookupFrameDataOnUI(key, false /* is_from_io */); |
| 315 } |
| 316 |
| 309 void ExtensionApiFrameIdMap::CacheFrameData(content::RenderFrameHost* rfh) { | 317 void ExtensionApiFrameIdMap::CacheFrameData(content::RenderFrameHost* rfh) { |
| 310 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 318 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 311 | 319 |
| 312 const RenderFrameIdKey key(rfh->GetProcess()->GetID(), rfh->GetRoutingID()); | 320 const RenderFrameIdKey key(rfh->GetProcess()->GetID(), rfh->GetRoutingID()); |
| 313 CacheFrameData(key); | 321 CacheFrameData(key); |
| 314 DCHECK(frame_data_map_.find(key) != frame_data_map_.end()); | 322 DCHECK(frame_data_map_.find(key) != frame_data_map_.end()); |
| 315 } | 323 } |
| 316 | 324 |
| 317 void ExtensionApiFrameIdMap::CacheFrameData(const RenderFrameIdKey& key) { | 325 void ExtensionApiFrameIdMap::CacheFrameData(const RenderFrameIdKey& key) { |
| 318 LookupFrameDataOnUI(key, false /* not for lookup */); | 326 LookupFrameDataOnUI(key, false /* is_from_io */); |
| 319 } | 327 } |
| 320 | 328 |
| 321 void ExtensionApiFrameIdMap::RemoveFrameData(content::RenderFrameHost* rfh) { | 329 void ExtensionApiFrameIdMap::RemoveFrameData(content::RenderFrameHost* rfh) { |
| 322 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 330 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 323 DCHECK(rfh); | 331 DCHECK(rfh); |
| 324 | 332 |
| 325 const RenderFrameIdKey key(rfh->GetProcess()->GetID(), rfh->GetRoutingID()); | 333 const RenderFrameIdKey key(rfh->GetProcess()->GetID(), rfh->GetRoutingID()); |
| 326 RemoveFrameData(key); | 334 RemoveFrameData(key); |
| 327 } | 335 } |
| 328 | 336 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 345 } | 353 } |
| 346 | 354 |
| 347 void ExtensionApiFrameIdMap::RemoveFrameData(const RenderFrameIdKey& key) { | 355 void ExtensionApiFrameIdMap::RemoveFrameData(const RenderFrameIdKey& key) { |
| 348 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 356 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 349 | 357 |
| 350 base::AutoLock lock(frame_data_map_lock_); | 358 base::AutoLock lock(frame_data_map_lock_); |
| 351 frame_data_map_.erase(key); | 359 frame_data_map_.erase(key); |
| 352 } | 360 } |
| 353 | 361 |
| 354 } // namespace extensions | 362 } // namespace extensions |
| OLD | NEW |