blob: 9f9fde11f1538c96718ba1e38eea7e9553d02f60 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_OMNIBOX_MODEL_PLACEHOLDER_SERVICE_PLACEHOLDER_SERVICE_H_
#define IOS_CHROME_BROWSER_OMNIBOX_MODEL_PLACEHOLDER_SERVICE_PLACEHOLDER_SERVICE_H_
#import <UIKit/UIKit.h>
#import "base/functional/callback.h"
#import "base/memory/raw_ptr.h"
#import "base/observer_list.h"
#import "base/task/cancelable_task_tracker.h"
#import "base/time/time.h"
#import "components/keyed_service/core/keyed_service.h"
#import "components/search_engines/template_url_id.h"
#import "components/search_engines/template_url_service_observer.h"
class FaviconLoader;
class TemplateURL;
class TemplateURLService;
#include "base/observer_list_types.h"
// TemplateURLServiceObserver is notified whenever the set of TemplateURLs
// are modified.
class PlaceholderServiceObserver : public base::CheckedObserver {
public:
// Notification that the placeholder text might have changed.
// Relevant for both normal and search-only text.
virtual void OnPlaceholderTextChanged() = 0;
// Notification that the search engine icon might have changed. This is called
// when an icon is fetched even if it's not the right size icon.
virtual void OnPlaceholderImageChanged() {}
// Notification that the placeholder service is shutting down. Observers that
// might outlive the service can use this to clear out any raw pointers to the
// service.
virtual void OnPlaceholderServiceShuttingDown() {}
protected:
~PlaceholderServiceObserver() override = default;
};
// A class that vends the placeholder data for omnibox and fakebox.
class PlaceholderService : public KeyedService,
public TemplateURLServiceObserver {
public:
explicit PlaceholderService(FaviconLoader* favicon_loader,
TemplateURLService* template_url_service);
PlaceholderService() = delete;
PlaceholderService(const PlaceholderService&) = delete;
PlaceholderService& operator=(const PlaceholderService&) = delete;
~PlaceholderService() override;
// Return a weak pointer to the current object.
base::WeakPtr<PlaceholderService> AsWeakPtr();
// Observers used to listen for changes to the model.
// TemplateURLService does NOT delete the observers when deleted.
void AddObserver(PlaceholderServiceObserver* observer);
void RemoveObserver(PlaceholderServiceObserver* observer);
using PlaceholderImageCallback = base::RepeatingCallback<void(UIImage*)>;
// Requests the icon for the current default search engine at the given
// `icon_point_size`. If the icon is available synchronously, the callback
// will be called immediately with the cached icon. Otherwise, the callback
// will be called with a placeholder icon first, and then updated with the
// real icon once it's available. The callback will not be updated if the
// default search engine changes during the fetch.
void FetchDefaultSearchEngineIcon(CGFloat icon_point_size,
PlaceholderImageCallback callback);
// Returns the icon for the current default search engine at the given
// `icon_point_size`. If the icon is unavailable, it will be fetched and
// `OnPlaceholderImageChanged` will be called once it becomes available.
UIImage* GetDefaultSearchEngineIcon(CGFloat icon_point_size);
NSString* GetCurrentPlaceholderText();
NSString* GetCurrentSearchOnlyPlaceholderText();
// TemplateURLServiceObserver
void OnTemplateURLServiceChanged() override;
private:
// Retrieves a bundled icon (e.g., Google icon) for the given `template_url`
// and `icon_point_size`, if available. Returns nil otherwise.
UIImage* GetBundledIconForTemplateURL(const TemplateURL* template_url,
CGFloat icon_point_size);
// Called when an icon has been successfully fetched or retrieved for a
// `template_url_id` at a specific `icon_point_size`. Caches the icon and
// notifies relevant callbacks.
void OnIconReceivedForTemplateURL(TemplateURLID template_url_id,
CGFloat icon_point_size,
UIImage* icon);
// Initiates a fetch for the icon of the given `template_url` at the specified
// `icon_point_size`.
void PerformIconFetch(const TemplateURL* template_url,
CGFloat icon_point_size);
raw_ptr<FaviconLoader> favicon_loader_;
raw_ptr<TemplateURLService> template_url_service_;
// Current default search engine.
raw_ptr<const TemplateURL> current_dse_;
base::ObserverList<PlaceholderServiceObserver> model_observers_;
// Cache for fetched/bundled icons. Keyed by icon size.
NSCache<NSNumber*, UIImage*>* icon_cache_;
// Map of icon sizes to a list of callbacks awaiting an icon of that size.
// This is cleared when default search engine changes.
std::map<CGFloat, std::vector<PlaceholderImageCallback>> icon_callbacks_;
// Map of icon sizes to a timestamp after which a fetch is allowed.
std::map<CGFloat, base::TimeTicks> fetch_cooldowns_;
base::WeakPtrFactory<PlaceholderService> weak_ptr_factory_{this};
};
#endif // IOS_CHROME_BROWSER_OMNIBOX_MODEL_PLACEHOLDER_SERVICE_PLACEHOLDER_SERVICE_H_