// Copyright 2014 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/manifest/manifest_manager_host.h" #include #include "base/bind.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/render_frame_host.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/manifest/manifest.h" namespace content { ManifestManagerHost::ManifestManagerHost(RenderFrameHost* render_frame_host) : manifest_manager_frame_(render_frame_host) { // Check that |manifest_manager_frame_| is a main frame. DCHECK(!manifest_manager_frame_->GetParent()); } ManifestManagerHost::~ManifestManagerHost() { OnConnectionError(); } void ManifestManagerHost::BindObserver( mojo::PendingAssociatedReceiver receiver) { manifest_url_change_observer_receiver_.Bind(std::move(receiver)); } ManifestManagerHost* ManifestManagerHost::GetOrCreateForCurrentDocument( RenderFrameHostImpl* rfh) { DCHECK(rfh->is_main_frame()); if (!GetForCurrentDocument(rfh)) CreateForCurrentDocument(rfh); return GetForCurrentDocument(rfh); } void ManifestManagerHost::GetManifest(GetManifestCallback callback) { auto& manifest_manager = GetManifestManager(); int request_id = callbacks_.Add( std::make_unique(std::move(callback))); manifest_manager.RequestManifest( base::BindOnce(&ManifestManagerHost::OnRequestManifestResponse, base::Unretained(this), request_id)); } void ManifestManagerHost::RequestManifestDebugInfo( blink::mojom::ManifestManager::RequestManifestDebugInfoCallback callback) { GetManifestManager().RequestManifestDebugInfo(std::move(callback)); } blink::mojom::ManifestManager& ManifestManagerHost::GetManifestManager() { if (!manifest_manager_) { manifest_manager_frame_->GetRemoteInterfaces()->GetInterface( manifest_manager_.BindNewPipeAndPassReceiver()); manifest_manager_.set_disconnect_handler(base::BindOnce( &ManifestManagerHost::OnConnectionError, base::Unretained(this))); } return *manifest_manager_; } void ManifestManagerHost::OnConnectionError() { std::vector callbacks; for (CallbackMap::iterator it(&callbacks_); !it.IsAtEnd(); it.Advance()) { callbacks.push_back(std::move(*it.GetCurrentValue())); } callbacks_.Clear(); for (auto& callback : callbacks) std::move(callback).Run(GURL(), blink::Manifest()); if (GetForCurrentDocument(manifest_manager_frame_)) { DeleteForCurrentDocument(manifest_manager_frame_); } } void ManifestManagerHost::OnRequestManifestResponse( int request_id, const GURL& url, const blink::Manifest& manifest) { auto callback = std::move(*callbacks_.Lookup(request_id)); callbacks_.Remove(request_id); std::move(callback).Run(url, manifest); } void ManifestManagerHost::ManifestUrlChanged( const base::Optional& manifest_url) { if (!manifest_manager_frame_->IsCurrent()) return; // TODO(yuzus): |NotifyManifestUrlChanged| should start taking a // |RenderFrameHost| parameter. WebContents* web_contents = WebContents::FromRenderFrameHost(manifest_manager_frame_); static_cast(web_contents) ->NotifyManifestUrlChanged(manifest_url); } RENDER_DOCUMENT_HOST_USER_DATA_KEY_IMPL(ManifestManagerHost) } // namespace content