diff options
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 14 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 2 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host_delegate.h | 5 | ||||
-rw-r--r-- | chrome/browser/session_history_uitest.cc | 37 | ||||
-rw-r--r-- | chrome/browser/tab_contents/navigation_controller.cc | 4 | ||||
-rw-r--r-- | chrome/browser/tab_contents/navigation_controller.h | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 25 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.h | 2 | ||||
-rw-r--r-- | chrome/common/chrome_constants.cc | 2 | ||||
-rw-r--r-- | chrome/common/chrome_constants.h | 3 | ||||
-rw-r--r-- | chrome/common/render_messages.h | 16 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 4 | ||||
-rw-r--r-- | chrome/renderer/navigation_state.h | 18 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 60 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 7 | ||||
-rw-r--r-- | chrome/test/data/session_history/record_length.html | 3 |
16 files changed, 119 insertions, 85 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 1c76a24..f4e297c 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -975,8 +975,6 @@ void RenderViewHost::OnMsgNavigate(const IPC::Message& msg) { FilterURL(policy, renderer_id, &validated_params.password_form.action); delegate_->DidNavigate(this, validated_params); - - UpdateBackForwardListCount(); } void RenderViewHost::OnMsgUpdateState(int32 page_id, @@ -1506,18 +1504,6 @@ void RenderViewHost::OnCrashedPlugin(const FilePath& plugin_path) { integration_delegate->OnCrashedPlugin(plugin_path); } -void RenderViewHost::UpdateBackForwardListCount() { - int back_list_count = 0, forward_list_count = 0; - RenderViewHostDelegate::BrowserIntegration* integration_delegate = - delegate_->GetBrowserIntegrationDelegate(); - if (integration_delegate) { - integration_delegate->GetHistoryListCount(&back_list_count, - &forward_list_count); - Send(new ViewMsg_UpdateBackForwardListCount( - routing_id(), back_list_count, forward_list_count)); - } -} - void RenderViewHost::GetAllSavableResourceLinksForCurrentPage( const GURL& page_url) { Send(new ViewMsg_GetAllSavableResourceLinksForCurrentPage(routing_id(), diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index cc52d47..b413239 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -624,8 +624,6 @@ class RenderViewHost : public RenderWidgetHost { private: friend class TestRenderViewHost; - void UpdateBackForwardListCount(); - // The SiteInstance associated with this RenderViewHost. All pages drawn // in this RenderViewHost are part of this SiteInstance. Should not change // over time. diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index b1a1148..d9fbb01 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -204,11 +204,6 @@ class RenderViewHostDelegate { // not valid. virtual void GoToEntryAtOffset(int offset) = 0; - // The page requests the size of the back and forward lists - // within the NavigationController. - virtual void GetHistoryListCount(int* back_list_count, - int* forward_list_count) = 0; - // Notification when default plugin updates status of the missing plugin. virtual void OnMissingPluginStatus(int status) = 0; diff --git a/chrome/browser/session_history_uitest.cc b/chrome/browser/session_history_uitest.cc index 8209338..e8ac1c5 100644 --- a/chrome/browser/session_history_uitest.cc +++ b/chrome/browser/session_history_uitest.cc @@ -23,6 +23,7 @@ const wchar_t kDocRoot[] = L"chrome/test/data"; class SessionHistoryTest : public UITest { protected: SessionHistoryTest() : UITest() { + dom_automation_enabled_ = true; } virtual void SetUp() { @@ -515,4 +516,40 @@ TEST_F(SessionHistoryTest, LocationChangeInSubframe) { EXPECT_EQ(L"Default Title", GetTabTitle()); } +TEST_F(SessionHistoryTest, HistoryLength) { + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(kDocRoot, NULL); + ASSERT_TRUE(server.get()); + + int length; + ASSERT_TRUE(tab_->ExecuteAndExtractInt( + L"", L"domAutomationController.send(history.length)", &length)); + EXPECT_EQ(1, length); + + ASSERT_TRUE(tab_->NavigateToURL(server->TestServerPage("files/title1.html"))); + + ASSERT_TRUE(tab_->ExecuteAndExtractInt( + L"", L"domAutomationController.send(history.length)", &length)); + EXPECT_EQ(2, length); + + // Now test that history.length is updated when the navigation is committed. + ASSERT_TRUE(tab_->NavigateToURL(server->TestServerPage( + "files/session_history/record_length.html"))); + ASSERT_TRUE(tab_->ExecuteAndExtractInt( + L"", L"domAutomationController.send(history.length)", &length)); + EXPECT_EQ(3, length); + ASSERT_TRUE(tab_->ExecuteAndExtractInt( + L"", L"domAutomationController.send(history_length)", &length)); + EXPECT_EQ(3, length); + + ASSERT_TRUE(tab_->GoBack()); + ASSERT_TRUE(tab_->GoBack()); + + // Ensure history.length is properly truncated. + ASSERT_TRUE(tab_->NavigateToURL(server->TestServerPage("files/title2.html"))); + ASSERT_TRUE(tab_->ExecuteAndExtractInt( + L"", L"domAutomationController.send(history.length)", &length)); + EXPECT_EQ(2, length); +} + } // namespace diff --git a/chrome/browser/tab_contents/navigation_controller.cc b/chrome/browser/tab_contents/navigation_controller.cc index bdcc811..991b289 100644 --- a/chrome/browser/tab_contents/navigation_controller.cc +++ b/chrome/browser/tab_contents/navigation_controller.cc @@ -22,6 +22,7 @@ #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/common/chrome_constants.h" #include "chrome/common/navigation_types.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" @@ -114,7 +115,8 @@ const base::TimeDelta kMaxAutoNavigationTimeDelta = // NavigationController --------------------------------------------------- // static -size_t NavigationController::max_entry_count_ = 50; +size_t NavigationController::max_entry_count_ = + chrome::kMaxSessionHistoryEntries; // static bool NavigationController::check_for_repost_ = true; diff --git a/chrome/browser/tab_contents/navigation_controller.h b/chrome/browser/tab_contents/navigation_controller.h index c2dae3f..16011d3 100644 --- a/chrome/browser/tab_contents/navigation_controller.h +++ b/chrome/browser/tab_contents/navigation_controller.h @@ -395,9 +395,11 @@ class NavigationController { static void DisablePromptOnRepost(); // Maximum number of entries before we start removing entries from the front. +#ifdef UNIT_TEST static void set_max_entry_count(size_t max_entry_count) { max_entry_count_ = max_entry_count; } +#endif static size_t max_entry_count() { return max_entry_count_; } // Cancels a repost that brought up a warning. diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 97e49b3..aa2bc97 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -204,15 +204,20 @@ ViewMsg_Navigate_Params::NavigationType GetNavigationType( return ViewMsg_Navigate_Params::NORMAL; } -void MakeNavigateParams(Profile* profile, const NavigationEntry& entry, +void MakeNavigateParams(const NavigationController& controller, NavigationController::ReloadType reload_type, ViewMsg_Navigate_Params* params) { + const NavigationEntry& entry = *controller.pending_entry(); params->page_id = entry.page_id(); + params->pending_history_list_offset = controller.pending_entry_index(); + params->current_history_list_offset = controller.last_committed_entry_index(); + params->current_history_list_length = controller.entry_count(); params->url = entry.url(); params->referrer = entry.referrer(); params->transition = entry.transition_type(); params->state = entry.content_state(); - params->navigation_type = GetNavigationType(profile, entry, reload_type); + params->navigation_type = + GetNavigationType(controller.profile(), entry, reload_type); params->request_time = base::Time::Now(); } @@ -739,10 +744,9 @@ bool TabContents::NavigateToPendingEntry( // Tell DevTools agent that it is attached prior to the navigation. DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); if (devtools_manager) { // NULL in unit tests. - devtools_manager->OnNavigatingToPendingEntry( - render_view_host(), - dest_render_view_host, - controller_.pending_entry()->url()); + devtools_manager->OnNavigatingToPendingEntry(render_view_host(), + dest_render_view_host, + entry.url()); } // Used for page load time metrics. @@ -750,7 +754,7 @@ bool TabContents::NavigateToPendingEntry( // Navigate in the desired RenderViewHost. ViewMsg_Navigate_Params navigate_params; - MakeNavigateParams(profile(), entry, reload_type, &navigate_params); + MakeNavigateParams(controller_, reload_type, &navigate_params); dest_render_view_host->Navigate(navigate_params); if (entry.page_id() == -1) { @@ -1807,13 +1811,6 @@ void TabContents::GoToEntryAtOffset(int offset) { controller_.GoToOffset(offset); } -void TabContents::GetHistoryListCount(int* back_list_count, - int* forward_list_count) { - int current_index = controller_.last_committed_entry_index(); - *back_list_count = current_index; - *forward_list_count = controller_.entry_count() - current_index - 1; -} - void TabContents::OnMissingPluginStatus(int status) { #if defined(OS_WIN) // TODO(PORT): pull in when plug-ins work diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index 15f1a09..b113dd5 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -802,8 +802,6 @@ class TabContents : public PageNavigator, int active_match_ordinal, bool final_update); virtual void GoToEntryAtOffset(int offset); - virtual void GetHistoryListCount(int* back_list_count, - int* forward_list_count); virtual void OnMissingPluginStatus(int status); virtual void OnCrashedPlugin(const FilePath& plugin_path); virtual void OnCrashedWorker(); diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index fe4e0fe..e88c835 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc @@ -131,6 +131,8 @@ const bool kRecordModeEnabled = false; const int kHistogramSynchronizerReservedSequenceNumber = 0; +const int kMaxSessionHistoryEntries = 50; + } // namespace chrome #undef FPL diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h index 0fe7d13..abe0283 100644 --- a/chrome/common/chrome_constants.h +++ b/chrome/common/chrome_constants.h @@ -79,6 +79,9 @@ extern const bool kRecordModeEnabled; extern const int kHistogramSynchronizerReservedSequenceNumber; +// The maximum number of session history entries per tab. +extern const int kMaxSessionHistoryEntries; + } // namespace chrome #endif // CHROME_COMMON_CHROME_CONSTANTS_H_ diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 07639d4..0046696 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -85,6 +85,16 @@ struct ViewMsg_Navigate_Params { // ViewHostMsg_FrameNavigate message. int32 page_id; + // If page_id is -1, then pending_history_list_offset will also be -1. + // Otherwise, it contains the offset into the history list corresponding to + // the current navigation. + int pending_history_list_offset; + + // Informs the RenderView of where its current page contents reside in + // session history and the total size of the session history list. + int current_history_list_offset; + int current_history_list_length; + // The URL to load. GURL url; @@ -810,6 +820,9 @@ struct ParamTraits<ViewMsg_Navigate_Params> { typedef ViewMsg_Navigate_Params param_type; static void Write(Message* m, const param_type& p) { WriteParam(m, p.page_id); + WriteParam(m, p.pending_history_list_offset); + WriteParam(m, p.current_history_list_offset); + WriteParam(m, p.current_history_list_length); WriteParam(m, p.url); WriteParam(m, p.referrer); WriteParam(m, p.transition); @@ -820,6 +833,9 @@ struct ParamTraits<ViewMsg_Navigate_Params> { static bool Read(const Message* m, void** iter, param_type* p) { return ReadParam(m, iter, &p->page_id) && + ReadParam(m, iter, &p->pending_history_list_offset) && + ReadParam(m, iter, &p->current_history_list_offset) && + ReadParam(m, iter, &p->current_history_list_length) && ReadParam(m, iter, &p->url) && ReadParam(m, iter, &p->referrer) && ReadParam(m, iter, &p->transition) && diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index d07665a..b6ee2a4 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -508,10 +508,6 @@ IPC_BEGIN_MESSAGES(View) // Used to instruct the RenderView to go into "view source" mode. IPC_MESSAGE_ROUTED0(ViewMsg_EnableViewSourceMode) - IPC_MESSAGE_ROUTED2(ViewMsg_UpdateBackForwardListCount, - int /* back_list_count */, - int /* forward_list_count */) - // Retreive information from the MSAA DOM subtree, for accessibility purposes. IPC_SYNC_MESSAGE_ROUTED1_1(ViewMsg_GetAccessibilityInfo, webkit_glue::WebAccessibility::InParams diff --git a/chrome/renderer/navigation_state.h b/chrome/renderer/navigation_state.h index d17b542..36a8441 100644 --- a/chrome/renderer/navigation_state.h +++ b/chrome/renderer/navigation_state.h @@ -33,15 +33,18 @@ class NavigationState : public WebKit::WebDataSource::ExtraData { static NavigationState* CreateBrowserInitiated( int32 pending_page_id, + int pending_history_list_offset, PageTransition::Type transition_type, base::Time request_time) { return new NavigationState(transition_type, request_time, false, - pending_page_id); + pending_page_id, + pending_history_list_offset); } static NavigationState* CreateContentInitiated() { // We assume navigations initiated by content are link clicks. - return new NavigationState(PageTransition::LINK, base::Time(), true, -1); + return new NavigationState(PageTransition::LINK, base::Time(), true, -1, + -1); } static NavigationState* FromDataSource(WebKit::WebDataSource* ds) { @@ -58,6 +61,12 @@ class NavigationState : public WebKit::WebDataSource::ExtraData { // Contains the page_id for this navigation or -1 if there is none yet. int32 pending_page_id() const { return pending_page_id_; } + // If pending_page_id() is not -1, then this contains the corresponding + // offset of the page in the back/forward history list. + int pending_history_list_offset() const { + return pending_history_list_offset_; + } + // Contains the transition type that the browser specified when it // initiated the load. PageTransition::Type transition_type() const { return transition_type_; } @@ -219,7 +228,8 @@ class NavigationState : public WebKit::WebDataSource::ExtraData { NavigationState(PageTransition::Type transition_type, const base::Time& request_time, bool is_content_initiated, - int32 pending_page_id) + int32 pending_page_id, + int pending_history_list_offset) : transition_type_(transition_type), load_type_(UNDEFINED_LOAD), request_time_(request_time), @@ -227,6 +237,7 @@ class NavigationState : public WebKit::WebDataSource::ExtraData { request_committed_(false), is_content_initiated_(is_content_initiated), pending_page_id_(pending_page_id), + pending_history_list_offset_(pending_history_list_offset), postpone_loading_data_(false), cache_policy_override_set_(false), cache_policy_override_(WebKit::WebURLRequest::UseProtocolCachePolicy), @@ -248,6 +259,7 @@ class NavigationState : public WebKit::WebDataSource::ExtraData { bool request_committed_; bool is_content_initiated_; int32 pending_page_id_; + int pending_history_list_offset_; GURL searchable_form_url_; std::string searchable_form_encoding_; scoped_ptr<webkit_glue::PasswordForm> password_form_data_; diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 818cbd0..d057a7c 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -306,8 +306,8 @@ RenderView::RenderView(RenderThreadBase* render_thread, devtools_agent_(NULL), devtools_client_(NULL), file_chooser_completion_(NULL), - history_back_list_count_(0), - history_forward_list_count_(0), + history_list_offset_(-1), + history_list_length_(0), has_unload_listener_(false), decrement_shared_popup_at_destruction_(false), autofill_query_id_(0), @@ -559,8 +559,6 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin) IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse) IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode) - IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount, - OnUpdateBackForwardListCount) IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage, OnGetAllSavableResourceLinksForCurrentPage) IPC_MESSAGE_HANDLER( @@ -850,6 +848,9 @@ void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) { if (!webview()) return; + history_list_offset_ = params.current_history_list_offset; + history_list_length_ = params.current_history_list_length; + if (devtools_agent_.get()) devtools_agent_->OnNavigate(); @@ -878,7 +879,10 @@ void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) { // initiated any load resulting from JS execution. if (!params.url.SchemeIs(chrome::kJavaScriptScheme)) { NavigationState* state = NavigationState::CreateBrowserInitiated( - params.page_id, params.transition, params.request_time); + params.page_id, + params.pending_history_list_offset, + params.transition, + params.request_time); if (params.navigation_type == ViewMsg_Navigate_Params::RESTORE) { // We're doing a load of a page that was restored from the last session. // By default this prefers the cache over loading (LOAD_PREFERRING_CACHE) @@ -958,7 +962,10 @@ void RenderView::OnLoadAlternateHTMLText(const std::string& html, return; pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated( - new_navigation ? -1 : page_id_, PageTransition::LINK, Time::Now())); + new_navigation ? -1 : page_id_, + history_list_offset_, + PageTransition::LINK, + Time::Now())); pending_navigation_state_->set_security_info(security_info); webview()->mainFrame()->loadHTMLString( @@ -1944,36 +1951,15 @@ void RenderView::focusPrevious() { } void RenderView::navigateBackForwardSoon(int offset) { - history_back_list_count_ += offset; - history_forward_list_count_ -= offset; - Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset)); } int RenderView::historyBackListCount() { - return history_back_list_count_; + return history_list_offset_ < 0 ? 0 : history_list_offset_; } int RenderView::historyForwardListCount() { - return history_forward_list_count_; -} - -void RenderView::didAddHistoryItem() { - // We don't want to update the history length for the start page - // navigation. - WebFrame* main_frame = webview()->mainFrame(); - DCHECK(main_frame != NULL); - - WebDataSource* ds = main_frame->dataSource(); - DCHECK(ds != NULL); - - NavigationState* navigation_state = NavigationState::FromDataSource(ds); - DCHECK(navigation_state); - if (navigation_state->transition_type() == PageTransition::START_PAGE) - return; - - history_back_list_count_++; - history_forward_list_count_ = 0; + return history_list_length_ - historyBackListCount() - 1; } void RenderView::didUpdateInspectorSettings() { @@ -2512,6 +2498,7 @@ void RenderView::didFailProvisionalLoad(WebFrame* frame, if (!navigation_state->is_content_initiated()) { pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated( navigation_state->pending_page_id(), + navigation_state->pending_history_list_offset(), navigation_state->transition_type(), navigation_state->request_time())); } @@ -2567,6 +2554,13 @@ void RenderView::didCommitProvisionalLoad(WebFrame* frame, // We bump our Page ID to correspond with the new session history entry. page_id_ = next_page_id_++; + // Advance our offset in session history, applying the length limit. There + // is now no forward history. + history_list_offset_++; + if (history_list_offset_ >= chrome::kMaxSessionHistoryEntries) + history_list_offset_ = chrome::kMaxSessionHistoryEntries - 1; + history_list_length_ = history_list_offset_ + 1; + MessageLoop::current()->PostDelayedTask(FROM_HERE, method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, page_id_, true), @@ -2588,6 +2582,8 @@ void RenderView::didCommitProvisionalLoad(WebFrame* frame, // This is a successful session history navigation! UpdateSessionHistory(frame); page_id_ = navigation_state->pending_page_id(); + + history_list_offset_ = navigation_state->pending_history_list_offset(); } } @@ -3724,12 +3720,6 @@ void RenderView::OnUpdateBrowserWindowId(int window_id) { browser_window_id_ = window_id; } -void RenderView::OnUpdateBackForwardListCount(int back_list_count, - int forward_list_count) { - history_back_list_count_ = back_list_count; - history_forward_list_count_ = forward_list_count; -} - void RenderView::OnGetAccessibilityInfo( const webkit_glue::WebAccessibility::InParams& in_params, webkit_glue::WebAccessibility::OutParams* out_params) { diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 8f7ec80..b70783c 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -263,7 +263,6 @@ class RenderView : public RenderWidget, virtual void navigateBackForwardSoon(int offset); virtual int historyBackListCount(); virtual int historyForwardListCount(); - virtual void didAddHistoryItem(); virtual void focusAccessibilityObject( const WebKit::WebAccessibilityObject& acc_obj); virtual void didChangeAccessibilityObjectState( @@ -709,8 +708,6 @@ class RenderView : public RenderWidget, void OnExecuteCode(const ViewMsg_ExecuteCode_Params& params); void ExecuteCodeImpl(WebKit::WebFrame* frame, const ViewMsg_ExecuteCode_Params& params); - void OnUpdateBackForwardListCount(int back_list_count, - int forward_list_count); void OnGetAccessibilityInfo( const webkit_glue::WebAccessibility::InParams& in_params, webkit_glue::WebAccessibility::OutParams* out_params); @@ -1010,8 +1007,8 @@ class RenderView : public RenderWidget, // choosing operation is underway. WebKit::WebFileChooserCompletion* file_chooser_completion_; - int history_back_list_count_; - int history_forward_list_count_; + int history_list_offset_; + int history_list_length_; // True if the page has any frame-level unload or beforeunload listeners. bool has_unload_listener_; diff --git a/chrome/test/data/session_history/record_length.html b/chrome/test/data/session_history/record_length.html new file mode 100644 index 0000000..0fb4f70 --- /dev/null +++ b/chrome/test/data/session_history/record_length.html @@ -0,0 +1,3 @@ +<script> +history_length = history.length; +</script> |