| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/web/content/navigation/content_navigation_manager.h" |
| |
| #import <Foundation/Foundation.h> |
| |
| #import <sstream> |
| |
| #import "base/apple/foundation_util.h" |
| #import "base/notimplemented.h" |
| #import "base/strings/sys_string_conversions.h" |
| #import "content/public/browser/navigation_controller.h" |
| #import "content/public/browser/navigation_entry.h" |
| #import "content/public/browser/navigation_handle.h" |
| #import "ios/web/content/navigation/content_navigation_item.h" |
| #import "ios/web/content/web_state/content_web_state.h" |
| #import "ios/web/navigation/navigation_context_impl.h" |
| #import "ios/web/public/navigation/navigation_item.h" |
| #import "ios/web/public/navigation/reload_type.h" |
| #import "ios/web/public/web_state_observer.h" |
| #import "net/http/http_request_headers.h" |
| #import "net/http/http_util.h" |
| |
| namespace web { |
| |
| namespace { |
| |
| network::mojom::ReferrerPolicy ToContentReferrerPolicy(ReferrerPolicy policy) { |
| switch (policy) { |
| case ReferrerPolicyAlways: |
| return network::mojom::ReferrerPolicy::kAlways; |
| case ReferrerPolicyDefault: |
| return network::mojom::ReferrerPolicy::kDefault; |
| case ReferrerPolicyNoReferrerWhenDowngrade: |
| return network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade; |
| case ReferrerPolicyNever: |
| return network::mojom::ReferrerPolicy::kNever; |
| case ReferrerPolicyOrigin: |
| return network::mojom::ReferrerPolicy::kOrigin; |
| case ReferrerPolicyOriginWhenCrossOrigin: |
| return network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin; |
| case ReferrerPolicySameOrigin: |
| return network::mojom::ReferrerPolicy::kSameOrigin; |
| case ReferrerPolicyStrictOrigin: |
| return network::mojom::ReferrerPolicy::kStrictOrigin; |
| case ReferrerPolicyStrictOriginWhenCrossOrigin: |
| return network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin; |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| } // namespace |
| |
| ContentNavigationManager::ContentNavigationManager( |
| ContentWebState* web_state, |
| BrowserState* browser_state, |
| content::NavigationController& controller) |
| : web_state_(web_state), |
| browser_state_(browser_state), |
| controller_(controller) {} |
| |
| ContentNavigationManager::~ContentNavigationManager() = default; |
| |
| BrowserState* ContentNavigationManager::GetBrowserState() const { |
| return browser_state_; |
| } |
| |
| WebState* ContentNavigationManager::GetWebState() const { |
| return web_state_; |
| } |
| |
| NavigationItem* ContentNavigationManager::GetVisibleItem() const { |
| return ContentNavigationItem::GetOrCreate(controller_->GetVisibleEntry()); |
| } |
| |
| NavigationItem* ContentNavigationManager::GetLastCommittedItem() const { |
| return ContentNavigationItem::GetOrCreate( |
| controller_->GetLastCommittedEntry()); |
| } |
| |
| NavigationItem* ContentNavigationManager::GetPendingItem() const { |
| return ContentNavigationItem::GetOrCreate(controller_->GetPendingEntry()); |
| } |
| |
| void ContentNavigationManager::DiscardNonCommittedItems() { |
| controller_->DiscardNonCommittedEntries(); |
| } |
| |
| void ContentNavigationManager::LoadURLWithParams( |
| const NavigationManager::WebLoadParams& web_params) { |
| content::NavigationController::LoadURLParams params(web_params.url); |
| params.referrer = |
| content::Referrer(web_params.referrer.url, |
| ToContentReferrerPolicy(web_params.referrer.policy)); |
| params.is_renderer_initiated = web_params.is_renderer_initiated; |
| params.transition_type = web_params.transition_type; |
| |
| std::ostringstream ss; |
| for (id key in web_params.extra_headers) { |
| auto key_utf8 = base::SysNSStringToUTF8(key); |
| auto value_utf8 = |
| base::SysNSStringToUTF8([web_params.extra_headers objectForKey:key]); |
| if (!net::HttpUtil::IsValidHeaderName(key_utf8) || |
| !net::HttpUtil::IsValidHeaderValue(value_utf8)) { |
| LOG(ERROR) << "Invalid header"; |
| return; |
| } |
| ss << key_utf8 << ": " << value_utf8 << "\n"; |
| } |
| params.extra_headers = ss.str(); |
| |
| if (web_params.post_data) { |
| params.post_data = new network::ResourceRequestBody(); |
| params.post_data->AppendCopyOfBytes( |
| base::apple::NSDataToSpan(web_params.post_data)); |
| } |
| |
| // We are not setting the virtual URL for data URL here. |
| controller_->LoadURLWithParams(params); |
| } |
| |
| void ContentNavigationManager::LoadIfNecessary() { |
| controller_->LoadIfNecessary(); |
| } |
| |
| void ContentNavigationManager::AddTransientURLRewriter( |
| BrowserURLRewriter::URLRewriter rewriter) { |
| // TODO(crbug.com/40257932) |
| NOTIMPLEMENTED(); |
| } |
| |
| int ContentNavigationManager::GetItemCount() const { |
| return controller_->GetEntryCount(); |
| } |
| |
| NavigationItem* ContentNavigationManager::GetItemAtIndex(size_t index) const { |
| return ContentNavigationItem::GetOrCreate( |
| controller_->GetEntryAtIndex(index)); |
| } |
| |
| int ContentNavigationManager::GetIndexOfItem(const NavigationItem* item) const { |
| for (int i = 0; i < GetItemCount(); ++i) { |
| if (GetItemAtIndex(i) == item) { |
| return i; |
| } |
| } |
| return 0; |
| } |
| |
| int ContentNavigationManager::GetPendingItemIndex() const { |
| return controller_->GetPendingEntryIndex(); |
| } |
| |
| int ContentNavigationManager::GetLastCommittedItemIndex() const { |
| return controller_->GetLastCommittedEntryIndex(); |
| } |
| |
| bool ContentNavigationManager::CanGoBack() const { |
| return controller_->CanGoBack(); |
| } |
| |
| bool ContentNavigationManager::CanGoForward() const { |
| return controller_->CanGoForward(); |
| } |
| |
| bool ContentNavigationManager::CanGoToOffset(int offset) const { |
| return controller_->CanGoToOffset(offset); |
| } |
| |
| void ContentNavigationManager::GoBack() { |
| controller_->GoBack(); |
| } |
| |
| void ContentNavigationManager::GoForward() { |
| controller_->GoForward(); |
| } |
| |
| void ContentNavigationManager::GoToIndex(int index) { |
| controller_->GoToIndex(index); |
| } |
| |
| void ContentNavigationManager::Reload(ReloadType reload_type, |
| bool check_for_reposts) { |
| if (reload_type == ReloadType::ORIGINAL_REQUEST_URL) { |
| controller_->LoadOriginalRequestURL(); |
| } else { |
| controller_->Reload(content::ReloadType::NORMAL, check_for_reposts); |
| } |
| } |
| |
| void ContentNavigationManager::ReloadWithUserAgentType( |
| UserAgentType user_agent_type) { |
| // TODO(crbug.com/40257932) |
| NOTIMPLEMENTED(); |
| } |
| |
| std::vector<NavigationItem*> ContentNavigationManager::GetBackwardItems() |
| const { |
| std::vector<NavigationItem*> items; |
| int last_committed_index = GetLastCommittedItemIndex(); |
| for (int i = last_committed_index - 1; i >= 0; --i) { |
| items.push_back(GetItemAtIndex(i)); |
| } |
| return items; |
| } |
| |
| std::vector<NavigationItem*> ContentNavigationManager::GetForwardItems() const { |
| std::vector<NavigationItem*> items; |
| int last_committed_index = GetLastCommittedItemIndex(); |
| int item_count = GetItemCount(); |
| for (int i = last_committed_index + 1; i < item_count; ++i) { |
| items.push_back(GetItemAtIndex(i)); |
| } |
| return items; |
| } |
| |
| void ContentNavigationManager::Restore( |
| int last_committed_item_index, |
| std::vector<std::unique_ptr<NavigationItem>> items) { |
| // TODO(crbug.com/40257932) |
| NOTIMPLEMENTED(); |
| } |
| |
| } // namespace web |