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 render_frame_host
->GetProcess()->Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE
,
26 } // anonymous namespace
28 ManifestManagerHost::ManifestManagerHost(WebContents
* web_contents
)
29 : WebContentsObserver(web_contents
) {
32 ManifestManagerHost::~ManifestManagerHost() {
35 ManifestManagerHost::CallbackMap
* ManifestManagerHost::GetCallbackMapForFrame(
36 RenderFrameHost
* render_frame_host
) {
37 FrameCallbackMap::iterator it
= pending_callbacks_
.find(render_frame_host
);
38 return it
!= pending_callbacks_
.end() ? it
->second
: 0;
41 void ManifestManagerHost::RenderFrameDeleted(
42 RenderFrameHost
* render_frame_host
) {
43 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
47 // Before deleting the callbacks, make sure they are called with a failure
48 // state. Do this in a block so the iterator is destroyed before |callbacks|.
50 CallbackMap::const_iterator
it(callbacks
);
51 for (; !it
.IsAtEnd(); it
.Advance())
52 it
.GetCurrentValue()->Run(Manifest());
56 pending_callbacks_
.erase(render_frame_host
);
59 void ManifestManagerHost::GetManifest(RenderFrameHost
* render_frame_host
,
60 const GetManifestCallback
& callback
) {
61 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
63 callbacks
= new CallbackMap();
64 pending_callbacks_
[render_frame_host
] = callbacks
;
67 int request_id
= callbacks
->Add(new GetManifestCallback(callback
));
69 render_frame_host
->Send(new ManifestManagerMsg_RequestManifest(
70 render_frame_host
->GetRoutingID(), request_id
));
73 bool ManifestManagerHost::OnMessageReceived(
74 const IPC::Message
& message
, RenderFrameHost
* render_frame_host
) {
77 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ManifestManagerHost
, message
,
79 IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse
,
80 OnRequestManifestResponse
)
81 IPC_MESSAGE_UNHANDLED(handled
= false)
87 void ManifestManagerHost::OnRequestManifestResponse(
88 RenderFrameHost
* render_frame_host
,
90 const Manifest
& insecure_manifest
) {
91 CallbackMap
* callbacks
= GetCallbackMapForFrame(render_frame_host
);
93 DVLOG(1) << "Unexpected RequestManifestResponse to from renderer. "
95 KillRenderer(render_frame_host
);
99 GetManifestCallback
* callback
= callbacks
->Lookup(request_id
);
101 DVLOG(1) << "Received a request_id (" << request_id
<< ") from renderer "
102 "with no associated callback. Killing renderer.";
103 KillRenderer(render_frame_host
);
107 // When receiving a Manifest, the browser process can't trust that it is
108 // coming from a known and secure source. It must be processed accordingly.
109 Manifest manifest
= insecure_manifest
;
110 manifest
.name
= base::NullableString16(
111 manifest
.name
.string().substr(0, Manifest::kMaxIPCStringLength
),
112 manifest
.name
.is_null());
113 manifest
.short_name
= base::NullableString16(
114 manifest
.short_name
.string().substr(0, Manifest::kMaxIPCStringLength
),
115 manifest
.short_name
.is_null());
116 if (!manifest
.start_url
.is_valid())
117 manifest
.start_url
= GURL();
118 for (size_t i
= 0; i
< manifest
.icons
.size(); ++i
) {
119 if (!manifest
.icons
[i
].src
.is_valid())
120 manifest
.icons
[i
].src
= GURL();
121 manifest
.icons
[i
].type
= base::NullableString16(
122 manifest
.icons
[i
].type
.string().substr(0,
123 Manifest::kMaxIPCStringLength
),
124 manifest
.icons
[i
].type
.is_null());
126 manifest
.gcm_sender_id
= base::NullableString16(
127 manifest
.gcm_sender_id
.string().substr(
128 0, Manifest::kMaxIPCStringLength
),
129 manifest
.gcm_sender_id
.is_null());
131 callback
->Run(manifest
);
132 callbacks
->Remove(request_id
);
133 if (callbacks
->IsEmpty()) {
135 pending_callbacks_
.erase(render_frame_host
);
139 } // namespace content