| // 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 "content/browser/appcache/appcache_dispatcher_host.h" | 
 |  | 
 | #include <map> | 
 | #include "base/bind.h" | 
 | #include "base/bind_helpers.h" | 
 | #include "content/browser/appcache/appcache_navigation_handle_core.h" | 
 | #include "content/browser/appcache/chrome_appcache_service.h" | 
 | #include "content/browser/bad_message.h" | 
 | #include "content/public/browser/render_process_host.h" | 
 | #include "content/public/common/browser_side_navigation_policy.h" | 
 |  | 
 | namespace content { | 
 |  | 
 | AppCacheDispatcherHost::AppCacheDispatcherHost( | 
 |     ChromeAppCacheService* appcache_service, | 
 |     int process_id) | 
 |     : appcache_service_(appcache_service), | 
 |       frontend_proxy_(process_id), | 
 |       weak_factory_(this) { | 
 |   if (appcache_service) { | 
 |     backend_impl_.Initialize(appcache_service, &frontend_proxy_, process_id); | 
 |   } | 
 | } | 
 |  | 
 | AppCacheDispatcherHost::~AppCacheDispatcherHost() = default; | 
 |  | 
 | // static | 
 | void AppCacheDispatcherHost::Create(ChromeAppCacheService* appcache_service, | 
 |                                     int process_id, | 
 |                                     mojom::AppCacheBackendRequest request) { | 
 |   // The process_id is the id of the RenderProcessHost, which can be reused for | 
 |   // a new renderer process if the previous renderer process was shutdown. | 
 |   // It can take some time after shutdown for the pipe error to propagate | 
 |   // and unregister the previous backend. Since the AppCacheService assumes | 
 |   // that there is one backend per process_id, we need to ensure that the | 
 |   // previous backend is unregistered by eagerly unbinding the pipe. | 
 |   appcache_service->Unbind(process_id); | 
 |  | 
 |   appcache_service->Bind( | 
 |       std::make_unique<AppCacheDispatcherHost>(appcache_service, process_id), | 
 |       std::move(request), process_id); | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::RegisterHost(int32_t host_id) { | 
 |   if (appcache_service_) { | 
 |     // The AppCacheHost could have been precreated in which case we want to | 
 |     // register it with the backend here. | 
 |     std::unique_ptr<content::AppCacheHost> host = | 
 |         AppCacheNavigationHandleCore::GetPrecreatedHost(host_id); | 
 |     if (host.get()) { | 
 |       backend_impl_.RegisterPrecreatedHost(std::move(host)); | 
 |       return; | 
 |     } | 
 |  | 
 |     if (!backend_impl_.RegisterHost(host_id)) { | 
 |       mojo::ReportBadMessage("ACDH_REGISTER"); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::UnregisterHost(int32_t host_id) { | 
 |   if (appcache_service_) { | 
 |     if (!backend_impl_.UnregisterHost(host_id)) { | 
 |       mojo::ReportBadMessage("ACDH_UNREGISTER"); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::SetSpawningHostId(int32_t host_id, | 
 |                                                int spawning_host_id) { | 
 |   if (appcache_service_) { | 
 |     if (!backend_impl_.SetSpawningHostId(host_id, spawning_host_id)) | 
 |       mojo::ReportBadMessage("ACDH_SET_SPAWNING"); | 
 |   } | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::SelectCache(int32_t host_id, | 
 |                                          const GURL& document_url, | 
 |                                          int64_t cache_document_was_loaded_from, | 
 |                                          const GURL& opt_manifest_url) { | 
 |   if (appcache_service_) { | 
 |     if (!backend_impl_.SelectCache(host_id, document_url, | 
 |                                    cache_document_was_loaded_from, | 
 |                                    opt_manifest_url)) { | 
 |       mojo::ReportBadMessage("ACDH_SELECT_CACHE"); | 
 |     } | 
 |   } else { | 
 |     frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo()); | 
 |   } | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::SelectCacheForSharedWorker(int32_t host_id, | 
 |                                                         int64_t appcache_id) { | 
 |   if (appcache_service_) { | 
 |     if (!backend_impl_.SelectCacheForSharedWorker(host_id, appcache_id)) | 
 |       mojo::ReportBadMessage("ACDH_SELECT_CACHE_FOR_SHARED_WORKER"); | 
 |   } else { | 
 |     frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo()); | 
 |   } | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::MarkAsForeignEntry( | 
 |     int32_t host_id, | 
 |     const GURL& document_url, | 
 |     int64_t cache_document_was_loaded_from) { | 
 |   if (appcache_service_) { | 
 |     if (!backend_impl_.MarkAsForeignEntry(host_id, document_url, | 
 |                                           cache_document_was_loaded_from)) { | 
 |       mojo::ReportBadMessage("ACDH_MARK_AS_FOREIGN_ENTRY"); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::GetResourceList(int32_t host_id, | 
 |                                              GetResourceListCallback callback) { | 
 |   std::vector<AppCacheResourceInfo> params; | 
 |   std::vector<mojom::AppCacheResourceInfoPtr> out; | 
 |   if (appcache_service_) { | 
 |     backend_impl_.GetResourceList(host_id, ¶ms); | 
 |  | 
 |     // Box up params for output. | 
 |     out.reserve(params.size()); | 
 |     for (auto& p : params) { | 
 |       out.emplace_back(base::in_place, std::move(p)); | 
 |     } | 
 |   } | 
 |   std::move(callback).Run(std::move(out)); | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::GetStatus(int32_t host_id, | 
 |                                        GetStatusCallback callback) { | 
 |   if (appcache_service_) { | 
 |     if (backend_impl_.GetStatusWithCallback(host_id, &callback)) { | 
 |       return; | 
 |     } else { | 
 |       mojo::ReportBadMessage("ACDH_GET_STATUS"); | 
 |     } | 
 |   } | 
 |   std::move(callback).Run(AppCacheStatus::APPCACHE_STATUS_UNCACHED); | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::StartUpdate(int32_t host_id, | 
 |                                          StartUpdateCallback callback) { | 
 |   if (appcache_service_) { | 
 |     if (backend_impl_.StartUpdateWithCallback(host_id, &callback)) { | 
 |       return; | 
 |     } else { | 
 |       mojo::ReportBadMessage("ACDH_START_UPDATE"); | 
 |     } | 
 |   } | 
 |   std::move(callback).Run(false); | 
 | } | 
 |  | 
 | void AppCacheDispatcherHost::SwapCache(int32_t host_id, | 
 |                                        SwapCacheCallback callback) { | 
 |   if (appcache_service_) { | 
 |     if (backend_impl_.SwapCacheWithCallback(host_id, &callback)) { | 
 |       return; | 
 |     } else { | 
 |       mojo::ReportBadMessage("ACDH_SWAP_CACHE"); | 
 |     } | 
 |   } | 
 |   std::move(callback).Run(false); | 
 | } | 
 |  | 
 | }  // namespace content |