chromium/ios/web/navigation/navigation_util.mm

// 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/public/navigation/navigation_util.h"

#import "base/strings/utf_string_conversions.h"
#import "ios/web/navigation/proto_util.h"
#import "ios/web/public/session/proto/metadata.pb.h"
#import "ios/web/public/session/proto/navigation.pb.h"
#import "ios/web/public/session/proto/proto_util.h"
#import "ios/web/public/session/proto/storage.pb.h"

namespace web {
namespace {

// Serialized the information for the request described by `params`, `title`
// and `creation_time` to protobuf message in `storage`.
void SerializeToNavigationItemStorage(
    const NavigationManager::WebLoadParams& params,
    const std::u16string& title,
    base::Time creation_time,
    UserAgentType user_agent,
    proto::NavigationItemStorage& storage) {
  if (params.url.is_valid()) {
    storage.set_url(params.url.spec());
  }
  if (params.url != params.virtual_url && params.virtual_url.is_valid()) {
    storage.set_virtual_url(params.virtual_url.spec());
  }
  if (!title.empty()) {
    storage.set_title(base::UTF16ToUTF8(title));
  }
  SerializeTimeToProto(creation_time, *storage.mutable_timestamp());
  storage.set_user_agent(UserAgentTypeToProto(user_agent));

  if (params.referrer.url.is_valid()) {
    SerializeReferrerToProto(params.referrer, *storage.mutable_referrer());
  }
  if (params.extra_headers.count) {
    SerializeHttpRequestHeadersToProto(params.extra_headers,
                                       *storage.mutable_http_request_headers());
  }
}

}  // namespace

proto::WebStateStorage CreateWebStateStorage(
    const NavigationManager::WebLoadParams& params,
    const std::u16string& title,
    bool created_with_opener,
    UserAgentType user_agent,
    base::Time creation_time) {
  DCHECK(!params.post_data);
  proto::WebStateStorage storage;

  // Create the NavigationItemStorage.
  SerializeToNavigationItemStorage(params, title, creation_time, user_agent,
                                   *storage.mutable_navigation()->add_items());

  storage.set_has_opener(created_with_opener);
  storage.set_user_agent(UserAgentTypeToProto(user_agent));

  proto::WebStateMetadataStorage& metadata = *storage.mutable_metadata();
  SerializeTimeToProto(creation_time, *metadata.mutable_creation_time());
  SerializeTimeToProto(creation_time, *metadata.mutable_last_active_time());
  metadata.set_navigation_item_count(storage.navigation().items_size());

  const int last_committed_item_index =
      storage.navigation().last_committed_item_index();

  DCHECK_GE(last_committed_item_index, 0);
  DCHECK_LT(last_committed_item_index, metadata.navigation_item_count());
  const proto::NavigationItemStorage& item =
      storage.navigation().items(last_committed_item_index);

  proto::PageMetadataStorage& page_metadata = *metadata.mutable_active_page();
  page_metadata.set_page_title(item.title());

  // Use the virtual URL if set, otherwise defaults to the real URL.
  const std::string& virtual_url = item.virtual_url();
  page_metadata.set_page_url(virtual_url.empty() ? item.url() : virtual_url);

  return storage;
}

}  // namespace web