19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Copyright (c) 2012 The Chromium Authors. All rights reserved. 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Use of this source code is governed by a BSD-style license that can be 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// found in the LICENSE file. 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "chrome/renderer/extensions/request_sender.h" 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "base/values.h" 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "chrome/common/extensions/extension_messages.h" 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "chrome/renderer/extensions/chrome_v8_context.h" 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "chrome/renderer/extensions/dispatcher.h" 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "content/public/renderer/render_view.h" 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "third_party/WebKit/public/web/WebDocument.h" 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "third_party/WebKit/public/web/WebFrame.h" 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace extensions { 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Contains info relevant to a pending API request. 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct PendingRequest { 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public : 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingRequest(const std::string& name, RequestSender::Source* source) 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : name(name), source(source) { 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string name; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RequestSender::Source* source; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectRequestSender::RequestSender(Dispatcher* dispatcher) : dispatcher_(dispatcher) { 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectRequestSender::~RequestSender() { 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid RequestSender::InsertRequest(int request_id, 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingRequest* pending_request) { 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DCHECK_EQ(0u, pending_requests_.count(request_id)); 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pending_requests_[request_id].reset(pending_request); 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectlinked_ptr<PendingRequest> RequestSender::RemoveRequest(int request_id) { 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingRequestMap::iterator i = pending_requests_.find(request_id); 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i == pending_requests_.end()) 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return linked_ptr<PendingRequest>(); 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project linked_ptr<PendingRequest> result = i->second; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pending_requests_.erase(i); 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint RequestSender::GetNextRequestId() const { 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static int next_request_id = 0; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return next_request_id++; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 540f9ae274b4a9641d8e6933108466dc432f5a0474Gilles Debunne 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid RequestSender::StartRequest(Source* source, 560f9ae274b4a9641d8e6933108466dc432f5a0474Gilles Debunne const std::string& name, 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int request_id, 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool has_callback, 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool for_io_thread, 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base::ListValue* value_args) { 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ChromeV8Context* context = source->GetContext(); 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!context) 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the current RenderView so that we can send a routed IPC message from 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the correct source. 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project content::RenderView* renderview = context->GetRenderView(); 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!renderview) 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 71d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien const std::set<std::string>& function_names = dispatcher_->function_names(); 72d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien if (function_names.find(name) == function_names.end()) { 73d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien NOTREACHED() << "Unexpected function " << name << 74d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien ". Did you remember to register it with ExtensionFunctionRegistry?"; 75d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien return; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 77d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien 78d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien // TODO(koz): See if we can make this a CHECK. 79d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien if (!dispatcher_->CheckContextAccessToExtensionAPI(name, context)) 80d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien return; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 82d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien GURL source_url; 83d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien if (blink::WebFrame* webframe = context->web_frame()) 84d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien source_url = webframe->document().url(); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 86d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien InsertRequest(request_id, new PendingRequest(name, source)); 87d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien 88d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien ExtensionHostMsg_Request_Params params; 89d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien params.name = name; 90d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien params.arguments.Swap(value_args); 91d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien params.extension_id = context->GetExtensionID(); 92d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien params.source_url = source_url; 93d570e8987ae50ee101c3d4cfa973e1a6b6ecc8f5Raph Levien params.request_id = request_id; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project params.has_callback = has_callback; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project params.user_gesture = 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project blink::WebUserGestureIndicator::isProcessingUserGesture(); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (for_io_thread) { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project renderview->Send(new ExtensionHostMsg_RequestForIOThread( 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project renderview->GetRoutingID(), params)); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project renderview->Send(new ExtensionHostMsg_Request( 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project renderview->GetRoutingID(), params)); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid RequestSender::HandleResponse(int request_id, 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool success, 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const base::ListValue& response, 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const std::string& error) { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project linked_ptr<PendingRequest> request = RemoveRequest(request_id); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!request.get()) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This can happen if a context is destroyed while a request is in flight. 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project request->source->OnResponseReceived(request->name, request_id, success, 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project response, error); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid RequestSender::InvalidateSource(Source* source) { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (PendingRequestMap::iterator it = pending_requests_.begin(); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project it != pending_requests_.end();) { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (it->second->source == source) 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pending_requests_.erase(it++); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ++it; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace extensions 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project