1// Copyright 2018 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import "ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.h" 6 7#include <memory> 8 9#include "base/check.h" 10#include "base/scoped_observer.h" 11#include "base/strings/sys_string_conversions.h" 12#include "components/strings/grit/components_strings.h" 13#include "components/translate/core/browser/translate_infobar_delegate.h" 14#include "ios/chrome/browser/translate/chrome_ios_translate_client.h" 15#import "ios/chrome/browser/translate/language_selection_context.h" 16#import "ios/chrome/browser/translate/language_selection_handler.h" 17#import "ios/chrome/browser/translate/translate_option_selection_handler.h" 18#import "ios/chrome/browser/ui/list_model/list_model.h" 19#import "ios/chrome/browser/ui/popup_menu/public/popup_menu_consumer.h" 20#import "ios/chrome/browser/ui/translate/cells/select_language_popup_menu_item.h" 21#import "ios/chrome/browser/ui/translate/cells/translate_popup_menu_item.h" 22#import "ios/chrome/browser/ui/translate/translate_notification_handler.h" 23#import "ios/chrome/browser/web_state_list/web_state_list.h" 24#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" 25#include "ui/base/l10n/l10n_util.h" 26 27#if !defined(__has_feature) || !__has_feature(objc_arc) 28#error "This file requires ARC support." 29#endif 30 31@interface LegacyTranslateInfobarMediator () <WebStateListObserving> { 32 // WebStateList observers. 33 std::unique_ptr<WebStateListObserverBridge> _webStateListObserverBridge; 34 std::unique_ptr<ScopedObserver<WebStateList, WebStateListObserver>> 35 _scopedWebStateListObserver; 36} 37 38// Presents and dismisses the language selection UI as well as the translate 39// option selection UI. 40@property(nonatomic, weak) 41 id<LanguageSelectionHandler, TranslateOptionSelectionHandler> 42 selectionHandler; 43 44// Presents and dismisses translate related notification UI. 45@property(nonatomic, weak) id<TranslateNotificationHandler> notificationHandler; 46 47@end 48 49@implementation LegacyTranslateInfobarMediator 50 51- (instancetype) 52 initWithSelectionHandler: 53 (id<LanguageSelectionHandler, TranslateOptionSelectionHandler>) 54 selectionHandler 55 notificationHandler: 56 (id<TranslateNotificationHandler>)notificationHandler { 57 DCHECK(selectionHandler); 58 DCHECK(notificationHandler); 59 if ((self = [super init])) { 60 _selectionHandler = selectionHandler; 61 _notificationHandler = notificationHandler; 62 } 63 return self; 64} 65 66#pragma mark - Public methods 67 68- (void)disconnect { 69 self.webStateList = nil; 70} 71 72#pragma mark - Properties 73 74- (void)setWebStateList:(WebStateList*)webStateList { 75 if (_webStateList == webStateList) 76 return; 77 78 if (_webStateList) { 79 [self removeWebStateListObserver]; 80 81 // Uninstall delegates for each WebState in WebStateList. 82 for (int i = 0; i < self.webStateList->count(); i++) { 83 [self uninstallDelegatesForWebState:self.webStateList->GetWebStateAt(i)]; 84 } 85 } 86 87 _webStateList = webStateList; 88 89 if (_webStateList) { 90 // Install delegates for each WebState in WebStateList. 91 for (int i = 0; i < _webStateList->count(); i++) { 92 [self installDelegatesForWebState:_webStateList->GetWebStateAt(i)]; 93 } 94 95 [self addWebStateListObserver]; 96 } 97} 98 99- (void)setConsumer:(id<PopupMenuConsumer>)consumer { 100 _consumer = consumer; 101 [_consumer setPopupMenuItems:self.items]; 102} 103 104#pragma mark - Private 105 106// Returns the menu items for either the language selection popup menu or the 107// translate option selection popup menu. 108- (NSArray<NSArray<TableViewItem<PopupMenuItem>*>*>*)items { 109 if (self.type == TranslatePopupMenuTypeLanguageSelection) { 110 return [self languageSelectionItems]; 111 } 112 return [self translateOptionSelectionItems]; 113} 114 115// Returns the menu items for the language selection popup menu. 116- (NSArray<NSArray<TableViewItem<PopupMenuItem>*>*>*)languageSelectionItems { 117 NSMutableArray* items = [NSMutableArray array]; 118 for (size_t index = 0; index < self.infobarDelegate->num_languages(); 119 index++) { 120 if (index == self.unavailableLanguageIndex) 121 continue; 122 123 SelectLanguagePopupMenuItem* item = 124 [[SelectLanguagePopupMenuItem alloc] initWithType:kItemTypeEnumZero]; 125 item.actionIdentifier = PopupMenuActionSelectLanguage; 126 item.title = 127 base::SysUTF16ToNSString(self.infobarDelegate->language_name_at(index)); 128 item.languageCode = 129 base::SysUTF8ToNSString(self.infobarDelegate->language_code_at(index)); 130 [items addObject:item]; 131 } 132 133 return @[ items ]; 134} 135 136// Returns the menu items for the translate option selection popup menu. 137- (NSArray<NSArray<TableViewItem<PopupMenuItem>*>*>*) 138 translateOptionSelectionItems { 139 base::string16 originalLanguageName = 140 self.infobarDelegate->original_language_name(); 141 142 TranslatePopupMenuItem* selectTargetLanguageItem = 143 [[TranslatePopupMenuItem alloc] initWithType:kItemTypeEnumZero]; 144 selectTargetLanguageItem.actionIdentifier = 145 PopupMenuActionChangeTargetLanguage; 146 selectTargetLanguageItem.title = base::SysUTF16ToNSString( 147 l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS_MORE_LANGUAGE)); 148 149 TranslatePopupMenuItem* alwaysTranslateLanguageItem = 150 [[TranslatePopupMenuItem alloc] initWithType:kItemTypeEnumZero]; 151 alwaysTranslateLanguageItem.actionIdentifier = 152 PopupMenuActionAlwaysTranslateSourceLanguage; 153 alwaysTranslateLanguageItem.title = 154 base::SysUTF16ToNSString(l10n_util::GetStringFUTF16( 155 IDS_TRANSLATE_INFOBAR_OPTIONS_ALWAYS, originalLanguageName)); 156 alwaysTranslateLanguageItem.selected = 157 self.infobarDelegate->ShouldAlwaysTranslate(); 158 159 TranslatePopupMenuItem* neverTranslateLanguageItem = 160 [[TranslatePopupMenuItem alloc] initWithType:kItemTypeEnumZero]; 161 neverTranslateLanguageItem.actionIdentifier = 162 PopupMenuActionNeverTranslateSourceLanguage; 163 neverTranslateLanguageItem.title = 164 base::SysUTF16ToNSString(l10n_util::GetStringFUTF16( 165 IDS_TRANSLATE_INFOBAR_OPTIONS_NEVER_TRANSLATE_LANG, 166 originalLanguageName)); 167 168 TranslatePopupMenuItem* neverTranslateSiteItem = 169 [[TranslatePopupMenuItem alloc] initWithType:kItemTypeEnumZero]; 170 neverTranslateSiteItem.actionIdentifier = PopupMenuActionNeverTranslateSite; 171 neverTranslateSiteItem.title = 172 base::SysUTF16ToNSString(l10n_util::GetStringUTF16( 173 IDS_TRANSLATE_INFOBAR_OPTIONS_NEVER_TRANSLATE_SITE)); 174 175 TranslatePopupMenuItem* selectSourceLanguageItem = 176 [[TranslatePopupMenuItem alloc] initWithType:kItemTypeEnumZero]; 177 selectSourceLanguageItem.actionIdentifier = 178 PopupMenuActionChangeSourceLanguage; 179 selectSourceLanguageItem.title = 180 base::SysUTF16ToNSString(l10n_util::GetStringFUTF16( 181 IDS_TRANSLATE_INFOBAR_OPTIONS_NOT_SOURCE_LANGUAGE, 182 originalLanguageName)); 183 184 return @[ 185 @[ selectTargetLanguageItem ], 186 @[ 187 alwaysTranslateLanguageItem, neverTranslateLanguageItem, 188 neverTranslateSiteItem, selectSourceLanguageItem 189 ] 190 ]; 191} 192 193// Adds observer for WebStateList. 194- (void)addWebStateListObserver { 195 _webStateListObserverBridge = 196 std::make_unique<WebStateListObserverBridge>(self); 197 _scopedWebStateListObserver = 198 std::make_unique<ScopedObserver<WebStateList, WebStateListObserver>>( 199 _webStateListObserverBridge.get()); 200 _scopedWebStateListObserver->Add(self.webStateList); 201} 202 203// Removes observer for WebStateList. 204- (void)removeWebStateListObserver { 205 _scopedWebStateListObserver.reset(); 206 _webStateListObserverBridge.reset(); 207} 208 209// Installs delegates for |webState|. 210- (void)installDelegatesForWebState:(web::WebState*)webState { 211 if (ChromeIOSTranslateClient::FromWebState(webState)) { 212 ChromeIOSTranslateClient::FromWebState(webState) 213 ->set_language_selection_handler(self.selectionHandler); 214 ChromeIOSTranslateClient::FromWebState(webState) 215 ->set_translate_option_selection_handler(self.selectionHandler); 216 ChromeIOSTranslateClient::FromWebState(webState) 217 ->set_translate_notification_handler(self.notificationHandler); 218 } 219} 220 221// Uninstalls delegates for |webState|. 222- (void)uninstallDelegatesForWebState:(web::WebState*)webState { 223 if (ChromeIOSTranslateClient::FromWebState(webState)) { 224 ChromeIOSTranslateClient::FromWebState(webState) 225 ->set_language_selection_handler(nil); 226 ChromeIOSTranslateClient::FromWebState(webState) 227 ->set_translate_option_selection_handler(nil); 228 ChromeIOSTranslateClient::FromWebState(webState) 229 ->set_translate_notification_handler(nil); 230 } 231} 232 233#pragma mark - WebStateListObserving 234 235- (void)webStateList:(WebStateList*)webStateList 236 didInsertWebState:(web::WebState*)webState 237 atIndex:(int)index 238 activating:(BOOL)activating { 239 [self installDelegatesForWebState:webState]; 240} 241 242- (void)webStateList:(WebStateList*)webStateList 243 didReplaceWebState:(web::WebState*)oldWebState 244 withWebState:(web::WebState*)newWebState 245 atIndex:(int)index { 246 [self uninstallDelegatesForWebState:oldWebState]; 247 [self installDelegatesForWebState:newWebState]; 248} 249 250- (void)webStateList:(WebStateList*)webStateList 251 didDetachWebState:(web::WebState*)webState 252 atIndex:(int)index { 253 [self uninstallDelegatesForWebState:webState]; 254} 255 256@end 257