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/extensions/api/web_navigation/frame_navigation_state.h" 6 7 #include "base/logging.h" 8 #include "chrome/common/url_constants.h" 9 #include "content/public/browser/render_frame_host.h" 10 #include "extensions/common/constants.h" 11 12 namespace extensions { 13 14 namespace { 15 16 // URL schemes for which we'll send events. 17 const char* kValidSchemes[] = { 18 content::kChromeUIScheme, 19 url::kHttpScheme, 20 url::kHttpsScheme, 21 url::kFileScheme, 22 url::kFtpScheme, 23 url::kJavaScriptScheme, 24 url::kDataScheme, 25 url::kFileSystemScheme, 26 }; 27 28 } // namespace 29 30 FrameNavigationState::FrameState::FrameState() {} 31 32 // static 33 bool FrameNavigationState::allow_extension_scheme_ = false; 34 35 FrameNavigationState::FrameNavigationState() : main_frame_host_(NULL) { 36 } 37 38 FrameNavigationState::~FrameNavigationState() {} 39 40 bool FrameNavigationState::CanSendEvents( 41 content::RenderFrameHost* frame_host) const { 42 FrameHostToStateMap::const_iterator it = 43 frame_host_state_map_.find(frame_host); 44 if (it == frame_host_state_map_.end() || it->second.error_occurred) { 45 return false; 46 } 47 return IsValidUrl(it->second.url); 48 } 49 50 bool FrameNavigationState::IsValidUrl(const GURL& url) const { 51 for (unsigned i = 0; i < arraysize(kValidSchemes); ++i) { 52 if (url.scheme() == kValidSchemes[i]) 53 return true; 54 } 55 // Allow about:blank and about:srcdoc. 56 if (url.spec() == url::kAboutBlankURL || 57 url.spec() == content::kAboutSrcDocURL) { 58 return true; 59 } 60 return allow_extension_scheme_ && url.scheme() == kExtensionScheme; 61 } 62 63 void FrameNavigationState::TrackFrame(content::RenderFrameHost* frame_host, 64 const GURL& url, 65 bool is_error_page, 66 bool is_iframe_srcdoc) { 67 FrameState& frame_state = frame_host_state_map_[frame_host]; 68 frame_state.error_occurred = is_error_page; 69 frame_state.url = url; 70 frame_state.is_iframe_srcdoc = is_iframe_srcdoc; 71 DCHECK(!is_iframe_srcdoc || url == GURL(url::kAboutBlankURL)); 72 frame_state.is_navigating = true; 73 frame_state.is_committed = false; 74 frame_state.is_server_redirected = false; 75 frame_state.is_parsing = true; 76 frame_hosts_.insert(frame_host); 77 } 78 79 void FrameNavigationState::FrameDetached(content::RenderFrameHost* frame_host) { 80 if (frame_host == main_frame_host_) 81 main_frame_host_ = NULL; 82 frame_host_state_map_.erase(frame_host); 83 frame_hosts_.erase(frame_host); 84 } 85 86 void FrameNavigationState::StopTrackingFramesInRVH( 87 content::RenderViewHost* render_view_host, 88 content::RenderFrameHost* frame_host_to_skip) { 89 for (std::set<content::RenderFrameHost*>::iterator it = frame_hosts_.begin(); 90 it != frame_hosts_.end();) { 91 if ((*it)->GetRenderViewHost() != render_view_host || 92 *it == frame_host_to_skip) { 93 ++it; 94 continue; 95 } 96 if (*it == main_frame_host_) 97 main_frame_host_ = NULL; 98 frame_host_state_map_.erase(*it); 99 frame_hosts_.erase(it++); 100 } 101 } 102 103 void FrameNavigationState::UpdateFrame(content::RenderFrameHost* frame_host, 104 const GURL& url) { 105 FrameHostToStateMap::iterator it = frame_host_state_map_.find(frame_host); 106 if (it == frame_host_state_map_.end()) { 107 NOTREACHED(); 108 return; 109 } 110 it->second.url = url; 111 } 112 113 bool FrameNavigationState::IsValidFrame( 114 content::RenderFrameHost* frame_host) const { 115 return frame_host_state_map_.find(frame_host) != frame_host_state_map_.end(); 116 } 117 118 GURL FrameNavigationState::GetUrl(content::RenderFrameHost* frame_host) const { 119 FrameHostToStateMap::const_iterator it = 120 frame_host_state_map_.find(frame_host); 121 if (it == frame_host_state_map_.end()) { 122 NOTREACHED(); 123 return GURL(); 124 } 125 if (it->second.is_iframe_srcdoc) 126 return GURL(content::kAboutSrcDocURL); 127 return it->second.url; 128 } 129 130 content::RenderFrameHost* FrameNavigationState::GetLastCommittedMainFrameHost() 131 const { 132 return main_frame_host_; 133 } 134 135 void FrameNavigationState::SetErrorOccurredInFrame( 136 content::RenderFrameHost* frame_host) { 137 FrameHostToStateMap::iterator it = frame_host_state_map_.find(frame_host); 138 if (it == frame_host_state_map_.end()) { 139 NOTREACHED(); 140 return; 141 } 142 it->second.error_occurred = true; 143 } 144 145 bool FrameNavigationState::GetErrorOccurredInFrame( 146 content::RenderFrameHost* frame_host) const { 147 FrameHostToStateMap::const_iterator it = 148 frame_host_state_map_.find(frame_host); 149 DCHECK(it != frame_host_state_map_.end()); 150 return it == frame_host_state_map_.end() || it->second.error_occurred; 151 } 152 153 void FrameNavigationState::SetNavigationCompleted( 154 content::RenderFrameHost* frame_host) { 155 FrameHostToStateMap::iterator it = frame_host_state_map_.find(frame_host); 156 if (it == frame_host_state_map_.end()) { 157 NOTREACHED(); 158 return; 159 } 160 it->second.is_navigating = false; 161 } 162 163 bool FrameNavigationState::GetNavigationCompleted( 164 content::RenderFrameHost* frame_host) const { 165 FrameHostToStateMap::const_iterator it = 166 frame_host_state_map_.find(frame_host); 167 DCHECK(it != frame_host_state_map_.end()); 168 return it == frame_host_state_map_.end() || !it->second.is_navigating; 169 } 170 171 void FrameNavigationState::SetParsingFinished( 172 content::RenderFrameHost* frame_host) { 173 FrameHostToStateMap::iterator it = frame_host_state_map_.find(frame_host); 174 if (it == frame_host_state_map_.end()) { 175 NOTREACHED(); 176 return; 177 } 178 it->second.is_parsing = false; 179 } 180 181 bool FrameNavigationState::GetParsingFinished( 182 content::RenderFrameHost* frame_host) const { 183 FrameHostToStateMap::const_iterator it = 184 frame_host_state_map_.find(frame_host); 185 DCHECK(it != frame_host_state_map_.end()); 186 return it == frame_host_state_map_.end() || !it->second.is_parsing; 187 } 188 189 void FrameNavigationState::SetNavigationCommitted( 190 content::RenderFrameHost* frame_host) { 191 FrameHostToStateMap::iterator it = frame_host_state_map_.find(frame_host); 192 if (it == frame_host_state_map_.end()) { 193 NOTREACHED(); 194 return; 195 } 196 it->second.is_committed = true; 197 if (!frame_host->GetParent()) 198 main_frame_host_ = frame_host; 199 } 200 201 bool FrameNavigationState::GetNavigationCommitted( 202 content::RenderFrameHost* frame_host) const { 203 FrameHostToStateMap::const_iterator it = 204 frame_host_state_map_.find(frame_host); 205 DCHECK(it != frame_host_state_map_.end()); 206 return it != frame_host_state_map_.end() && it->second.is_committed; 207 } 208 209 void FrameNavigationState::SetIsServerRedirected( 210 content::RenderFrameHost* frame_host) { 211 FrameHostToStateMap::iterator it = frame_host_state_map_.find(frame_host); 212 if (it == frame_host_state_map_.end()) { 213 NOTREACHED(); 214 return; 215 } 216 it->second.is_server_redirected = true; 217 } 218 219 bool FrameNavigationState::GetIsServerRedirected( 220 content::RenderFrameHost* frame_host) const { 221 FrameHostToStateMap::const_iterator it = 222 frame_host_state_map_.find(frame_host); 223 DCHECK(it != frame_host_state_map_.end()); 224 return it != frame_host_state_map_.end() && it->second.is_server_redirected; 225 } 226 227 } // namespace extensions 228