| // Copyright 2019 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/translate/model/translate_app_interface.h" |
| |
| #import "base/command_line.h" |
| #import "base/containers/contains.h" |
| #import "base/memory/singleton.h" |
| #import "base/strings/sys_string_conversions.h" |
| #import "base/strings/utf_string_conversions.h" |
| #import "components/translate/core/browser/translate_infobar_delegate.h" |
| #import "components/translate/core/browser/translate_manager.h" |
| #import "components/translate/core/browser/translate_prefs.h" |
| #import "components/translate/core/common/language_detection_details.h" |
| #import "components/translate/core/common/translate_switches.h" |
| #import "components/translate/core/common/translate_util.h" |
| #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" |
| #import "ios/chrome/browser/translate/model/chrome_ios_translate_client.h" |
| #import "ios/chrome/test/app/chrome_test_util.h" |
| #import "ios/chrome/test/app/tab_test_util.h" |
| #import "ios/chrome/test/fakes/fake_language_detection_tab_helper_observer.h" |
| #import "ios/web/public/js_messaging/web_frame.h" |
| #import "net/base/network_change_notifier.h" |
| |
| namespace { |
| |
| // Simulates a given network connection type for tests. |
| // TODO(crbug.com/41445136): Refactor this and similar |
| // net::NetworkChangeNotifier subclasses for testing into a separate file. |
| class FakeNetworkChangeNotifier : public net::NetworkChangeNotifier { |
| public: |
| FakeNetworkChangeNotifier( |
| net::NetworkChangeNotifier::ConnectionType connection_type_to_return) |
| : connection_type_to_return_(connection_type_to_return) {} |
| |
| FakeNetworkChangeNotifier(const FakeNetworkChangeNotifier&) = delete; |
| FakeNetworkChangeNotifier& operator=(const FakeNetworkChangeNotifier&) = |
| delete; |
| |
| private: |
| ConnectionType GetCurrentConnectionType() const override { |
| return connection_type_to_return_; |
| } |
| |
| // The currently simulated network connection type. If this is set to |
| // CONNECTION_NONE, then NetworkChangeNotifier::IsOffline will return true. |
| net::NetworkChangeNotifier::ConnectionType connection_type_to_return_ = |
| net::NetworkChangeNotifier::CONNECTION_UNKNOWN; |
| }; |
| |
| // Helper singleton object to hold states for fake objects to facility testing. |
| class TranslateAppInterfaceHelper { |
| public: |
| static TranslateAppInterfaceHelper* GetInstance() { |
| return base::Singleton<TranslateAppInterfaceHelper>::get(); |
| } |
| |
| FakeLanguageDetectionTabHelperObserver& tab_helper_observer() const { |
| return *tab_helper_observer_; |
| } |
| void set_tab_helper_observer( |
| std::unique_ptr<FakeLanguageDetectionTabHelperObserver> observer) { |
| tab_helper_observer_ = std::move(observer); |
| } |
| |
| void SetUpFakeWiFiConnection() { |
| // Disables the net::NetworkChangeNotifier singleton and replace it with a |
| // FakeNetworkChangeNotifier to simulate a WIFI network connection. |
| network_change_notifier_disabler_ = |
| std::make_unique<net::NetworkChangeNotifier::DisableForTest>(); |
| network_change_notifier_ = std::make_unique<FakeNetworkChangeNotifier>( |
| net::NetworkChangeNotifier::CONNECTION_WIFI); |
| } |
| void TearDownFakeWiFiConnection() { |
| // Note: Tears down in the opposite order of construction. |
| network_change_notifier_.reset(); |
| network_change_notifier_disabler_.reset(); |
| } |
| |
| private: |
| TranslateAppInterfaceHelper() {} |
| ~TranslateAppInterfaceHelper() = default; |
| friend struct base::DefaultSingletonTraits<TranslateAppInterfaceHelper>; |
| |
| // Observes the language detection tab helper and captures the translation |
| // details for inspection by tests. |
| std::unique_ptr<FakeLanguageDetectionTabHelperObserver> tab_helper_observer_; |
| // Helps fake the network condition for tests. |
| std::unique_ptr<net::NetworkChangeNotifier::DisableForTest> |
| network_change_notifier_disabler_; |
| std::unique_ptr<FakeNetworkChangeNotifier> network_change_notifier_; |
| }; |
| |
| } // namespace |
| |
| #pragma mark - TranslateAppInterface |
| |
| @implementation TranslateAppInterface |
| |
| #pragma mark public methods |
| |
| + (void)setUpWithScriptServer:(NSString*)translateScriptServerURL { |
| // Allows the offering of translate in builds without an API key. |
| translate::TranslateManager::SetIgnoreMissingKeyForTesting(true); |
| [self setUpLanguageDetectionTabHelperObserver]; |
| [self setDefaultTranslatePrefs]; |
| TranslateAppInterfaceHelper::GetInstance()->SetUpFakeWiFiConnection(); |
| |
| // Sets URL for the translate script to hit a HTTP server selected by |
| // the test app |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| command_line->AppendSwitchASCII( |
| translate::switches::kTranslateScriptURL, |
| base::SysNSStringToUTF8(translateScriptServerURL)); |
| } |
| |
| + (void)tearDown { |
| TranslateAppInterfaceHelper::GetInstance()->TearDownFakeWiFiConnection(); |
| [self setDefaultTranslatePrefs]; |
| [TranslateAppInterface tearDownLanguageDetectionTabHelperObserver]; |
| // Stops allowing the offering of translate in builds without an API key. |
| translate::TranslateManager::SetIgnoreMissingKeyForTesting(false); |
| } |
| |
| + (void)setUpLanguageDetectionTabHelperObserver { |
| TranslateAppInterfaceHelper::GetInstance()->set_tab_helper_observer( |
| std::make_unique<FakeLanguageDetectionTabHelperObserver>( |
| chrome_test_util::GetCurrentWebState())); |
| } |
| |
| + (void)tearDownLanguageDetectionTabHelperObserver { |
| TranslateAppInterfaceHelper::GetInstance()->set_tab_helper_observer(nullptr); |
| } |
| |
| + (void)resetLanguageDetectionTabHelperObserver { |
| TranslateAppInterfaceHelper::GetInstance() |
| ->tab_helper_observer() |
| .ResetLanguageDetectionDetails(); |
| } |
| |
| + (BOOL)isLanguageDetected { |
| return TranslateAppInterfaceHelper::GetInstance() |
| ->tab_helper_observer() |
| .GetLanguageDetectionDetails() != nullptr; |
| } |
| |
| + (NSString*)contentLanguage { |
| translate::LanguageDetectionDetails* details = |
| TranslateAppInterfaceHelper::GetInstance() |
| ->tab_helper_observer() |
| .GetLanguageDetectionDetails(); |
| return base::SysUTF8ToNSString(details->content_language); |
| } |
| |
| + (NSString*)htmlRootLanguage { |
| translate::LanguageDetectionDetails* details = |
| TranslateAppInterfaceHelper::GetInstance() |
| ->tab_helper_observer() |
| .GetLanguageDetectionDetails(); |
| return base::SysUTF8ToNSString(details->html_root_language); |
| } |
| |
| + (NSString*)adoptedLanguage { |
| translate::LanguageDetectionDetails* details = |
| TranslateAppInterfaceHelper::GetInstance() |
| ->tab_helper_observer() |
| .GetLanguageDetectionDetails(); |
| return base::SysUTF8ToNSString(details->adopted_language); |
| } |
| |
| + (BOOL)shouldAutoTranslateFromLanguage:(NSString*)source |
| toLanguage:(NSString*)target { |
| std::unique_ptr<translate::TranslatePrefs> prefs( |
| ChromeIOSTranslateClient::CreateTranslatePrefs( |
| chrome_test_util::GetOriginalBrowserState()->GetPrefs())); |
| return prefs->IsLanguagePairOnAlwaysTranslateList( |
| base::SysNSStringToUTF8(source), base::SysNSStringToUTF8(target)); |
| } |
| |
| + (BOOL)isBlockedLanguage:(NSString*)language { |
| std::unique_ptr<translate::TranslatePrefs> prefs( |
| ChromeIOSTranslateClient::CreateTranslatePrefs( |
| chrome_test_util::GetOriginalBrowserState()->GetPrefs())); |
| return prefs->IsBlockedLanguage(base::SysNSStringToUTF8(language)); |
| } |
| |
| + (BOOL)isBlockedSite:(NSString*)hostName { |
| std::unique_ptr<translate::TranslatePrefs> prefs( |
| ChromeIOSTranslateClient::CreateTranslatePrefs( |
| chrome_test_util::GetOriginalBrowserState()->GetPrefs())); |
| return prefs->IsSiteOnNeverPromptList(base::SysNSStringToUTF8(hostName)); |
| } |
| |
| + (int)infobarAutoAlwaysThreshold { |
| return translate::GetAutoAlwaysThreshold(); |
| } |
| |
| + (int)infobarAutoNeverThreshold { |
| return translate::GetAutoNeverThreshold(); |
| } |
| |
| + (int)infobarMaximumNumberOfAutoAlways { |
| return translate::GetMaximumNumberOfAutoAlways(); |
| } |
| |
| + (int)infobarMaximumNumberOfAutoNever { |
| return translate::GetMaximumNumberOfAutoNever(); |
| } |
| |
| #pragma mark private methods |
| |
| // Reset translate prefs to default. |
| + (void)setDefaultTranslatePrefs { |
| std::unique_ptr<translate::TranslatePrefs> prefs( |
| ChromeIOSTranslateClient::CreateTranslatePrefs( |
| chrome_test_util::GetOriginalBrowserState()->GetPrefs())); |
| prefs->ResetToDefaults(); |
| } |
| |
| @end |