blob: ee879f588a9696691bde0e889dde076f2f52560c [file] [log] [blame]
// Copyright (c) 2012 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 <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/atomic_ref_count.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_current.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_file_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/background/background_contents_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h"
#include "chrome/browser/component_updater/chrome_component_updater_configurator.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.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"
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_management_constants.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/install_verifier.h"
#include "chrome/browser/extensions/shared_module_service.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/updater/extension_cache_fake.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/media/router/media_router_feature.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
#include "chrome/browser/media/webrtc/webrtc_event_log_manager.h"
#include "chrome/browser/net/prediction_options.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/net/url_request_mock_util.h"
#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/policy/cloud/test_request_interceptor.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/resource_coordinator/tab_load_tracker_test_support.h"
#include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
#include "chrome/browser/search/ntp_features.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ssl/ssl_blocking_page.h"
#include "chrome/browser/task_manager/task_manager_interface.h"
#include "chrome/browser/translate/chrome_translate_client.h"
#include "chrome/browser/translate/translate_service.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/location_bar/location_bar.h"
#include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h"
#include "chrome/browser/ui/search/instant_test_utils.h"
#include "chrome/browser/ui/search/local_ntp_test_utils.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h"
#include "chrome/browser/ui/toolbar/media_router_action_controller.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
#include "chrome/browser/usb/usb_chooser_context.h"
#include "chrome/browser/usb/usb_chooser_context_factory.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/net/safe_search_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/web_application_info.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/locale_settings.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/search_test_utils.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
#include "components/browsing_data/core/pref_names.h"
#include "components/component_updater/component_updater_service.h"
#include "components/component_updater/component_updater_switches.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/download/public/common/download_item.h"
#include "components/infobars/core/infobar.h"
#include "components/language/core/browser/pref_names.h"
#include "components/network_time/network_time_tracker.h"
#include "components/omnibox/browser/autocomplete_controller.h"
#include "components/omnibox/browser/omnibox_edit_model.h"
#include "components/omnibox/browser/omnibox_view.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/external_data_fetcher.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/policy/core/common/policy_service.h"
#include "components/policy/core/common/policy_service_impl.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/features.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_service.h"
#include "components/security_interstitials/content/security_interstitial_page.h"
#include "components/security_interstitials/content/security_interstitial_tab_helper.h"
#include "components/security_interstitials/core/controller_client.h"
#include "components/strings/grit/components_strings.h"
#include "components/translate/core/browser/language_state.h"
#include "components/translate/core/browser/translate_infobar_delegate.h"
#include "components/unified_consent/pref_names.h"
#include "components/update_client/update_client.h"
#include "components/update_client/update_client_errors.h"
#include "components/update_client/url_loader_post_interceptor.h"
#include "components/user_prefs/user_prefs.h"
#include "components/variations/service/variations_service.h"
#include "components/variations/variations_params_manager.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/web_preferences.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/mock_notification_observer.h"
#include "content/public/test/network_service_test_helper.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/usb/mock_usb_device.h"
#include "device/usb/mojo/type_converters.h"
#include "extensions/browser/api/messaging/messaging_delegate.h"
#include "extensions/browser/disable_reason.h"
#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/scoped_ignore_content_verifier_for_test.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/browser/uninstall_reason.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "extensions/common/switches.h"
#include "extensions/common/value_builder.h"
#include "media/media_buildflags.h"
#include "net/base/hash_value.h"
#include "net/base/net_errors.h"
#include "net/base/url_util.h"
#include "net/cert/x509_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_stream_factory.h"
#include "net/http/transport_security_state.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/test/url_request/url_request_mock_http_job.h"
#include "net/url_request/test_url_request_interceptor.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/display/manager/display_manager.h"
#include "url/gurl.h"
#include "url/origin.h"
#if defined(OS_CHROMEOS)
#include "ash/public/cpp/ash_switches.h"
#include "ash/shell.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
#include "chrome/browser/chromeos/accessibility/magnifier_type.h"
#include "chrome/browser/chromeos/arc/arc_session_manager.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"
#include "chrome/browser/ui/ash/chrome_screenshot_grabber_test_observer.h"
#include "chromeos/audio/cras_audio_handler.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "components/account_id/account_id.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_session_runner.h"
#include "components/arc/arc_util.h"
#include "components/arc/test/fake_arc_session.h"
#include "components/user_manager/user_manager.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/snapshot/screenshot_grabber.h"
#endif
#if !defined(OS_MACOSX)
#include "base/compiler_specific.h"
#include "chrome/browser/ui/extensions/app_launch_params.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/app_window/native_app_window.h"
#include "ui/base/window_open_disposition.h"
#endif
#if defined(OS_WIN)
#include "base/win/win_util.h"
#endif
#if !defined(OS_ANDROID)
#include "chrome/browser/media/router/media_router_feature.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
#endif
using content::BrowserThread;
using net::URLRequestMockHTTPJob;
using testing::_;
using testing::Mock;
using testing::Return;
using webrtc_event_logging::WebRtcEventLogManager;
namespace policy {
namespace {
#if defined(OS_CHROMEOS)
const int kOneHourInMs = 60 * 60 * 1000;
const int kThreeHoursInMs = 180 * 60 * 1000;
#endif
const char kURL[] = "http://example.com";
const char kCookieValue[] = "converted=true";
// Assigned to Philip J. Fry to fix eventually.
// TODO(maksims): use year 3000 when we get rid off the 32-bit
// versions. https://crbug.com/619828
const char kCookieOptions[] = ";expires=Wed Jan 01 2038 00:00:00 GMT";
const base::FilePath::CharType kTestExtensionsDir[] =
FILE_PATH_LITERAL("extensions");
const base::FilePath::CharType kGoodCrxName[] = FILE_PATH_LITERAL("good.crx");
const base::FilePath::CharType kSimpleWithIconCrxName[] =
FILE_PATH_LITERAL("simple_with_icon.crx");
const base::FilePath::CharType kHostedAppCrxName[] =
FILE_PATH_LITERAL("hosted_app.crx");
const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
const char kSimpleWithIconCrxId[] = "dehdlahnlebladnfleagmjdapdjdcnlp";
const char kHostedAppCrxId[] = "kbmnembihfiondgfjekmnmcbddelicoi";
const base::FilePath::CharType kGoodV1CrxName[] =
FILE_PATH_LITERAL("good_v1.crx");
const base::FilePath::CharType kSimpleWithPopupExt[] =
FILE_PATH_LITERAL("simple_with_popup");
const base::FilePath::CharType kAppUnpackedExt[] =
FILE_PATH_LITERAL("app");
const char kAutoplayTestPageURL[] = "/media/autoplay_iframe.html";
#if !defined(OS_MACOSX)
const base::FilePath::CharType kUnpackedFullscreenAppName[] =
FILE_PATH_LITERAL("fullscreen_app");
#endif // !defined(OS_MACOSX)
// Arbitrary port range for testing the WebRTC UDP port policy.
const char kTestWebRtcUdpPortRange[] = "10000-10100";
constexpr size_t kWebAppId = 42;
void GetTestDataDirectory(base::FilePath* test_data_directory) {
ASSERT_TRUE(
base::PathService::Get(chrome::DIR_TEST_DATA, test_data_directory));
}
content::RenderFrameHost* GetMostVisitedIframe(content::WebContents* tab) {
for (content::RenderFrameHost* frame : tab->GetAllFrames()) {
if (frame->GetFrameName() == "mv-single")
return frame;
}
return nullptr;
}
// Filters requests to the hosts in |urls| and redirects them to the test data
// dir through URLRequestMockHTTPJobs.
void RedirectHostsToTestData(const char* const urls[], size_t size) {
// Map the given hosts to the test data dir.
net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
base::FilePath base_path;
GetTestDataDirectory(&base_path);
for (size_t i = 0; i < size; ++i) {
const GURL url(urls[i]);
EXPECT_TRUE(url.is_valid());
filter->AddUrlInterceptor(
url, URLRequestMockHTTPJob::CreateInterceptor(base_path));
}
}
// Fails requests using ERR_CONNECTION_RESET.
class FailedJobInterceptor : public net::URLRequestInterceptor {
public:
FailedJobInterceptor() {}
~FailedJobInterceptor() override {}
// URLRequestInterceptor implementation:
net::URLRequestJob* MaybeInterceptRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override {
return new net::URLRequestFailedJob(request, network_delegate,
net::ERR_CONNECTION_RESET);
}
private:
DISALLOW_COPY_AND_ASSIGN(FailedJobInterceptor);
};
// While |MakeRequestFail| is in scope URLRequests to |host| will fail.
class MakeRequestFail {
public:
// Sets up the filter on IO thread such that requests to |host| fail.
explicit MakeRequestFail(const std::string& host) : host_(host) {
base::RunLoop run_loop;
base::PostTaskWithTraitsAndReply(FROM_HERE, {BrowserThread::IO},
base::BindOnce(MakeRequestFailOnIO, host_),
run_loop.QuitClosure());
run_loop.Run();
}
~MakeRequestFail() {
base::RunLoop run_loop;
base::PostTaskWithTraitsAndReply(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(UndoMakeRequestFailOnIO, host_), run_loop.QuitClosure());
run_loop.Run();
}
private:
// Filters requests to the |host| such that they fail. Run on IO thread.
static void MakeRequestFailOnIO(const std::string& host) {
net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
filter->AddHostnameInterceptor("http", host,
std::unique_ptr<net::URLRequestInterceptor>(
new FailedJobInterceptor()));
filter->AddHostnameInterceptor("https", host,
std::unique_ptr<net::URLRequestInterceptor>(
new FailedJobInterceptor()));
}
// Remove filters for requests to the |host|. Run on IO thread.
static void UndoMakeRequestFailOnIO(const std::string& host) {
net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
filter->RemoveHostnameHandler("http", host);
filter->RemoveHostnameHandler("https", host);
}
const std::string host_;
};
// Registers a handler to respond to requests whose path matches |match_path|.
// The response contents are generated from |template_file|, by replacing all
// "${URL_PLACEHOLDER}" substrings in the file with the request URL excluding
// filename, query values and fragment.
void RegisterURLReplacingHandler(net::EmbeddedTestServer* test_server,
const std::string& match_path,
const base::FilePath& template_file) {
test_server->RegisterRequestHandler(base::Bind(
[](net::EmbeddedTestServer* test_server, const std::string& match_path,
const base::FilePath& template_file,
const net::test_server::HttpRequest& request)
-> std::unique_ptr<net::test_server::HttpResponse> {
GURL url = test_server->GetURL(request.relative_url);
if (url.path() != match_path)
return nullptr;
std::string contents;
CHECK(base::ReadFileToString(template_file, &contents));
GURL url_base = url.GetWithoutFilename();
base::ReplaceSubstringsAfterOffset(&contents, 0, "${URL_PLACEHOLDER}",
url_base.spec());
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
response->set_content(contents);
response->set_content_type("text/plain");
return response;
},
base::Unretained(test_server), match_path, template_file));
}
// Verifies that the given url |spec| can be opened. This assumes that |spec|
// points at empty.html in the test data dir.
void CheckCanOpenURL(Browser* browser, const std::string& spec) {
GURL url(spec);
ui_test_utils::NavigateToURL(browser, url);
content::WebContents* contents =
browser->tab_strip_model()->GetActiveWebContents();
EXPECT_EQ(url, contents->GetURL());
base::string16 blocked_page_title;
if (url.has_host()) {
blocked_page_title = base::UTF8ToUTF16(url.host());
} else {
// Local file paths show the full URL.
blocked_page_title = base::UTF8ToUTF16(url.spec());
}
EXPECT_NE(blocked_page_title, contents->GetTitle());
}
// Verifies that access to the given url |spec| is blocked.
void CheckURLIsBlockedInWebContents(content::WebContents* web_contents,
const GURL& url) {
EXPECT_EQ(url, web_contents->GetURL());
base::string16 blocked_page_title;
if (url.has_host()) {
blocked_page_title = base::UTF8ToUTF16(url.host());
} else {
// Local file paths show the full URL.
blocked_page_title = base::UTF8ToUTF16(url.spec());
}
EXPECT_EQ(blocked_page_title, web_contents->GetTitle());
// Verify that the expected error page is being displayed.
bool result = false;
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
web_contents,
"var textContent = document.body.textContent;"
"var hasError = textContent.indexOf('ERR_BLOCKED_BY_ADMINISTRATOR') >= 0;"
"domAutomationController.send(hasError);",
&result));
EXPECT_TRUE(result);
}
// Verifies that access to the given url |spec| is blocked.
void CheckURLIsBlocked(Browser* browser, const std::string& spec) {
GURL url(spec);
ui_test_utils::NavigateToURL(browser, url);
content::WebContents* contents =
browser->tab_strip_model()->GetActiveWebContents();
CheckURLIsBlockedInWebContents(contents, url);
}
// Downloads a file named |file| and expects it to be saved to |dir|, which
// must be empty.
void DownloadAndVerifyFile(Browser* browser,
const base::FilePath& dir,
const base::FilePath& file) {
net::EmbeddedTestServer embedded_test_server;
base::FilePath test_data_directory;
GetTestDataDirectory(&test_data_directory);
embedded_test_server.ServeFilesFromDirectory(test_data_directory);
ASSERT_TRUE(embedded_test_server.Start());
content::DownloadManager* download_manager =
content::BrowserContext::GetDownloadManager(browser->profile());
content::DownloadTestObserverTerminal observer(
download_manager, 1,
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
GURL url(embedded_test_server.GetURL("/" + file.MaybeAsASCII()));
base::FilePath downloaded = dir.Append(file);
EXPECT_FALSE(base::PathExists(downloaded));
ui_test_utils::NavigateToURL(browser, url);
observer.WaitForFinished();
EXPECT_EQ(1u,
observer.NumDownloadsSeenInState(download::DownloadItem::COMPLETE));
EXPECT_TRUE(base::PathExists(downloaded));
base::FileEnumerator enumerator(dir, false, base::FileEnumerator::FILES);
EXPECT_EQ(file, enumerator.Next().BaseName());
EXPECT_EQ(base::FilePath(), enumerator.Next());
}
#if defined(OS_CHROMEOS)
int CountScreenshots() {
DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext(
ProfileManager::GetActiveUserProfile());
base::FileEnumerator enumerator(download_prefs->DownloadPath(),
false, base::FileEnumerator::FILES,
"Screenshot*");
int count = 0;
while (!enumerator.Next().empty())
count++;
return count;
}
#endif
// Checks if WebGL is enabled in the given WebContents.
bool IsWebGLEnabled(content::WebContents* contents) {
bool result = false;
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
contents,
"var canvas = document.createElement('canvas');"
"var context = canvas.getContext('webgl');"
"domAutomationController.send(context != null);",
&result));
return result;
}
bool IsJavascriptEnabled(content::WebContents* contents) {
std::unique_ptr<base::Value> value =
content::ExecuteScriptAndGetValue(contents->GetMainFrame(), "123");
int result = 0;
if (!value->GetAsInteger(&result))
EXPECT_EQ(base::Value::Type::NONE, value->type());
return result == 123;
}
bool IsNetworkPredictionEnabled(PrefService* prefs) {
return chrome_browser_net::CanPrefetchAndPrerenderUI(prefs) ==
chrome_browser_net::NetworkPredictionStatus::ENABLED;
}
void FlushBlacklistPolicy() {
// Updates of the URLBlacklist are done on IO, after building the blacklist
// on the blocking pool, which is initiated from IO.
content::RunAllPendingInMessageLoop(BrowserThread::IO);
content::RunAllTasksUntilIdle();
content::RunAllPendingInMessageLoop(BrowserThread::IO);
}
bool ContainsVisibleElement(content::WebContents* contents,
const std::string& id) {
bool result;
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
contents,
"var elem = document.getElementById('" + id + "');"
"domAutomationController.send(!!elem && !elem.hidden);",
&result));
return result;
}
bool ContainsWebstoreTile(content::RenderFrameHost* iframe) {
int num_webstore_tiles = 0;
EXPECT_TRUE(instant_test_utils::GetIntFromJS(
iframe,
"document.querySelectorAll(\".md-tile[href='" +
l10n_util::GetStringUTF8(IDS_WEBSTORE_URL) + "']\").length",
&num_webstore_tiles));
return num_webstore_tiles == 1;
}
#if defined(OS_CHROMEOS)
class TestAudioObserver : public chromeos::CrasAudioHandler::AudioObserver {
public:
TestAudioObserver() : output_mute_changed_count_(0) {
}
int output_mute_changed_count() const {
return output_mute_changed_count_;
}
~TestAudioObserver() override {}
protected:
// chromeos::CrasAudioHandler::AudioObserver overrides.
void OnOutputMuteChanged(bool /* mute_on */,
bool /* system_adjust */) override {
++output_mute_changed_count_;
}
private:
int output_mute_changed_count_;
DISALLOW_COPY_AND_ASSIGN(TestAudioObserver);
};
#endif
// This class waits until either a load stops or the WebContents is destroyed.
class WebContentsLoadedOrDestroyedWatcher
: public content::WebContentsObserver {
public:
explicit WebContentsLoadedOrDestroyedWatcher(
content::WebContents* web_contents);
~WebContentsLoadedOrDestroyedWatcher() override;
// Waits until the WebContents's load is done or until it is destroyed.
void Wait();
// Overridden WebContentsObserver methods.
void WebContentsDestroyed() override;
void DidStopLoading() override;
private:
scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
DISALLOW_COPY_AND_ASSIGN(WebContentsLoadedOrDestroyedWatcher);
};
WebContentsLoadedOrDestroyedWatcher::WebContentsLoadedOrDestroyedWatcher(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
message_loop_runner_(new content::MessageLoopRunner) {
}
WebContentsLoadedOrDestroyedWatcher::~WebContentsLoadedOrDestroyedWatcher() {}
void WebContentsLoadedOrDestroyedWatcher::Wait() {
message_loop_runner_->Run();
}
void WebContentsLoadedOrDestroyedWatcher::WebContentsDestroyed() {
message_loop_runner_->Quit();
}
void WebContentsLoadedOrDestroyedWatcher::DidStopLoading() {
message_loop_runner_->Quit();
}
#if !defined(OS_MACOSX)
// Observer used to wait for the creation of a new app window.
class TestAddAppWindowObserver
: public extensions::AppWindowRegistry::Observer {
public:
explicit TestAddAppWindowObserver(extensions::AppWindowRegistry* registry);
~TestAddAppWindowObserver() override;
// extensions::AppWindowRegistry::Observer:
void OnAppWindowAdded(extensions::AppWindow* app_window) override;
extensions::AppWindow* WaitForAppWindow();
private:
extensions::AppWindowRegistry* registry_; // Not owned.
extensions::AppWindow* window_; // Not owned.
base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(TestAddAppWindowObserver);
};
TestAddAppWindowObserver::TestAddAppWindowObserver(
extensions::AppWindowRegistry* registry)
: registry_(registry), window_(NULL) {
registry_->AddObserver(this);
}
TestAddAppWindowObserver::~TestAddAppWindowObserver() {
registry_->RemoveObserver(this);
}
void TestAddAppWindowObserver::OnAppWindowAdded(
extensions::AppWindow* app_window) {
window_ = app_window;
run_loop_.Quit();
}
extensions::AppWindow* TestAddAppWindowObserver::WaitForAppWindow() {
run_loop_.Run();
return window_;
}
#endif
#if !defined(OS_CHROMEOS)
extensions::MessagingDelegate::PolicyPermission IsNativeMessagingHostAllowed(
content::BrowserContext* browser_context,
const std::string& native_host_name) {
extensions::MessagingDelegate* messaging_delegate =
extensions::ExtensionsAPIClient::Get()->GetMessagingDelegate();
EXPECT_NE(messaging_delegate, nullptr);
return messaging_delegate->IsNativeMessagingHostAllowed(browser_context,
native_host_name);
}
#endif
class MockPasswordProtectionService
: public safe_browsing::ChromePasswordProtectionService {
public:
MockPasswordProtectionService(safe_browsing::SafeBrowsingService* sb_service,
Profile* profile)
: safe_browsing::ChromePasswordProtectionService(sb_service, profile) {}
~MockPasswordProtectionService() override {}
MOCK_CONST_METHOD0(GetSyncAccountType,
safe_browsing::LoginReputationClientRequest::
PasswordReuseEvent::SyncAccountType());
AccountInfo GetAccountInfo() const override {
AccountInfo info;
info.email = "user@mycompany.com";
return info;
}
};
} // namespace
class PolicyTest : public InProcessBrowserTest {
protected:
PolicyTest() {}
~PolicyTest() override {}
void SetUp() override {
test_extension_cache_.reset(new extensions::ExtensionCacheFake());
InProcessBrowserTest::SetUp();
}
void SetUpInProcessBrowserTestFixture() override {
base::CommandLine::ForCurrentProcess()->AppendSwitch("noerrdialogs");
EXPECT_CALL(provider_, IsInitializationComplete(_))
.WillRepeatedly(Return(true));
BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
}
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(chrome_browser_net::SetUrlRequestMocksEnabled, true));
if (extension_service()->updater()) {
extension_service()->updater()->SetExtensionCacheForTesting(
test_extension_cache_.get());
}
}
void SetScreenshotPolicy(bool enabled) {
PolicyMap policies;
policies.Set(key::kDisableScreenshots, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(!enabled), nullptr);
UpdateProviderPolicy(policies);
}
void SetShouldRequireCTForTesting(bool* required) {
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
network::mojom::NetworkServiceTestPtr network_service_test;
content::ServiceManagerConnection::GetForProcess()
->GetConnector()
->BindInterface(content::mojom::kNetworkServiceName,
&network_service_test);
network::mojom::NetworkServiceTest::ShouldRequireCT required_ct;
if (!required) {
required_ct =
network::mojom::NetworkServiceTest::ShouldRequireCT::RESET;
} else {
required_ct =
*required
? network::mojom::NetworkServiceTest::ShouldRequireCT::REQUIRE
: network::mojom::NetworkServiceTest::ShouldRequireCT::
DONT_REQUIRE;
}
mojo::ScopedAllowSyncCallForTesting allow_sync_call;
network_service_test->SetShouldRequireCT(required_ct);
return;
}
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&net::TransportSecurityState::SetShouldRequireCTForTesting,
required));
}
#if defined(OS_CHROMEOS)
class QuitMessageLoopAfterScreenshot
: public ChromeScreenshotGrabberTestObserver {
public:
explicit QuitMessageLoopAfterScreenshot(base::OnceClosure done)
: done_(std::move(done)) {}
void OnScreenshotCompleted(
ui::ScreenshotResult screenshot_result,
const base::FilePath& screenshot_path) override {
base::PostTaskWithTraitsAndReply(FROM_HERE, {BrowserThread::IO},
base::DoNothing(), std::move(done_));
}
~QuitMessageLoopAfterScreenshot() override {}
private:
base::OnceClosure done_;
};
void TestScreenshotFile(bool enabled) {
base::RunLoop run_loop;
QuitMessageLoopAfterScreenshot observer_(run_loop.QuitClosure());
ChromeScreenshotGrabber* grabber = ChromeScreenshotGrabber::Get();
grabber->test_observer_ = &observer_;
SetScreenshotPolicy(enabled);
grabber->HandleTakeScreenshotForAllRootWindows();
run_loop.Run();
grabber->test_observer_ = nullptr;
}
#endif // defined(OS_CHROMEOS)
extensions::ExtensionService* extension_service() {
extensions::ExtensionSystem* system =
extensions::ExtensionSystem::Get(browser()->profile());
return system->extension_service();
}
const extensions::Extension* InstallExtension(
const base::FilePath::StringType& name) {
base::FilePath extension_path(ui_test_utils::GetTestFilePath(
base::FilePath(kTestExtensionsDir), base::FilePath(name)));
scoped_refptr<extensions::CrxInstaller> installer =
extensions::CrxInstaller::CreateSilent(extension_service());
installer->set_allow_silent_install(true);
installer->set_install_cause(extension_misc::INSTALL_CAUSE_UPDATE);
installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE);
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
installer->InstallCrx(extension_path);
observer.Wait();
content::Details<const extensions::Extension> details = observer.details();
return details.ptr();
}
const extensions::Extension* InstallBookmarkApp() {
WebApplicationInfo web_app;
web_app.title = base::ASCIIToUTF16("Bookmark App");
web_app.app_url = GURL("http://www.google.com");
scoped_refptr<extensions::CrxInstaller> installer =
extensions::CrxInstaller::CreateSilent(extension_service());
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
installer->InstallWebApp(web_app);
observer.Wait();
content::Details<const extensions::Extension> details = observer.details();
return details.ptr();
}
scoped_refptr<const extensions::Extension> LoadUnpackedExtension(
const base::FilePath::StringType& name) {
base::FilePath extension_path(ui_test_utils::GetTestFilePath(
base::FilePath(kTestExtensionsDir), base::FilePath(name)));
extensions::ChromeTestExtensionLoader loader(browser()->profile());
return loader.LoadExtension(extension_path);
}
void UninstallExtension(const std::string& id, bool expect_success) {
if (expect_success) {
extensions::TestExtensionRegistryObserver observer(
extensions::ExtensionRegistry::Get(browser()->profile()));
extension_service()->UninstallExtension(
id, extensions::UNINSTALL_REASON_FOR_TESTING, NULL);
observer.WaitForExtensionUninstalled();
} else {
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_EXTENSION_UNINSTALL_NOT_ALLOWED,
content::NotificationService::AllSources());
extension_service()->UninstallExtension(
id,
extensions::UNINSTALL_REASON_FOR_TESTING,
NULL);
observer.Wait();
}
}
void DisableExtension(const std::string& id) {
extensions::TestExtensionRegistryObserver observer(
extensions::ExtensionRegistry::Get(browser()->profile()));
extension_service()->DisableExtension(
id, extensions::disable_reason::DISABLE_USER_ACTION);
observer.WaitForExtensionUnloaded();
}
void UpdateProviderPolicy(const PolicyMap& policy) {
PolicyMap policy_with_defaults;
policy_with_defaults.CopyFrom(policy);
#if defined(OS_CHROMEOS)
SetEnterpriseUsersDefaults(&policy_with_defaults);
#endif
provider_.UpdateChromePolicy(policy_with_defaults);
DCHECK(base::MessageLoopCurrent::Get());
base::RunLoop loop;
loop.RunUntilIdle();
}
// Sends a mouse click at the given coordinates to the current renderer.
void PerformClick(int x, int y) {
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
blink::WebMouseEvent click_event(
blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
click_event.button = blink::WebMouseEvent::Button::kLeft;
click_event.click_count = 1;
click_event.SetPositionInWidget(x, y);
contents->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(click_event);
click_event.SetType(blink::WebInputEvent::kMouseUp);
contents->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(click_event);
}
void SetPolicy(PolicyMap* policies,
const char* key,
std::unique_ptr<base::Value> value) {
if (value) {
policies->Set(key, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, std::move(value), nullptr);
} else {
policies->Erase(key);
}
}
void ApplySafeSearchPolicy(std::unique_ptr<base::Value> legacy_safe_search,
std::unique_ptr<base::Value> google_safe_search,
std::unique_ptr<base::Value> legacy_youtube,
std::unique_ptr<base::Value> youtube_restrict) {
PolicyMap policies;
SetPolicy(&policies, key::kForceSafeSearch, std::move(legacy_safe_search));
SetPolicy(&policies, key::kForceGoogleSafeSearch,
std::move(google_safe_search));
SetPolicy(&policies, key::kForceYouTubeSafetyMode,
std::move(legacy_youtube));
SetPolicy(&policies, key::kForceYouTubeRestrict,
std::move(youtube_restrict));
UpdateProviderPolicy(policies);
}
static GURL GetExpectedSearchURL(bool expect_safe_search) {
std::string expected_url("http://google.com/");
if (expect_safe_search) {
expected_url += "?" +
std::string(safe_search_util::kSafeSearchSafeParameter) +
"&" + safe_search_util::kSafeSearchSsuiParameter;
}
return GURL(expected_url);
}
static void CheckSafeSearch(Browser* browser, bool expect_safe_search) {
content::WebContents* web_contents =
browser->tab_strip_model()->GetActiveWebContents();
content::TestNavigationObserver observer(web_contents);
LocationBar* location_bar = browser->window()->GetLocationBar();
ui_test_utils::SendToOmniboxAndSubmit(location_bar, "http://google.com/");
OmniboxEditModel* model = location_bar->GetOmniboxView()->model();
observer.Wait();
EXPECT_TRUE(model->CurrentMatch(NULL).destination_url.is_valid());
EXPECT_EQ(GetExpectedSearchURL(expect_safe_search), web_contents->GetURL());
}
static void CheckYouTubeRestricted(
int youtube_restrict_mode,
const std::map<GURL, net::HttpRequestHeaders>& urls_requested,
const GURL& url) {
auto iter = urls_requested.find(url);
ASSERT_TRUE(iter != urls_requested.end());
std::string header;
iter->second.GetHeader(safe_search_util::kYouTubeRestrictHeaderName,
&header);
if (youtube_restrict_mode == safe_search_util::YOUTUBE_RESTRICT_OFF) {
EXPECT_TRUE(header.empty());
} else if (youtube_restrict_mode ==
safe_search_util::YOUTUBE_RESTRICT_MODERATE) {
EXPECT_EQ(header, safe_search_util::kYouTubeRestrictHeaderValueModerate);
} else if (youtube_restrict_mode ==
safe_search_util::YOUTUBE_RESTRICT_STRICT) {
EXPECT_EQ(header, safe_search_util::kYouTubeRestrictHeaderValueStrict);
}
}
static void CheckAllowedDomainsHeader(
const std::string& allowed_domain,
const std::map<GURL, net::HttpRequestHeaders>& urls_requested,
const GURL& url) {
auto iter = urls_requested.find(url);
ASSERT_TRUE(iter != urls_requested.end());
if (allowed_domain.empty()) {
EXPECT_TRUE(
!iter->second.HasHeader(safe_search_util::kGoogleAppsAllowedDomains));
return;
}
std::string header;
iter->second.GetHeader(safe_search_util::kGoogleAppsAllowedDomains,
&header);
EXPECT_EQ(header, allowed_domain);
}
static bool FetchSubresource(content::WebContents* web_contents,
const GURL& url) {
std::string script(
"var xhr = new XMLHttpRequest();"
"xhr.open('GET', '");
script += url.spec() +
"', true);"
"xhr.onload = function (e) {"
" if (xhr.readyState === 4) {"
" window.domAutomationController.send(xhr.status === 200);"
" }"
"};"
"xhr.onerror = function () {"
" window.domAutomationController.send(false);"
"};"
"xhr.send(null)";
bool xhr_result = false;
bool execute_result =
content::ExecuteScriptAndExtractBool(web_contents, script, &xhr_result);
return xhr_result && execute_result;
}
MockConfigurationPolicyProvider provider_;
std::unique_ptr<extensions::ExtensionCacheFake> test_extension_cache_;
extensions::ScopedIgnoreContentVerifierForTest ignore_content_verifier_;
};
// A subclass of PolicyTest that runs each test with the old interstitial code
// path and the new one, called committed interstitials.
// TODO(https://crbug.com/448486): This can be removed after committed
// interstitials are launched.
class SSLPolicyTestCommittedInterstitials
: public PolicyTest,
public testing::WithParamInterface<bool> {
public:
SSLPolicyTestCommittedInterstitials() {}
void SetUpCommandLine(base::CommandLine* command_line) override {
PolicyTest::SetUpCommandLine(command_line);
if (AreCommittedInterstitialsEnabled()) {
scoped_feature_list_.InitAndEnableFeature(
features::kSSLCommittedInterstitials);
}
// Ensure SSL interstitials are capable of sending reports.
variations::testing::VariationParamsManager::AppendVariationParams(
"ReportCertificateErrors", "ShowAndPossiblySend",
{{"sendingThreshold", "1.0"}}, command_line);
}
protected:
bool AreCommittedInterstitialsEnabled() const { return GetParam(); }
bool IsShowingInterstitial(content::WebContents* tab) {
if (AreCommittedInterstitialsEnabled()) {
security_interstitials::SecurityInterstitialTabHelper* helper =
security_interstitials::SecurityInterstitialTabHelper::
FromWebContents(tab);
if (!helper) {
return false;
}
return helper
->GetBlockingPageForCurrentlyCommittedNavigationForTesting() !=
nullptr;
}
return tab->GetInterstitialPage() != nullptr;
}
void WaitForInterstitial(content::WebContents* tab) {
if (!AreCommittedInterstitialsEnabled()) {
content::WaitForInterstitialAttach(tab);
ASSERT_TRUE(IsShowingInterstitial(tab));
ASSERT_TRUE(
WaitForRenderFrameReady(tab->GetInterstitialPage()->GetMainFrame()));
} else {
ASSERT_TRUE(IsShowingInterstitial(tab));
ASSERT_TRUE(WaitForRenderFrameReady(tab->GetMainFrame()));
}
}
int IsExtendedReportingCheckboxVisibleOnInterstitial() {
const std::string command = base::StringPrintf(
"var node = document.getElementById('extended-reporting-opt-in');"
"if (node) {"
" window.domAutomationController.send(node.offsetWidth > 0 || "
" node.offsetHeight > 0 ? %d : %d);"
"} else {"
// The node should be present but not visible, so trigger an error
// by sending false if it's not present.
" window.domAutomationController.send(%d);"
"}",
security_interstitials::CMD_TEXT_FOUND,
security_interstitials::CMD_TEXT_NOT_FOUND,
security_interstitials::CMD_ERROR);
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
WaitForInterstitial(tab);
int result = 0;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
AreCommittedInterstitialsEnabled()
? tab->GetMainFrame()
: tab->GetInterstitialPage()->GetMainFrame(),
command, &result));
return result;
}
void SendInterstitialCommand(
content::WebContents* tab,
security_interstitials::SecurityInterstitialCommand command) {
if (AreCommittedInterstitialsEnabled()) {
security_interstitials::SecurityInterstitialTabHelper* helper =
security_interstitials::SecurityInterstitialTabHelper::
FromWebContents(tab);
helper->GetBlockingPageForCurrentlyCommittedNavigationForTesting()
->CommandReceived(base::IntToString(command));
return;
}
tab->GetInterstitialPage()->GetDelegateForTesting()->CommandReceived(
base::IntToString(command));
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(SSLPolicyTestCommittedInterstitials);
};
INSTANTIATE_TEST_CASE_P(,
SSLPolicyTestCommittedInterstitials,
::testing::Values(false, true));
#if defined(OS_WIN)
// This policy only exists on Windows.
// Sets the locale policy before the browser is started.
class LocalePolicyTest : public PolicyTest {
public:
LocalePolicyTest() {}
~LocalePolicyTest() override {}
void SetUpInProcessBrowserTestFixture() override {
PolicyTest::SetUpInProcessBrowserTestFixture();
PolicyMap policies;
policies.Set(key::kApplicationLocaleValue, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>("fr"), nullptr);
provider_.UpdateChromePolicy(policies);
// The "en-US" ResourceBundle is always loaded before this step for tests,
// but in this test we want the browser to load the bundle as it
// normally would.
ui::ResourceBundle::CleanupSharedInstance();
}
};
IN_PROC_BROWSER_TEST_F(LocalePolicyTest, ApplicationLocaleValue) {
// Verifies that the default locale can be overridden with policy.
EXPECT_EQ("fr", g_browser_process->GetApplicationLocale());
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);
}
#endif
#if defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, PRE_AllowedLanguages) {
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, kEmptyServices);
const user_manager::User* const user =
user_manager::UserManager::Get()->GetActiveUser();
Profile* const profile =
chromeos::ProfileHelper::Get()->GetProfileByUser(user);
PrefService* prefs = profile->GetPrefs();
// Set locale and preferred languages to "en-US".
prefs->SetString(language::prefs::kApplicationLocale, "en-US");
prefs->SetString(prefs::kLanguagePreferredLanguages, "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()->UpdatePolicy(*policy, base::DictionaryValue(), profile);
}
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, AllowedLanguages) {
LogIn(kAccountId, kAccountPassword, kEmptyServices);
const user_manager::User* const user =
user_manager::UserManager::Get()->GetActiveUser();
Profile* const profile =
chromeos::ProfileHelper::Get()->GetProfileByUser(user);
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(prefs::kLanguagePreferredLanguages));
}
IN_PROC_BROWSER_TEST_F(LoginPolicyTestBase, AllowedInputMethods) {
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, kEmptyServices);
const user_manager::User* const user =
user_manager::UserManager::Get()->GetActiveUser();
Profile* const profile =
chromeos::ProfileHelper::Get()->GetProfileByUser(user);
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()->UpdatePolicy(*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()->UpdatePolicy(*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()->UpdatePolicy(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]));
}
#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.
// Test starts in about:blank.
PrefService* prefs = browser()->profile()->GetPrefs();
EXPECT_FALSE(prefs->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar));
EXPECT_FALSE(prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar));
EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
PolicyMap policies;
policies.Set(key::kBookmarkBarEnabled, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(true), nullptr);
UpdateProviderPolicy(policies);
EXPECT_TRUE(prefs->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar));
EXPECT_TRUE(prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar));
EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
// The NTP has special handling of the bookmark bar.
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
policies.Set(key::kBookmarkBarEnabled, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(false), nullptr);
UpdateProviderPolicy(policies);
EXPECT_TRUE(prefs->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar));
EXPECT_FALSE(prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar));
// The bookmark bar is hidden in the NTP when disabled by policy.
EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
policies.Clear();
UpdateProviderPolicy(policies);
EXPECT_FALSE(prefs->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar));
EXPECT_FALSE(prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar));
// The bookmark bar is shown detached in the NTP, when disabled by prefs only.
EXPECT_EQ(BookmarkBar::DETACHED, browser()->bookmark_bar_state());
}
IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_PRE_DefaultCookiesSetting) {
// Verifies that cookies are deleted on shutdown. This test is split in 3
// parts because it spans 2 browser restarts.
Profile* profile = browser()->profile();
GURL url(kURL);
// No cookies at startup.
EXPECT_TRUE(content::GetCookies(profile, url).empty());
// Set a cookie now.
std::string value = base::StrCat({kCookieValue, kCookieOptions});
EXPECT_TRUE(content::SetCookie(profile, url, value));
// Verify it was set.
EXPECT_EQ(kCookieValue, GetCookies(profile, url));
}
IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_DefaultCookiesSetting) {
// Verify that the cookie persists across restarts.
EXPECT_EQ(kCookieValue, GetCookies(browser()->profile(), GURL(kURL)));
// Now set the policy and the cookie should be gone after another restart.
PolicyMap policies;
policies.Set(key::kDefaultCookiesSetting, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(CONTENT_SETTING_SESSION_ONLY),
nullptr);
UpdateProviderPolicy(policies);
}
IN_PROC_BROWSER_TEST_F(PolicyTest, DefaultCookiesSetting) {
// Verify that the cookie is gone.
EXPECT_TRUE(GetCookies(browser()->profile(), GURL(kURL)).empty());
}
IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_PRE_WebsiteCookiesSetting) {
// Verifies that cookies are deleted on shutdown. This test is split in 3
// parts because it spans 2 browser restarts.
Profile* profile = browser()->profile();
GURL url(kURL);
// No cookies at startup.
EXPECT_TRUE(content::GetCookies(profile, url).empty());
// Set a cookie now.
std::string value = base::StrCat({kCookieValue, kCookieOptions});
EXPECT_TRUE(content::SetCookie(profile, url, value));
// Verify it was set.
EXPECT_EQ(kCookieValue, GetCookies(profile, url));
}
IN_PROC_BROWSER_TEST_F(PolicyTest, PRE_WebsiteCookiesSetting) {
// Verify that the cookie persists across restarts.
EXPECT_EQ(kCookieValue, GetCookies(browser()->profile(), GURL(kURL)));
// Now set the policy and the cookie should be gone after another restart.
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
->SetWebsiteSettingDefaultScope(
GURL(kURL), GURL(kURL), CONTENT_SETTINGS_TYPE_COOKIES, std::string(),
std::make_unique<base::Value>(CONTENT_SETTING_SESSION_ONLY));
}
IN_PROC_BROWSER_TEST_F(PolicyTest, WebsiteCookiesSetting) {
// Verify that the cookie is gone.
EXPECT_TRUE(GetCookies(browser()->profile(), GURL(kURL)).empty());
}
IN_PROC_BROWSER_TEST_F(PolicyTest, DefaultSearchProvider) {
MakeRequestFail make_request_fail("search.example");
// Verifies that a default search is made using the provider configured via
// policy. Also checks that default search can be completely disabled.
const base::string16 kKeyword(base::ASCIIToUTF16("testsearch"));
const std::string kSearchURL("http://search.example/search?q={searchTerms}");
const std::string kAlternateURL0(
"http://search.example/search#q={searchTerms}");
const std::string kAlternateURL1("http://search.example/#q={searchTerms}");
const std::string kImageURL("http://test.com/searchbyimage/upload");
const std::string kImageURLPostParams(
"image_content=content,image_url=http://test.com/test.png");
const std::string kNewTabURL("http://search.example/newtab");
TemplateURLService* service = TemplateURLServiceFactory::GetForProfile(
browser()->profile());
search_test_utils::WaitForTemplateURLServiceToLoad(service);
const TemplateURL* default_search = service->GetDefaultSearchProvider();
ASSERT_TRUE(default_search);
EXPECT_NE(kKeyword, default_search->keyword());
EXPECT_NE(kSearchURL, default_search->url());
EXPECT_FALSE(
default_search->alternate_urls().size() == 2 &&
default_search->alternate_urls()[0] == kAlternateURL0 &&
default_search->alternate_urls()[1] == kAlternateURL1 &&
default_search->image_url() == kImageURL &&
default_search->image_url_post_params() == kImageURLPostParams &&
default_search->new_tab_url() == kNewTabURL);
// Override the default search provider using policies.
PolicyMap policies;
policies.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(true), nullptr);
policies.Set(key::kDefaultSearchProviderKeyword, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(kKeyword), nullptr);
policies.Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(kSearchURL), nullptr);
std::unique_ptr<base::ListValue> alternate_urls(new base::ListValue);
alternate_urls->AppendString(kAlternateURL0);
alternate_urls->AppendString(kAlternateURL1);
policies.Set(key::kDefaultSearchProviderAlternateURLs, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::move(alternate_urls), nullptr);
policies.Set(key::kDefaultSearchProviderImageURL, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(kImageURL), nullptr);
policies.Set(key::kDefaultSearchProviderImageURLPostParams,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(kImageURLPostParams), nullptr);
policies.Set(key::kDefaultSearchProviderNewTabURL, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(kNewTabURL), nullptr);
UpdateProviderPolicy(policies);
default_search = service->GetDefaultSearchProvider();
ASSERT_TRUE(default_search);
EXPECT_EQ(kKeyword, default_search->keyword());
EXPECT_EQ(kSearchURL, default_search->url());
EXPECT_EQ(2U, default_search->alternate_urls().size());
EXPECT_EQ(kAlternateURL0, default_search->alternate_urls()[0]);
EXPECT_EQ(kAlternateURL1, default_search->alternate_urls()[1]);
EXPECT_EQ(kImageURL, default_search->image_url());
EXPECT_EQ(kImageURLPostParams, default_search->image_url_post_params());
EXPECT_EQ(kNewTabURL, default_search->new_tab_url());
// Verify that searching from the omnibox uses kSearchURL.
chrome::FocusLocationBar(browser());
LocationBar* location_bar = browser()->window()->GetLocationBar();
ui_test_utils::SendToOmniboxAndSubmit(location_bar, "stuff to search for");
OmniboxEditModel* model = location_bar->GetOmniboxView()->model();
EXPECT_TRUE(model->CurrentMatch(NULL).destination_url.is_valid());
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
GURL expected("http://search.example/search?q=stuff+to+search+for");
EXPECT_EQ(expected, web_contents->GetURL());
// Verify that searching from the omnibox can be disabled.
ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
policies.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(false), nullptr);
EXPECT_TRUE(service->GetDefaultSearchProvider());
UpdateProviderPolicy(policies);
EXPECT_FALSE(service->GetDefaultSearchProvider());
ui_test_utils::SendToOmniboxAndSubmit(location_bar, "should not work");
// This means that submitting won't trigger any action.
EXPECT_FALSE(model->CurrentMatch(NULL).destination_url.is_valid());
EXPECT_EQ(GURL(url::kAboutBlankURL), web_contents->GetURL());
}
IN_PROC_BROWSER_TEST_F(PolicyTest, SeparateProxyPoliciesMerging) {
// Add an individual proxy policy value.
PolicyMap policies;
policies.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(3), nullptr);
UpdateProviderPolicy(policies);
// It should be removed and replaced with a dictionary.
PolicyMap expected;
std::unique_ptr<base::DictionaryValue> expected_value(
new base::DictionaryValue);
expected_value->SetInteger(key::kProxyServerMode, 3);
expected.Set(key::kProxySettings, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, std::move(expected_value), nullptr);
#if defined(OS_CHROMEOS)
SetEnterpriseUsersDefaults(&expected);
#endif
// Check both the browser and the profile.
const PolicyMap& actual_from_browser =
g_browser_process->browser_policy_connector()
->GetPolicyService()
->GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
EXPECT_TRUE(expected.Equals(actual_from_browser));
const PolicyMap& actual_from_profile =
ProfilePolicyConnectorFactory::GetForBrowserContext(browser()->profile())
->policy_service()
->GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
EXPECT_TRUE(expected.Equals(actual_from_profile));
}
IN_PROC_BROWSER_TEST_F(PolicyTest, LegacySafeSearch) {
static_assert(safe_search_util::YOUTUBE_RESTRICT_OFF == 0 &&
safe_search_util::YOUTUBE_RESTRICT_MODERATE == 1 &&
safe_search_util::YOUTUBE_RESTRICT_STRICT == 2 &&
safe_search_util::YOUTUBE_RESTRICT_COUNT == 3,
"This test relies on mapping ints to enum values.");
// Go over all combinations of (undefined, true, false) for the policies
// ForceSafeSearch, ForceGoogleSafeSearch and ForceYouTubeSafetyMode as well
// as (undefined, off, moderate, strict) for ForceYouTubeRestrict and make
// sure the prefs are set as expected.
const int num_restrict_modes = 1 + safe_search_util::YOUTUBE_RESTRICT_COUNT;
for (int i = 0; i < 3 * 3 * 3 * num_restrict_modes; i++) {
int val = i;
int legacy_safe_search = val % 3; val /= 3;
int google_safe_search = val % 3; val /= 3;
int legacy_youtube = val % 3; val /= 3;
int youtube_restrict = val % num_restrict_modes;
// Override the default SafeSearch setting using policies.
ApplySafeSearchPolicy(
legacy_safe_search == 0
? nullptr
: std::make_unique<base::Value>(legacy_safe_search == 1),
google_safe_search == 0
? nullptr
: std::make_unique<base::Value>(google_safe_search == 1),
legacy_youtube == 0
? nullptr
: std::make_unique<base::Value>(legacy_youtube == 1),
youtube_restrict == 0
? nullptr // subtracting 1 gives 0,1,2, see above
: std::make_unique<base::Value>(youtube_restrict - 1));
// The legacy ForceSafeSearch policy should only have an effect if none of
// the other 3 policies are defined.
bool legacy_safe_search_in_effect =
google_safe_search == 0 && legacy_youtube == 0 &&
youtube_restrict == 0 && legacy_safe_search != 0;
bool legacy_safe_search_enabled =
legacy_safe_search_in_effect && legacy_safe_search == 1;
// Likewise, ForceYouTubeSafetyMode should only have an effect if
// ForceYouTubeRestrict is not set.
bool legacy_youtube_in_effect =
youtube_restrict == 0 && legacy_youtube != 0;
bool legacy_youtube_enabled =
legacy_youtube_in_effect && legacy_youtube == 1;
// Consistency check, can't have both legacy modes at the same time.
EXPECT_FALSE(legacy_youtube_in_effect && legacy_safe_search_in_effect);
// Google safe search can be triggered by the ForceGoogleSafeSearch policy
// or the legacy safe search mode.
PrefService* prefs = browser()->profile()->GetPrefs();
EXPECT_EQ(google_safe_search != 0 || legacy_safe_search_in_effect,
prefs->IsManagedPreference(prefs::kForceGoogleSafeSearch));
EXPECT_EQ(google_safe_search == 1 || legacy_safe_search_enabled,
prefs->GetBoolean(prefs::kForceGoogleSafeSearch));
// YouTube restrict mode can be triggered by the ForceYouTubeRestrict policy
// or any of the legacy modes.
EXPECT_EQ(youtube_restrict != 0 || legacy_safe_search_in_effect ||
legacy_youtube_in_effect,
prefs->IsManagedPreference(prefs::kForceYouTubeRestrict));
if (youtube_restrict != 0) {
// The ForceYouTubeRestrict policy should map directly to the pref.
EXPECT_EQ(youtube_restrict - 1,
prefs->GetInteger(prefs::kForceYouTubeRestrict));
} else {
// The legacy modes should result in MODERATE strictness, if enabled.
safe_search_util::YouTubeRestrictMode expected_mode =
legacy_safe_search_enabled || legacy_youtube_enabled
? safe_search_util::YOUTUBE_RESTRICT_MODERATE
: safe_search_util::YOUTUBE_RESTRICT_OFF;
EXPECT_EQ(prefs->GetInteger(prefs::kForceYouTubeRestrict), expected_mode);
}
}
}
IN_PROC_BROWSER_TEST_F(PolicyTest, ForceGoogleSafeSearch) {
base::Lock lock;
std::set<GURL> google_urls_requested;
content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
[&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
if (params->url_request.url.host() != "google.com")
return false;
base::AutoLock auto_lock(lock);
google_urls_requested.insert(params->url_request.url);
std::string relative_path("chrome/test/data/simple.html");
content::URLLoaderInterceptor::WriteResponse(relative_path,
params->client.get());
return true;
}));
// Verifies that requests to Google Search engine with the SafeSearch
// enabled set the safe=active&ssui=on parameters at the end of the query.
// First check that nothing happens.
CheckSafeSearch(browser(), false);
// Go over all combinations of (undefined, true, false) for the
// ForceGoogleSafeSearch policy.
for (int safe_search = 0; safe_search < 3; safe_search++) {
// Override the Google safe search policy.
ApplySafeSearchPolicy(nullptr, // ForceSafeSearch
safe_search == 0 // ForceGoogleSafeSearch
? nullptr
: std::make_unique<base::Value>(safe_search == 1),
nullptr, // ForceYouTubeSafetyMode
nullptr); // ForceYouTubeRestrict
// Verify that the safe search pref behaves the way we expect.
PrefService* prefs = browser()->profile()->GetPrefs();
EXPECT_EQ(safe_search != 0,
prefs->IsManagedPreference(prefs::kForceGoogleSafeSearch));
EXPECT_EQ(safe_search == 1,
prefs->GetBoolean(prefs::kForceGoogleSafeSearch));
// Verify that safe search actually works.
CheckSafeSearch(browser(), safe_search == 1);
GURL google_url(GetExpectedSearchURL(safe_search == 1));
{
// Verify that the network request is what we expect.
base::AutoLock auto_lock(lock);
ASSERT_TRUE(google_urls_requested.find(google_url) !=
google_urls_requested.end());
google_urls_requested.clear();
}
{
// Now check subresource loads.
FetchSubresource(browser()->tab_strip_model()->GetActiveWebContents(),
GURL("http://google.com/"));
base::AutoLock auto_lock(lock);
ASSERT_TRUE(google_urls_requested.find(google_url) !=
google_urls_requested.end());
}
}
}
IN_PROC_BROWSER_TEST_F(PolicyTest, ForceYouTubeRestrict) {
base::Lock lock;
std::map<GURL, net::HttpRequestHeaders> urls_requested;
content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
[&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
if (params->url_request.url.host() != "youtube.com")
return false;
base::AutoLock auto_lock(lock);
urls_requested[params->url_request.url] = params->url_request.headers;
std::string relative_path("chrome/test/data/simple.html");
content::URLLoaderInterceptor::WriteResponse(relative_path,
params->client.get());
return true;
}));
for (int youtube_restrict_mode = safe_search_util::YOUTUBE_RESTRICT_OFF;
youtube_restrict_mode < safe_search_util::YOUTUBE_RESTRICT_COUNT;
++youtube_restrict_mode) {
ApplySafeSearchPolicy(nullptr, // ForceSafeSearch
nullptr, // ForceGoogleSafeSearch
nullptr, // ForceYouTubeSafetyMode
std::make_unique<base::Value>(youtube_restrict_mode));
{
// First check frame requests.
GURL youtube_url("http://youtube.com");
ui_test_utils::NavigateToURL(browser(), youtube_url);
base::AutoLock auto_lock(lock);
CheckYouTubeRestricted(youtube_restrict_mode, urls_requested,
youtube_url);
}
{
// Now check subresource loads.
GURL youtube_script("http://youtube.com/foo.js");
FetchSubresource(browser()->tab_strip_model()->GetActiveWebContents(),
youtube_script);
base::AutoLock auto_lock(lock);
CheckYouTubeRestricted(youtube_restrict_mode, urls_requested,
youtube_script);
}
}
}
IN_PROC_BROWSER_TEST_F(PolicyTest, AllowedDomainsForApps) {
ASSERT_TRUE(embedded_test_server()->Start());
base::Lock lock;
std::map<GURL, net::HttpRequestHeaders> urls_requested;
content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
[&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
base::AutoLock auto_lock(lock);
urls_requested[params->url_request.url] = params->url_request.headers;
return false;
}));
for (int allowed_domains = 0; allowed_domains < 2; ++allowed_domains) {
std::string allowed_domain;
if (allowed_domains) {
PolicyMap policies;
allowed_domain = "foo.com";
SetPolicy(&policies, key::kAllowedDomainsForApps,
std::make_unique<base::Value>(allowed_domain));
UpdateProviderPolicy(policies);
}
{
// First check frame requests.
GURL google_url =
embedded_test_server()->GetURL("google.com", "/empty.html");
ui_test_utils::NavigateToURL(browser(), google_url);
base::AutoLock auto_lock(lock);
CheckAllowedDomainsHeader(allowed_domain, urls_requested, google_url);
}
{
// Now check subresource loads.
GURL google_script =
embedded_test_server()->GetURL("google.com", "/result_queue.js");
FetchSubresource(browser()->tab_strip_model()->GetActiveWebContents(),
google_script);
base::AutoLock auto_lock(lock);
CheckAllowedDomainsHeader(allowed_domain, urls_requested, google_script);
}
{
// Double check that a frame to a non-Google url doesn't have the header.
GURL non_google_url = embedded_test_server()->GetURL("/empty.html");
ui_test_utils::NavigateToURL(browser(), non_google_url);
base::AutoLock auto_lock(lock);
CheckAllowedDomainsHeader(std::string(), urls_requested, non_google_url);
}
}
}
IN_PROC_BROWSER_TEST_F(PolicyTest, Disable3DAPIs) {
// This test assumes Gpu access.
if (!content::GpuDataManager::GetInstance()->HardwareAccelerationEnabled())
return;
ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
// WebGL is enabled by default.
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(IsWebGLEnabled(contents));
// Disable with a policy.
PolicyMap policies;
policies.Set(key::kDisable3DAPIs, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true),
nullptr);
UpdateProviderPolicy(policies);
// Crash and reload the tab to get a new renderer.
content::CrashTab(contents);
EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_RELOAD));
EXPECT_FALSE(IsWebGLEnabled(contents));
// Enable with a policy.
policies.Set(key::kDisable3DAPIs, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
nullptr);
UpdateProviderPolicy(policies);
content::CrashTab(contents);
EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_RELOAD));
EXPECT_TRUE(IsWebGLEnabled(contents));
}
namespace {
bool GetPacHttpsUrlStrippingEnabled() {
network::mojom::NetworkContextParamsPtr network_context_params =
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams();
return !network_context_params->dangerously_allow_pac_access_to_secure_urls;
}
} // namespace
// Verifies that stripping of https:// URLs before sending to PAC scripts can
// be disabled via a policy. Also verifies that stripping is enabled by
// default.
IN_PROC_BROWSER_TEST_F(PolicyTest, DisablePacHttpsUrlStripping) {
// Stripping is enabled by default.
EXPECT_TRUE(g_browser_process->local_state()->GetBoolean(
prefs::kPacHttpsUrlStrippingEnabled));
EXPECT_TRUE(GetPacHttpsUrlStrippingEnabled());
// Disable it via a policy.
PolicyMap policies;
policies.Set(key::kPacHttpsUrlStrippingEnabled, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::WrapUnique(new base::Value(false)), nullptr);
UpdateProviderPolicy(policies);
content::RunAllPendingInMessageLoop();
// It should now reflect as disabled.
EXPECT_FALSE(g_browser_process->local_state()->GetBoolean(
prefs::kPacHttpsUrlStrippingEnabled));
EXPECT_FALSE(GetPacHttpsUrlStrippingEnabled());
}
IN_PROC_BROWSER_TEST_F(PolicyTest, DeveloperToolsDisabledByLegacyPolicy) {
// Verifies that access to the developer tools can be disabled by setting the
// legacy DeveloperToolsDisabled policy.
// Open devtools.
EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_DEV_TOOLS));
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
DevToolsWindow* devtools_window =
DevToolsWindow::GetInstanceForInspectedWebContents(contents);
EXPECT_TRUE(devtools_window);
// Disable devtools via policy.
PolicyMap policies;
policies.Set(key::kDeveloperToolsDisabled, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(true), nullptr);
content::WindowedNotificationObserver close_observer(
content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
content::Source<content::WebContents>(
DevToolsWindowTesting::Get(devtools_window)->main_web_contents()));
UpdateProviderPolicy(policies);
// wait for devtools close
close_observer.Wait();
// The existing devtools window should have closed.
EXPECT_FALSE(DevToolsWindow::GetInstanceForInspectedWebContents(contents));
// And it's not possible to open it again.
EXPECT_FALSE(chrome::ExecuteCommand(browser(), IDC_DEV_TOOLS));
EXPECT_FALSE(DevToolsWindow::GetInstanceForInspectedWebContents(contents));
}
IN_PROC_BROWSER_TEST_F(PolicyTest,
DeveloperToolsDisabledByDeveloperToolsAvailability) {
// Verifies that access to the developer tools can be disabled by setting the
// DeveloperToolsAvailability policy.
// Open devtools.
EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_DEV_TOOLS));
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
DevToolsWindow* devtools_window =
DevToolsWindow::GetInstanceForInspectedWebContents(contents);
EXPECT_TRUE(devtools_window);
// Disable devtools via policy.
PolicyMap policies;
policies.Set(key::kDeveloperToolsAvailability, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(2 /* DeveloperToolsDisallowed */),
nullptr);
content::WindowedNotificationObserver close_observer(
content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
content::Source<content::WebContents>(
DevToolsWindowTesting::Get(devtools_window)->main_web_contents()));
UpdateProviderPolicy(policies);
// wait for devtools close
close_observer.Wait();
// The existing devtools window should have closed.
EXPECT_FALSE(DevToolsWindow::GetInstanceForInspectedWebContents(contents));
// And it's not possible to open it again.
EXPECT_FALSE(chrome::ExecuteCommand(browser(), IDC_DEV_TOOLS));
EXPECT_FALSE(DevToolsWindow::GetInstanceForInspectedWebContents(contents));
}
namespace {
// Utility for waiting until the dev-mode controls are visible/hidden
// Uses a MutationObserver on the attributes of the DOM element.
void WaitForExtensionsDevModeControlsVisibility(
content::WebContents* contents,
const char* dev_controls_accessor_js,
const char* dev_controls_visibility_check_js,
bool expected_visible) {
bool done = false;
ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
contents,
base::StringPrintf(
"var screenElement = %s;"
"function SendReplyIfAsExpected() {"
" var is_visible = %s;"
" if (is_visible != %s)"
" return false;"
" observer.disconnect();"
" domAutomationController.send(true);"
" return true;"
"}"
"var observer = new MutationObserver(SendReplyIfAsExpected);"
"if (!SendReplyIfAsExpected()) {"
" var options = { 'attributes': true };"
" observer.observe(screenElement, options);"
"}",
dev_controls_accessor_js,
dev_controls_visibility_check_js,
(expected_visible ? "true" : "false")),
&done));
}
} // namespace
IN_PROC_BROWSER_TEST_F(PolicyTest, DeveloperToolsDisabledExtensionsDevMode) {
// Verifies that when DeveloperToolsDisabled policy is set, the "dev mode"
// in chrome://extensions is actively turned off and the checkbox
// is disabled.
// Note: We don't test the indicator as it is tested in the policy pref test
// for kDeveloperToolsDisabled and kDeveloperToolsAvailability.
// This test depends on the following helper methods to locate the DOM elemens
// to be tested.
const char define_helpers_js[] =
R"(function getToolbar() {
const manager = document.querySelector('extensions-manager');
return manager.$$('extensions-toolbar');
}
function getToggle() {
return getToolbar().$.devMode;
}
function getControls() {
return getToolbar().$.devDrawer;
}
)";
const char toggle_dev_mode_accessor_js[] = "getToggle()";
const char dev_controls_accessor_js[] = "getControls()";
const char dev_controls_visibility_check_js[] =
"getControls().hasAttribute('expanded')";
// Navigate to the extensions frame and enabled "Developer mode"
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIExtensionsURL));
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(content::ExecuteScript(contents, std::string(define_helpers_js)));
EXPECT_TRUE(content::ExecuteScript(
contents, base::StringPrintf("domAutomationController.send(%s.click());",
toggle_dev_mode_accessor_js)));
WaitForExtensionsDevModeControlsVisibility(contents, dev_controls_accessor_js,
dev_controls_visibility_check_js,
true);
// Disable devtools via policy.
PolicyMap policies;
policies.Set(key::kDeveloperToolsAvailability, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(2 /*DeveloperToolsDisallowed*/),
nullptr);
UpdateProviderPolicy(policies);
// Expect devcontrols to be hidden now...
WaitForExtensionsDevModeControlsVisibility(contents, dev_controls_accessor_js,
dev_controls_visibility_check_js,
false);
// ... and checkbox is disabled
bool is_toggle_dev_mode_checkbox_disabled = false;
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
contents,
base::StringPrintf(
"domAutomationController.send(%s.hasAttribute('disabled'))",
toggle_dev_mode_accessor_js),
&is_toggle_dev_mode_checkbox_disabled));
EXPECT_TRUE(is_toggle_dev_mode_checkbox_disabled);
}
IN_PROC_BROWSER_TEST_F(PolicyTest, DownloadDirectory) {
// Verifies that the download directory can be forced by policy.
// Don't prompt for the download location during this test.
browser()->profile()->GetPrefs()->SetBoolean(
prefs::kPromptForDownload, false);
base::FilePath initial_dir =
DownloadPrefs(browser()->profile()).DownloadPath();
// Verify that downloads end up on the default directory.
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
DownloadAndVerifyFile(browser(), initial_dir, file);
base::DieFileDie(initial_dir.Append(file), false);
// Override the download directory with the policy and verify a download.
base::FilePath forced_dir = initial_dir.AppendASCII("forced");
PolicyMap policies;
policies.Set(key::kDownloadDirectory, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(forced_dir.value()), nullptr);
UpdateProviderPolicy(policies);
DownloadAndVerifyFile(browser(), forced_dir, file);
// Verify that the first download location wasn't affected.
EXPECT_FALSE(base::PathExists(initial_dir.Append(file)));
}
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionInstallBlacklistSelective) {
// Verifies that blacklisted extensions can't be installed.
extensions::ExtensionService* service = extension_service();
ASSERT_FALSE(service->GetExtensionById(kGoodCrxId, true));
ASSERT_FALSE(service->GetExtensionById(kSimpleWithIconCrxId, true));
base::ListValue blacklist;
blacklist.AppendString(kGoodCrxId);
PolicyMap policies;
policies.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
blacklist.CreateDeepCopy(), nullptr);
UpdateProviderPolicy(policies);
// "good.crx" is blacklisted.
EXPECT_FALSE(InstallExtension(kGoodCrxName));
EXPECT_FALSE(service->GetExtensionById(kGoodCrxId, true));
// "simple_with_icon.crx" is not.
const extensions::Extension* simple_with_icon =
InstallExtension(kSimpleWithIconCrxName);
ASSERT_TRUE(simple_with_icon);
EXPECT_EQ(kSimpleWithIconCrxId, simple_with_icon->id());
EXPECT_EQ(simple_with_icon,
service->GetExtensionById(kSimpleWithIconCrxId, true));
}
// Ensure that bookmark apps are not blocked by the ExtensionInstallBlacklist
// policy.
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionInstallBlacklist_BookmarkApp) {
const extensions::Extension* bookmark_app = InstallBookmarkApp();
ASSERT_TRUE(bookmark_app);
EXPECT_TRUE(InstallExtension(kGoodCrxName));
extensions::ExtensionService* service = extension_service();
EXPECT_TRUE(service->IsExtensionEnabled(kGoodCrxId));
EXPECT_TRUE(service->IsExtensionEnabled(bookmark_app->id()));
// Now set ExtensionInstallBlacklist policy to block all extensions.
PolicyMap policies;
policies.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
extensions::ListBuilder().Append("*").Build(), nullptr);
UpdateProviderPolicy(policies);
// The bookmark app should still be enabled, with |kGoodCrxId| being disabled.
EXPECT_FALSE(service->IsExtensionEnabled(kGoodCrxId));
EXPECT_TRUE(service->IsExtensionEnabled(bookmark_app->id()));
}
// Ensure that bookmark apps are not blocked by the ExtensionAllowedTypes
// policy.
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionAllowedTypes_BookmarkApp) {
const extensions::Extension* bookmark_app = InstallBookmarkApp();
ASSERT_TRUE(bookmark_app);
EXPECT_TRUE(InstallExtension(kGoodCrxName));
extensions::ExtensionService* service = extension_service();
EXPECT_TRUE(service->IsExtensionEnabled(kGoodCrxId));
EXPECT_TRUE(service->IsExtensionEnabled(bookmark_app->id()));
// Now set policy to only allow themes. Note: Bookmark apps are hosted
// apps.
PolicyMap policies;
policies.Set(key::kExtensionAllowedTypes, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
extensions::ListBuilder().Append("theme").Build(), nullptr);
UpdateProviderPolicy(policies);
// The bookmark app should still be enabled, with |kGoodCrxId| being disabled.
EXPECT_FALSE(service->IsExtensionEnabled(kGoodCrxId));
EXPECT_TRUE(service->IsExtensionEnabled(bookmark_app->id()));
}
// Ensure that bookmark apps are not blocked by the ExtensionSettings
// policy.
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionSettings_BookmarkApp) {
const extensions::Extension* bookmark_app = InstallBookmarkApp();
ASSERT_TRUE(bookmark_app);
EXPECT_TRUE(InstallExtension(kGoodCrxName));
extensions::ExtensionService* service = extension_service();
EXPECT_TRUE(service->IsExtensionEnabled(kGoodCrxId));
EXPECT_TRUE(service->IsExtensionEnabled(bookmark_app->id()));
// Now set policy to block all extensions.
PolicyMap policies;
policies.Set(key::kExtensionSettings, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
extensions::DictionaryBuilder()
.Set("*", extensions::DictionaryBuilder()
.Set("installation_mode", "blocked")
.Build())
.Build(),
nullptr);
UpdateProviderPolicy(policies);
// The bookmark app should still be enabled, with |kGoodCrxId| being disabled.
EXPECT_FALSE(service->IsExtensionEnabled(kGoodCrxId));
EXPECT_TRUE(service->IsExtensionEnabled(bookmark_app->id()));
// Clear all policies.
policies.Clear();
UpdateProviderPolicy(policies);
EXPECT_TRUE(service->IsExtensionEnabled(kGoodCrxId));
EXPECT_TRUE(service->IsExtensionEnabled(bookmark_app->id()));
// Now set policy to only allow themes. Note: Bookmark apps are hosted
// apps.
policies.Set(
key::kExtensionSettings, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD,
extensions::DictionaryBuilder()
.Set("*", extensions::DictionaryBuilder()
.Set("allowed_types",
extensions::ListBuilder().Append("theme").Build())
.Build())
.Build(),
nullptr);
UpdateProviderPolicy(policies);
// The bookmark app should still be enabled, with |kGoodCrxId| being disabled.
EXPECT_FALSE(service->IsExtensionEnabled(kGoodCrxId));
EXPECT_TRUE(service->IsExtensionEnabled(bookmark_app->id()));
}
// Flaky on windows; http://crbug.com/307994.
#if defined(OS_WIN)
#define MAYBE_ExtensionInstallBlacklistWildcard DISABLED_ExtensionInstallBlacklistWildcard
#else
#define MAYBE_ExtensionInstallBlacklistWildcard ExtensionInstallBlacklistWildcard
#endif
IN_PROC_BROWSER_TEST_F(PolicyTest, MAYBE_ExtensionInstallBlacklistWildcard) {
// Verify that a wildcard blacklist takes effect.
EXPECT_TRUE(InstallExtension(kSimpleWithIconCrxName));
extensions::ExtensionService* service = extension_service();
ASSERT_FALSE(service->GetExtensionById(kGoodCrxId, true));
ASSERT_TRUE(service->GetExtensionById(kSimpleWithIconCrxId, true));
base::ListValue blacklist;
blacklist.AppendString("*");
PolicyMap policies;
policies.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
blacklist.CreateDeepCopy(), nullptr);
UpdateProviderPolicy(policies);
// "simple_with_icon" should be disabled.
EXPECT_TRUE(service->GetExtensionById(kSimpleWithIconCrxId, true));
EXPECT_FALSE(service->IsExtensionEnabled(kSimpleWithIconCrxId));
// It shouldn't be possible to re-enable "simple_with_icon", until it
// satisfies management policy.
service->EnableExtension(kSimpleWithIconCrxId);
EXPECT_FALSE(service->IsExtensionEnabled(kSimpleWithIconCrxId));
// It shouldn't be possible to install good.crx.
EXPECT_FALSE(InstallExtension(kGoodCrxName));
EXPECT_FALSE(service->GetExtensionById(kGoodCrxId, true));
}
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionInstallBlacklistSharedModules) {
// Verifies that shared_modules are not affected by the blacklist.
base::FilePath base_path;
GetTestDataDirectory(&base_path);
base::FilePath update_xml_template_path =
base_path.Append(kTestExtensionsDir)
.AppendASCII("policy_shared_module")
.AppendASCII("update_template.xml");
std::string update_xml_path =
"/" + base::FilePath(kTestExtensionsDir).MaybeAsASCII() +
"/policy_shared_module/gen_update.xml";
RegisterURLReplacingHandler(embedded_test_server(), update_xml_path,
update_xml_template_path);
ASSERT_TRUE(embedded_test_server()->Start());
const char kImporterId[] = "pchakhniekfaeoddkifplhnfbffomabh";
const char kSharedModuleId[] = "nfgclafboonjbiafbllihiailjlhelpm";
// Make sure that "import" and "export" are available to these extension IDs
// by mocking the release channel.
extensions::ScopedCurrentChannel channel(version_info::Channel::DEV);
// Verify that the extensions are not installed initially.
extensions::ExtensionService* service = extension_service();
ASSERT_FALSE(service->GetExtensionById(kImporterId, true));
ASSERT_FALSE(service->GetExtensionById(kSharedModuleId, true));
// Mock the webstore update URL. This is where the shared module extension
// will be installed from.
GURL update_xml_url = embedded_test_server()->GetURL(update_xml_path);
extension_test_util::SetGalleryUpdateURL(update_xml_url);
ui_test_utils::NavigateToURL(browser(), update_xml_url);
// Blacklist "*" but force-install the importer extension. The shared module
// should be automatically installed too.
base::ListValue blacklist;
blacklist.AppendString("*");
base::ListValue forcelist;
forcelist.AppendString(
base::StringPrintf("%s;%s", kImporterId, update_xml_url.spec().c_str()));
PolicyMap policies;
policies.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
blacklist.CreateDeepCopy(), nullptr);
policies.Set(key::kExtensionInstallForcelist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
forcelist.CreateDeepCopy(), nullptr);
extensions::ExtensionRegistry* registry =
extensions::ExtensionRegistry::Get(browser()->profile());
extensions::TestExtensionRegistryObserver observe_importer(
registry, kImporterId);
extensions::TestExtensionRegistryObserver observe_shared_module(
registry, kSharedModuleId);
UpdateProviderPolicy(policies);
observe_importer.WaitForExtensionLoaded();
observe_shared_module.WaitForExtensionLoaded();
// Verify that both extensions got installed.
const extensions::Extension* importer =
service->GetExtensionById(kImporterId, true);
ASSERT_TRUE(importer);
EXPECT_EQ(kImporterId, importer->id());
const extensions::Extension* shared_module =
service->GetExtensionById(kSharedModuleId, true);
ASSERT_TRUE(shared_module);
EXPECT_EQ(kSharedModuleId, shared_module->id());
EXPECT_TRUE(shared_module->is_shared_module());
// Verify the dependency.
std::unique_ptr<extensions::ExtensionSet> set =
service->shared_module_service()->GetDependentExtensions(shared_module);
ASSERT_TRUE(set);
EXPECT_EQ(1u, set->size());
EXPECT_TRUE(set->Contains(importer->id()));
std::vector<extensions::SharedModuleInfo::ImportInfo> imports =
extensions::SharedModuleInfo::GetImports(importer);
ASSERT_EQ(1u, imports.size());
EXPECT_EQ(kSharedModuleId, imports[0].extension_id);
}
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionInstallWhitelist) {
// Verifies that the whitelist can open exceptions to the blacklist.
extensions::ExtensionService* service = extension_service();
ASSERT_FALSE(service->GetExtensionById(kGoodCrxId, true));
ASSERT_FALSE(service->GetExtensionById(kSimpleWithIconCrxId, true));
base::ListValue blacklist;
blacklist.AppendString("*");
base::ListValue whitelist;
whitelist.AppendString(kGoodCrxId);
PolicyMap policies;
policies.Set(key::kExtensionInstallBlacklist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
blacklist.CreateDeepCopy(), nullptr);
policies.Set(key::kExtensionInstallWhitelist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
whitelist.CreateDeepCopy(), nullptr);
UpdateProviderPolicy(policies);
// "simple_with_icon.crx" is blacklisted.
EXPECT_FALSE(InstallExtension(kSimpleWithIconCrxName));
EXPECT_FALSE(service->GetExtensionById(kSimpleWithIconCrxId, true));
// "good.crx" has a whitelist exception.
const extensions::Extension* good = InstallExtension(kGoodCrxName);
ASSERT_TRUE(good);
EXPECT_EQ(kGoodCrxId, good->id());
EXPECT_EQ(good, service->GetExtensionById(kGoodCrxId, true));
// The user can also remove this extension.
UninstallExtension(kGoodCrxId, true);
}
namespace {
class ExtensionRequestInterceptor {
public:
ExtensionRequestInterceptor()
: interceptor_(
base::BindRepeating(&ExtensionRequestInterceptor::OnRequest,
base::Unretained(this))) {}
void set_interceptor_hook(
content::URLLoaderInterceptor::InterceptCallback callback) {
callback_ = std::move(callback);
}
private:
bool OnRequest(content::URLLoaderInterceptor::RequestParams* params) {
if (callback_ && callback_.Run(params))
return true;
// Mock out requests to the Web Store.
if (params->url_request.url.host() == "clients2.google.com" &&
params->url_request.url.path() == "/service/update2/crx") {
content::URLLoaderInterceptor::WriteResponse(
"chrome/test/data/extensions/good2_update_manifest.xml",
params->client.get());
return true;
}
if (params->url_request.url.path() == "/good_update_manifest.xml") {
content::URLLoaderInterceptor::WriteResponse(
"chrome/test/data/extensions/good2_update_manifest.xml",
params->client.get());
return true;
}
if (params->url_request.url.path() == "/extensions/good_v1.crx") {
content::URLLoaderInterceptor::WriteResponse(
"chrome/test/data/extensions/good_v1.crx", params->client.get());
return true;
}
if (params->url_request.url.path() == "/extensions/good2.crx") {
content::URLLoaderInterceptor::WriteResponse(
"chrome/test/data/extensions/good2.crx", params->client.get());
return true;
}
return false;
}
content::URLLoaderInterceptor::InterceptCallback callback_;
content::URLLoaderInterceptor interceptor_;
};
} // namespace
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionInstallForcelist) {
// Verifies that extensions that are force-installed by policies are
// installed and can't be uninstalled.
ExtensionRequestInterceptor interceptor;
extensions::ExtensionService* service = extension_service();
ASSERT_FALSE(service->GetExtensionById(kGoodCrxId, true));
// Extensions that are force-installed come from an update URL, which defaults
// to the webstore. Use a test URL for this test with an update manifest
// that includes "good_v1.crx".
embedded_test_server()->AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
ASSERT_TRUE(embedded_test_server()->Start());
GURL url =
embedded_test_server()->GetURL("/extensions/good_v1_update_manifest.xml");
// Setting the forcelist extension should install "good_v1.crx".
base::ListValue forcelist;
forcelist.AppendString(
base::StringPrintf("%s;%s", kGoodCrxId, url.spec().c_str()));
PolicyMap policies;
policies.Set(key::kExtensionInstallForcelist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
forcelist.CreateDeepCopy(), nullptr);
extensions::TestExtensionRegistryObserver observer(
extensions::ExtensionRegistry::Get(browser()->profile()));
UpdateProviderPolicy(policies);
observer.WaitForExtensionWillBeInstalled();
// Note: Cannot check that the notification details match the expected
// exception, since the details object has already been freed prior to
// the completion of observer.WaitForExtensionWillBeInstalled().
EXPECT_TRUE(service->GetExtensionById(kGoodCrxId, true));
// The user is not allowed to uninstall force-installed extensions.
UninstallExtension(kGoodCrxId, false);
scoped_refptr<extensions::UnpackedInstaller> installer =
extensions::UnpackedInstaller::Create(extension_service());
// The user is not allowed to load an unpacked extension with the
// same ID as a force-installed extension.
base::FilePath good_extension_path(ui_test_utils::GetTestFilePath(
base::FilePath(kTestExtensionsDir), base::FilePath(kSimpleWithPopupExt)));
content::WindowedNotificationObserver extension_load_error_observer(
extensions::NOTIFICATION_EXTENSION_LOAD_ERROR,
content::NotificationService::AllSources());
installer->Load(good_extension_path);
extension_load_error_observer.Wait();
// Loading other unpacked extensions are not blocked.
scoped_refptr<const extensions::Extension> extension =
LoadUnpackedExtension(kAppUnpackedExt);
ASSERT_TRUE(extension);
const std::string old_version_number =
service->GetExtensionById(kGoodCrxId, true)->version().GetString();
content::WindowedNotificationObserver new_process_observer(
content::NOTIFICATION_RENDERER_PROCESS_CREATED,
content::NotificationService::AllSources());
// Updating the force-installed extension.
extensions::ExtensionUpdater* updater = service->updater();
extensions::ExtensionUpdater::CheckParams params;
params.install_immediately = true;
extensions::TestExtensionRegistryObserver update_observer(
extensions::ExtensionRegistry::Get(browser()->profile()));
updater->CheckNow(std::move(params));
update_observer.WaitForExtensionWillBeInstalled();
const base::Version& new_version =
service->GetExtensionById(kGoodCrxId, true)->version();
ASSERT_TRUE(new_version.IsValid());
base::Version old_version(old_version_number);
ASSERT_TRUE(old_version.IsValid());
EXPECT_EQ(1, new_version.CompareTo(old_version));
// Wait for the new extension process to launch.
new_process_observer.Wait();
// Wait until any background pages belonging to force-installed extensions
// have been loaded.
extensions::ProcessManager* manager =
extensions::ProcessManager::Get(browser()->profile());
extensions::ProcessManager::FrameSet all_frames = manager->GetAllFrames();
for (auto iter = all_frames.begin(); iter != all_frames.end();) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(*iter);
ASSERT_TRUE(web_contents);
if (!web_contents->IsLoading()) {
++iter;
} else {
WebContentsLoadedOrDestroyedWatcher(web_contents).Wait();
// Test activity may have modified the set of extension processes during
// message processing, so re-start the iteration to catch added/removed
// processes.
all_frames = manager->GetAllFrames();
iter = all_frames.begin();
}
}
// Test policy-installed extensions are reloaded when killed.
BackgroundContentsService::
SetRestartDelayForForceInstalledAppsAndExtensionsForTesting(0);
content::WindowedNotificationObserver extension_crashed_observer(
extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
content::NotificationService::AllSources());
extensions::TestExtensionRegistryObserver extension_loaded_observer(
extensions::ExtensionRegistry::Get(browser()->profile()), kGoodCrxId);
extensions::ExtensionHost* extension_host =
extensions::ProcessManager::Get(browser()->profile())
->GetBackgroundHostForExtension(kGoodCrxId);
extension_host->render_process_host()->Shutdown(content::RESULT_CODE_KILLED);
extension_crashed_observer.Wait();
extension_loaded_observer.WaitForExtensionLoaded();
}
IN_PROC_BROWSER_TEST_F(PolicyTest,
ExtensionInstallForcelist_DefaultedUpdateUrl) {
// Verifies the ExtensionInstallForcelist policy with an empty (defaulted)
// "update" URL.
ExtensionRequestInterceptor interceptor;
extensions::ExtensionService* service = extension_service();
ASSERT_FALSE(service->GetExtensionById(kGoodCrxId, true));
// Setting the forcelist extension should install "good_v1.crx".
base::ListValue forcelist;
forcelist.AppendString(kGoodCrxId);
PolicyMap policies;
policies.Set(key::kExtensionInstallForcelist, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
forcelist.CreateDeepCopy(), nullptr);
extensions::TestExtensionRegistryObserver observer(
extensions::ExtensionRegistry::Get(browser()->profile()));
UpdateProviderPolicy(policies);
observer.WaitForExtensionWillBeInstalled();
EXPECT_TRUE(service->GetExtensionById(kGoodCrxId, true));
}
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionRecommendedInstallationMode) {
// Verifies that extensions that are recommended-installed by policies are
// installed, can be disabled but not uninstalled.
ExtensionRequestInterceptor interceptor;
// Extensions that are force-installed come from an update URL, which defaults
// to the webstore. Use a test URL for this test with an update manifest
// that includes "good_v1.crx".
embedded_test_server()->AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
ASSERT_TRUE(embedded_test_server()->Start());
GURL url =
embedded_test_server()->GetURL("/extensions/good_v1_update_manifest.xml");
// Mark as enterprise managed.
#if defined(OS_WIN)
base::win::ScopedDomainStateForTesting scoped_domain(true);
#endif
extensions::ExtensionService* service = extension_service();
ASSERT_FALSE(service->GetExtensionById(kGoodCrxId, true));
// Setting the forcelist extension should install "good_v1.crx".
base::DictionaryValue dict_value;
dict_value.SetString(std::string(kGoodCrxId) + "." +
extensions::schema_constants::kInstallationMode,
extensions::schema_constants::kNormalInstalled);
dict_value.SetString(
std::string(kGoodCrxId) + "." + extensions::schema_constants::kUpdateUrl,
url.spec());
PolicyMap policies;
policies.Set(key::kExtensionSettings, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
dict_value.CreateDeepCopy(), nullptr);
extensions::TestExtensionRegistryObserver observer(
extensions::ExtensionRegistry::Get(browser()->profile()));
UpdateProviderPolicy(policies);
observer.WaitForExtensionWillBeInstalled();
EXPECT_TRUE(service->GetExtensionById(kGoodCrxId, true));
// The user is not allowed to uninstall recommended-installed extensions.
UninstallExtension(kGoodCrxId, false);
// Explictly re-enables the extension.
service->EnableExtension(kGoodCrxId);
// But the user is allowed to disable them.
EXPECT_TRUE(service->IsExtensionEnabled(kGoodCrxId));
DisableExtension(kGoodCrxId);
EXPECT_FALSE(service->IsExtensionEnabled(kGoodCrxId));
}
IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionAllowedTypes) {
// Verifies that extensions are blocked if policy specifies an allowed types
// list and the extension's type is not on that list.
extensions::ExtensionService* service = extension_service();
ASSERT_FALSE(service->GetExtensionById(kGoodCrxId, true));
ASSERT_FALSE(service->GetExtensionById(kHostedAppCrxId, true));
base::ListValue allowed_types;
allowed_types.AppendString("hosted_app");
PolicyMap policies;
policies.Set(key::kExtensionAllowedTypes, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
allowed_types.CreateDeepCopy(), nullptr);
UpdateProviderPolicy(policies);
// "good.crx" is blocked.
EXPECT_FALSE(InstallExtension(kGoodCrxName));
EXPECT_FALSE(service->GetExtensionById(