| Index: content/browser/manifest/manifest_manager_host.cc
|
| diff --git a/content/browser/manifest/manifest_manager_host.cc b/content/browser/manifest/manifest_manager_host.cc
|
| index e6c70b5f87708eef81e962dc3b4415679a82377e..34e500e772c5cbdb0a434af7eaf0e7c09dac0dbf 100644
|
| --- a/content/browser/manifest/manifest_manager_host.cc
|
| +++ b/content/browser/manifest/manifest_manager_host.cc
|
| @@ -4,230 +4,118 @@
|
|
|
| #include "content/browser/manifest/manifest_manager_host.h"
|
|
|
| -#include <stdint.h>
|
| -
|
| -#include "base/stl_util.h"
|
| -#include "content/common/manifest_manager_messages.h"
|
| +#include "base/id_map.h"
|
| #include "content/public/browser/render_frame_host.h"
|
| -#include "content/public/browser/render_process_host.h"
|
| #include "content/public/common/manifest.h"
|
| -#include "content/public/common/result_codes.h"
|
| +#include "content/public/common/service_registry.h"
|
|
|
| namespace content {
|
|
|
| -namespace {
|
| +class ManifestManagerHost::FrameManifestManagerHost {
|
| + public:
|
| + FrameManifestManagerHost(ManifestManagerHost* owner,
|
| + RenderFrameHost* render_frame_host)
|
| + : owner_(owner), render_frame_host_(render_frame_host) {
|
| + render_frame_host->GetServiceRegistry()->ConnectToRemoteService(
|
| + mojo::GetProxy(&manifest_manager_));
|
| + manifest_manager_.set_connection_error_handler(
|
| + base::Bind(&ManifestManagerHost::FrameManifestManagerHost::DeleteThis,
|
| + base::Unretained(this)));
|
| + }
|
|
|
| -void KillRenderer(RenderFrameHost* render_frame_host) {
|
| - base::ProcessHandle process_handle =
|
| - render_frame_host->GetProcess()->GetHandle();
|
| - if (process_handle == base::kNullProcessHandle)
|
| - return;
|
| - render_frame_host->GetProcess()->Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE,
|
| - false);
|
| -}
|
| + ~FrameManifestManagerHost() {
|
| + for (GetCallbackMap::const_iterator it(&get_callbacks_); !it.IsAtEnd();
|
| + it.Advance()) {
|
| + it.GetCurrentValue()->Run(Manifest());
|
| + }
|
| + for (HasCallbackMap::const_iterator it(&has_callbacks_); !it.IsAtEnd();
|
| + it.Advance()) {
|
| + it.GetCurrentValue()->Run(false);
|
| + }
|
| + }
|
|
|
| -} // anonymous namespace
|
| + // Calls the given callback with the manifest associated with the
|
| + // given RenderFrameHost. If the frame has no manifest or if getting it failed
|
| + // the callback will have an empty manifest.
|
| + void GetManifest(const GetManifestCallback& callback) {
|
| + int request_id = get_callbacks_.Add(new GetManifestCallback(callback));
|
|
|
| -ManifestManagerHost::ManifestManagerHost(WebContents* web_contents)
|
| - : WebContentsObserver(web_contents) {
|
| -}
|
| + manifest_manager_->RequestManifest(
|
| + base::Bind(&ManifestManagerHost::FrameManifestManagerHost::
|
| + OnRequestManifestResponse,
|
| + base::Unretained(this), request_id));
|
| + }
|
|
|
| -ManifestManagerHost::~ManifestManagerHost() {
|
| - STLDeleteValues(&pending_get_callbacks_);
|
| - STLDeleteValues(&pending_has_callbacks_);
|
| -}
|
| + // Calls the given callback with a bool indicating whether or not the document
|
| + // associated with the given RenderFrameHost has a manifest.
|
| + void HasManifest(const HasManifestCallback& callback) {
|
| + int request_id = has_callbacks_.Add(new HasManifestCallback(callback));
|
|
|
| -ManifestManagerHost::GetCallbackMap*
|
| -ManifestManagerHost::GetCallbackMapForFrame(
|
| - RenderFrameHost* render_frame_host) {
|
| - FrameGetCallbackMap::iterator it =
|
| - pending_get_callbacks_.find(render_frame_host);
|
| - return it != pending_get_callbacks_.end() ? it->second : nullptr;
|
| -}
|
| + manifest_manager_->HasManifest(base::Bind(
|
| + &ManifestManagerHost::FrameManifestManagerHost::OnHasManifestResponse,
|
| + base::Unretained(this), request_id));
|
| + }
|
|
|
| -ManifestManagerHost::HasCallbackMap*
|
| -ManifestManagerHost::HasCallbackMapForFrame(
|
| - RenderFrameHost* render_frame_host) {
|
| - FrameHasCallbackMap::iterator it =
|
| - pending_has_callbacks_.find(render_frame_host);
|
| - return it != pending_has_callbacks_.end() ? it->second : nullptr;
|
| -}
|
| + private:
|
| + using GetCallbackMap = IDMap<GetManifestCallback, IDMapOwnPointer>;
|
| + using HasCallbackMap = IDMap<HasManifestCallback, IDMapOwnPointer>;
|
|
|
| -void ManifestManagerHost::RenderFrameDeleted(
|
| - RenderFrameHost* render_frame_host) {
|
| - {
|
| - GetCallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
|
| - if (!callbacks)
|
| - return;
|
| -
|
| - // Call the callbacks with a failure state before deleting them. Do this in
|
| - // a block so the iterator is destroyed before |callbacks|.
|
| - {
|
| - GetCallbackMap::const_iterator it(callbacks);
|
| - for (; !it.IsAtEnd(); it.Advance())
|
| - it.GetCurrentValue()->Run(Manifest());
|
| - }
|
| + void DeleteThis() { owner_->RenderFrameDeleted(render_frame_host_); }
|
|
|
| - delete callbacks;
|
| - pending_get_callbacks_.erase(render_frame_host);
|
| + void OnRequestManifestResponse(int request_id, const Manifest& manifest) {
|
| + get_callbacks_.Lookup(request_id)->Run(manifest);
|
| + get_callbacks_.Remove(request_id);
|
| + DeleteIfIdle();
|
| }
|
|
|
| - {
|
| - HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host);
|
| - if (!callbacks)
|
| - return;
|
| -
|
| - // Call the callbacks with a failure state before deleting them. Do this in
|
| - // a block so the iterator is destroyed before |callbacks|.
|
| - {
|
| - HasCallbackMap::const_iterator it(callbacks);
|
| - for (; !it.IsAtEnd(); it.Advance())
|
| - it.GetCurrentValue()->Run(false);
|
| - }
|
| -
|
| - delete callbacks;
|
| - pending_has_callbacks_.erase(render_frame_host);
|
| + void OnHasManifestResponse(int request_id, bool has_manifest) {
|
| + has_callbacks_.Lookup(request_id)->Run(has_manifest);
|
| + has_callbacks_.Remove(request_id);
|
| + DeleteIfIdle();
|
| }
|
| -}
|
|
|
| -void ManifestManagerHost::GetManifest(RenderFrameHost* render_frame_host,
|
| - const GetManifestCallback& callback) {
|
| - GetCallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
|
| - if (!callbacks) {
|
| - callbacks = new GetCallbackMap();
|
| - pending_get_callbacks_[render_frame_host] = callbacks;
|
| + void DeleteIfIdle() {
|
| + if (get_callbacks_.IsEmpty() && has_callbacks_.IsEmpty())
|
| + DeleteThis();
|
| }
|
|
|
| - int request_id = callbacks->Add(new GetManifestCallback(callback));
|
| + ManifestManagerHost* owner_;
|
| + RenderFrameHost* render_frame_host_;
|
| + blink::mojom::ManifestManagerPtr manifest_manager_;
|
| + GetCallbackMap get_callbacks_;
|
| + HasCallbackMap has_callbacks_;
|
|
|
| - render_frame_host->Send(new ManifestManagerMsg_RequestManifest(
|
| - render_frame_host->GetRoutingID(), request_id));
|
| -}
|
| + DISALLOW_COPY_AND_ASSIGN(FrameManifestManagerHost);
|
| +};
|
|
|
| -void ManifestManagerHost::HasManifest(RenderFrameHost* render_frame_host,
|
| - const HasManifestCallback& callback) {
|
| - HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host);
|
| - if (!callbacks) {
|
| - callbacks = new HasCallbackMap();
|
| - pending_has_callbacks_[render_frame_host] = callbacks;
|
| - }
|
| +ManifestManagerHost::ManifestManagerHost(WebContents* web_contents)
|
| + : WebContentsObserver(web_contents) {}
|
|
|
| - int request_id = callbacks->Add(new HasManifestCallback(callback));
|
| +ManifestManagerHost::~ManifestManagerHost() = default;
|
|
|
| - render_frame_host->Send(new ManifestManagerMsg_HasManifest(
|
| - render_frame_host->GetRoutingID(), request_id));
|
| +void ManifestManagerHost::RenderFrameDeleted(
|
| + RenderFrameHost* render_frame_host) {
|
| + hosts_.erase(render_frame_host);
|
| }
|
|
|
| -bool ManifestManagerHost::OnMessageReceived(
|
| - const IPC::Message& message, RenderFrameHost* render_frame_host) {
|
| - bool handled = true;
|
| -
|
| - IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ManifestManagerHost, message,
|
| - render_frame_host)
|
| - IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse,
|
| - OnRequestManifestResponse)
|
| - IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_HasManifestResponse,
|
| - OnHasManifestResponse)
|
| - IPC_MESSAGE_UNHANDLED(handled = false)
|
| - IPC_END_MESSAGE_MAP()
|
| -
|
| - return handled;
|
| +void ManifestManagerHost::GetManifest(RenderFrameHost* render_frame_host,
|
| + const GetManifestCallback& callback) {
|
| + GetOrCreateHostForFrame(render_frame_host).GetManifest(callback);
|
| }
|
|
|
| -void ManifestManagerHost::OnRequestManifestResponse(
|
| - RenderFrameHost* render_frame_host,
|
| - int request_id,
|
| - const Manifest& insecure_manifest) {
|
| - GetCallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
|
| - if (!callbacks) {
|
| - DVLOG(1) << "Unexpected RequestManifestResponse to from renderer. "
|
| - "Killing renderer.";
|
| - KillRenderer(render_frame_host);
|
| - return;
|
| - }
|
| -
|
| - GetManifestCallback* callback = callbacks->Lookup(request_id);
|
| - if (!callback) {
|
| - DVLOG(1) << "Received a request_id (" << request_id << ") from renderer "
|
| - "with no associated callback. Killing renderer.";
|
| - KillRenderer(render_frame_host);
|
| - return;
|
| - }
|
| -
|
| - // When receiving a Manifest, the browser process can't trust that it is
|
| - // coming from a known and secure source. It must be processed accordingly.
|
| - Manifest manifest = insecure_manifest;
|
| - manifest.name = base::NullableString16(
|
| - manifest.name.string().substr(0, Manifest::kMaxIPCStringLength),
|
| - manifest.name.is_null());
|
| - manifest.short_name = base::NullableString16(
|
| - manifest.short_name.string().substr(0, Manifest::kMaxIPCStringLength),
|
| - manifest.short_name.is_null());
|
| - if (!manifest.start_url.is_valid())
|
| - manifest.start_url = GURL();
|
| - for (auto& icon : manifest.icons) {
|
| - if (!icon.src.is_valid())
|
| - icon.src = GURL();
|
| - icon.type = base::NullableString16(
|
| - icon.type.string().substr(0, Manifest::kMaxIPCStringLength),
|
| - icon.type.is_null());
|
| - }
|
| - manifest.gcm_sender_id = base::NullableString16(
|
| - manifest.gcm_sender_id.string().substr(
|
| - 0, Manifest::kMaxIPCStringLength),
|
| - manifest.gcm_sender_id.is_null());
|
| - for (auto& related_application : manifest.related_applications) {
|
| - if (!related_application.url.is_valid())
|
| - related_application.url = GURL();
|
| - related_application.id =
|
| - base::NullableString16(related_application.id.string().substr(
|
| - 0, Manifest::kMaxIPCStringLength),
|
| - related_application.id.is_null());
|
| - }
|
| - // theme_color and background_color are 32 bit unsigned integers with 64 bit
|
| - // integers simply being used to encode the occurence of an error. Therefore,
|
| - // any value outside the range of a 32 bit integer is invalid.
|
| - if (manifest.theme_color < std::numeric_limits<int32_t>::min() ||
|
| - manifest.theme_color > std::numeric_limits<int32_t>::max())
|
| - manifest.theme_color = Manifest::kInvalidOrMissingColor;
|
| - if (manifest.background_color < std::numeric_limits<int32_t>::min() ||
|
| - manifest.background_color > std::numeric_limits<int32_t>::max())
|
| - manifest.background_color = Manifest::kInvalidOrMissingColor;
|
| -
|
| - callback->Run(manifest);
|
| - callbacks->Remove(request_id);
|
| - if (callbacks->IsEmpty()) {
|
| - delete callbacks;
|
| - pending_get_callbacks_.erase(render_frame_host);
|
| - }
|
| +void ManifestManagerHost::HasManifest(RenderFrameHost* render_frame_host,
|
| + const HasManifestCallback& callback) {
|
| + GetOrCreateHostForFrame(render_frame_host).HasManifest(callback);
|
| }
|
|
|
| -void ManifestManagerHost::OnHasManifestResponse(
|
| - RenderFrameHost* render_frame_host,
|
| - int request_id,
|
| - bool has_manifest) {
|
| - HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host);
|
| - if (!callbacks) {
|
| - DVLOG(1) << "Unexpected HasManifestResponse from renderer. "
|
| - "Killing renderer.";
|
| - KillRenderer(render_frame_host);
|
| - return;
|
| - }
|
| -
|
| - HasManifestCallback* callback = callbacks->Lookup(request_id);
|
| - if (!callback) {
|
| - DVLOG(1) << "Received a request_id (" << request_id << ") from renderer "
|
| - "with no associated callback. Killing renderer.";
|
| - KillRenderer(render_frame_host);
|
| - return;
|
| - }
|
| -
|
| - callback->Run(has_manifest);
|
| - callbacks->Remove(request_id);
|
| - if (callbacks->IsEmpty()) {
|
| - delete callbacks;
|
| - pending_has_callbacks_.erase(render_frame_host);
|
| - }
|
| +ManifestManagerHost::FrameManifestManagerHost&
|
| +ManifestManagerHost::GetOrCreateHostForFrame(
|
| + RenderFrameHost* render_frame_host) {
|
| + std::unique_ptr<ManifestManagerHost::FrameManifestManagerHost>& host =
|
| + hosts_[render_frame_host];
|
| + if (!host)
|
| + host.reset(new FrameManifestManagerHost(this, render_frame_host));
|
| + return *host;
|
| }
|
|
|
| -} // namespace content
|
| +} // namespace content
|
|
|