// 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/chrome/browser/ui/search_engine_choice/search_engine_choice_mediator.h"
#import <memory>
#import "base/memory/raw_ptr.h"
#import "base/strings/sys_string_conversions.h"
#import "base/strings/utf_string_conversions.h"
#import "components/search_engines/choice_made_location.h"
#import "components/search_engines/prepopulated_engines.h"
#import "components/search_engines/search_engine_choice/search_engine_choice_service.h"
#import "components/search_engines/search_engine_choice/search_engine_choice_utils.h"
#import "components/search_engines/template_url.h"
#import "components/search_engines/template_url_service.h"
#import "ios/chrome/browser/shared/ui/list_model/list_model.h"
#import "ios/chrome/browser/ui/search_engine_choice/search_engine_choice_consumer.h"
#import "ios/chrome/browser/ui/search_engine_choice/search_engine_choice_ui_util.h"
#import "ios/chrome/browser/ui/search_engine_choice/snippet_search_engine_element.h"
namespace {
// Creates a SnippetSearchEngineElement for `template_url`. The template url can
// only be for a prepopulated search engine. This function doesn't support
// custom search engine.
SnippetSearchEngineElement* CreateSnippetSearchEngineElementFromTemplateURL(
const TemplateURL& template_url) {
SnippetSearchEngineElement* element = nil;
// Only works for prepopulated search engines.
CHECK_GT(template_url.prepopulate_id(), 0, base::NotFatalUntil::M127)
<< base::UTF16ToUTF8(template_url.short_name());
element = [[SnippetSearchEngineElement alloc] init];
// Add the name and snippet to the element.
element.name = base::SysUTF16ToNSString(template_url.short_name());
std::u16string string =
search_engines::GetMarketingSnippetString(template_url.data());
element.snippetDescription = base::SysUTF16ToNSString(string);
// Add the favicon to the element.
element.faviconImage = SearchEngineFaviconFromTemplateURL(template_url);
// With the choice screen, all the search engines should have embedded icons,
// since the search engine list cannot modified by the user.
CHECK(element.faviconImage, base::NotFatalUntil::M127)
<< base::SysNSStringToUTF8(element.name);
element.keyword = base::SysUTF16ToNSString(template_url.keyword());
return element;
}
} // namespace
@implementation SearchEngineChoiceMediator {
raw_ptr<search_engines::SearchEngineChoiceService>
_searchEngineChoiceService; // weak
raw_ptr<TemplateURLService> _templateURLService; // weak
// The template URLs to be shown on the choice screen and some associated
// data.
std::unique_ptr<search_engines::ChoiceScreenData> _choiceScreenData;
NSString* _selectedSearchEngineKeyword;
}
- (instancetype)
initWithTemplateURLService:(TemplateURLService*)templateURLService
searchEngineChoiceService:
(search_engines::SearchEngineChoiceService*)searchEngineChoiceService {
self = [super init];
if (self) {
_templateURLService = templateURLService;
_searchEngineChoiceService = searchEngineChoiceService;
_templateURLService->Load();
}
return self;
}
- (void)saveDefaultSearchEngine {
CHECK(_selectedSearchEngineKeyword);
std::u16string keyword =
base::SysNSStringToUTF16(_selectedSearchEngineKeyword);
TemplateURL* selectedTemplateURL = nil;
search_engines::ChoiceScreenDisplayState display_state =
_choiceScreenData->display_state();
for (size_t i = 0; i < _choiceScreenData->search_engines().size(); ++i) {
auto& templateURL = _choiceScreenData->search_engines()[i];
if (templateURL->keyword() == keyword) {
selectedTemplateURL = templateURL.get();
display_state.selected_engine_index = i;
break;
}
}
CHECK(selectedTemplateURL);
_templateURLService->SetUserSelectedDefaultSearchProvider(
selectedTemplateURL, search_engines::ChoiceMadeLocation::kChoiceScreen);
_searchEngineChoiceService->MaybeRecordChoiceScreenDisplayState(
display_state);
}
- (void)disconnect {
_searchEngineChoiceService = nullptr;
_templateURLService = nullptr;
}
#pragma mark - Properties
- (void)setConsumer:(id<SearchEngineChoiceConsumer>)consumer {
_consumer = consumer;
if (_consumer) {
[self loadSearchEngines];
}
}
#pragma mark - SearchEngineChoiceMutator
- (void)selectSearchEnginewWithKeyword:(NSString*)keyword {
_selectedSearchEngineKeyword = keyword;
}
#pragma mark - Private
// Loads all the data for the choice screen in `_choiceScreenData` and updates
// the consumer.
- (void)loadSearchEngines {
_choiceScreenData = _templateURLService->GetChoiceScreenData();
NSMutableArray<SnippetSearchEngineElement*>* searchEngineList =
[[NSMutableArray<SnippetSearchEngineElement*> alloc]
initWithCapacity:_choiceScreenData->search_engines().size()];
// Convert TemplateURLs to SnippetSearchEngineElements.
for (auto& templateURL : _choiceScreenData->search_engines()) {
SnippetSearchEngineElement* element =
CreateSnippetSearchEngineElementFromTemplateURL(*templateURL);
[searchEngineList addObject:element];
}
self.consumer.searchEngines = [searchEngineList copy];
}
@end