Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5779)

Unified Diff: chrome/browser/chromeos/policy/device_local_account_browsertest.cc

Issue 24261010: Allow explicitly whitelisted apps/extensions in public sessions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix handing of guest user ID. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/policy/device_local_account_browsertest.cc
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 59eb85be77a6a69c85f3d90b8e037f88261c3301..aae8978aa6fd4d78bbbd39ae373eb297629a5557 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/file_util.h"
@@ -17,6 +18,7 @@
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
@@ -33,6 +35,8 @@
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_policy_builder.h"
#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
#include "chrome/browser/policy/cloud/policy_builder.h"
@@ -52,11 +56,14 @@
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_method_call_status.h"
#include "chromeos/dbus/fake_session_manager_client.h"
#include "chromeos/dbus/session_manager_client.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/test/browser_test_utils.h"
@@ -64,7 +71,11 @@
#include "crypto/rsa_private_key.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
+#include "net/base/url_util.h"
+#include "net/http/http_status_code.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 "testing/gmock/include/gmock/gmock.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/l10n/l10n_util.h"
@@ -90,6 +101,129 @@ const char* kStartupURLs[] = {
};
const char kExistentTermsOfServicePath[] = "chromeos/enterprise/tos.txt";
const char kNonexistentTermsOfServicePath[] = "chromeos/enterprise/tos404.txt";
+const char kRelativeUpdateURL[] = "/service/update2/crx";
+const char kUpdateManifestHeader[] =
+ "<?xml version='1.0' encoding='UTF-8'?>\n"
+ "<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>\n";
+const char kUpdateManifestTemplate[] =
+ " <app appid='%s'>\n"
+ " <updatecheck codebase='%s' version='%s' />\n"
+ " </app>\n";
+const char kUpdateManifestFooter[] =
+ "</gupdate>\n";
+const char kHostedAppID[] = "kbmnembihfiondgfjekmnmcbddelicoi";
+const char kHostedAppCRXPath[] = "extensions/hosted_app.crx";
+const char kHostedAppVersion[] = "0.1";
+const char kGoodExtensionID[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
+const char kGoodExtensionPath[] = "extensions/good.crx";
+const char kGoodExtensionVersion[] = "1.0";
+
+// Helper that serves extension update manifests to Chrome.
+class TestingUpdateManifestProvider {
+ public:
+
+ // Update manifests will be served at |relative_update_url|.
+ explicit TestingUpdateManifestProvider(
+ const std::string& relative_update_url);
+ ~TestingUpdateManifestProvider();
+
+ // When an update manifest is requested for the given extension |id|, indicate
+ // that |version| of the extension can be downloaded at |crx_url|.
+ void AddUpdate(const std::string& id,
+ const std::string& version,
+ const GURL& crx_url);
+
+ // This method must be registered with the test's EmbeddedTestServer to start
+ // serving update manifests.
+ scoped_ptr<net::test_server::HttpResponse> HandleRequest(
+ const net::test_server::HttpRequest& request);
+
+ private:
+ struct Update {
+ public:
+ Update(const std::string& version, const GURL& crx_url);
+ Update();
+
+ std::string version;
+ GURL crx_url;
+ };
+ typedef std::map<std::string, Update> UpdateMap;
+ UpdateMap updates_;
+
+ const std::string relative_update_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestingUpdateManifestProvider);
+};
+
+TestingUpdateManifestProvider::Update::Update(const std::string& version,
+ const GURL& crx_url)
+ : version(version),
+ crx_url(crx_url) {
+}
+
+TestingUpdateManifestProvider::Update::Update() {
+}
+
+TestingUpdateManifestProvider::TestingUpdateManifestProvider(
+ const std::string& relative_update_url)
+ : relative_update_url_(relative_update_url) {
+}
+
+TestingUpdateManifestProvider::~TestingUpdateManifestProvider() {
+}
+
+void TestingUpdateManifestProvider::AddUpdate(const std::string& id,
+ const std::string& version,
+ const GURL& crx_url) {
+ updates_[id] = Update(version, crx_url);
+}
+
+scoped_ptr<net::test_server::HttpResponse>
+ TestingUpdateManifestProvider::HandleRequest(
+ const net::test_server::HttpRequest& request) {
+ const GURL url("http://localhost" + request.relative_url);
+ if (url.path() != relative_update_url_)
+ return scoped_ptr<net::test_server::HttpResponse>();
+
+ std::string content = kUpdateManifestHeader;
+ for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
+ if (it.GetKey() != "x")
+ continue;
+ // Extract the extension id from the subquery. Since GetValueForKeyInQuery()
+ // expects a complete URL, dummy scheme and host must be prepended.
+ std::string id;
+ net::GetValueForKeyInQuery(GURL("http://dummy?" + it.GetUnescapedValue()),
+ "id", &id);
+ UpdateMap::const_iterator entry = updates_.find(id);
+ if (entry != updates_.end()) {
+ content += base::StringPrintf(kUpdateManifestTemplate,
+ id.c_str(),
+ entry->second.crx_url.spec().c_str(),
+ entry->second.version.c_str());
+ }
+ }
+ content += kUpdateManifestFooter;
+ scoped_ptr<net::test_server::BasicHttpResponse>
+ http_response(new net::test_server::BasicHttpResponse);
+ http_response->set_code(net::HTTP_OK);
+ http_response->set_content(content);
+ http_response->set_content_type("text/xml");
+ return http_response.PassAs<net::test_server::HttpResponse>();
+}
+
+bool DoesInstallSuccessReferToId(const std::string& id,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ return content::Details<const extensions::InstalledExtensionInfo>(details)->
+ extension->id() == id;
+}
+
+bool DoesInstallFailureReferToId(const std::string& id,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ return content::Details<const string16>(details)->find(UTF8ToUTF16(id)) !=
+ string16::npos;
+}
} // namespace
@@ -420,6 +554,92 @@ IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, FullscreenDisallowed) {
EXPECT_FALSE(browser_window->IsFullscreen());
}
+IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExtensionWhitelist) {
+ // Make it possible to force-install a hosted app and an extension.
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ TestingUpdateManifestProvider testing_update_manifest_provider(
+ kRelativeUpdateURL);
+ testing_update_manifest_provider.AddUpdate(
+ kHostedAppID,
+ kHostedAppVersion,
+ embedded_test_server()->GetURL(std::string("/") + kHostedAppCRXPath));
+ testing_update_manifest_provider.AddUpdate(
+ kGoodExtensionID,
+ kGoodExtensionVersion,
+ embedded_test_server()->GetURL(std::string("/") + kGoodExtensionPath));
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&TestingUpdateManifestProvider::HandleRequest,
+ base::Unretained(&testing_update_manifest_provider)));
+
+ // Specify policy to force-install the hosted app and the extension.
+ em::StringList* forcelist = device_local_account_policy_.payload()
+ .mutable_extensioninstallforcelist()->mutable_value();
+ forcelist->add_entries(base::StringPrintf(
+ "%s;%s",
+ kHostedAppID,
+ embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
+ forcelist->add_entries(base::StringPrintf(
+ "%s;%s",
+ kGoodExtensionID,
+ embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
+
+ UploadAndInstallDeviceLocalAccountPolicy();
+ AddPublicSessionToDevicePolicy(kAccountId1);
+
+ // This observes the display name becoming available as this indicates
+ // device-local account policy is fully loaded, which is a prerequisite for
+ // successful login.
+ content::WindowedNotificationObserver(
+ chrome::NOTIFICATION_USER_LIST_CHANGED,
+ base::Bind(&DisplayNameMatches, user_id_1_, kDisplayName)).Wait();
+
+ // Wait for the login UI to be ready.
+ chromeos::LoginDisplayHostImpl* host =
+ reinterpret_cast<chromeos::LoginDisplayHostImpl*>(
+ chromeos::LoginDisplayHostImpl::default_host());
+ ASSERT_TRUE(host);
+ chromeos::OobeUI* oobe_ui = host->GetOobeUI();
+ ASSERT_TRUE(oobe_ui);
+ base::RunLoop run_loop;
+ const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure());
+ if (!oobe_ui_ready)
+ run_loop.Run();
+
+ // Ensure that the browser stays alive, even though no windows are opened
+ // during session start.
+ chrome::StartKeepAlive();
+
+ // Start listening for app/extension installation results.
+ content::WindowedNotificationObserver hosted_app_observer(
+ chrome::NOTIFICATION_EXTENSION_INSTALLED,
+ base::Bind(DoesInstallSuccessReferToId, kHostedAppID));
+ content::WindowedNotificationObserver extension_observer(
+ chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
+ base::Bind(DoesInstallFailureReferToId, kGoodExtensionID));
+
+ // Start login into the device-local account.
+ host->StartSignInScreen();
+ chromeos::ExistingUserController* controller =
+ chromeos::ExistingUserController::current_controller();
+ ASSERT_TRUE(controller);
+ controller->LoginAsPublicAccount(user_id_1_);
+
+ // Wait for the hosted app installation to succeed and the extension
+ // installation to fail.
+ hosted_app_observer.Wait();
+ extension_observer.Wait();
+
+ // Verify that the hosted app was installed.
+ Profile* profile = ProfileManager::GetDefaultProfile();
+ ASSERT_TRUE(profile);
+ ExtensionService* extension_service =
+ extensions::ExtensionSystem::Get(profile)->extension_service();
+ EXPECT_TRUE(extension_service->GetExtensionById(kHostedAppID, true));
+
+ // Verify that the extension was not installed.
+ EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
+}
+
class TermsOfServiceTest : public DeviceLocalAccountTest,
public testing::WithParamInterface<bool> {
};

Powered by Google App Engine
This is Rietveld 408576698