| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/commerce/ios/browser/commerce_tab_helper.h" |
| |
| #include "base/memory/ptr_util.h" |
| #include "ios/web/public/navigation/navigation_context.h" |
| #include "ios/web/public/navigation/navigation_item.h" |
| #include "ios/web/public/navigation/navigation_manager.h" |
| #include "ios/web/public/web_state.h" |
| #include "net/http/http_response_headers.h" |
| |
| namespace commerce { |
| |
| namespace { |
| bool ShouldUpdateRecentlyViewedURL(web::WebState* web_state, |
| web::NavigationContext* navigation_context) { |
| if (navigation_context->GetError()) { |
| return false; |
| } |
| |
| if (navigation_context->GetResponseHeaders() && |
| navigation_context->GetResponseHeaders()->response_code() == 404) { |
| return false; |
| } |
| |
| if (!navigation_context->HasCommitted() || |
| !web_state->GetNavigationManager()->GetLastCommittedItem()) { |
| // Navigation was replaced or aborted. |
| return false; |
| } |
| |
| web::NavigationItem* last_committed_item = |
| web_state->GetNavigationManager()->GetLastCommittedItem(); |
| const GURL& url = last_committed_item->GetURL(); |
| if (url.SchemeIs(url::kDataScheme)) { |
| return false; |
| } |
| |
| return true; |
| } |
| } // namespace |
| |
| CommerceTabHelper::CommerceTabHelper(web::WebState* state, |
| bool is_off_the_record, |
| ShoppingService* shopping_service) |
| : is_off_the_record_(is_off_the_record), |
| web_wrapper_(std::make_unique<WebStateWrapper>(state)), |
| shopping_service_(shopping_service) { |
| scoped_observation_.Observe(state); |
| |
| if (shopping_service_) |
| shopping_service_->WebWrapperCreated(web_wrapper_.get()); |
| } |
| |
| CommerceTabHelper::~CommerceTabHelper() = default; |
| |
| void CommerceTabHelper::DidFinishNavigation( |
| web::WebState* web_state, |
| web::NavigationContext* navigation_context) { |
| if (!shopping_service_ || |
| previous_main_frame_url_ == navigation_context->GetUrl()) { |
| return; |
| } |
| |
| // Notify the service that we're no longer interested in a particular URL. |
| shopping_service_->DidNavigateAway(web_wrapper_.get(), |
| previous_main_frame_url_); |
| previous_main_frame_url_ = navigation_context->GetUrl(); |
| |
| // If navigating to a different document, expect PageLoaded to be |
| // triggered. |
| if (!navigation_context->IsSameDocument()) { |
| web_wrapper_->SetIsFirstLoadForNavigationFinished(false); |
| } |
| |
| shopping_service_->DidNavigatePrimaryMainFrame(web_wrapper_.get()); |
| |
| if (web_state->IsVisible() && |
| ShouldUpdateRecentlyViewedURL(web_state, navigation_context)) { |
| shopping_service_->OnWebWrapperViewed(web_wrapper_.get()); |
| } |
| } |
| |
| void CommerceTabHelper::DidStopLoading(web::WebState* web_state) { |
| if (!shopping_service_) { |
| return; |
| } |
| |
| web_wrapper_->SetIsFirstLoadForNavigationFinished(true); |
| shopping_service_->DidStopLoading(web_wrapper_.get()); |
| } |
| |
| void CommerceTabHelper::PageLoaded( |
| web::WebState* web_state, |
| web::PageLoadCompletionStatus load_completion_status) { |
| if (!shopping_service_) |
| return; |
| |
| web_wrapper_->SetIsFirstLoadForNavigationFinished(true); |
| |
| shopping_service_->DidFinishLoad(web_wrapper_.get()); |
| } |
| |
| void CommerceTabHelper::WasShown(web::WebState* web_state) { |
| if (!shopping_service_) { |
| return; |
| } |
| |
| shopping_service_->OnWebWrapperSwitched(web_wrapper_.get()); |
| } |
| |
| void CommerceTabHelper::WebStateDestroyed(web::WebState* web_state) { |
| if (shopping_service_) |
| shopping_service_->WebWrapperDestroyed(web_wrapper_.get()); |
| |
| web_wrapper_->ClearWebStatePointer(); |
| |
| // This needs to be reset prior to the destruction of the web state in order |
| // to prevent a CHECK failure for observer count. |
| scoped_observation_.Reset(); |
| } |
| |
| } // namespace commerce |