11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/manifest/manifest_manager_host.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/common/manifest_manager_messages.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/render_frame_host.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/render_process_host.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/common/manifest.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/common/result_codes.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace content { 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid KillRenderer(RenderFrameHost* render_frame_host) { 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ProcessHandle process_handle = 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_host->GetProcess()->GetHandle(); 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (process_handle == base::kNullProcessHandle) 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::KillProcess(process_handle, RESULT_CODE_KILLED_BAD_MESSAGE, false); 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // anonymous namespace 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciManifestManagerHost::ManifestManagerHost(WebContents* web_contents) 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : WebContentsObserver(web_contents) { 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciManifestManagerHost::~ManifestManagerHost() { 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciManifestManagerHost::CallbackMap* ManifestManagerHost::GetCallbackMapForFrame( 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RenderFrameHost* render_frame_host) { 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FrameCallbackMap::iterator it = pending_callbacks_.find(render_frame_host); 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return it != pending_callbacks_.end() ? it->second : 0; 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ManifestManagerHost::RenderFrameDeleted( 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RenderFrameHost* render_frame_host) { 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host); 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!callbacks) 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Before deleting the callbacks, make sure they are called with a failure 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // state. 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CallbackMap::const_iterator it(callbacks); 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (; !it.IsAtEnd(); it.Advance()) 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it.GetCurrentValue()->Run(Manifest()); 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_callbacks_.erase(render_frame_host); 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ManifestManagerHost::GetManifest(RenderFrameHost* render_frame_host, 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GetManifestCallback& callback) { 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host); 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!callbacks) { 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callbacks = new CallbackMap(); 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_callbacks_[render_frame_host] = callbacks; 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int request_id = callbacks->Add(new GetManifestCallback(callback)); 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_host->Send(new ManifestManagerMsg_RequestManifest( 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_host->GetRoutingID(), request_id)); 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ManifestManagerHost::OnMessageReceived( 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const IPC::Message& message, RenderFrameHost* render_frame_host) { 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool handled = true; 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ManifestManagerHost, message, 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_host) 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse, 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnRequestManifestResponse) 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_UNHANDLED(handled = false) 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_END_MESSAGE_MAP() 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return handled; 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ManifestManagerHost::OnRequestManifestResponse( 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RenderFrameHost* render_frame_host, 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int request_id, 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Manifest& insecure_manifest) { 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host); 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!callbacks) { 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << "Unexpected RequestManifestResponse to from renderer. " 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Killing renderer."; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci KillRenderer(render_frame_host); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetManifestCallback* callback = callbacks->Lookup(request_id); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!callback) { 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(1) << "Received a request_id (" << request_id << ") from renderer " 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "with no associated callback. Killing renderer."; 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci KillRenderer(render_frame_host); 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // When receiving a Manifest, the browser process can't trust that it is 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // coming from a known and secure source. It must be processed accordingly. 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Manifest manifest = insecure_manifest; 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.name = base::NullableString16( 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.name.string().substr(0, Manifest::kMaxIPCStringLength), 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.name.is_null()); 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.short_name = base::NullableString16( 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.short_name.string().substr(0, Manifest::kMaxIPCStringLength), 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.short_name.is_null()); 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!manifest.start_url.is_valid()) 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.start_url = GURL(); 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < manifest.icons.size(); ++i) { 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!manifest.icons[i].src.is_valid()) 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.icons[i].src = GURL(); 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.icons[i].type = base::NullableString16( 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.icons[i].type.string().substr(0, 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Manifest::kMaxIPCStringLength), 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manifest.icons[i].type.is_null()); 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback->Run(manifest); 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callbacks->Remove(request_id); 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (callbacks->IsEmpty()) { 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delete callbacks; 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_callbacks_.erase(render_frame_host); 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace content 132