Commit d34e1de0 authored by jochen@chromium.org's avatar jochen@chromium.org

When an iframe displays its srcdoc, generate navigation events for about:srcdoc

BUG=143337
TEST=unit_tests:FrameNavigationStateTest.SrcDoc, browser_tests:WebNavigationApiTest.SrcDoc
R=marja@chromium.org,creis@chromium.org


Review URL: https://chromiumcodereview.appspot.com/11791018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175518 0039d316-1c4b-4281-b951-d872f2087c98
parent d643dd66
......@@ -55,6 +55,8 @@ bool FrameNavigationState::FrameID::operator!=(
return !(*this == other);
}
FrameNavigationState::FrameState::FrameState() {}
// static
bool FrameNavigationState::allow_extension_scheme_ = false;
......@@ -77,9 +79,11 @@ bool FrameNavigationState::IsValidUrl(const GURL& url) const {
if (url.scheme() == kValidSchemes[i])
return true;
}
// Allow about:blank.
if (url.spec() == chrome::kAboutBlankURL)
// Allow about:blank and about:srcdoc.
if (url.spec() == chrome::kAboutBlankURL ||
url.spec() == chrome::kAboutSrcDocURL) {
return true;
}
if (allow_extension_scheme_ && url.scheme() == extensions::kExtensionScheme)
return true;
return false;
......@@ -89,11 +93,14 @@ void FrameNavigationState::TrackFrame(FrameID frame_id,
FrameID parent_frame_id,
const GURL& url,
bool is_main_frame,
bool is_error_page) {
bool is_error_page,
bool is_iframe_srcdoc) {
FrameState& frame_state = frame_state_map_[frame_id];
frame_state.error_occurred = is_error_page;
frame_state.url = url;
frame_state.is_main_frame = is_main_frame;
frame_state.is_iframe_srcdoc = is_iframe_srcdoc;
DCHECK(!is_iframe_srcdoc || url == GURL(chrome::kAboutBlankURL));
frame_state.is_navigating = true;
frame_state.is_committed = false;
frame_state.is_server_redirected = false;
......@@ -146,6 +153,8 @@ GURL FrameNavigationState::GetUrl(FrameID frame_id) const {
NOTREACHED();
return GURL();
}
if (frame_state->second.is_iframe_srcdoc)
return GURL(chrome::kAboutSrcDocURL);
return frame_state->second.url;
}
......
......@@ -54,7 +54,8 @@ class FrameNavigationState {
FrameID parent_frame_id,
const GURL& url,
bool is_main_frame,
bool is_error_page);
bool is_error_page,
bool is_iframe_srcdoc);
// Stops tracking all frames but the frame with |id_to_skip| for a given
// RenderViewHost.
......@@ -116,8 +117,11 @@ class FrameNavigationState {
private:
struct FrameState {
FrameState();
bool error_occurred; // True if an error has occurred in this frame.
bool is_main_frame; // True if this is a main frame.
bool is_iframe_srcdoc; // True if the frame is displaying its srcdoc.
bool is_navigating; // True if there is a navigation going on.
bool is_committed; // True if the navigation is already committed.
bool is_server_redirected; // True if a server redirect happened.
......
......@@ -25,7 +25,7 @@ TEST(FrameNavigationStateTest, TrackFrame) {
// Create a main frame.
EXPECT_FALSE(navigation_state.CanSendEvents(frame_id1));
EXPECT_FALSE(navigation_state.IsValidFrame(frame_id1));
navigation_state.TrackFrame(frame_id1, frame_id0, url1, true, false);
navigation_state.TrackFrame(frame_id1, frame_id0, url1, true, false, false);
navigation_state.SetNavigationCommitted(frame_id1);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1));
EXPECT_TRUE(navigation_state.IsValidFrame(frame_id1));
......@@ -33,7 +33,7 @@ TEST(FrameNavigationStateTest, TrackFrame) {
// Add a sub frame.
EXPECT_FALSE(navigation_state.CanSendEvents(frame_id2));
EXPECT_FALSE(navigation_state.IsValidFrame(frame_id2));
navigation_state.TrackFrame(frame_id2, frame_id1, url2, false, false);
navigation_state.TrackFrame(frame_id2, frame_id1, url2, false, false, false);
navigation_state.SetNavigationCommitted(frame_id2);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id2));
EXPECT_TRUE(navigation_state.IsValidFrame(frame_id2));
......@@ -62,7 +62,7 @@ TEST(FrameNavigationStateTest, ErrorState) {
const FrameNavigationState::FrameID frame_id1(42, fake_rvh);
const GURL url("http://www.google.com/");
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false);
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false, false);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1));
EXPECT_FALSE(navigation_state.GetErrorOccurredInFrame(frame_id1));
......@@ -72,12 +72,12 @@ TEST(FrameNavigationStateTest, ErrorState) {
EXPECT_TRUE(navigation_state.GetErrorOccurredInFrame(frame_id1));
// Navigations to a network error page should be ignored.
navigation_state.TrackFrame(frame_id1, frame_id0, GURL(), true, true);
navigation_state.TrackFrame(frame_id1, frame_id0, GURL(), true, true, false);
EXPECT_FALSE(navigation_state.CanSendEvents(frame_id1));
EXPECT_TRUE(navigation_state.GetErrorOccurredInFrame(frame_id1));
// However, when the frame navigates again, it should send events again.
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false);
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false, false);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1));
EXPECT_FALSE(navigation_state.GetErrorOccurredInFrame(frame_id1));
}
......@@ -91,8 +91,8 @@ TEST(FrameNavigationStateTest, ErrorStateFrame) {
const FrameNavigationState::FrameID frame_id2(42, fake_rvh);
const GURL url("http://www.google.com/");
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false);
navigation_state.TrackFrame(frame_id2, frame_id1, url, false, false);
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false, false);
navigation_state.TrackFrame(frame_id2, frame_id1, url, false, false, false);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1));
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id2));
......@@ -102,12 +102,12 @@ TEST(FrameNavigationStateTest, ErrorStateFrame) {
EXPECT_FALSE(navigation_state.CanSendEvents(frame_id2));
// Navigations to a network error page should be ignored.
navigation_state.TrackFrame(frame_id2, frame_id1, GURL(), false, true);
navigation_state.TrackFrame(frame_id2, frame_id1, GURL(), false, true, false);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1));
EXPECT_FALSE(navigation_state.CanSendEvents(frame_id2));
// However, when the frame navigates again, it should send events again.
navigation_state.TrackFrame(frame_id2, frame_id1, url, false, false);
navigation_state.TrackFrame(frame_id2, frame_id1, url, false, false, false);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1));
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id2));
}
......@@ -119,7 +119,7 @@ TEST(FrameNavigationStateTest, WebSafeScheme) {
const FrameNavigationState::FrameID frame_id1(23, fake_rvh);
const GURL url("unsafe://www.google.com/");
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false);
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false, false);
EXPECT_FALSE(navigation_state.CanSendEvents(frame_id1));
}
......@@ -131,8 +131,8 @@ TEST(FrameNavigationStateTest, ParentFrameID) {
const FrameNavigationState::FrameID frame_id2(42, fake_rvh);
const GURL url("http://www.google.com/");
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false);
navigation_state.TrackFrame(frame_id2, frame_id1, url, false, false);
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false, false);
navigation_state.TrackFrame(frame_id2, frame_id1, url, false, false, false);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1));
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id2));
......@@ -140,4 +140,25 @@ TEST(FrameNavigationStateTest, ParentFrameID) {
EXPECT_TRUE(navigation_state.GetParentFrameID(frame_id2) == frame_id1);
}
// Test for <iframe srcdoc=""> frames.
TEST(FrameNavigationStateTest, SrcDoc) {
FrameNavigationState navigation_state;
const FrameNavigationState::FrameID frame_id0(-1, fake_rvh);
const FrameNavigationState::FrameID frame_id1(23, fake_rvh);
const FrameNavigationState::FrameID frame_id2(42, fake_rvh);
const GURL url("http://www.google.com/");
const GURL blank("about:blank");
const GURL srcdoc("about:srcdoc");
navigation_state.TrackFrame(frame_id1, frame_id0, url, true, false, false);
navigation_state.TrackFrame(frame_id2, frame_id1, blank, false, false, true);
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1));
EXPECT_TRUE(navigation_state.CanSendEvents(frame_id2));
EXPECT_TRUE(navigation_state.GetUrl(frame_id1) == url);
EXPECT_TRUE(navigation_state.GetUrl(frame_id2) == srcdoc);
EXPECT_TRUE(navigation_state.IsValidUrl(srcdoc));
}
} // namespace extensions
......@@ -26,6 +26,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "net/base/net_errors.h"
namespace GetFrame = extensions::api::web_navigation::GetFrame;
......@@ -376,7 +377,9 @@ void WebNavigationTabObserver::DidStartProvisionalLoadForFrame(
parent_frame_id,
validated_url,
is_main_frame,
is_error_page);
is_error_page,
is_iframe_srcdoc);
if (!navigation_state_.CanSendEvents(frame_id))
return;
......@@ -387,7 +390,7 @@ void WebNavigationTabObserver::DidStartProvisionalLoadForFrame(
is_main_frame,
parent_frame_num,
navigation_state_.IsMainFrame(parent_frame_id),
validated_url);
navigation_state_.GetUrl(frame_id));
}
void WebNavigationTabObserver::DidCommitProvisionalLoadForFrame(
......@@ -441,7 +444,7 @@ void WebNavigationTabObserver::DidCommitProvisionalLoadForFrame(
web_contents(),
frame_num,
is_main_frame,
url,
navigation_state_.GetUrl(frame_id),
transition_type);
} else if (is_history_state_modification) {
helpers::DispatchOnCommitted(
......@@ -449,7 +452,7 @@ void WebNavigationTabObserver::DidCommitProvisionalLoadForFrame(
web_contents(),
frame_num,
is_main_frame,
url,
navigation_state_.GetUrl(frame_id),
transition_type);
} else {
if (navigation_state_.GetIsServerRedirected(frame_id)) {
......@@ -461,7 +464,7 @@ void WebNavigationTabObserver::DidCommitProvisionalLoadForFrame(
web_contents(),
frame_num,
is_main_frame,
url,
navigation_state_.GetUrl(frame_id),
transition_type);
}
}
......@@ -485,8 +488,12 @@ void WebNavigationTabObserver::DidFailProvisionalLoad(
FrameNavigationState::FrameID frame_id(frame_num, render_view_host);
if (navigation_state_.CanSendEvents(frame_id)) {
helpers::DispatchOnErrorOccurred(
web_contents(), render_view_host->GetProcess()->GetID(), validated_url,
frame_num, is_main_frame, error_code);
web_contents(),
render_view_host->GetProcess()->GetID(),
navigation_state_.GetUrl(frame_id),
frame_num,
is_main_frame,
error_code);
}
navigation_state_.SetErrorOccurredInFrame(frame_id);
if (stop_tracking_frames) {
......@@ -524,10 +531,12 @@ void WebNavigationTabObserver::DidFinishLoad(
navigation_state_.SetNavigationCompleted(frame_id);
if (!navigation_state_.CanSendEvents(frame_id))
return;
DCHECK_EQ(navigation_state_.GetUrl(frame_id), validated_url);
DCHECK(navigation_state_.GetUrl(frame_id) == validated_url ||
(navigation_state_.GetUrl(frame_id) == GURL(chrome::kAboutSrcDocURL) &&
validated_url == GURL(chrome::kAboutBlankURL)));
DCHECK_EQ(navigation_state_.IsMainFrame(frame_id), is_main_frame);
helpers::DispatchOnCompleted(web_contents(),
validated_url,
navigation_state_.GetUrl(frame_id),
is_main_frame,
frame_num);
}
......@@ -548,8 +557,12 @@ void WebNavigationTabObserver::DidFailLoad(
return;
if (navigation_state_.CanSendEvents(frame_id)) {
helpers::DispatchOnErrorOccurred(
web_contents(), render_view_host->GetProcess()->GetID(), validated_url,
frame_num, is_main_frame, error_code);
web_contents(),
render_view_host->GetProcess()->GetID(),
navigation_state_.GetUrl(frame_id),
frame_num,
is_main_frame,
error_code);
}
navigation_state_.SetErrorOccurredInFrame(frame_id);
}
......
......@@ -444,6 +444,11 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, IFrame) {
RunExtensionSubtest("webnavigation", "test_iframe.html")) << message_;
}
IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, SrcDoc) {
ASSERT_TRUE(
RunExtensionSubtest("webnavigation", "test_srcdoc.html")) << message_;
}
IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, OpenTab) {
ASSERT_TRUE(
RunExtensionSubtest("webnavigation", "test_openTab.html")) << message_;
......
<script src="test_srcdoc.js"></script>
<script src="framework.js"></script>
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
onload = function() {
var getURL = chrome.extension.getURL;
chrome.tabs.create({"url": "about:blank"}, function(tab) {
var tabId = tab.id;
chrome.test.runTests([
// Navigates to a.html which includes an iframe with a srcdoc attribute.
function srcdoc() {
expect([
{ label: "a-onBeforeNavigate",
event: "onBeforeNavigate",
details: { frameId: 0,
parentFrameId: -1,
processId: 0,
tabId: 0,
timeStamp: 0,
url: getURL('srcdoc/a.html') }},
{ label: "a-onCommitted",
event: "onCommitted",
details: { frameId: 0,
processId: 0,
tabId: 0,
timeStamp: 0,
transitionQualifiers: [],
transitionType: "link",
url: getURL('srcdoc/a.html') }},
{ label: "a-onDOMContentLoaded",
event: "onDOMContentLoaded",
details: { frameId: 0,
processId: 0,
tabId: 0,
timeStamp: 0,
url: getURL('srcdoc/a.html') }},
{ label: "a-onCompleted",
event: "onCompleted",
details: { frameId: 0,
processId: 0,
tabId: 0,
timeStamp: 0,
url: getURL('srcdoc/a.html') }},
{ label: "b-onBeforeNavigate",
event: "onBeforeNavigate",
details: { frameId: 1,
parentFrameId: 0,
processId: 0,
tabId: 0,
timeStamp: 0,
url: 'about:srcdoc' }},
{ label: "b-onCommitted",
event: "onCommitted",
details: { frameId: 1,
processId: 0,
tabId: 0,
timeStamp: 0,
transitionQualifiers: [],
transitionType: "auto_subframe",
url: 'about:srcdoc' }},
{ label: "b-onDOMContentLoaded",
event: "onDOMContentLoaded",
details: { frameId: 1,
processId: 0,
tabId: 0,
timeStamp: 0,
url: 'about:srcdoc' }},
{ label: "b-onCompleted",
event: "onCompleted",
details: { frameId: 1,
processId: 0,
tabId: 0,
timeStamp: 0,
url: 'about:srcdoc' }}],
[ navigationOrder("a-"),
navigationOrder("b-"),
isIFrameOf("b-", "a-")]);
chrome.tabs.update(tabId, { url: getURL('srcdoc/a.html') });
},
]);
});
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment