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 "base/macros.h" 6#include "base/values.h" 7#include "chrome/browser/extensions/api/web_navigation/frame_navigation_state.h" 8#include "chrome/test/base/chrome_render_view_host_test_harness.h" 9#include "chrome/test/base/testing_profile.h" 10#include "testing/gtest/include/gtest/gtest.h" 11 12namespace extensions { 13 14class FrameNavigationStateTest : public ChromeRenderViewHostTestHarness { 15 protected: 16 FrameNavigationStateTest() {} 17 virtual ~FrameNavigationStateTest() {} 18 19 FrameNavigationState navigation_state_; 20 21 private: 22 DISALLOW_COPY_AND_ASSIGN(FrameNavigationStateTest); 23}; 24 25// Test that a frame is correctly tracked, and removed once the tab contents 26// goes away. 27TEST_F(FrameNavigationStateTest, TrackFrame) { 28 const GURL url1("http://www.google.com/"); 29 const GURL url2("http://mail.google.com/"); 30 31 // Create a main frame. 32 EXPECT_FALSE(navigation_state_.CanSendEvents(main_rfh())); 33 EXPECT_FALSE(navigation_state_.IsValidFrame(main_rfh())); 34 navigation_state_.TrackFrame(main_rfh(), url1, false, false); 35 navigation_state_.SetNavigationCommitted(main_rfh()); 36 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 37 EXPECT_TRUE(navigation_state_.IsValidFrame(main_rfh())); 38 39 // Add a sub frame. 40 content::RenderFrameHost* sub_frame = 41 content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"); 42 EXPECT_FALSE(navigation_state_.CanSendEvents(sub_frame)); 43 EXPECT_FALSE(navigation_state_.IsValidFrame(sub_frame)); 44 navigation_state_.TrackFrame(sub_frame, url2, false, false); 45 navigation_state_.SetNavigationCommitted(sub_frame); 46 EXPECT_TRUE(navigation_state_.CanSendEvents(sub_frame)); 47 EXPECT_TRUE(navigation_state_.IsValidFrame(sub_frame)); 48 49 // Check frame state. 50 EXPECT_EQ(url1, navigation_state_.GetUrl(main_rfh())); 51 EXPECT_EQ(url2, navigation_state_.GetUrl(sub_frame)); 52 EXPECT_EQ(main_rfh(), navigation_state_.GetLastCommittedMainFrameHost()); 53 54 // Drop the frames. 55 navigation_state_.StopTrackingFramesInRVH(rvh(), NULL); 56 EXPECT_FALSE(navigation_state_.CanSendEvents(main_rfh())); 57 EXPECT_FALSE(navigation_state_.IsValidFrame(main_rfh())); 58 EXPECT_FALSE(navigation_state_.CanSendEvents(sub_frame)); 59 EXPECT_FALSE(navigation_state_.IsValidFrame(sub_frame)); 60} 61 62// Test that no events can be sent for a frame after an error occurred, but 63// before a new navigation happened in this frame. 64TEST_F(FrameNavigationStateTest, ErrorState) { 65 const GURL url("http://www.google.com/"); 66 67 navigation_state_.TrackFrame(main_rfh(), url, false, false); 68 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 69 EXPECT_FALSE(navigation_state_.GetErrorOccurredInFrame(main_rfh())); 70 71 // After an error occurred, no further events should be sent. 72 navigation_state_.SetErrorOccurredInFrame(main_rfh()); 73 EXPECT_FALSE(navigation_state_.CanSendEvents(main_rfh())); 74 EXPECT_TRUE(navigation_state_.GetErrorOccurredInFrame(main_rfh())); 75 76 // Navigations to a network error page should be ignored. 77 navigation_state_.TrackFrame(main_rfh(), GURL(), true, false); 78 EXPECT_FALSE(navigation_state_.CanSendEvents(main_rfh())); 79 EXPECT_TRUE(navigation_state_.GetErrorOccurredInFrame(main_rfh())); 80 81 // However, when the frame navigates again, it should send events again. 82 navigation_state_.TrackFrame(main_rfh(), url, false, false); 83 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 84 EXPECT_FALSE(navigation_state_.GetErrorOccurredInFrame(main_rfh())); 85} 86 87// Tests that for a sub frame, no events are send after an error occurred, but 88// before a new navigation happened in this frame. 89TEST_F(FrameNavigationStateTest, ErrorStateFrame) { 90 const GURL url("http://www.google.com/"); 91 92 content::RenderFrameHost* sub_frame = 93 content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"); 94 navigation_state_.TrackFrame(main_rfh(), url, false, false); 95 navigation_state_.TrackFrame(sub_frame, url, false, false); 96 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 97 EXPECT_TRUE(navigation_state_.CanSendEvents(sub_frame)); 98 99 // After an error occurred, no further events should be sent. 100 navigation_state_.SetErrorOccurredInFrame(sub_frame); 101 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 102 EXPECT_FALSE(navigation_state_.CanSendEvents(sub_frame)); 103 104 // Navigations to a network error page should be ignored. 105 navigation_state_.TrackFrame(sub_frame, GURL(), true, false); 106 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 107 EXPECT_FALSE(navigation_state_.CanSendEvents(sub_frame)); 108 109 // However, when the frame navigates again, it should send events again. 110 navigation_state_.TrackFrame(sub_frame, url, false, false); 111 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 112 EXPECT_TRUE(navigation_state_.CanSendEvents(sub_frame)); 113} 114 115// Tests that no events are send for a not web-safe scheme. 116TEST_F(FrameNavigationStateTest, WebSafeScheme) { 117 const GURL url("unsafe://www.google.com/"); 118 119 navigation_state_.TrackFrame(main_rfh(), url, false, false); 120 EXPECT_FALSE(navigation_state_.CanSendEvents(main_rfh())); 121} 122 123// Test for <iframe srcdoc=""> frames. 124TEST_F(FrameNavigationStateTest, SrcDoc) { 125 const GURL url("http://www.google.com/"); 126 const GURL blank("about:blank"); 127 const GURL srcdoc("about:srcdoc"); 128 129 content::RenderFrameHost* sub_frame = 130 content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"); 131 navigation_state_.TrackFrame(main_rfh(), url, false, false); 132 navigation_state_.TrackFrame(sub_frame, blank, false, true); 133 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 134 EXPECT_TRUE(navigation_state_.CanSendEvents(sub_frame)); 135 136 EXPECT_EQ(url, navigation_state_.GetUrl(main_rfh())); 137 EXPECT_EQ(srcdoc, navigation_state_.GetUrl(sub_frame)); 138 139 EXPECT_TRUE(navigation_state_.IsValidUrl(srcdoc)); 140} 141 142// Test that an individual frame can be detached. 143TEST_F(FrameNavigationStateTest, DetachFrame) { 144 const GURL url1("http://www.google.com/"); 145 const GURL url2("http://mail.google.com/"); 146 147 // Create a main frame. 148 EXPECT_FALSE(navigation_state_.CanSendEvents(main_rfh())); 149 EXPECT_FALSE(navigation_state_.IsValidFrame(main_rfh())); 150 navigation_state_.TrackFrame(main_rfh(), url1, false, false); 151 navigation_state_.SetNavigationCommitted(main_rfh()); 152 EXPECT_TRUE(navigation_state_.CanSendEvents(main_rfh())); 153 EXPECT_TRUE(navigation_state_.IsValidFrame(main_rfh())); 154 155 // Add a sub frame. 156 content::RenderFrameHost* sub_frame = 157 content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"); 158 EXPECT_FALSE(navigation_state_.CanSendEvents(sub_frame)); 159 EXPECT_FALSE(navigation_state_.IsValidFrame(sub_frame)); 160 navigation_state_.TrackFrame(sub_frame, url2, false, false); 161 navigation_state_.SetNavigationCommitted(sub_frame); 162 EXPECT_TRUE(navigation_state_.CanSendEvents(sub_frame)); 163 EXPECT_TRUE(navigation_state_.IsValidFrame(sub_frame)); 164 165 // Check frame state. 166 EXPECT_EQ(url1, navigation_state_.GetUrl(main_rfh())); 167 EXPECT_EQ(url2, navigation_state_.GetUrl(sub_frame)); 168 EXPECT_EQ(main_rfh(), navigation_state_.GetLastCommittedMainFrameHost()); 169 170 // Drop one frame. 171 navigation_state_.FrameDetached(sub_frame); 172 EXPECT_EQ(url1, navigation_state_.GetUrl(main_rfh())); 173 EXPECT_EQ(main_rfh(), navigation_state_.GetLastCommittedMainFrameHost()); 174 EXPECT_FALSE(navigation_state_.CanSendEvents(sub_frame)); 175 EXPECT_FALSE(navigation_state_.IsValidFrame(sub_frame)); 176} 177 178} // namespace extensions 179