Commit a4bf85a8 authored by Swapnil's avatar Swapnil Committed by Commit Bot

Split login test base browsertests

The browsertests of login test base and all the related tests are moved
from policy_browsertests to a separate file.

Bug: 1084166
Change-Id: I63c270c7866d64ece3e3397e8914e31fc2b2872a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2207217
Commit-Queue: Swapnil Gupta <swapnilgupta@google.com>
Reviewed-by: default avatarSergey Poromov <poromov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#770713}
parent ce982dfd
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <vector>
#include "base/strings/string16.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/test/session_manager_state_waiter.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/login_policy_test_base.h"
#include "chrome/browser/chromeos/policy/user_policy_test_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/constants/chromeos_pref_names.h"
#include "components/language/core/browser/pref_names.h"
#include "components/policy/core/common/policy_service.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/ime/chromeos/input_method_manager.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "url/gurl.h"
namespace policy {
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, PRE_AllowedLanguages) {
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, kEmptyServices);
Profile* const profile = GetProfileForActiveUser();
PrefService* prefs = profile->GetPrefs();
// Set locale and preferred languages to "en-US".
prefs->SetString(language::prefs::kApplicationLocale, "en-US");
prefs->SetString(language::prefs::kPreferredLanguages, "en-US");
// Set policy to only allow "fr" as locale.
std::unique_ptr<base::DictionaryValue> policy =
std::make_unique<base::DictionaryValue>();
base::ListValue allowed_languages;
allowed_languages.AppendString("fr");
policy->SetKey(key::kAllowedLanguages, std::move(allowed_languages));
user_policy_helper()->SetPolicyAndWait(*policy, base::DictionaryValue(),
profile);
}
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, AllowedLanguages) {
LogIn(kAccountId, kAccountPassword, kEmptyServices);
Profile* const profile = GetProfileForActiveUser();
const PrefService* prefs = profile->GetPrefs();
// Verifies that the default locale has been overridden by policy
// (see |GetMandatoryPoliciesValue|)
Browser* browser = CreateBrowser(profile);
EXPECT_EQ("fr", prefs->GetString(language::prefs::kApplicationLocale));
ui_test_utils::NavigateToURL(browser, GURL(chrome::kChromeUINewTabURL));
base::string16 french_title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
base::string16 title;
EXPECT_TRUE(ui_test_utils::GetCurrentTabTitle(browser, &title));
EXPECT_EQ(french_title, title);
// Make sure this is really French and differs from the English title.
base::ScopedAllowBlockingForTesting allow_blocking;
std::string loaded =
ui::ResourceBundle::GetSharedInstance().ReloadLocaleResources("en-US");
EXPECT_EQ("en-US", loaded);
base::string16 english_title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
EXPECT_NE(french_title, english_title);
// Verifiy that the enforced locale is added into the list of
// preferred languages.
EXPECT_EQ("fr", prefs->GetString(language::prefs::kPreferredLanguages));
}
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, AllowedInputMethods) {
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, kEmptyServices);
Profile* const profile = GetProfileForActiveUser();
chromeos::input_method::InputMethodManager* imm =
chromeos::input_method::InputMethodManager::Get();
ASSERT_TRUE(imm);
scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state =
imm->GetActiveIMEState();
ASSERT_TRUE(ime_state.get());
std::vector<std::string> input_methods;
input_methods.emplace_back("xkb:us::eng");
input_methods.emplace_back("xkb:fr::fra");
input_methods.emplace_back("xkb:de::ger");
EXPECT_TRUE(imm->MigrateInputMethods(&input_methods));
// No restrictions and current input method should be "xkb:us::eng" (default).
EXPECT_EQ(0U, ime_state->GetAllowedInputMethods().size());
EXPECT_EQ(input_methods[0], ime_state->GetCurrentInputMethod().id());
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[1]));
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
// Set policy to only allow "xkb:fr::fra", "xkb:de::ger" an an invalid value
// as input method.
std::unique_ptr<base::DictionaryValue> policy =
std::make_unique<base::DictionaryValue>();
base::ListValue allowed_input_methods;
allowed_input_methods.AppendString("xkb:fr::fra");
allowed_input_methods.AppendString("xkb:de::ger");
allowed_input_methods.AppendString("invalid_value_will_be_ignored");
policy->SetKey(key::kAllowedInputMethods, std::move(allowed_input_methods));
user_policy_helper()->SetPolicyAndWait(*policy, base::DictionaryValue(),
profile);
// Only "xkb:fr::fra", "xkb:de::ger" should be allowed, current input method
// should be "xkb:fr::fra", enabling "xkb:us::eng" should not be possible,
// enabling "xkb:de::ger" should be possible.
EXPECT_EQ(2U, ime_state->GetAllowedInputMethods().size());
EXPECT_EQ(2U, ime_state->GetActiveInputMethods()->size());
EXPECT_EQ(input_methods[1], ime_state->GetCurrentInputMethod().id());
EXPECT_FALSE(ime_state->EnableInputMethod(input_methods[0]));
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
// Set policy to only allow an invalid value as input method.
std::unique_ptr<base::DictionaryValue> policy_invalid =
std::make_unique<base::DictionaryValue>();
base::ListValue invalid_input_methods;
invalid_input_methods.AppendString("invalid_value_will_be_ignored");
policy_invalid->SetKey(key::kAllowedInputMethods,
std::move(invalid_input_methods));
user_policy_helper()->SetPolicyAndWait(*policy_invalid,
base::DictionaryValue(), profile);
// No restrictions and current input method should still be "xkb:fr::fra".
EXPECT_EQ(0U, ime_state->GetAllowedInputMethods().size());
EXPECT_EQ(input_methods[1], ime_state->GetCurrentInputMethod().id());
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[0]));
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
// Allow all input methods again.
user_policy_helper()->SetPolicyAndWait(base::DictionaryValue(),
base::DictionaryValue(), profile);
// No restrictions and current input method should still be "xkb:fr::fra".
EXPECT_EQ(0U, ime_state->GetAllowedInputMethods().size());
EXPECT_EQ(input_methods[1], ime_state->GetCurrentInputMethod().id());
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[0]));
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
}
class StartupBrowserWindowLaunchSuppressedTest : public LoginPolicyTestBase {
public:
StartupBrowserWindowLaunchSuppressedTest() = default;
void SetUpPolicy(bool enabled) {
std::unique_ptr<base::DictionaryValue> policy =
std::make_unique<base::DictionaryValue>();
policy->SetKey(key::kStartupBrowserWindowLaunchSuppressed,
base::Value(enabled));
user_policy_helper()->SetPolicy(*policy, base::DictionaryValue());
}
void CheckLaunchedBrowserCount(unsigned int count) {
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, kEmptyServices);
Profile* const profile = GetProfileForActiveUser();
ASSERT_EQ(count, chrome::GetBrowserCount(profile));
}
private:
DISALLOW_COPY_AND_ASSIGN(StartupBrowserWindowLaunchSuppressedTest);
};
// Test that the browser window is not launched when
// StartupBrowserWindowLaunchSuppressed is set to true.
IN_PROC_BROWSER_TEST_F(StartupBrowserWindowLaunchSuppressedTest,
TrueDoesNotAllowBrowserWindowLaunch) {
SetUpPolicy(true);
CheckLaunchedBrowserCount(0u);
}
// Test that the browser window is launched when
// StartupBrowserWindowLaunchSuppressed is set to false.
IN_PROC_BROWSER_TEST_F(StartupBrowserWindowLaunchSuppressedTest,
FalseAllowsBrowserWindowLaunch) {
SetUpPolicy(false);
CheckLaunchedBrowserCount(1u);
}
class PrimaryUserPoliciesProxiedTest : public LoginPolicyTestBase {
public:
PrimaryUserPoliciesProxiedTest() = default;
private:
DISALLOW_COPY_AND_ASSIGN(PrimaryUserPoliciesProxiedTest);
};
IN_PROC_BROWSER_TEST_F(PrimaryUserPoliciesProxiedTest,
AvailableInLocalStateEarly) {
PolicyService* const device_wide_policy_service =
g_browser_process->platform_part()
->browser_policy_connector_chromeos()
->GetPolicyService();
// Sanity check default state without a policy active.
EXPECT_FALSE(device_wide_policy_service
->GetPolicies(PolicyNamespace(
POLICY_DOMAIN_CHROME, std::string() /* component_id */))
.GetValue(key::kAudioOutputAllowed));
const PrefService::Preference* pref =
g_browser_process->local_state()->FindPreference(
chromeos::prefs::kAudioOutputAllowed);
EXPECT_FALSE(pref->IsManaged());
EXPECT_TRUE(pref->GetValue()->GetBool());
base::DictionaryValue policy;
policy.SetKey(key::kAudioOutputAllowed, base::Value(false));
user_policy_helper()->SetPolicy(policy, base::DictionaryValue());
SkipToLoginScreen();
content::WindowedNotificationObserver profile_created_observer(
chrome::NOTIFICATION_PROFILE_CREATED,
content::NotificationService::AllSources());
TriggerLogIn(kAccountId, kAccountPassword, kEmptyServices);
profile_created_observer.Wait();
const base::Value* policy_value =
device_wide_policy_service
->GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME,
std::string() /* component_id */))
.GetValue(key::kAudioOutputAllowed);
ASSERT_TRUE(policy_value);
EXPECT_FALSE(policy_value->GetBool());
EXPECT_TRUE(pref->IsManaged());
EXPECT_FALSE(pref->GetValue()->GetBool());
// Make sure that session startup finishes before letting chrome exit.
// Rationale: We've seen CHECK-failures when exiting chrome right after
// NOTIFICATION_PROFILE_CREATED, see e.g. https://crbug.com/1002066 .
chromeos::test::WaitForPrimaryUserSessionStart();
}
} // namespace policy
......@@ -67,8 +67,6 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/test/session_manager_state_waiter.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/devtools/devtools_window_testing.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/extensions/api/chrome_extensions_api_client.h"
......@@ -113,7 +111,6 @@
#include "components/content_settings/core/common/pref_names.h"
#include "components/download/public/common/download_item.h"
#include "components/google/core/common/google_util.h"
#include "components/language/core/browser/pref_names.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/network_time/network_time_tracker.h"
#include "components/omnibox/browser/autocomplete_controller.h"
......@@ -211,8 +208,6 @@
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/login/test/js_checker.h"
#include "chrome/browser/chromeos/note_taking_helper.h"
#include "chrome/browser/chromeos/policy/login_policy_test_base.h"
#include "chrome/browser/chromeos/policy/user_policy_test_helper.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/system/timezone_resolver_manager.h"
#include "chrome/browser/ui/ash/chrome_screenshot_grabber.h"
......@@ -224,7 +219,6 @@
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/user_manager.h"
#include "ui/base/ime/chromeos/input_method_manager.h"
#include "ui/snapshot/screenshot_grabber.h"
#endif
......@@ -508,230 +502,6 @@ IN_PROC_BROWSER_TEST_F(LocalePolicyTest, ApplicationLocaleValue) {
}
#endif
#if defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, PRE_AllowedLanguages) {
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, kEmptyServices);
Profile* const profile = GetProfileForActiveUser();
PrefService* prefs = profile->GetPrefs();
// Set locale and preferred languages to "en-US".
prefs->SetString(language::prefs::kApplicationLocale, "en-US");
prefs->SetString(language::prefs::kPreferredLanguages, "en-US");
// Set policy to only allow "fr" as locale.
std::unique_ptr<base::DictionaryValue> policy =
std::make_unique<base::DictionaryValue>();
base::ListValue allowed_languages;
allowed_languages.AppendString("fr");
policy->SetKey(key::kAllowedLanguages, std::move(allowed_languages));
user_policy_helper()->SetPolicyAndWait(*policy, base::DictionaryValue(),
profile);
}
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, AllowedLanguages) {
LogIn(kAccountId, kAccountPassword, kEmptyServices);
Profile* const profile = GetProfileForActiveUser();
const PrefService* prefs = profile->GetPrefs();
// Verifies that the default locale has been overridden by policy
// (see |GetMandatoryPoliciesValue|)
Browser* browser = CreateBrowser(profile);
EXPECT_EQ("fr", prefs->GetString(language::prefs::kApplicationLocale));
ui_test_utils::NavigateToURL(browser, GURL(chrome::kChromeUINewTabURL));
base::string16 french_title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
base::string16 title;
EXPECT_TRUE(ui_test_utils::GetCurrentTabTitle(browser, &title));
EXPECT_EQ(french_title, title);
// Make sure this is really French and differs from the English title.
base::ScopedAllowBlockingForTesting allow_blocking;
std::string loaded =
ui::ResourceBundle::GetSharedInstance().ReloadLocaleResources("en-US");
EXPECT_EQ("en-US", loaded);
base::string16 english_title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
EXPECT_NE(french_title, english_title);
// Verifiy that the enforced locale is added into the list of
// preferred languages.
EXPECT_EQ("fr", prefs->GetString(language::prefs::kPreferredLanguages));
}
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, AllowedInputMethods) {
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, kEmptyServices);
Profile* const profile = GetProfileForActiveUser();
chromeos::input_method::InputMethodManager* imm =
chromeos::input_method::InputMethodManager::Get();
ASSERT_TRUE(imm);
scoped_refptr<chromeos::input_method::InputMethodManager::State> ime_state =
imm->GetActiveIMEState();
ASSERT_TRUE(ime_state.get());
std::vector<std::string> input_methods;
input_methods.emplace_back("xkb:us::eng");
input_methods.emplace_back("xkb:fr::fra");
input_methods.emplace_back("xkb:de::ger");
EXPECT_TRUE(imm->MigrateInputMethods(&input_methods));
// No restrictions and current input method should be "xkb:us::eng" (default).
EXPECT_EQ(0U, ime_state->GetAllowedInputMethods().size());
EXPECT_EQ(input_methods[0], ime_state->GetCurrentInputMethod().id());
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[1]));
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
// Set policy to only allow "xkb:fr::fra", "xkb:de::ger" an an invalid value
// as input method.
std::unique_ptr<base::DictionaryValue> policy =
std::make_unique<base::DictionaryValue>();
base::ListValue allowed_input_methods;
allowed_input_methods.AppendString("xkb:fr::fra");
allowed_input_methods.AppendString("xkb:de::ger");
allowed_input_methods.AppendString("invalid_value_will_be_ignored");
policy->SetKey(key::kAllowedInputMethods, std::move(allowed_input_methods));
user_policy_helper()->SetPolicyAndWait(*policy, base::DictionaryValue(),
profile);
// Only "xkb:fr::fra", "xkb:de::ger" should be allowed, current input method
// should be "xkb:fr::fra", enabling "xkb:us::eng" should not be possible,
// enabling "xkb:de::ger" should be possible.
EXPECT_EQ(2U, ime_state->GetAllowedInputMethods().size());
EXPECT_EQ(2U, ime_state->GetActiveInputMethods()->size());
EXPECT_EQ(input_methods[1], ime_state->GetCurrentInputMethod().id());
EXPECT_FALSE(ime_state->EnableInputMethod(input_methods[0]));
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
// Set policy to only allow an invalid value as input method.
std::unique_ptr<base::DictionaryValue> policy_invalid =
std::make_unique<base::DictionaryValue>();
base::ListValue invalid_input_methods;
invalid_input_methods.AppendString("invalid_value_will_be_ignored");
policy_invalid->SetKey(key::kAllowedInputMethods,
std::move(invalid_input_methods));
user_policy_helper()->SetPolicyAndWait(*policy_invalid,
base::DictionaryValue(), profile);
// No restrictions and current input method should still be "xkb:fr::fra".
EXPECT_EQ(0U, ime_state->GetAllowedInputMethods().size());
EXPECT_EQ(input_methods[1], ime_state->GetCurrentInputMethod().id());
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[0]));
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
// Allow all input methods again.
user_policy_helper()->SetPolicyAndWait(base::DictionaryValue(),
base::DictionaryValue(), profile);
// No restrictions and current input method should still be "xkb:fr::fra".
EXPECT_EQ(0U, ime_state->GetAllowedInputMethods().size());
EXPECT_EQ(input_methods[1], ime_state->GetCurrentInputMethod().id());
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[0]));
EXPECT_TRUE(ime_state->EnableInputMethod(input_methods[2]));
}
class StartupBrowserWindowLaunchSuppressedTest : public LoginPolicyTestBase {
public:
StartupBrowserWindowLaunchSuppressedTest() = default;
void SetUpPolicy(bool enabled) {
std::unique_ptr<base::DictionaryValue> policy =
std::make_unique<base::DictionaryValue>();
policy->SetKey(key::kStartupBrowserWindowLaunchSuppressed,
base::Value(enabled));
user_policy_helper()->SetPolicy(*policy, base::DictionaryValue());
}
void CheckLaunchedBrowserCount(unsigned int count) {
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, kEmptyServices);
Profile* const profile = GetProfileForActiveUser();
ASSERT_EQ(count, chrome::GetBrowserCount(profile));
}
private:
DISALLOW_COPY_AND_ASSIGN(StartupBrowserWindowLaunchSuppressedTest);
};
// Test that the browser window is not launched when
// StartupBrowserWindowLaunchSuppressed is set to true.
IN_PROC_BROWSER_TEST_F(StartupBrowserWindowLaunchSuppressedTest,
TrueDoesNotAllowBrowserWindowLaunch) {
SetUpPolicy(true);
CheckLaunchedBrowserCount(0u);
}
// Test that the browser window is launched when
// StartupBrowserWindowLaunchSuppressed is set to false.
IN_PROC_BROWSER_TEST_F(StartupBrowserWindowLaunchSuppressedTest,
FalseAllowsBrowserWindowLaunch) {
SetUpPolicy(false);
CheckLaunchedBrowserCount(1u);
}
class PrimaryUserPoliciesProxiedTest : public LoginPolicyTestBase {
public:
PrimaryUserPoliciesProxiedTest() = default;
private:
DISALLOW_COPY_AND_ASSIGN(PrimaryUserPoliciesProxiedTest);
};
IN_PROC_BROWSER_TEST_F(PrimaryUserPoliciesProxiedTest,
AvailableInLocalStateEarly) {
PolicyService* const device_wide_policy_service =
g_browser_process->platform_part()
->browser_policy_connector_chromeos()
->GetPolicyService();
// Sanity check default state without a policy active.
EXPECT_FALSE(device_wide_policy_service
->GetPolicies(PolicyNamespace(
POLICY_DOMAIN_CHROME, std::string() /* component_id */))
.GetValue(key::kAudioOutputAllowed));
const PrefService::Preference* pref =
g_browser_process->local_state()->FindPreference(
chromeos::prefs::kAudioOutputAllowed);
EXPECT_FALSE(pref->IsManaged());
EXPECT_TRUE(pref->GetValue()->GetBool());
base::DictionaryValue policy;
policy.SetKey(key::kAudioOutputAllowed, base::Value(false));
user_policy_helper()->SetPolicy(policy, base::DictionaryValue());
SkipToLoginScreen();
content::WindowedNotificationObserver profile_created_observer(
chrome::NOTIFICATION_PROFILE_CREATED,
content::NotificationService::AllSources());
TriggerLogIn(kAccountId, kAccountPassword, kEmptyServices);
profile_created_observer.Wait();
const base::Value* policy_value =
device_wide_policy_service
->GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME,
std::string() /* component_id */))
.GetValue(key::kAudioOutputAllowed);
ASSERT_TRUE(policy_value);
EXPECT_FALSE(policy_value->GetBool());
EXPECT_TRUE(pref->IsManaged());
EXPECT_FALSE(pref->GetValue()->GetBool());
// Make sure that session startup finishes before letting chrome exit.
// Rationale: We've seen CHECK-failures when exiting chrome right after
// NOTIFICATION_PROFILE_CREATED, see e.g. https://crbug.com/1002066 .
chromeos::test::WaitForPrimaryUserSessionStart();
}
#endif // defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(PolicyTest, BookmarkBarEnabled) {
// Verifies that the bookmarks bar can be forced to always or never show up.
......
......@@ -1518,6 +1518,7 @@ if (!is_android) {
"../browser/policy/accessibility_policy_browsertest.cc",
"../browser/policy/arc_policy_browsertest.cc",
"../browser/policy/assistant_policy_browsertest.cc",
"../browser/policy/login_policy_test_base_browsertest.cc",
"../browser/policy/system_features_policy_browsertest.cc",
"../browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc",
]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment