Bundle core applicatons in the shell.

For release and official build, core mojo applicatons are bundled in the
shell.

This allows to greatly reduce the time needed for the first run. After
this, application are updated from the network.

R=etiennej@chromium.org

Review URL: https://codereview.chromium.org/1364243002 .
diff --git a/services/url_response_disk_cache/BUILD.gn b/services/url_response_disk_cache/BUILD.gn
index bb0bb87..2adba41 100644
--- a/services/url_response_disk_cache/BUILD.gn
+++ b/services/url_response_disk_cache/BUILD.gn
@@ -21,6 +21,7 @@
   sources = [
     "url_response_disk_cache_app.cc",
     "url_response_disk_cache_app.h",
+    "url_response_disk_cache_delegate.h",
     "url_response_disk_cache_impl.cc",
     "url_response_disk_cache_impl.h",
   ]
diff --git a/services/url_response_disk_cache/url_response_disk_cache_app.cc b/services/url_response_disk_cache/url_response_disk_cache_app.cc
index 67632ae..ba7b456 100644
--- a/services/url_response_disk_cache/url_response_disk_cache_app.cc
+++ b/services/url_response_disk_cache/url_response_disk_cache_app.cc
@@ -10,8 +10,9 @@
 namespace mojo {
 
 URLResponseDiskCacheApp::URLResponseDiskCacheApp(
-    scoped_refptr<base::TaskRunner> task_runner)
-    : task_runner_(task_runner) {}
+    scoped_refptr<base::TaskRunner> task_runner,
+    URLResponseDiskCacheDelegate* delegate)
+    : task_runner_(task_runner), delegate_(delegate) {}
 
 URLResponseDiskCacheApp::~URLResponseDiskCacheApp() {
 }
@@ -31,8 +32,9 @@
 void URLResponseDiskCacheApp::Create(
     ApplicationConnection* connection,
     InterfaceRequest<URLResponseDiskCache> request) {
-  new URLResponseDiskCacheImpl(
-      task_runner_, db_, connection->GetRemoteApplicationURL(), request.Pass());
+  new URLResponseDiskCacheImpl(task_runner_, delegate_, db_,
+                               connection->GetRemoteApplicationURL(),
+                               request.Pass());
 }
 
 }  // namespace mojo
diff --git a/services/url_response_disk_cache/url_response_disk_cache_app.h b/services/url_response_disk_cache/url_response_disk_cache_app.h
index 47c0dd4..5f5a701 100644
--- a/services/url_response_disk_cache/url_response_disk_cache_app.h
+++ b/services/url_response_disk_cache/url_response_disk_cache_app.h
@@ -15,13 +15,15 @@
 #include "mojo/public/cpp/application/interface_factory.h"
 #include "mojo/services/url_response_disk_cache/public/interfaces/url_response_disk_cache.mojom.h"
 #include "services/url_response_disk_cache/url_response_disk_cache_db.h"
+#include "services/url_response_disk_cache/url_response_disk_cache_delegate.h"
 
 namespace mojo {
 
 class URLResponseDiskCacheApp : public ApplicationDelegate,
                                 public InterfaceFactory<URLResponseDiskCache> {
  public:
-  explicit URLResponseDiskCacheApp(scoped_refptr<base::TaskRunner> task_runner);
+  explicit URLResponseDiskCacheApp(scoped_refptr<base::TaskRunner> task_runner,
+                                   URLResponseDiskCacheDelegate* delegate);
   ~URLResponseDiskCacheApp() override;
 
  private:
@@ -35,6 +37,7 @@
 
   scoped_refptr<base::TaskRunner> task_runner_;
   scoped_refptr<URLResponseDiskCacheDB> db_;
+  URLResponseDiskCacheDelegate* delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(URLResponseDiskCacheApp);
 };
diff --git a/services/url_response_disk_cache/url_response_disk_cache_delegate.h b/services/url_response_disk_cache/url_response_disk_cache_delegate.h
new file mode 100644
index 0000000..5f8777c
--- /dev/null
+++ b/services/url_response_disk_cache/url_response_disk_cache_delegate.h
@@ -0,0 +1,39 @@
+// Copyright 2015 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.
+
+#ifndef SERVICES_URL_RESPONSE_DISK_CACHE_URL_RESPONSE_DISK_CACHE_DELEGATE_H_
+#define SERVICES_URL_RESPONSE_DISK_CACHE_URL_RESPONSE_DISK_CACHE_DELEGATE_H_
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/task_runner.h"
+
+namespace mojo {
+
+// This class allows to customized the behavior of the |URLResponseDiskCache|
+// implementation.
+class URLResponseDiskCacheDelegate {
+ public:
+  URLResponseDiskCacheDelegate() {}
+  virtual ~URLResponseDiskCacheDelegate() {}
+
+  // Allows to prefill the cache with content. This method will be called by the
+  // cache when an item that has never been in the cache is requested.
+  // |task_runner| is a task runner that can be used to do I/O. |url| is the url
+  // of the entry. |target| is a path where the content must be copied to if it
+  // exists. |callback| must be called with |true| if the delegate can retrieve
+  // an initial content for |url| after having push the content to |target|,
+  // otherwise, |callback| must be called with |false|. |callback| can be called
+  // before this method returns.
+  virtual void GetInitialPath(scoped_refptr<base::TaskRunner> task_runner,
+                              const std::string& url,
+                              const base::FilePath& target,
+                              const base::Callback<void(bool)>& callback) = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(URLResponseDiskCacheDelegate);
+};
+
+}  // namespace mojo
+
+#endif  // SERVICES_URL_RESPONSE_DISK_CACHE_URL_RESPONSE_DISK_CACHE_DELEGATE_H_
diff --git a/services/url_response_disk_cache/url_response_disk_cache_impl.cc b/services/url_response_disk_cache/url_response_disk_cache_impl.cc
index d38ec1c..795fda4 100644
--- a/services/url_response_disk_cache/url_response_disk_cache_impl.cc
+++ b/services/url_response_disk_cache/url_response_disk_cache_impl.cc
@@ -203,6 +203,25 @@
   callback.Run(PathToArray(path1), PathToArray(path2));
 }
 
