From c6d51440206327ee177c949a4e7e1e9a8120a555 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Courteau Date: Fri, 1 Sep 2017 14:06:34 +0000 Subject: [PATCH] Adds IsRendererInitiated to NavigationContext. This mimics content/public/browser/navigation_handle.h. IsRenderInitiated will return true if the current navigation was initiated by the renderer, and false if it was user initiated. Bug: Change-Id: I094442e501a17a4741edca228810533e4b08253f Reviewed-on: https://chromium-review.googlesource.com/646660 Commit-Queue: Marc-Antoine Courteau Reviewed-by: Rohit Rao (ping after 24h) Reviewed-by: Kurt Horimoto Cr-Commit-Position: refs/heads/master@{#499188} --- ios/chrome/browser/tabs/tab_unittest.mm | 4 ++-- .../test/fakes/crw_test_web_state_observer.mm | 4 ++-- .../test/fakes/fake_navigation_context.h | 1 + .../test/fakes/fake_navigation_context.mm | 4 ++++ .../test/fakes/test_web_state_observer.mm | 4 ++-- ios/web/public/web_state/navigation_context.h | 8 +++++++ ios/web/web_state/navigation_context_impl.h | 9 ++++++-- ios/web/web_state/navigation_context_impl.mm | 21 ++++++++++++++----- .../navigation_context_impl_unittest.mm | 20 ++++++++++++++++-- ios/web/web_state/ui/crw_web_controller.mm | 18 ++++++++++------ .../ui/crw_wk_navigation_states_unittest.mm | 10 ++++++--- ios/web/web_state/web_state_impl_unittest.mm | 2 +- .../web_state_observer_bridge_unittest.mm | 4 ++-- ios/web/webui/crw_web_ui_manager_unittest.mm | 2 +- 14 files changed, 83 insertions(+), 28 deletions(-) diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm index 76880a9cc006b..8bad1507d74eb 100644 --- a/ios/chrome/browser/tabs/tab_unittest.mm +++ b/ios/chrome/browser/tabs/tab_unittest.mm @@ -217,7 +217,7 @@ void BrowseTo(const GURL& userUrl, const GURL& redirectUrl, NSString* title) { std::unique_ptr context1 = web::NavigationContextImpl::CreateNavigationContext( web_state_impl_.get(), userUrl, - ui::PageTransition::PAGE_TRANSITION_TYPED); + ui::PageTransition::PAGE_TRANSITION_TYPED, false); web_state_impl_->OnNavigationStarted(context1.get()); [tab_ webWillAddPendingURL:redirectUrl transition:ui::PAGE_TRANSITION_CLIENT_REDIRECT]; @@ -231,7 +231,7 @@ void BrowseTo(const GURL& userUrl, const GURL& redirectUrl, NSString* title) { std::unique_ptr context2 = web::NavigationContextImpl::CreateNavigationContext( web_state_impl_.get(), redirectUrl, - ui::PageTransition::PAGE_TRANSITION_TYPED); + ui::PageTransition::PAGE_TRANSITION_TYPED, false); web_state_impl_->OnNavigationStarted(context2.get()); [tab_ navigationManagerImpl]->CommitPendingItem(); web_state_impl_->UpdateHttpResponseHeaders(redirectUrl); diff --git a/ios/web/public/test/fakes/crw_test_web_state_observer.mm b/ios/web/public/test/fakes/crw_test_web_state_observer.mm index 59193fbee5db6..6547da99b71e6 100644 --- a/ios/web/public/test/fakes/crw_test_web_state_observer.mm +++ b/ios/web/public/test/fakes/crw_test_web_state_observer.mm @@ -152,7 +152,7 @@ - (void)webState:(web::WebState*)webState std::unique_ptr context = web::NavigationContextImpl::CreateNavigationContext( navigation->GetWebState(), navigation->GetUrl(), - navigation->GetPageTransition()); + navigation->GetPageTransition(), navigation->IsRendererInitiated()); context->SetIsSameDocument(navigation->IsSameDocument()); context->SetError(navigation->GetError()); _didStartNavigationInfo->context = std::move(context); @@ -175,7 +175,7 @@ - (void)webState:(web::WebState*)webState std::unique_ptr context = web::NavigationContextImpl::CreateNavigationContext( navigation->GetWebState(), navigation->GetUrl(), - navigation->GetPageTransition()); + navigation->GetPageTransition(), navigation->IsRendererInitiated()); context->SetIsSameDocument(navigation->IsSameDocument()); context->SetError(navigation->GetError()); _didFinishNavigationInfo->context = std::move(context); diff --git a/ios/web/public/test/fakes/fake_navigation_context.h b/ios/web/public/test/fakes/fake_navigation_context.h index 19fbef86e0cea..7db3a1a562b31 100644 --- a/ios/web/public/test/fakes/fake_navigation_context.h +++ b/ios/web/public/test/fakes/fake_navigation_context.h @@ -29,6 +29,7 @@ class FakeNavigationContext : public NavigationContext { bool IsPost() const override; NSError* GetError() const override; net::HttpResponseHeaders* GetResponseHeaders() const override; + bool IsRendererInitiated() const override; // Setters for navigation context data members. void SetResponseHeaders( diff --git a/ios/web/public/test/fakes/fake_navigation_context.mm b/ios/web/public/test/fakes/fake_navigation_context.mm index 37a6b7bdc9611..217e401e8ebf6 100644 --- a/ios/web/public/test/fakes/fake_navigation_context.mm +++ b/ios/web/public/test/fakes/fake_navigation_context.mm @@ -44,6 +44,10 @@ return response_headers_.get(); } +bool FakeNavigationContext::IsRendererInitiated() const { + return false; +} + void FakeNavigationContext::SetResponseHeaders( const scoped_refptr& response_headers) { response_headers_ = response_headers; diff --git a/ios/web/public/test/fakes/test_web_state_observer.mm b/ios/web/public/test/fakes/test_web_state_observer.mm index c90af93e7ba06..080c0f32ced87 100644 --- a/ios/web/public/test/fakes/test_web_state_observer.mm +++ b/ios/web/public/test/fakes/test_web_state_observer.mm @@ -80,7 +80,7 @@ std::unique_ptr context = web::NavigationContextImpl::CreateNavigationContext( navigation->GetWebState(), navigation->GetUrl(), - navigation->GetPageTransition()); + navigation->GetPageTransition(), navigation->IsRendererInitiated()); context->SetIsSameDocument(navigation->IsSameDocument()); context->SetError(navigation->GetError()); did_start_navigation_info_->context = std::move(context); @@ -94,7 +94,7 @@ std::unique_ptr context = web::NavigationContextImpl::CreateNavigationContext( navigation->GetWebState(), navigation->GetUrl(), - navigation->GetPageTransition()); + navigation->GetPageTransition(), navigation->IsRendererInitiated()); context->SetIsSameDocument(navigation->IsSameDocument()); context->SetError(navigation->GetError()); did_finish_navigation_info_->context = std::move(context); diff --git a/ios/web/public/web_state/navigation_context.h b/ios/web/public/web_state/navigation_context.h index cbfcc19c42b6d..c8ca372628deb 100644 --- a/ios/web/public/web_state/navigation_context.h +++ b/ios/web/public/web_state/navigation_context.h @@ -59,6 +59,14 @@ class NavigationContext { // returned should not be modified, as modifications will not be reflected. virtual net::HttpResponseHeaders* GetResponseHeaders() const = 0; + // Whether the navigation was initiated by the renderer process. Examples of + // renderer-initiated navigations include: + // * link click + // * changing window.location.href + // * redirect via the tag + // * using window.history.pushState + virtual bool IsRendererInitiated() const = 0; + virtual ~NavigationContext() {} }; diff --git a/ios/web/web_state/navigation_context_impl.h b/ios/web/web_state/navigation_context_impl.h index 4e5687b4238ab..1432e7cc269e1 100644 --- a/ios/web/web_state/navigation_context_impl.h +++ b/ios/web/web_state/navigation_context_impl.h @@ -23,7 +23,8 @@ class NavigationContextImpl : public NavigationContext { static std::unique_ptr CreateNavigationContext( WebState* web_state, const GURL& url, - ui::PageTransition page_transition); + ui::PageTransition page_transition, + bool is_renderer_initiated); #ifndef NDEBUG // Returns human readable description of this object. @@ -38,6 +39,7 @@ class NavigationContextImpl : public NavigationContext { bool IsPost() const override; NSError* GetError() const override; net::HttpResponseHeaders* GetResponseHeaders() const override; + bool IsRendererInitiated() const override; ~NavigationContextImpl() override; // Setters for navigation context data members. @@ -46,6 +48,7 @@ class NavigationContextImpl : public NavigationContext { void SetError(NSError* error); void SetResponseHeaders( const scoped_refptr& response_headers); + void SetIsRendererInitiated(bool is_renderer_initiated); // Optional unique id of the navigation item associated with this navigaiton. int GetNavigationItemUniqueID() const; @@ -54,7 +57,8 @@ class NavigationContextImpl : public NavigationContext { private: NavigationContextImpl(WebState* web_state, const GURL& url, - ui::PageTransition page_transition); + ui::PageTransition page_transition, + bool is_renderer_initiated); WebState* web_state_ = nullptr; GURL url_; @@ -63,6 +67,7 @@ class NavigationContextImpl : public NavigationContext { bool is_post_ = false; base::scoped_nsobject error_; scoped_refptr response_headers_; + bool is_renderer_initiated_ = false; int navigation_item_unique_id_ = -1; DISALLOW_COPY_AND_ASSIGN(NavigationContextImpl); diff --git a/ios/web/web_state/navigation_context_impl.mm b/ios/web/web_state/navigation_context_impl.mm index d5055e096a881..5cd26f7123ed2 100644 --- a/ios/web/web_state/navigation_context_impl.mm +++ b/ios/web/web_state/navigation_context_impl.mm @@ -20,9 +20,10 @@ NavigationContextImpl::CreateNavigationContext( WebState* web_state, const GURL& url, - ui::PageTransition page_transition) { - std::unique_ptr result( - new NavigationContextImpl(web_state, url, page_transition)); + ui::PageTransition page_transition, + bool is_renderer_initiated) { + std::unique_ptr result(new NavigationContextImpl( + web_state, url, page_transition, is_renderer_initiated)); return result; } @@ -64,6 +65,10 @@ return response_headers_.get(); } +bool NavigationContextImpl::IsRendererInitiated() const { + return is_renderer_initiated_; +} + void NavigationContextImpl::SetIsSameDocument(bool is_same_document) { is_same_document_ = is_same_document; } @@ -81,6 +86,10 @@ response_headers_ = response_headers; } +void NavigationContextImpl::SetIsRendererInitiated(bool is_renderer_initiated) { + is_renderer_initiated_ = is_renderer_initiated; +} + int NavigationContextImpl::GetNavigationItemUniqueID() const { return navigation_item_unique_id_; } @@ -91,13 +100,15 @@ NavigationContextImpl::NavigationContextImpl(WebState* web_state, const GURL& url, - ui::PageTransition page_transition) + ui::PageTransition page_transition, + bool is_renderer_initiated) : web_state_(web_state), url_(url), page_transition_(page_transition), is_same_document_(false), error_(nil), - response_headers_(nullptr) {} + response_headers_(nullptr), + is_renderer_initiated_(is_renderer_initiated) {} NavigationContextImpl::~NavigationContextImpl() = default; diff --git a/ios/web/web_state/navigation_context_impl_unittest.mm b/ios/web/web_state/navigation_context_impl_unittest.mm index 533524d469f91..4688e4cf9019e 100644 --- a/ios/web/web_state/navigation_context_impl_unittest.mm +++ b/ios/web/web_state/navigation_context_impl_unittest.mm @@ -38,7 +38,8 @@ TEST_F(NavigationContextImplTest, NavigationContext) { std::unique_ptr context = NavigationContextImpl::CreateNavigationContext( - &web_state_, url_, ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK); + &web_state_, url_, ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK, + true); ASSERT_TRUE(context); EXPECT_EQ(&web_state_, context->GetWebState()); @@ -49,18 +50,21 @@ EXPECT_FALSE(context->IsSameDocument()); EXPECT_FALSE(context->GetError()); EXPECT_FALSE(context->GetResponseHeaders()); + EXPECT_TRUE(context->IsRendererInitiated()); } // Tests NavigationContextImpl Setters. TEST_F(NavigationContextImplTest, Setters) { std::unique_ptr context = NavigationContextImpl::CreateNavigationContext( - &web_state_, url_, ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK); + &web_state_, url_, ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK, + false); ASSERT_TRUE(context); ASSERT_FALSE(context->IsSameDocument()); ASSERT_FALSE(context->IsPost()); ASSERT_FALSE(context->GetError()); + ASSERT_FALSE(context->IsRendererInitiated()); ASSERT_NE(response_headers_.get(), context->GetResponseHeaders()); // SetSameDocument @@ -68,6 +72,7 @@ EXPECT_TRUE(context->IsSameDocument()); ASSERT_FALSE(context->IsPost()); EXPECT_FALSE(context->GetError()); + EXPECT_FALSE(context->IsRendererInitiated()); EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); // SetPost @@ -75,6 +80,7 @@ EXPECT_TRUE(context->IsSameDocument()); ASSERT_TRUE(context->IsPost()); EXPECT_FALSE(context->GetError()); + EXPECT_FALSE(context->IsRendererInitiated()); EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); // SetErrorPage @@ -83,6 +89,7 @@ EXPECT_TRUE(context->IsSameDocument()); ASSERT_TRUE(context->IsPost()); EXPECT_EQ(error, context->GetError()); + EXPECT_FALSE(context->IsRendererInitiated()); EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); // SetResponseHeaders @@ -90,6 +97,15 @@ EXPECT_TRUE(context->IsSameDocument()); ASSERT_TRUE(context->IsPost()); EXPECT_EQ(error, context->GetError()); + EXPECT_FALSE(context->IsRendererInitiated()); + EXPECT_EQ(response_headers_.get(), context->GetResponseHeaders()); + + // SetIsRendererInitiated + context->SetIsRendererInitiated(true); + EXPECT_TRUE(context->IsSameDocument()); + ASSERT_TRUE(context->IsPost()); + EXPECT_EQ(error, context->GetError()); + EXPECT_TRUE(context->IsRendererInitiated()); EXPECT_EQ(response_headers_.get(), context->GetResponseHeaders()); } diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 17c70f92331d6..a8103acd67626 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm @@ -1279,8 +1279,8 @@ - (void)pushStateWithPageURL:(const GURL&)pageURL stateObject:(NSString*)stateObject transition:(ui::PageTransition)transition { std::unique_ptr context = - web::NavigationContextImpl::CreateNavigationContext(_webStateImpl, - pageURL, transition); + web::NavigationContextImpl::CreateNavigationContext( + _webStateImpl, pageURL, transition, true); context->SetIsSameDocument(true); _webStateImpl->OnNavigationStarted(context.get()); [[self sessionController] pushNewItemWithURL:pageURL @@ -1295,7 +1295,7 @@ - (void)replaceStateWithPageURL:(const GURL&)pageURL std::unique_ptr context = web::NavigationContextImpl::CreateNavigationContext( _webStateImpl, pageURL, - ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT); + ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT, true); context->SetIsSameDocument(true); _webStateImpl->OnNavigationStarted(context.get()); [[self sessionController] updateCurrentItemWithURL:pageURL @@ -1438,10 +1438,16 @@ - (double)loadingProgress { [_delegate webWillAddPendingURL:requestURL transition:transition]; // Add or update pending url. - if (self.navigationManagerImpl->GetPendingItem()) { + bool isRendererInitiated = true; + web::NavigationItem* pendingItem = + self.navigationManagerImpl->GetPendingItem(); + if (pendingItem) { // Update the existing pending entry. // Typically on PAGE_TRANSITION_CLIENT_REDIRECT. self.navigationManagerImpl->UpdatePendingItemUrl(requestURL); + isRendererInitiated = static_cast(pendingItem) + ->NavigationInitiationType() == + web::NavigationInitiationType::RENDERER_INITIATED; } else { // A new session history entry needs to be created. self.navigationManagerImpl->AddPendingItem( @@ -1451,7 +1457,7 @@ - (double)loadingProgress { } std::unique_ptr context = web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, requestURL, transition); + _webStateImpl, requestURL, transition, isRendererInitiated); web::NavigationItem* item = self.navigationManagerImpl->GetPendingItem(); // TODO(crbug.com/676129): AddPendingItem does not always create a pending @@ -4018,7 +4024,7 @@ - (void)loadHTML:(NSString*)HTML forURL:(const GURL&)URL { // should not be treated as a navigation, but WKNavigationDelegate callbacks // still expect a valid context. context = web::NavigationContextImpl::CreateNavigationContext( - _webStateImpl, URL, loadHTMLTransition); + _webStateImpl, URL, loadHTMLTransition, false); } else { context = [self registerLoadRequestForURL:URL referrer:web::Referrer() diff --git a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm index 9266aa9bb613c..db6b3eee345c4 100644 --- a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm +++ b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm @@ -85,7 +85,7 @@ std::unique_ptr context = NavigationContextImpl::CreateNavigationContext( nullptr /*web_state*/, GURL(kTestUrl1), - ui::PageTransition::PAGE_TRANSITION_SERVER_REDIRECT); + ui::PageTransition::PAGE_TRANSITION_SERVER_REDIRECT, true); [states_ setContext:std::move(context) forNavigation:navigation3_]; EXPECT_EQ(navigation3_, [states_ lastAddedNavigation]); EXPECT_EQ(WKNavigationState::NONE, [states_ lastAddedNavigationState]); @@ -101,7 +101,7 @@ std::unique_ptr context1 = NavigationContextImpl::CreateNavigationContext( nullptr /*web_state*/, GURL(kTestUrl1), - ui::PageTransition::PAGE_TRANSITION_RELOAD); + ui::PageTransition::PAGE_TRANSITION_RELOAD, false); context1->SetIsSameDocument(true); [states_ setContext:std::move(context1) forNavigation:navigation1_]; EXPECT_FALSE([states_ contextForNavigation:navigation2_]); @@ -111,12 +111,14 @@ [states_ contextForNavigation:navigation1_]->GetUrl()); EXPECT_TRUE([states_ contextForNavigation:navigation1_]->IsSameDocument()); EXPECT_FALSE([states_ contextForNavigation:navigation1_]->GetError()); + EXPECT_FALSE( + [states_ contextForNavigation:navigation1_]->IsRendererInitiated()); // Replace existing context. std::unique_ptr context2 = NavigationContextImpl::CreateNavigationContext( nullptr /*web_state*/, GURL(kTestUrl2), - ui::PageTransition::PAGE_TRANSITION_GENERATED); + ui::PageTransition::PAGE_TRANSITION_GENERATED, true); NSError* error = [[NSError alloc] init]; context2->SetError(error); [states_ setContext:std::move(context2) forNavigation:navigation1_]; @@ -127,6 +129,8 @@ [states_ contextForNavigation:navigation1_]->GetUrl()); EXPECT_FALSE([states_ contextForNavigation:navigation1_]->IsSameDocument()); EXPECT_EQ(error, [states_ contextForNavigation:navigation1_]->GetError()); + EXPECT_TRUE( + [states_ contextForNavigation:navigation1_]->IsRendererInitiated()); } // Tests null WKNavigation object. diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm index 53c35a1ff574b..3f9a60b39730f 100644 --- a/ios/web/web_state/web_state_impl_unittest.mm +++ b/ios/web/web_state/web_state_impl_unittest.mm @@ -364,7 +364,7 @@ bool HandleScriptCommand(bool* is_called, std::unique_ptr context = NavigationContextImpl::CreateNavigationContext( web_state_.get(), url, - ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK); + ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK, true); web_state_->OnNavigationFinished(context.get()); ASSERT_TRUE(observer->did_finish_navigation_info()); EXPECT_EQ(web_state_.get(), diff --git a/ios/web/web_state/web_state_observer_bridge_unittest.mm b/ios/web/web_state/web_state_observer_bridge_unittest.mm index 03427475506bd..e2451b081c20e 100644 --- a/ios/web/web_state/web_state_observer_bridge_unittest.mm +++ b/ios/web/web_state/web_state_observer_bridge_unittest.mm @@ -60,7 +60,7 @@ std::unique_ptr context = web::NavigationContextImpl::CreateNavigationContext( &test_web_state_, url, - ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK); + ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK, false); bridge_->DidStartNavigation(context.get()); ASSERT_TRUE([observer_ didStartNavigationInfo]); @@ -87,7 +87,7 @@ std::unique_ptr context = web::NavigationContextImpl::CreateNavigationContext( &test_web_state_, url, - ui::PageTransition::PAGE_TRANSITION_FROM_ADDRESS_BAR); + ui::PageTransition::PAGE_TRANSITION_FROM_ADDRESS_BAR, false); bridge_->DidFinishNavigation(context.get()); ASSERT_TRUE([observer_ didFinishNavigationInfo]); diff --git a/ios/web/webui/crw_web_ui_manager_unittest.mm b/ios/web/webui/crw_web_ui_manager_unittest.mm index 3fd058827fffc..99bfa6566c5f6 100644 --- a/ios/web/webui/crw_web_ui_manager_unittest.mm +++ b/ios/web/webui/crw_web_ui_manager_unittest.mm @@ -144,7 +144,7 @@ void SetUp() override { std::unique_ptr context = NavigationContextImpl::CreateNavigationContext( web_state_impl_.get(), url, - ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK); + ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK, true); web_state_impl_->OnNavigationStarted(context.get()); }