Add ICU message format support
[chromium-blink-merge.git] / content / browser / manifest / manifest_manager_host.cc
bloba978f70295b859da87c36cf55f8bba2703228256
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"
14 namespace content {
16 namespace {
18 void KillRenderer(RenderFrameHost* render_frame_host) {
19 base::ProcessHandle process_handle =
20 render_frame_host->GetProcess()->GetHandle();
21 if (process_handle == base::kNullProcessHandle)
22 return;
23 render_frame_host->GetProcess()->Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE,
24 false);
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);
46 if (!callbacks)
47 return;
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());
57 delete callbacks;
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);
64 if (!callbacks) {
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) {
77 bool handled = true;
79 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ManifestManagerHost, message,
80 render_frame_host)
81 IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse,
82 OnRequestManifestResponse)
83 IPC_MESSAGE_UNHANDLED(handled = false)
84 IPC_END_MESSAGE_MAP()
86 return handled;
89 void ManifestManagerHost::OnRequestManifestResponse(
90 RenderFrameHost* render_frame_host,
91 int request_id,
92 const Manifest& insecure_manifest) {
93 CallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
94 if (!callbacks) {
95 DVLOG(1) << "Unexpected RequestManifestResponse to from renderer. "
96 "Killing renderer.";
97 KillRenderer(render_frame_host);
98 return;
101 GetManifestCallback* callback = callbacks->Lookup(request_id);
102 if (!callback) {
103 DVLOG(1) << "Received a request_id (" << request_id << ") from renderer "
104 "with no associated callback. Killing renderer.";
105 KillRenderer(render_frame_host);
106 return;
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 (auto& icon : manifest.icons) {
121 if (!icon.src.is_valid())
122 icon.src = GURL();
123 icon.type = base::NullableString16(
124 icon.type.string().substr(0, Manifest::kMaxIPCStringLength),
125 icon.type.is_null());
127 manifest.gcm_sender_id = base::NullableString16(
128 manifest.gcm_sender_id.string().substr(
129 0, Manifest::kMaxIPCStringLength),
130 manifest.gcm_sender_id.is_null());
131 for (auto& related_application : manifest.related_applications) {
132 if (!related_application.url.is_valid())
133 related_application.url = GURL();
134 related_application.id =
135 base::NullableString16(related_application.id.string().substr(
136 0, Manifest::kMaxIPCStringLength),
137 related_application.id.is_null());
139 // theme_color is a 32 bit unsigned integer with a 64 bit integer simply
140 // being used to encode an error occuring. Therefore, any value outside the
141 // range of an unsigned 32 bit integer is invalid.
142 if (manifest.theme_color < 0 || manifest.theme_color > 0xFFFFFFFF)
143 manifest.theme_color = Manifest::kInvalidOrMissingThemeColor;
145 callback->Run(manifest);
146 callbacks->Remove(request_id);
147 if (callbacks->IsEmpty()) {
148 delete callbacks;
149 pending_callbacks_.erase(render_frame_host);
153 } // namespace content