+mojo::URLResponsePtr GetMinimalResponse(const std::string& url) {
+  mojo::URLResponsePtr response = mojo::URLResponse::New();
+  response->url = url;
+  response->status_code = 200;
+  return response.Pass();
+}
+
+void RunMojoCallbackWithResponse(
+    const Callback<void(mojo::URLResponsePtr, Array<uint8_t>, Array<uint8_t>)>&
+        callback,
+    const std::string& url,
+    const base::FilePath& path1,
+    const base::FilePath& path2) {
+  mojo::URLResponsePtr response;
+  if (!path1.empty())
+    response = GetMinimalResponse(url);
+  callback.Run(response.Pass(), PathToArray(path1), PathToArray(path2));
+}
+
 // Returns the list of values for the given |header_name| in the given list of
 // headers.
 std::vector<std::string> GetHeaderValues(const std::string& header_name,
@@ -320,10 +339,14 @@
 
 URLResponseDiskCacheImpl::URLResponseDiskCacheImpl(
     scoped_refptr<base::TaskRunner> task_runner,
+    URLResponseDiskCacheDelegate* delegate,
     scoped_refptr<URLResponseDiskCacheDB> db,
     const std::string& remote_application_url,
     InterfaceRequest<URLResponseDiskCache> request)
-    : task_runner_(task_runner), db_(db), binding_(this, request.Pass()) {
+    : task_runner_(task_runner),
+      delegate_(delegate),
+      db_(db),
+      binding_(this, request.Pass()) {
   request_origin_ = GURL(remote_application_url).GetOrigin().spec();
 }
 
@@ -340,9 +363,29 @@
 
 void URLResponseDiskCacheImpl::Get(const String& url,
                                    const GetCallback& callback) {
+  std::string canonilized_url = CanonicalizeURL(url);
   CacheKeyPtr key;
-  CacheEntryPtr entry =
-      db_->GetNewest(request_origin_, CanonicalizeURL(url), &key);
+  CacheEntryPtr entry = db_->GetNewest(request_origin_, canonilized_url, &key);
+  if (!entry && delegate_) {
+    // This is the first request for the given |url|. Ask |delegate| for initial
+    // content.
+
+    std::string identifier = GetNewIdentifier();
+    // The content is copied to the staging directory so that files are not
+    // leaked if the shell terminates before an entry is saved to the database.
+    base::FilePath staged_response_body_path =
+        GetStagingDirectory().Append(identifier);
+
+    delegate_->GetInitialPath(
+        task_runner_, canonilized_url, staged_response_body_path,
+        base::Bind(
+            RunCallbackWithSuccess,
+            base::Bind(&RunMojoCallbackWithResponse, callback, canonilized_url),
+            identifier, request_origin_, canonilized_url,
+            base::Passed(GetMinimalResponse(canonilized_url)), db_,
+            task_runner_));
+    return;
+  }
   if (IsInvalidated(entry) || !IsCacheEntryValid(entry)) {
     callback.Run(URLResponsePtr(), Array<uint8_t>(), Array<uint8_t>());
     return;
diff --git a/services/url_response_disk_cache/url_response_disk_cache_impl.h b/services/url_response_disk_cache/url_response_disk_cache_impl.h
index 593e0b3..6f4e64f 100644
--- a/services/url_response_disk_cache/url_response_disk_cache_impl.h
+++ b/services/url_response_disk_cache/url_response_disk_cache_impl.h
@@ -12,6 +12,7 @@
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/services/url_response_disk_cache/public/interfaces/url_response_disk_cache.mojom.h"
 #include "services/url_response_disk_cache/url_response_disk_cache_db.h"
+#include "services/url_response_disk_cache/url_response_disk_cache_delegate.h"
 
 namespace mojo {
 
@@ -29,6 +30,7 @@
       bool force_clean);
 
   URLResponseDiskCacheImpl(scoped_refptr<base::TaskRunner> task_runner,
+                           URLResponseDiskCacheDelegate* delegate,
                            scoped_refptr<URLResponseDiskCacheDB> db,
                            const std::string& remote_application_url,
                            InterfaceRequest<URLResponseDiskCache> request);
@@ -64,6 +66,7 @@
 
   scoped_refptr<base::TaskRunner> task_runner_;
   std::string request_origin_;
+  URLResponseDiskCacheDelegate* delegate_;
   scoped_refptr<URLResponseDiskCacheDB> db_;
   StrongBinding<URLResponseDiskCache> binding_;
 
diff --git a/shell/BUILD.gn b/shell/BUILD.gn
index cf4e187..deb46a4 100644
--- a/shell/BUILD.gn
+++ b/shell/BUILD.gn
@@ -226,6 +226,8 @@
       "android/native_viewport_application_loader.h",
       "android/ui_application_loader_android.cc",
       "android/ui_application_loader_android.h",
+      "android/url_response_disk_cache_delegate_impl.cc",
+      "android/url_response_disk_cache_delegate_impl.h",
     ]
 
     deps += [
@@ -397,6 +399,32 @@
       ":bootstrap_java",
       "//mojo/public/tools:copy_network_service",
     ]
+
+    if (!is_debug) {
+      sources += [
+        "$root_out_dir/authenticating_url_loader_interceptor.mojo",
+        "$root_out_dir/dart_content_handler.mojo",
+        "$root_out_dir/device_info.mojo",
+        "$root_out_dir/icu_data.mojo",
+        "$root_out_dir/java_handler.mojo",
+        "$root_out_dir/kiosk_wm.mojo",
+        "$root_out_dir/surfaces_service.mojo",
+        "$root_out_dir/tracing.mojo",
+        "$root_out_dir/view_manager.mojo",
+      ]
+
+      deps += [
+        "//services/authenticating_url_loader_interceptor",
+        "//services/android:java_handler",
+        "//services/dart:dart_content_handler",
+        "//services/device_info",
+        "//services/icu_data",
+        "//services/kiosk_wm",
+        "//services/surfaces",
+        "//services/tracing",
+        "//services/view_manager",
+      ]
+    }
   }
 
   copy_ex("copy_mojo_shell_test_assets") {
diff --git a/shell/android/apk/src/org/chromium/mojo/shell/ShellService.java b/shell/android/apk/src/org/chromium/mojo/shell/ShellService.java
index d961d96..b3804c3 100644
--- a/shell/android/apk/src/org/chromium/mojo/shell/ShellService.java
+++ b/shell/android/apk/src/org/chromium/mojo/shell/ShellService.java
@@ -10,6 +10,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.res.AssetManager;
 import android.os.Binder;
 import android.os.IBinder;
 import android.util.JsonReader;
@@ -120,6 +121,7 @@
     static interface IShellBindingActivity {
         // Called when the ShellService service is connected.
         void onShellBound(ShellService shellService);
+
         // Called when the ShellService service is disconnected.
         void onShellUnbound();
     }
@@ -213,7 +215,8 @@
                 parametersList.add("--url-mappings=mojo:window_manager=" + DEFAULT_WM);
             }
 
-            nativeStart(applicationContext, mojoShellChild.getAbsolutePath(),
+            nativeStart(applicationContext, applicationContext.getAssets(),
+                    mojoShellChild.getAbsolutePath(),
                     parametersList.toArray(new String[parametersList.size()]),
                     getLocalAppsDir(applicationContext).getAbsolutePath(),
                     getTmpDir(applicationContext).getAbsolutePath(),
@@ -306,8 +309,9 @@
     /**
      * Initializes the native system. This API should be called only once per process.
      **/
-    private static native void nativeStart(Context context, String mojoShellChildPath,
-            String[] parameters, String bundledAppsDirectory, String tmpDir, String homeDir);
+    private static native void nativeStart(Context context, AssetManager assetManager,
+            String mojoShellChildPath, String[] parameters, String bundledAppsDirectory,
+            String tmpDir, String homeDir);
 
     private static native void nativeAddApplicationURL(String url);
 
diff --git a/shell/android/main.cc b/shell/android/main.cc
index 05e62ce..92d4bb3 100644
--- a/shell/android/main.cc
+++ b/shell/android/main.cc
@@ -32,6 +32,7 @@
 #include "shell/android/java_application_loader.h"
 #include "shell/android/native_viewport_application_loader.h"
 #include "shell/android/ui_application_loader_android.h"
+#include "shell/android/url_response_disk_cache_delegate_impl.h"
 #include "shell/application_manager/application_loader.h"
 #include "shell/background_application_loader.h"
 #include "shell/command_line_util.h"
@@ -95,6 +96,10 @@
 
   // Event signalling when the shell task runner has been initialized.
   scoped_ptr<base::WaitableEvent> shell_runner_ready;
+
+  // Delegate for URLResponseDiskCache. Allows to access bundled application on
+  // cold start.
+  scoped_ptr<URLResponseDiskCacheDelegateImpl> url_response_disk_cache_delegate;
 };
 
 LazyInstance<InternalShellData> g_internal_data = LAZY_INSTANCE_INITIALIZER;
@@ -147,7 +152,9 @@
 
   Context* context = g_internal_data.Get().context.get();
   ConfigureAndroidServices(context);
-  CHECK(context->InitWithPaths(mojo_shell_child_path_));
+  CHECK(context->InitWithPaths(
+      mojo_shell_child_path_,
+      g_internal_data.Get().url_response_disk_cache_delegate.get()));
 
   RunCommandLineApps(context);
 
@@ -219,6 +226,7 @@
 static void Start(JNIEnv* env,
                   jclass clazz,
                   jobject application_context,
+                  jobject j_asset_manager,
                   jstring mojo_shell_child_path,
                   jobjectArray jparameters,
                   jstring j_local_apps_directory,
@@ -284,6 +292,9 @@
       base::android::ConvertJavaStringToUTF8(env, j_local_apps_directory)));
   g_internal_data.Get().context.reset(shell_context);
 
+  g_internal_data.Get().url_response_disk_cache_delegate.reset(
+      new URLResponseDiskCacheDelegateImpl(shell_context, j_asset_manager));
+
   g_internal_data.Get().java_message_loop.reset(new base::MessageLoopForUI);
   base::MessageLoopForUI::current()->Start();
   tracer->DidCreateMessageLoop();
diff --git a/shell/android/url_response_disk_cache_delegate_impl.cc b/shell/android/url_response_disk_cache_delegate_impl.cc
new file mode 100644
index 0000000..5e7d0ac
--- /dev/null
+++ b/shell/android/url_response_disk_cache_delegate_impl.cc
@@ -0,0 +1,99 @@
+// Copyright 2015 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 "shell/android/url_response_disk_cache_delegate_impl.h"
+
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/files/file.h"
+#include "base/strings/string_util.h"
+#include "base/task_runner_util.h"
+
+namespace shell {
+
+namespace {
+const char kMojoApplicationSuffix[] = ".mojo";
+}  // namespace
+
+URLResponseDiskCacheDelegateImpl::URLResponseDiskCacheDelegateImpl(
+    Context* context,
+    jobject j_asset_manager)
+    : context_(context),
+      j_asset_manager_(base::android::AttachCurrentThread(), j_asset_manager),
+      asset_manager_(
+          AAssetManager_fromJava(base::android::AttachCurrentThread(),
+                                 j_asset_manager_.obj())) {}
+
+URLResponseDiskCacheDelegateImpl::~URLResponseDiskCacheDelegateImpl() {}
+
+void URLResponseDiskCacheDelegateImpl::GetInitialPath(
+    scoped_refptr<base::TaskRunner> task_runner,
+    const std::string& url,
+    const base::FilePath& target,
+    const base::Callback<void(bool)>& callback) {
+  PopulateAssetsIfNeeded();
+  if (url_to_asset_name_.find(url) == url_to_asset_name_.end()) {
+    callback.Run(false);
+    return;
+  }
+
+  PostTaskAndReplyWithResult(
+      task_runner.get(), FROM_HERE,
+      base::Bind(&URLResponseDiskCacheDelegateImpl::ExtractAsset,
+                 base::Unretained(this), url_to_asset_name_[url], target),
+      callback);
+}
+
+bool URLResponseDiskCacheDelegateImpl::ExtractAsset(
+    const std::string& asset_name,
+    const base::FilePath& target) {
+  AAsset* asset = AAssetManager_open(asset_manager_, asset_name.c_str(),
+                                     AASSET_MODE_STREAMING);
+  if (!asset)
+    return false;
+  base::ScopedClosureRunner cleanup(
+      base::Bind(&AAsset_close, base::Unretained(asset)));
+  base::File target_file(target,
+                         base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+  if (!target_file.IsValid())
+    return false;
+  char buffer[4096];
+  int nb_read;
+  do {
+    nb_read = AAsset_read(asset, buffer, arraysize(buffer));
+    if (nb_read > 0) {
+      if (target_file.WriteAtCurrentPos(buffer, nb_read) != nb_read)
+        return false;
+    }
+  } while (nb_read > 0);
+  return nb_read == 0;
+}
+
+void URLResponseDiskCacheDelegateImpl::PopulateAssetsIfNeeded() {
+  if (url_to_asset_name_.empty()) {
+    AAssetDir* dir = AAssetManager_openDir(asset_manager_, "");
+    if (!dir)
+      return;
+    base::ScopedClosureRunner cleanup(
+        base::Bind(&AAssetDir_close, base::Unretained(dir)));
+    while (const char* filename = AAssetDir_getNextFileName(dir)) {
+      std::string file_name_string = filename;
+      if (EndsWith(file_name_string, kMojoApplicationSuffix, true)) {
+        std::string base_name = file_name_string.substr(
+            0,
+            file_name_string.size() - (arraysize(kMojoApplicationSuffix) - 1));
+        std::string url = context_->url_resolver()
+                              ->ResolveMojoURL(GURL("mojo:" + base_name))
+                              .spec();
+        url_to_asset_name_[url] = file_name_string;
+      }
+    }
+  }
+}
+
+}  // namespace shell
diff --git a/shell/android/url_response_disk_cache_delegate_impl.h b/shell/android/url_response_disk_cache_delegate_impl.h
new file mode 100644
index 0000000..c1f12ab
--- /dev/null
+++ b/shell/android/url_response_disk_cache_delegate_impl.h
@@ -0,0 +1,46 @@
+// Copyright 2015 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.
+
+#ifndef SHELL_ANDROID_URL_RESPONSE_DISK_CACHE_DELEGATE_IMPL_H_
+#define SHELL_ANDROID_URL_RESPONSE_DISK_CACHE_DELEGATE_IMPL_H_
+
+#include <map>
+
+#include "base/android/scoped_java_ref.h"
+#include "services/url_response_disk_cache/url_response_disk_cache_delegate.h"
+#include "shell/context.h"
+
+struct AAssetManager;
+
+namespace shell {
+
+class URLResponseDiskCacheDelegateImpl
+    : public mojo::URLResponseDiskCacheDelegate {
+ public:
+  URLResponseDiskCacheDelegateImpl(Context* contest, jobject j_asset_manager);
+  ~URLResponseDiskCacheDelegateImpl() override;
+
+ private:
+  // mojo:URLResponseDiskCacheDelegate implementation:
+  void GetInitialPath(scoped_refptr<base::TaskRunner> task_runner,
+                      const std::string& url,
+                      const base::FilePath& target,
+                      const base::Callback<void(bool)>& callback) override;
+
+  bool ExtractAsset(const std::string& asset_name,
+                    const base::FilePath& target);
+
+  void PopulateAssetsIfNeeded();
+
+  Context* context_;
+  base::android::ScopedJavaGlobalRef<jobject> j_asset_manager_;
+  std::map<std::string, std::string> url_to_asset_name_;
+  AAssetManager* asset_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(URLResponseDiskCacheDelegateImpl);
+};
+
+}  // namespace shell
+
+#endif  // SHELL_ANDROID_URL_RESPONSE_DISK_CACHE_DELEGATE_IMPL_H_
diff --git a/shell/context.cc b/shell/context.cc
index fe1ffaf..65e11f1 100644
--- a/shell/context.cc
+++ b/shell/context.cc
@@ -264,10 +264,12 @@
       base::CommandLine::ForCurrentProcess()->GetProgram());
   base::FilePath shell_child_path =
       shell_path.DirName().AppendASCII("mojo_shell_child");
-  return InitWithPaths(shell_child_path);
+  return InitWithPaths(shell_child_path, nullptr);
 }
 
-bool Context::InitWithPaths(const base::FilePath& shell_child_path) {
+bool Context::InitWithPaths(
+    const base::FilePath& shell_child_path,
+    mojo::URLResponseDiskCacheDelegate* url_response_disk_cache_delegate) {
   TRACE_EVENT0("mojo_shell", "Context::InitWithPaths");
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
@@ -284,7 +286,8 @@
   application_manager()->SetLoaderForURL(
       make_scoped_ptr(new BackgroundApplicationLoader(
           make_scoped_ptr(
-              new URLResponseDiskCacheLoader(task_runners_->blocking_pool())),
+              new URLResponseDiskCacheLoader(task_runners_->blocking_pool(),
+                                             url_response_disk_cache_delegate)),
           "url_response_disk_cache", base::MessageLoop::TYPE_DEFAULT)),
       GURL("mojo:url_response_disk_cache"));
 #endif
diff --git a/shell/context.h b/shell/context.h
index 7760f6d..feb1fb0 100644
--- a/shell/context.h
+++ b/shell/context.h
@@ -13,6 +13,10 @@
 #include "shell/task_runners.h"
 #include "shell/url_resolver.h"
 
+namespace mojo {
+class URLResponseDiskCacheDelegate;
+}
+
 namespace shell {
 class Tracer;
 
@@ -48,8 +52,11 @@
   // success.
   bool Init();
 
-  // Like Init(), but specifies |mojo_shell_child_path()| explicitly.
-  bool InitWithPaths(const base::FilePath& shell_child_path);
+  // Like Init(), but specifies |mojo_shell_child_path()| explicitly. Also
+  // allows to set a delegate for the application offline cache.
+  bool InitWithPaths(
+      const base::FilePath& shell_child_path,
+      mojo::URLResponseDiskCacheDelegate* url_response_disk_cache_delegate);
 
   // If Init() was called and succeeded, this must be called before destruction.
   void Shutdown();
diff --git a/shell/url_response_disk_cache_loader.cc b/shell/url_response_disk_cache_loader.cc
index ef0d259..e9629ff 100644
--- a/shell/url_response_disk_cache_loader.cc
+++ b/shell/url_response_disk_cache_loader.cc
@@ -7,8 +7,9 @@
 namespace shell {
 
 URLResponseDiskCacheLoader::URLResponseDiskCacheLoader(
-    scoped_refptr<base::TaskRunner> task_runner)
-    : url_response_disk_cache_(task_runner) {}
+    scoped_refptr<base::TaskRunner> task_runner,
+    mojo::URLResponseDiskCacheDelegate* delegate)
+    : url_response_disk_cache_(task_runner, delegate) {}
 
 URLResponseDiskCacheLoader::~URLResponseDiskCacheLoader() {
 }
diff --git a/shell/url_response_disk_cache_loader.h b/shell/url_response_disk_cache_loader.h
index 8f52610..a47e273 100644
--- a/shell/url_response_disk_cache_loader.h
+++ b/shell/url_response_disk_cache_loader.h
@@ -16,7 +16,8 @@
 
 class URLResponseDiskCacheLoader : public ApplicationLoader {
  public:
-  URLResponseDiskCacheLoader(scoped_refptr<base::TaskRunner> task_runner);
+  URLResponseDiskCacheLoader(scoped_refptr<base::TaskRunner> task_runner,
+                             mojo::URLResponseDiskCacheDelegate* delegate);
   ~URLResponseDiskCacheLoader() override;
 
  private: