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 "base/stl_util.h"
8 #include "content/common/manifest_manager_messages.h"
9 #include "content/public/browser/render_frame_host.h"
10 #include "content/public/browser/render_process_host.h"
11 #include "content/public/common/manifest.h"
12 #include "content/public/common/result_codes.h"
18 void KillRenderer(RenderFrameHost
* render_frame_host
) {
19 base::ProcessHandle process_handle
=
20 render_frame_host
->GetProcess()->GetHandle();
21 if (process_handle
== base::kNullProcessHandle
)
23 render_frame_host
->GetProcess()->Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE
,
27 } // anonymous namespace
29 ManifestManagerHost::ManifestManagerHost(WebContents
* web_contents
)
30 : WebContentsObserver(web_contents
) {
33 ManifestManagerHost::~ManifestManagerHost() {
34 STLDeleteValues(&pending_callbacks_
);
37 ManifestManagerHost::CallbackMap
* ManifestManagerHost::GetCallbackMapForFrame(
38 RenderFrameHost
* render_frame_host
) {
39 FrameCallbackMap::iterator it
= pending_callbacks_
.find(render_frame_host
);
40 return it
!= pending_callbacks_
.end() ? it
->second
: 0;
43 void ManifestManagerHost::RenderFrameDeleted(
44 RenderFrameHost
* render_frame_host
) {
45 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
49 // Before deleting the callbacks, make sure they are called with a failure
50 // state. Do this in a block so the iterator is destroyed before |callbacks|.
52 CallbackMap::const_iterator
it(callbacks
);
53 for (; !it
.IsAtEnd(); it
.Advance())
54 it
.GetCurrentValue()->Run(Manifest());
58 pending_callbacks_
.erase(render_frame_host
);
61 void ManifestManagerHost::GetManifest(RenderFrameHost
* render_frame_host
,
62 const GetManifestCallback
& callback
) {
63 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
65 callbacks
= new CallbackMap();
66 pending_callbacks_
[render_frame_host
] = callbacks
;
69 int request_id
= callbacks
->Add(new GetManifestCallback(callback
));
71 render_frame_host
->Send(new ManifestManagerMsg_RequestManifest(
72 render_frame_host
->GetRoutingID(), request_id
));
75 bool ManifestManagerHost::OnMessageReceived(
76 const IPC::Message
& message
, RenderFrameHost
* render_frame_host
) {
79 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ManifestManagerHost
, message
,
81 IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse
,
82 OnRequestManifestResponse
)
83 IPC_MESSAGE_UNHANDLED(handled
= false)
89 void ManifestManagerHost::OnRequestManifestResponse(
90 RenderFrameHost
* render_frame_host
,
92 const Manifest
& insecure_manifest
) {
93 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
95 DVLOG(1) << "Unexpected RequestManifestResponse to from renderer. "
97 KillRenderer(render_frame_host
);
101 GetManifestCallback
* callback
= callbacks
->Lookup(request_id
);
103 DVLOG(1) << "Received a request_id (" << request_id
<< ") from renderer "
104 "with no associated callback. Killing renderer.";
105 KillRenderer(render_frame_host
);
109 // When receiving a Manifest, the browser process can't trust that it is
110 // coming from a known and secure source. It must be processed accordingly.
111 Manifest manifest
= insecure_manifest
;
112 manifest
.name
= base::NullableString16(
113 manifest
.name
.string().substr(0, Manifest::kMaxIPCStringLength
),
114 manifest
.name
.is_null());
115 manifest
.short_name
= base::NullableString16(
116 manifest
.short_name
.string().substr(0, Manifest::kMaxIPCStringLength
),
117 manifest
.short_name
.is_null());
118 if (!manifest
.start_url
.is_valid())
119 manifest
.start_url
= GURL();
120 for (size_t i
= 0; i
< manifest
.icons
.size(); ++i
) {
121 if (!manifest
.icons
[i
].src
.is_valid())
122 manifest
.icons
[i
].src
= GURL();
123 manifest
.icons
[i
].type
= base::NullableString16(
124 manifest
.icons
[i
].type
.string().substr(0,
125 Manifest::kMaxIPCStringLength
),
126 manifest
.icons
[i
].type
.is_null());
128 manifest
.gcm_sender_id
= base::NullableString16(
129 manifest
.gcm_sender_id
.string().substr(
130 0, Manifest::kMaxIPCStringLength
),
131 manifest
.gcm_sender_id
.is_null());
133 callback
->Run(manifest
);
134 callbacks
->Remove(request_id
);
135 if (callbacks
->IsEmpty()) {
137 pending_callbacks_
.erase(render_frame_host
);
141 } // namespace content