1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/manifest/manifest_manager_host.h"
7 #include "content/common/manifest_manager_messages.h"
8 #include "content/public/browser/render_frame_host.h"
9 #include "content/public/browser/render_process_host.h"
10 #include "content/public/common/manifest.h"
11 #include "content/public/common/result_codes.h"
17 void KillRenderer(RenderFrameHost
* render_frame_host
) {
18 base::ProcessHandle process_handle
=
19 render_frame_host
->GetProcess()->GetHandle();
20 if (process_handle
== base::kNullProcessHandle
)
22 base::KillProcess(process_handle
, RESULT_CODE_KILLED_BAD_MESSAGE
, false);
25 } // anonymous namespace
27 ManifestManagerHost::ManifestManagerHost(WebContents
* web_contents
)
28 : WebContentsObserver(web_contents
) {
31 ManifestManagerHost::~ManifestManagerHost() {
34 ManifestManagerHost::CallbackMap
* ManifestManagerHost::GetCallbackMapForFrame(
35 RenderFrameHost
* render_frame_host
) {
36 FrameCallbackMap::iterator it
= pending_callbacks_
.find(render_frame_host
);
37 return it
!= pending_callbacks_
.end() ? it
->second
: 0;
40 void ManifestManagerHost::RenderFrameDeleted(
41 RenderFrameHost
* render_frame_host
) {
42 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
46 // Before deleting the callbacks, make sure they are called with a failure
47 // state. Do this in a block so the iterator is destroyed before |callbacks|.
49 CallbackMap::const_iterator
it(callbacks
);
50 for (; !it
.IsAtEnd(); it
.Advance())
51 it
.GetCurrentValue()->Run(Manifest());
55 pending_callbacks_
.erase(render_frame_host
);
58 void ManifestManagerHost::GetManifest(RenderFrameHost
* render_frame_host
,
59 const GetManifestCallback
& callback
) {
60 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
62 callbacks
= new CallbackMap();
63 pending_callbacks_
[render_frame_host
] = callbacks
;
66 int request_id
= callbacks
->Add(new GetManifestCallback(callback
));
68 render_frame_host
->Send(new ManifestManagerMsg_RequestManifest(
69 render_frame_host
->GetRoutingID(), request_id
));
72 bool ManifestManagerHost::OnMessageReceived(
73 const IPC::Message
& message
, RenderFrameHost
* render_frame_host
) {
76 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ManifestManagerHost
, message
,
78 IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse
,
79 OnRequestManifestResponse
)
80 IPC_MESSAGE_UNHANDLED(handled
= false)
86 void ManifestManagerHost::OnRequestManifestResponse(
87 RenderFrameHost
* render_frame_host
,
89 const Manifest
& insecure_manifest
) {
90 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
92 DVLOG(1) << "Unexpected RequestManifestResponse to from renderer. "
94 KillRenderer(render_frame_host
);
98 GetManifestCallback
* callback
= callbacks
->Lookup(request_id
);
100 DVLOG(1) << "Received a request_id (" << request_id
<< ") from renderer "
101 "with no associated callback. Killing renderer.";
102 KillRenderer(render_frame_host
);
106 // When receiving a Manifest, the browser process can't trust that it is
107 // coming from a known and secure source. It must be processed accordingly.
108 Manifest manifest
= insecure_manifest
;
109 manifest
.name
= base::NullableString16(
110 manifest
.name
.string().substr(0, Manifest::kMaxIPCStringLength
),
111 manifest
.name
.is_null());
112 manifest
.short_name
= base::NullableString16(
113 manifest
.short_name
.string().substr(0, Manifest::kMaxIPCStringLength
),
114 manifest
.short_name
.is_null());
115 if (!manifest
.start_url
.is_valid())
116 manifest
.start_url
= GURL();
117 for (size_t i
= 0; i
< manifest
.icons
.size(); ++i
) {
118 if (!manifest
.icons
[i
].src
.is_valid())
119 manifest
.icons
[i
].src
= GURL();
120 manifest
.icons
[i
].type
= base::NullableString16(
121 manifest
.icons
[i
].type
.string().substr(0,
122 Manifest::kMaxIPCStringLength
),
123 manifest
.icons
[i
].type
.is_null());
125 manifest
.gcm_sender_id
= base::NullableString16(
126 manifest
.gcm_sender_id
.string().substr(
127 0, Manifest::kMaxIPCStringLength
),
128 manifest
.gcm_sender_id
.is_null());
130 callback
->Run(manifest
);
131 callbacks
->Remove(request_id
);
132 if (callbacks
->IsEmpty()) {
134 pending_callbacks_
.erase(render_frame_host
);
138 } // namespace content