Home | History | Annotate | Download | only in web_navigation
      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 "extensions/common/constants.h"
     10 
     11 namespace extensions {
     12 
     13 namespace {
     14 
     15 // URL schemes for which we'll send events.
     16 const char* kValidSchemes[] = {
     17     content::kChromeUIScheme,
     18     url::kHttpScheme,
     19     url::kHttpsScheme,
     20     url::kFileScheme,
     21     url::kFtpScheme,
     22     url::kJavaScriptScheme,
     23     url::kDataScheme,
     24     url::kFileSystemScheme,
     25 };
     26 
     27 }  // namespace
     28 
     29 FrameNavigationState::FrameID::FrameID()
     30     : frame_num(-1),
     31       render_view_host(NULL) {
     32 }
     33 
     34 FrameNavigationState::FrameID::FrameID(
     35     int64 frame_num,
     36     content::RenderViewHost* render_view_host)
     37     : frame_num(frame_num),
     38       render_view_host(render_view_host) {
     39 }
     40 
     41 bool FrameNavigationState::FrameID::operator<(
     42     const FrameNavigationState::FrameID& other) const {
     43   return frame_num < other.frame_num ||
     44       (frame_num == other.frame_num &&
     45        render_view_host < other.render_view_host);
     46 }
     47 
     48 bool FrameNavigationState::FrameID::operator==(
     49     const FrameNavigationState::FrameID& other) const {
     50   return frame_num == other.frame_num &&
     51       render_view_host == other.render_view_host;
     52 }
     53 
     54 bool FrameNavigationState::FrameID::operator!=(
     55     const FrameNavigationState::FrameID& other) const {
     56   return !(*this == other);
     57 }
     58 
     59 FrameNavigationState::FrameState::FrameState() {}
     60 
     61 // static
     62 bool FrameNavigationState::allow_extension_scheme_ = false;
     63 
     64 FrameNavigationState::FrameNavigationState() {}
     65 
     66 FrameNavigationState::~FrameNavigationState() {}
     67 
     68 bool FrameNavigationState::CanSendEvents(FrameID frame_id) const {
     69   FrameIdToStateMap::const_iterator frame_state =
     70       frame_state_map_.find(frame_id);
     71   if (frame_state == frame_state_map_.end() ||
     72       frame_state->second.error_occurred) {
     73     return false;
     74   }
     75   return IsValidUrl(frame_state->second.url);
     76 }
     77 
     78 bool FrameNavigationState::IsValidUrl(const GURL& url) const {
     79   for (unsigned i = 0; i < arraysize(kValidSchemes); ++i) {
     80     if (url.scheme() == kValidSchemes[i])
     81       return true;
     82   }
     83   // Allow about:blank and about:srcdoc.
     84   if (url.spec() == url::kAboutBlankURL ||
     85       url.spec() == content::kAboutSrcDocURL) {
     86     return true;
     87   }
     88   if (allow_extension_scheme_ && url.scheme() == extensions::kExtensionScheme)
     89     return true;
     90   return false;
     91 }
     92 
     93 void FrameNavigationState::TrackFrame(FrameID frame_id,
     94                                       FrameID parent_frame_id,
     95                                       const GURL& url,
     96                                       bool is_main_frame,
     97                                       bool is_error_page,
     98                                       bool is_iframe_srcdoc) {
     99   FrameState& frame_state = frame_state_map_[frame_id];
    100   frame_state.error_occurred = is_error_page;
    101   frame_state.url = url;
    102   frame_state.is_main_frame = is_main_frame;
    103   frame_state.is_iframe_srcdoc = is_iframe_srcdoc;
    104   DCHECK(!is_iframe_srcdoc || url == GURL(url::kAboutBlankURL));
    105   frame_state.is_navigating = true;
    106   frame_state.is_committed = false;
    107   frame_state.is_server_redirected = false;
    108   frame_state.is_parsing = true;
    109   if (!is_main_frame) {
    110     frame_state.parent_frame_num = parent_frame_id.frame_num;
    111   } else {
    112     DCHECK(parent_frame_id.frame_num == -1);
    113     frame_state.parent_frame_num = -1;
    114   }
    115   frame_ids_.insert(frame_id);
    116 }
    117 
    118 void FrameNavigationState::FrameDetached(FrameID frame_id) {
    119   FrameIdToStateMap::const_iterator frame_state =
    120       frame_state_map_.find(frame_id);
    121   if (frame_state == frame_state_map_.end())
    122     return;
    123   if (frame_id == main_frame_id_)
    124     main_frame_id_ = FrameID();
    125   frame_state_map_.erase(frame_id);
    126   frame_ids_.erase(frame_id);
    127 #ifndef NDEBUG
    128   // Check that the deleted frame was not the parent of any other frame. WebKit
    129   // should always detach frames starting with the children.
    130   for (FrameIdToStateMap::const_iterator frame = frame_state_map_.begin();
    131        frame != frame_state_map_.end(); ++frame) {
    132     if (frame->first.render_view_host != frame_id.render_view_host)
    133       continue;
    134     if (frame->second.parent_frame_num != frame_id.frame_num)
    135       continue;
    136     NOTREACHED();
    137   }
    138 #endif
    139 }
    140 
    141 void FrameNavigationState::StopTrackingFramesInRVH(
    142     content::RenderViewHost* render_view_host,
    143     FrameID id_to_skip) {
    144   for (std::set<FrameID>::iterator frame = frame_ids_.begin();
    145        frame != frame_ids_.end();) {
    146     if (frame->render_view_host != render_view_host || *frame == id_to_skip) {
    147       ++frame;
    148       continue;
    149     }
    150     FrameID frame_id = *frame;
    151     ++frame;
    152     if (frame_id == main_frame_id_)
    153       main_frame_id_ = FrameID();
    154     frame_state_map_.erase(frame_id);
    155     frame_ids_.erase(frame_id);
    156   }
    157 }
    158 
    159 void FrameNavigationState::UpdateFrame(FrameID frame_id, const GURL& url) {
    160   FrameIdToStateMap::iterator frame_state = frame_state_map_.find(frame_id);
    161   if (frame_state == frame_state_map_.end()) {
    162     NOTREACHED();
    163     return;
    164   }
    165   frame_state->second.url = url;
    166 }
    167 
    168 bool FrameNavigationState::IsValidFrame(FrameID frame_id) const {
    169   FrameIdToStateMap::const_iterator frame_state =
    170       frame_state_map_.find(frame_id);
    171   return (frame_state != frame_state_map_.end());
    172 }
    173 
    174 GURL FrameNavigationState::GetUrl(FrameID frame_id) const {
    175   FrameIdToStateMap::const_iterator frame_state =
    176       frame_state_map_.find(frame_id);
    177   if (frame_state == frame_state_map_.end()) {
    178     NOTREACHED();
    179     return GURL();
    180   }
    181   if (frame_state->second.is_iframe_srcdoc)
    182     return GURL(content::kAboutSrcDocURL);
    183   return frame_state->second.url;
    184 }
    185 
    186 bool FrameNavigationState::IsMainFrame(FrameID frame_id) const {
    187   FrameIdToStateMap::const_iterator frame_state =
    188       frame_state_map_.find(frame_id);
    189   return (frame_state != frame_state_map_.end() &&
    190           frame_state->second.is_main_frame);
    191 }
    192 
    193 FrameNavigationState::FrameID FrameNavigationState::GetMainFrameID() const {
    194   return main_frame_id_;
    195 }
    196 
    197 FrameNavigationState::FrameID FrameNavigationState::GetParentFrameID(
    198     FrameID frame_id) const {
    199   FrameIdToStateMap::const_iterator frame_state =
    200       frame_state_map_.find(frame_id);
    201   if (frame_state == frame_state_map_.end()) {
    202     NOTREACHED();
    203     return FrameID();
    204   }
    205   return FrameID(frame_state->second.parent_frame_num,
    206                  frame_id.render_view_host);
    207 }
    208 
    209 void FrameNavigationState::SetErrorOccurredInFrame(FrameID frame_id) {
    210   DCHECK(frame_state_map_.find(frame_id) != frame_state_map_.end());
    211   frame_state_map_[frame_id].error_occurred = true;
    212 }
    213 
    214 bool FrameNavigationState::GetErrorOccurredInFrame(FrameID frame_id) const {
    215   FrameIdToStateMap::const_iterator frame_state =
    216       frame_state_map_.find(frame_id);
    217   return (frame_state == frame_state_map_.end() ||
    218           frame_state->second.error_occurred);
    219 }
    220 
    221 void FrameNavigationState::SetNavigationCompleted(FrameID frame_id) {
    222   DCHECK(frame_state_map_.find(frame_id) != frame_state_map_.end());
    223   frame_state_map_[frame_id].is_navigating = false;
    224 }
    225 
    226 bool FrameNavigationState::GetNavigationCompleted(FrameID frame_id) const {
    227   FrameIdToStateMap::const_iterator frame_state =
    228       frame_state_map_.find(frame_id);
    229   return (frame_state == frame_state_map_.end() ||
    230           !frame_state->second.is_navigating);
    231 }
    232 
    233 void FrameNavigationState::SetParsingFinished(FrameID frame_id) {
    234   DCHECK(frame_state_map_.find(frame_id) != frame_state_map_.end());
    235   frame_state_map_[frame_id].is_parsing = false;
    236 }
    237 
    238 bool FrameNavigationState::GetParsingFinished(FrameID frame_id) const {
    239   FrameIdToStateMap::const_iterator frame_state =
    240       frame_state_map_.find(frame_id);
    241   return (frame_state == frame_state_map_.end() ||
    242           !frame_state->second.is_parsing);
    243 }
    244 
    245 void FrameNavigationState::SetNavigationCommitted(FrameID frame_id) {
    246   DCHECK(frame_state_map_.find(frame_id) != frame_state_map_.end());
    247   frame_state_map_[frame_id].is_committed = true;
    248   if (frame_state_map_[frame_id].is_main_frame)
    249     main_frame_id_ = frame_id;
    250 }
    251 
    252 bool FrameNavigationState::GetNavigationCommitted(FrameID frame_id) const {
    253   FrameIdToStateMap::const_iterator frame_state =
    254       frame_state_map_.find(frame_id);
    255   return (frame_state != frame_state_map_.end() &&
    256           frame_state->second.is_committed);
    257 }
    258 
    259 void FrameNavigationState::SetIsServerRedirected(FrameID frame_id) {
    260   DCHECK(frame_state_map_.find(frame_id) != frame_state_map_.end());
    261   frame_state_map_[frame_id].is_server_redirected = true;
    262 }
    263 
    264 bool FrameNavigationState::GetIsServerRedirected(FrameID frame_id) const {
    265   FrameIdToStateMap::const_iterator frame_state =
    266       frame_state_map_.find(frame_id);
    267   return (frame_state != frame_state_map_.end() &&
    268           frame_state->second.is_server_redirected);
    269 }
    270 
    271 }  // namespace extensions
    272