From 622474da11d604470683db72ae4f7478f84cb9b1 Mon Sep 17 00:00:00 2001 From: "jochen@chromium.org" Date: Thu, 4 Nov 2010 09:21:08 +0000 Subject: Implement onDOMContentLoaded event of the webNavigation API. BUG=50943 TEST=browser_tests:*.WebNavigationEvents*,unit_tests:FrameNavigationStateTest.* Review URL: http://codereview.chromium.org/4381001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65034 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/chromeos/login/web_page_view.cc | 3 +- chrome/browser/chromeos/login/web_page_view.h | 2 +- .../extensions/extension_webnavigation_api.cc | 76 ++++++++++++++++++---- .../extensions/extension_webnavigation_api.h | 23 +++++-- .../extensions/extension_webnavigation_unittest.cc | 14 +++- chrome/browser/renderer_host/render_view_host.cc | 4 +- chrome/browser/renderer_host/render_view_host.h | 2 +- .../renderer_host/render_view_host_delegate.h | 2 +- chrome/browser/tab_contents/tab_contents.cc | 6 +- chrome/browser/tab_contents/tab_contents.h | 2 +- chrome/common/notification_type.h | 8 ++- chrome/common/render_messages_internal.h | 3 +- chrome/renderer/render_view.cc | 2 +- .../api_test/webnavigation/navigation1/test.html | 70 ++++++++++++++++++++ .../api_test/webnavigation/navigation2/test.html | 20 ++++++ 15 files changed, 207 insertions(+), 30 deletions(-) diff --git a/chrome/browser/chromeos/login/web_page_view.cc b/chrome/browser/chromeos/login/web_page_view.cc index 5205fa1..5a7c30a 100644 --- a/chrome/browser/chromeos/login/web_page_view.cc +++ b/chrome/browser/chromeos/login/web_page_view.cc @@ -78,7 +78,8 @@ void WizardWebPageViewTabContents::DidRunInsecureContent( page_delegate_->OnPageLoadFailed(security_origin); } -void WizardWebPageViewTabContents::DocumentLoadedInFrame() { +void WizardWebPageViewTabContents::DocumentLoadedInFrame( + long long /*frame_id*/) { page_delegate_->OnPageLoaded(); } diff --git a/chrome/browser/chromeos/login/web_page_view.h b/chrome/browser/chromeos/login/web_page_view.h index b497715..0e2bfcc 100644 --- a/chrome/browser/chromeos/login/web_page_view.h +++ b/chrome/browser/chromeos/login/web_page_view.h @@ -52,7 +52,7 @@ class WizardWebPageViewTabContents : public TabContents { virtual void DidDisplayInsecureContent(); virtual void DidRunInsecureContent(const std::string& security_origin); - virtual void DocumentLoadedInFrame(); + virtual void DocumentLoadedInFrame(long long frame_id); virtual void OnContentBlocked(ContentSettingsType type); private: diff --git a/chrome/browser/extensions/extension_webnavigation_api.cc b/chrome/browser/extensions/extension_webnavigation_api.cc index 5ef6190..3b5f0e3 100644 --- a/chrome/browser/extensions/extension_webnavigation_api.cc +++ b/chrome/browser/extensions/extension_webnavigation_api.cc @@ -44,10 +44,10 @@ FrameNavigationState::~FrameNavigationState() { } bool FrameNavigationState::CanSendEvents(long long frame_id) const { - FrameIdToErrorStateMap::const_iterator frame_state = + FrameIdToStateMap::const_iterator frame_state = frame_state_map_.find(frame_id); return frame_state != frame_state_map_.end() && - !frame_state->second; + !frame_state->second.error_occurred; } void FrameNavigationState::TrackFrame(long long frame_id, @@ -58,12 +58,35 @@ void FrameNavigationState::TrackFrame(long long frame_id, RemoveTabContentsState(tab_contents); tab_contents_map_.insert( TabContentsToFrameIdMap::value_type(tab_contents, frame_id)); - frame_state_map_[frame_id] = (url.spec() == chrome::kUnreachableWebDataURL); + FrameState& frame_state = frame_state_map_[frame_id]; + frame_state.error_occurred = (url.spec() == chrome::kUnreachableWebDataURL); + frame_state.url = url; + frame_state.is_main_frame = is_main_frame; +} + +GURL FrameNavigationState::GetUrl(long long frame_id) const { + FrameIdToStateMap::const_iterator frame_state = + frame_state_map_.find(frame_id); + if (frame_state == frame_state_map_.end()) { + NOTREACHED(); + return GURL(); + } + return frame_state->second.url; +} + +bool FrameNavigationState::IsMainFrame(long long frame_id) const { + FrameIdToStateMap::const_iterator frame_state = + frame_state_map_.find(frame_id); + if (frame_state == frame_state_map_.end()) { + NOTREACHED(); + return false; + } + return frame_state->second.is_main_frame; } void FrameNavigationState::ErrorOccurredInFrame(long long frame_id) { DCHECK(frame_state_map_.find(frame_id) != frame_state_map_.end()); - frame_state_map_[frame_id] = true; + frame_state_map_[frame_id].error_occurred = true; } void FrameNavigationState::RemoveTabContentsState( @@ -94,6 +117,9 @@ void ExtensionWebNavigationEventRouter::Init() { NotificationType::FRAME_PROVISIONAL_LOAD_COMMITTED, NotificationService::AllSources()); registrar_.Add(this, + NotificationType::FRAME_DOM_CONTENT_LOADED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR, NotificationService::AllSources()); registrar_.Add(this, @@ -117,6 +143,11 @@ void ExtensionWebNavigationEventRouter::Observe( Source(source).ptr(), Details(details).ptr()); break; + case NotificationType::FRAME_DOM_CONTENT_LOADED: + FrameDomContentLoaded( + Source(source).ptr(), + *Details(details).ptr()); + break; case NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR: FailProvisionalLoadWithError( Source(source).ptr(), @@ -139,6 +170,8 @@ void ExtensionWebNavigationEventRouter::FrameProvisionalLoadStart( details->url(), details->main_frame(), controller->tab_contents()); + if (!navigation_state_.CanSendEvents(details->frame_id())) + return; ListValue args; DictionaryValue* dict = new DictionaryValue(); dict->SetInteger(keys::kTabIdKey, @@ -152,13 +185,14 @@ void ExtensionWebNavigationEventRouter::FrameProvisionalLoadStart( std::string json_args; base::JSONWriter::Write(&args, false, &json_args); - if (navigation_state_.CanSendEvents(details->frame_id())) - DispatchEvent(controller->profile(), keys::kOnBeforeNavigate, json_args); + DispatchEvent(controller->profile(), keys::kOnBeforeNavigate, json_args); } void ExtensionWebNavigationEventRouter::FrameProvisionalLoadCommitted( NavigationController* controller, ProvisionalLoadDetails* details) { + if (!navigation_state_.CanSendEvents(details->frame_id())) + return; ListValue args; DictionaryValue* dict = new DictionaryValue(); dict->SetInteger(keys::kTabIdKey, @@ -177,13 +211,33 @@ void ExtensionWebNavigationEventRouter::FrameProvisionalLoadCommitted( std::string json_args; base::JSONWriter::Write(&args, false, &json_args); - if (navigation_state_.CanSendEvents(details->frame_id())) - DispatchEvent(controller->profile(), keys::kOnCommitted, json_args); + DispatchEvent(controller->profile(), keys::kOnCommitted, json_args); +} + +void ExtensionWebNavigationEventRouter::FrameDomContentLoaded( + NavigationController* controller, long long frame_id) { + if (!navigation_state_.CanSendEvents(frame_id)) + return; + ListValue args; + DictionaryValue* dict = new DictionaryValue(); + dict->SetInteger(keys::kTabIdKey, + ExtensionTabUtil::GetTabId(controller->tab_contents())); + dict->SetString(keys::kUrlKey, navigation_state_.GetUrl(frame_id).spec()); + dict->SetInteger(keys::kFrameIdKey, navigation_state_.IsMainFrame(frame_id) ? + 0 : static_cast(frame_id)); + dict->SetReal(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now())); + args.Append(dict); + + std::string json_args; + base::JSONWriter::Write(&args, false, &json_args); + DispatchEvent(controller->profile(), keys::kOnDOMContentLoaded, json_args); } void ExtensionWebNavigationEventRouter::FailProvisionalLoadWithError( NavigationController* controller, ProvisionalLoadDetails* details) { + if (!navigation_state_.CanSendEvents(details->frame_id())) + return; ListValue args; DictionaryValue* dict = new DictionaryValue(); dict->SetInteger(keys::kTabIdKey, @@ -198,10 +252,8 @@ void ExtensionWebNavigationEventRouter::FailProvisionalLoadWithError( std::string json_args; base::JSONWriter::Write(&args, false, &json_args); - if (navigation_state_.CanSendEvents(details->frame_id())) { - navigation_state_.ErrorOccurredInFrame(details->frame_id()); - DispatchEvent(controller->profile(), keys::kOnErrorOccurred, json_args); - } + navigation_state_.ErrorOccurredInFrame(details->frame_id()); + DispatchEvent(controller->profile(), keys::kOnErrorOccurred, json_args); } void ExtensionWebNavigationEventRouter::DispatchEvent( diff --git a/chrome/browser/extensions/extension_webnavigation_api.h b/chrome/browser/extensions/extension_webnavigation_api.h index eb78231..81d06cf 100644 --- a/chrome/browser/extensions/extension_webnavigation_api.h +++ b/chrome/browser/extensions/extension_webnavigation_api.h @@ -39,6 +39,12 @@ class FrameNavigationState { bool is_main_frame, const TabContents* tab_contents); + // Returns the URL corresponding to a tracked frame given by its |frame_id|. + GURL GetUrl(long long frame_id) const; + + // True if the frame given by its |frame_id| is the main frame of its tab. + bool IsMainFrame(long long frame_id) const; + // Marks a frame as in an error state. void ErrorOccurredInFrame(long long frame_id); @@ -47,14 +53,18 @@ class FrameNavigationState { private: typedef std::multimap TabContentsToFrameIdMap; - typedef std::map FrameIdToErrorStateMap; + struct FrameState { + bool error_occurred; // True if an error has occurred in this frame. + bool is_main_frame; // True if this is a main frame. + GURL url; // URL of this frame. + }; + typedef std::map FrameIdToStateMap; // Tracks which frames belong to a given tab contents object. TabContentsToFrameIdMap tab_contents_map_; - // Tracks which frames are in an error state. Maps to true, if an error has - // occurred in a given frame. - FrameIdToErrorStateMap frame_state_map_; + // Tracks the state of known frames. + FrameIdToStateMap frame_state_map_; DISALLOW_COPY_AND_ASSIGN(FrameNavigationState); }; @@ -91,6 +101,11 @@ class ExtensionWebNavigationEventRouter : public NotificationObserver { void FrameProvisionalLoadCommitted(NavigationController* controller, ProvisionalLoadDetails* details); + // Handler for the FRAME_DOM_CONTENT_LOADED event. The method takes the frame + // ID and constructs a suitable JSON formatted extension event from it. + void FrameDomContentLoaded(NavigationController* controller, + long long frame_id); + // Handler for the FAIL_PROVISIONAL_LOAD_WITH_ERROR event. The method takes // the details of such an event and constructs a suitable JSON formatted // extension event from it. diff --git a/chrome/browser/extensions/extension_webnavigation_unittest.cc b/chrome/browser/extensions/extension_webnavigation_unittest.cc index 04662fc..5ac378e 100644 --- a/chrome/browser/extensions/extension_webnavigation_unittest.cc +++ b/chrome/browser/extensions/extension_webnavigation_unittest.cc @@ -24,18 +24,26 @@ TEST_F(FrameNavigationStateTest, TrackFrame) { FrameNavigationState navigation_state; const long long frame_id1 = 23; const long long frame_id2 = 42; - const GURL url("http://www.google.com/"); + const GURL url1("http://www.google.com/"); + const GURL url2("http://mail.google.com/"); // Create a main frame. EXPECT_FALSE(navigation_state.CanSendEvents(frame_id1)); - navigation_state.TrackFrame(frame_id1, url, true, contents()); + navigation_state.TrackFrame(frame_id1, url1, true, contents()); EXPECT_TRUE(navigation_state.CanSendEvents(frame_id1)); // Add a sub frame. EXPECT_FALSE(navigation_state.CanSendEvents(frame_id2)); - navigation_state.TrackFrame(frame_id2, url, false, contents()); + navigation_state.TrackFrame(frame_id2, url2, false, contents()); EXPECT_TRUE(navigation_state.CanSendEvents(frame_id2)); + // Check frame state. + EXPECT_TRUE(navigation_state.IsMainFrame(frame_id1)); + EXPECT_EQ(url1, navigation_state.GetUrl(frame_id1)); + EXPECT_FALSE(navigation_state.IsMainFrame(frame_id2)); + EXPECT_EQ(url2, navigation_state.GetUrl(frame_id2)); + + // Removing the tab contents should also remove all state of its frames. navigation_state.RemoveTabContentsState(contents()); EXPECT_FALSE(navigation_state.CanSendEvents(frame_id1)); diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 0f02f0e..35932c0 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1364,11 +1364,11 @@ void RenderViewHost::OnMsgForwardMessageToExternalHost( delegate_->ProcessExternalHostMessage(message, origin, target); } -void RenderViewHost::OnMsgDocumentLoadedInFrame() { +void RenderViewHost::OnMsgDocumentLoadedInFrame(long long frame_id) { RenderViewHostDelegate::Resource* resource_delegate = delegate_->GetResourceDelegate(); if (resource_delegate) - resource_delegate->DocumentLoadedInFrame(); + resource_delegate->DocumentLoadedInFrame(frame_id); } void RenderViewHost::DisassociateFromPopupCount() { diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index acca883..6fd4cd9 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -594,7 +594,7 @@ class RenderViewHost : public RenderWidgetHost { void OnMsgForwardMessageToExternalHost(const std::string& message, const std::string& origin, const std::string& target); - void OnMsgDocumentLoadedInFrame(); + void OnMsgDocumentLoadedInFrame(long long frame_id); void OnMsgGoToEntryAtOffset(int offset); void OnMsgSetTooltipText(const std::wstring& tooltip_text, WebKit::WebTextDirection text_direction_hint); diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index 93aabb0..7f62f7e 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -361,7 +361,7 @@ class RenderViewHostDelegate { bool showing_repost_interstitial) = 0; // Notification that a document has been loaded in a frame. - virtual void DocumentLoadedInFrame() = 0; + virtual void DocumentLoadedInFrame(long long frame_id) = 0; protected: virtual ~Resource() {} diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 49cbdf4..a41fed5 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -2247,8 +2247,12 @@ void TabContents::DidFailProvisionalLoadWithError( Details(&details)); } -void TabContents::DocumentLoadedInFrame() { +void TabContents::DocumentLoadedInFrame(long long frame_id) { controller_.DocumentLoadedInFrame(); + NotificationService::current()->Notify( + NotificationType::FRAME_DOM_CONTENT_LOADED, + Source(&controller_), + Details(&frame_id)); } void TabContents::OnContentSettingsAccessed(bool content_was_blocked) { diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index 239ed92..448cb3e 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -916,7 +916,7 @@ class TabContents : public PageNavigator, int error_code, const GURL& url, bool showing_repost_interstitial); - virtual void DocumentLoadedInFrame(); + virtual void DocumentLoadedInFrame(long long frame_id); // RenderViewHostDelegate implementation. virtual RenderViewHostDelegate::View* GetViewDelegate(); diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index 8137c4b..943e0f5 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -107,13 +107,19 @@ class NotificationType { FRAME_PROVISIONAL_LOAD_START, // The provisional load for a frame was committed. The source is a - // NavigationController corresponding to the tab in which the load occured. + // NavigationController corresponding to the tab in which the load occurred. // Details is a ProvisionalLoadDetails object. In contrast to // NAV_ENTRY_COMMITTED, this notification is sent when the load was // committed, even if no navigation entry was committed (such as // AUTO_SUBFRAME navigations). FRAME_PROVISIONAL_LOAD_COMMITTED, + // The DOM for a frame was fully constructed, but referenced resources + // might not be fully loaded yet. The source is a + // Source corresponding to the tab in which the load + // occurred. Details are the long long frame ID. + FRAME_DOM_CONTENT_LOADED, + // Content was loaded from an in-memory cache. The source will be a // Source corresponding to the tab in which the load // occurred. Details in the form of a LoadFromMemoryCacheDetails object diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index be4915e..23e4ed0 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -1214,7 +1214,8 @@ IPC_BEGIN_MESSAGES(ViewHost) std::string /* state */) // Notifies the browser that a document has been loaded in a frame. - IPC_MESSAGE_ROUTED0(ViewHostMsg_DocumentLoadedInFrame) + IPC_MESSAGE_ROUTED1(ViewHostMsg_DocumentLoadedInFrame, + long long /* frame_id */) // Changes the title for the page in the UI when the page is navigated or the // title changes. diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index f918b5d..9e3bc83 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -3285,7 +3285,7 @@ void RenderView::didFinishDocumentLoad(WebFrame* frame) { DCHECK(navigation_state); navigation_state->set_finish_document_load_time(Time::Now()); - Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_)); + Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_, frame->identifier())); page_click_tracker_->StartTrackingFrame(frame); // The document has now been fully loaded. Scan for forms to be sent up to diff --git a/chrome/test/data/extensions/api_test/webnavigation/navigation1/test.html b/chrome/test/data/extensions/api_test/webnavigation/navigation1/test.html index 88ffc7c..f8a0e3f 100644 --- a/chrome/test/data/extensions/api_test/webnavigation/navigation1/test.html +++ b/chrome/test/data/extensions/api_test/webnavigation/navigation1/test.html @@ -42,6 +42,11 @@ chrome.experimental.webNavigation.onCommitted.addListener(function(details) { captureEvent("onCommitted", details); }); +chrome.experimental.webNavigation.onDOMContentLoaded.addListener( + function(details) { + captureEvent("onDOMContentLoaded", details); +}); + chrome.experimental.webNavigation.onErrorOccurred.addListener( function(details) { captureEvent("onErrorOccurred", details); @@ -67,6 +72,11 @@ chrome.tabs.getSelected(null, function(tab) { timeStamp: 0, transitionQualifiers: "", transitionType: "link", + url: getURL('simpleLoad/a.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, url: getURL('simpleLoad/a.html') }]]); chrome.tabs.update(tabId, { url: getURL('simpleLoad/a.html') }); }, @@ -89,6 +99,11 @@ chrome.tabs.getSelected(null, function(tab) { transitionQualifiers: "", transitionType: "link", url: getURL('clientRedirect/a.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, + url: getURL('clientRedirect/a.html') }], [ "onBeforeNavigate", { frameId: 0, requestId: 0, @@ -101,6 +116,11 @@ chrome.tabs.getSelected(null, function(tab) { timeStamp: 0, transitionQualifiers: "client_redirect", transitionType: "link", + url: getURL('clientRedirect/b.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, url: getURL('clientRedirect/b.html') }]]); chrome.tabs.update(tabId, { url: getURL('clientRedirect/a.html') }); }, @@ -122,6 +142,11 @@ chrome.tabs.getSelected(null, function(tab) { transitionQualifiers: "", transitionType: "link", url: getURL('forwardBack/a.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, + url: getURL('forwardBack/a.html') }], [ "onBeforeNavigate", { frameId: 0, requestId: 0, @@ -135,6 +160,11 @@ chrome.tabs.getSelected(null, function(tab) { transitionQualifiers: "client_redirect", transitionType: "link", url: getURL('forwardBack/b.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, + url: getURL('forwardBack/b.html') }], [ "onBeforeNavigate", { frameId: 0, requestId: 0, @@ -147,6 +177,11 @@ chrome.tabs.getSelected(null, function(tab) { timeStamp: 0, transitionQualifiers: "forward_back", transitionType: "link", + url: getURL('forwardBack/a.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, url: getURL('forwardBack/a.html') }]]); chrome.tabs.update(tabId, { url: getURL('forwardBack/a.html') }); }, @@ -174,6 +209,11 @@ chrome.tabs.getSelected(null, function(tab) { tabId: tabId, timeStamp: 0, url: getURL('iframe/b.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, + url: getURL('iframe/a.html') }], [ "onCommitted", { frameId: 1, tabId: tabId, @@ -181,6 +221,11 @@ chrome.tabs.getSelected(null, function(tab) { transitionQualifiers: "", transitionType: "auto_subframe", url: getURL('iframe/b.html') }], + [ "onDOMContentLoaded", + { frameId: 1, + tabId: tabId, + timeStamp: 0, + url: getURL('iframe/b.html') }], [ "onBeforeNavigate", { frameId: 1, requestId: 0, @@ -193,6 +238,11 @@ chrome.tabs.getSelected(null, function(tab) { timeStamp: 0, transitionQualifiers: "", transitionType: "manual_subframe", + url: getURL('iframe/c.html') }], + [ "onDOMContentLoaded", + { frameId: 1, + tabId: tabId, + timeStamp: 0, url: getURL('iframe/c.html') }]]); chrome.tabs.update(tabId, { url: getURL('iframe/a.html') }); }, @@ -221,6 +271,11 @@ chrome.tabs.getSelected(null, function(tab) { tabId: tabId, timeStamp: 0, url: getURL('iframe/e.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, + url: getURL('iframe/d.html') }], [ "onCommitted", { frameId: 1, tabId: tabId, @@ -228,6 +283,11 @@ chrome.tabs.getSelected(null, function(tab) { transitionQualifiers: "", transitionType: "auto_subframe", url: getURL('iframe/e.html') }], + [ "onDOMContentLoaded", + { frameId: 1, + tabId: tabId, + timeStamp: 0, + url: getURL('iframe/e.html') }], [ "onBeforeNavigate", { frameId: 2, requestId: 0, @@ -241,6 +301,11 @@ chrome.tabs.getSelected(null, function(tab) { transitionQualifiers: "", transitionType: "auto_subframe", url: getURL('iframe/f.html') }], + [ "onDOMContentLoaded", + { frameId: 2, + tabId: tabId, + timeStamp: 0, + url: getURL('iframe/f.html') }], [ "onBeforeNavigate", { frameId: 2, requestId: 0, @@ -253,6 +318,11 @@ chrome.tabs.getSelected(null, function(tab) { timeStamp: 0, transitionQualifiers: "", transitionType: "manual_subframe", + url: getURL('iframe/g.html') }], + [ "onDOMContentLoaded", + { frameId: 2, + tabId: tabId, + timeStamp: 0, url: getURL('iframe/g.html') }]]); chrome.tabs.update(tabId, { url: getURL('iframe/d.html') }); }, diff --git a/chrome/test/data/extensions/api_test/webnavigation/navigation2/test.html b/chrome/test/data/extensions/api_test/webnavigation/navigation2/test.html index 9bf4b47..e97a67a 100644 --- a/chrome/test/data/extensions/api_test/webnavigation/navigation2/test.html +++ b/chrome/test/data/extensions/api_test/webnavigation/navigation2/test.html @@ -42,6 +42,11 @@ chrome.experimental.webNavigation.onCommitted.addListener(function(details) { captureEvent("onCommitted", details); }); +chrome.experimental.webNavigation.onDOMContentLoaded.addListener( + function(details) { + captureEvent("onDOMContentLoaded", details); +}); + chrome.experimental.webNavigation.onErrorOccurred.addListener( function(details) { captureEvent("onErrorOccurred", details); @@ -92,6 +97,11 @@ chrome.tabs.getSelected(null, function(tab) { tabId: tabId, timeStamp: 0, url: getURL('iframeFail/c.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, + url: getURL('iframeFail/d.html') }], [ "onErrorOccurred", { error: "net::ERR_FILE_NOT_FOUND", frameId: 1, @@ -123,6 +133,11 @@ chrome.tabs.getSelected(null, function(tab) { tabId: tabId, timeStamp: 0, url: getURL('iframeFail/b.html') }], + [ "onDOMContentLoaded", + { frameId: 0, + tabId: tabId, + timeStamp: 0, + url: getURL('iframeFail/a.html') }], [ "onCommitted", { frameId: 1, tabId: tabId, @@ -130,6 +145,11 @@ chrome.tabs.getSelected(null, function(tab) { transitionQualifiers: "", transitionType: "auto_subframe", url: getURL('iframeFail/b.html') }], + [ "onDOMContentLoaded", + { frameId: 1, + tabId: tabId, + timeStamp: 0, + url: getURL('iframeFail/b.html') }], [ "onBeforeNavigate", { frameId: 1, requestId: 0, -- cgit v1.1