Cache force-installed apps/extensions in device-local accounts

This CL adds the DeviceLocalAccountExternalPolicyLoader, a replacement for
the ExternalPolicyLoader that caches force-installed apps/extensions,
allowing them to be installed offline. The caches for individual accounts
are managed by the DeviceLocalAccountPolicyService which makes sure to
remove obsolete cache directories.

BUG=287802
TEST=Full coverage with new browser and unit tests
NOTRY=true

Review URL: https://codereview.chromium.org/27548004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229912 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc
index 20a72b88..df29f6ac 100644
--- a/chrome/browser/extensions/external_provider_impl.cc
+++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -34,9 +34,13 @@
 #include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
 #include "chrome/browser/chromeos/extensions/external_pref_cache_loader.h"
+#include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/policy/app_pack_updater.h"
+#include "chrome/browser/chromeos/policy/device_local_account.h"
+#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
 #include "chrome/browser/policy/browser_policy_connector.h"
 #else
 #include "chrome/browser/extensions/default_apps.h"
@@ -61,12 +65,13 @@
 const char ExternalProviderImpl::kRequirePermissionsConsent[] =
     "require_permissions_consent";
 
-ExternalProviderImpl::ExternalProviderImpl(VisitorInterface* service,
-                                           ExternalLoader* loader,
-                                           Profile* profile,
-                                           Manifest::Location crx_location,
-                                           Manifest::Location download_location,
-                                           int creation_flags)
+ExternalProviderImpl::ExternalProviderImpl(
+    VisitorInterface* service,
+    const scoped_refptr<ExternalLoader>& loader,
+    Profile* profile,
+    Manifest::Location crx_location,
+    Manifest::Location download_location,
+    int creation_flags)
     : crx_location_(crx_location),
       download_location_(download_location),
       service_(service),
@@ -346,16 +351,41 @@
     VisitorInterface* service,
     Profile* profile,
     ProviderCollection* provider_list) {
+  scoped_refptr<ExternalLoader> external_loader;
+  extensions::Manifest::Location crx_location = Manifest::INVALID_LOCATION;
+#if defined(OS_CHROMEOS)
+  const chromeos::User* user =
+      chromeos::UserManager::Get()->GetUserByProfile(profile);
+  if (user && policy::IsDeviceLocalAccountUser(user->email(), NULL)) {
+    policy::DeviceLocalAccountPolicyBroker* broker =
+        g_browser_process->browser_policy_connector()->
+            GetDeviceLocalAccountPolicyService()->
+                GetBrokerForUser(user->email());
+    if (broker) {
+      external_loader = broker->extension_loader();
+      crx_location = Manifest::EXTERNAL_POLICY;
+    } else {
+      NOTREACHED();
+    }
+  } else {
+    external_loader = new ExternalPolicyLoader(profile);
+  }
+#else
+  external_loader = new ExternalPolicyLoader(profile);
+#endif
+
   // Policies are mandatory so they can't be skipped with command line flag.
-  provider_list->push_back(
-      linked_ptr<ExternalProviderInterface>(
-          new ExternalProviderImpl(
-              service,
-              new ExternalPolicyLoader(profile),
-              profile,
-              Manifest::INVALID_LOCATION,
-              Manifest::EXTERNAL_POLICY_DOWNLOAD,
-              Extension::NO_FLAGS)));
+  if (external_loader) {
+    provider_list->push_back(
+        linked_ptr<ExternalProviderInterface>(
+            new ExternalProviderImpl(
+                service,
+                external_loader,
+                profile,
+                crx_location,
+                Manifest::EXTERNAL_POLICY_DOWNLOAD,
+                Extension::NO_FLAGS)));
+  }
 
   // In tests don't install extensions from default external sources.
   // It would only slowdown tests and make them flaky.