Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: chrome/renderer/extensions/request_sender.cc

Issue 11571014: Lazy load chrome.* APIs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: windows interactive_ui_tests fix Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/extensions/request_sender.h" 5 #include "chrome/renderer/extensions/request_sender.h"
6 6
7 #include "base/values.h" 7 #include "base/values.h"
8 #include "chrome/common/extensions/extension_messages.h" 8 #include "chrome/common/extensions/extension_messages.h"
9 #include "chrome/renderer/extensions/chrome_v8_context.h" 9 #include "chrome/renderer/extensions/chrome_v8_context.h"
10 #include "chrome/renderer/extensions/chrome_v8_context_set.h"
11 #include "chrome/renderer/extensions/dispatcher.h" 10 #include "chrome/renderer/extensions/dispatcher.h"
12 #include "content/public/renderer/render_view.h" 11 #include "content/public/renderer/render_view.h"
13 #include "content/public/renderer/v8_value_converter.h" 12 #include "content/public/renderer/v8_value_converter.h"
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
17 16
18 using content::V8ValueConverter; 17 using content::V8ValueConverter;
19 18
20 namespace extensions { 19 namespace extensions {
21 20
22 // Contains info relevant to a pending API request. 21 // Contains info relevant to a pending API request.
23 struct PendingRequest { 22 struct PendingRequest {
24 public : 23 public :
25 PendingRequest(v8::Persistent<v8::Context> context, const std::string& name, 24 PendingRequest(ChromeV8Context* context,
26 const std::string& extension_id) 25 ChromeV8Context* caller_context,
27 : context(context), name(name), extension_id(extension_id) { 26 const std::string& name)
27 : name(name), context(context), caller_context(caller_context) {
28 } 28 }
29 29
30 ~PendingRequest() {
31 context.Dispose(context->GetIsolate());
32 }
33
34 v8::Persistent<v8::Context> context;
35 std::string name; 30 std::string name;
36 std::string extension_id; 31 ChromeV8Context* context;
32 ChromeV8Context* caller_context;
37 }; 33 };
38 34
39 RequestSender::RequestSender(Dispatcher* dispatcher, 35 RequestSender::RequestSender(Dispatcher* dispatcher) : dispatcher_(dispatcher) {
40 ChromeV8ContextSet* context_set)
41 : dispatcher_(dispatcher), context_set_(context_set) {
42 } 36 }
43 37
44 RequestSender::~RequestSender() { 38 RequestSender::~RequestSender() {
45 } 39 }
46 40
47 void RequestSender::InsertRequest(int request_id, 41 void RequestSender::InsertRequest(int request_id,
48 PendingRequest* pending_request) { 42 PendingRequest* pending_request) {
49 DCHECK_EQ(0u, pending_requests_.count(request_id)); 43 DCHECK_EQ(0u, pending_requests_.count(request_id));
50 pending_requests_[request_id].reset(pending_request); 44 pending_requests_[request_id].reset(pending_request);
51 } 45 }
52 46
53 linked_ptr<PendingRequest> RequestSender::RemoveRequest(int request_id) { 47 linked_ptr<PendingRequest> RequestSender::RemoveRequest(int request_id) {
54 PendingRequestMap::iterator i = pending_requests_.find(request_id); 48 PendingRequestMap::iterator i = pending_requests_.find(request_id);
55 if (i == pending_requests_.end()) 49 if (i == pending_requests_.end())
56 return linked_ptr<PendingRequest>(); 50 return linked_ptr<PendingRequest>();
57 linked_ptr<PendingRequest> result = i->second; 51 linked_ptr<PendingRequest> result = i->second;
58 pending_requests_.erase(i); 52 pending_requests_.erase(i);
59 return result; 53 return result;
60 } 54 }
61 55
62 void RequestSender::StartRequest(const std::string& name, 56 void RequestSender::StartRequest(ChromeV8Context* context,
57 const std::string& name,
63 int request_id, 58 int request_id,
64 bool has_callback, 59 bool has_callback,
65 bool for_io_thread, 60 bool for_io_thread,
66 base::ListValue* value_args) { 61 base::ListValue* value_args) {
67 ChromeV8Context* current_context = context_set_->GetCurrent();
68 if (!current_context)
69 return;
70
71 // Get the current RenderView so that we can send a routed IPC message from 62 // Get the current RenderView so that we can send a routed IPC message from
72 // the correct source. 63 // the correct source.
73 content::RenderView* renderview = current_context->GetRenderView(); 64 content::RenderView* renderview = context->GetRenderView();
74 if (!renderview) 65 if (!renderview)
75 return; 66 return;
76 67
77 const std::set<std::string>& function_names = dispatcher_->function_names(); 68 const std::set<std::string>& function_names = dispatcher_->function_names();
78 if (function_names.find(name) == function_names.end()) { 69 if (function_names.find(name) == function_names.end()) {
79 NOTREACHED() << "Unexpected function " << name << 70 NOTREACHED() << "Unexpected function " << name <<
80 ". Did you remember to register it with ExtensionFunctionRegistry?"; 71 ". Did you remember to register it with ExtensionFunctionRegistry?";
81 return; 72 return;
82 } 73 }
83 74
84 // TODO(koz): See if we can make this a CHECK. 75 // TODO(koz): See if we can make this a CHECK.
85 if (!dispatcher_->CheckCurrentContextAccessToExtensionAPI(name)) 76 if (!dispatcher_->CheckContextAccessToExtensionAPI(name, context))
86 return; 77 return;
87 78
88 GURL source_url; 79 GURL source_url;
89 WebKit::WebSecurityOrigin source_origin; 80 WebKit::WebSecurityOrigin source_origin;
90 WebKit::WebFrame* webframe = current_context->web_frame(); 81 WebKit::WebFrame* webframe = context->web_frame();
91 if (webframe) { 82 if (webframe) {
92 source_url = webframe->document().url(); 83 source_url = webframe->document().url();
93 source_origin = webframe->document().securityOrigin(); 84 source_origin = webframe->document().securityOrigin();
94 } 85 }
95 86
96 v8::Local<v8::Context> ctx = v8::Context::GetCurrent(); 87 std::string extension_id = context->GetExtensionID();
97 v8::Persistent<v8::Context> v8_context = 88 // Insert the current context into the PendingRequest because that's the
98 v8::Persistent<v8::Context>::New(ctx->GetIsolate(), ctx); 89 // context that we call back on.
99 DCHECK(!v8_context.IsEmpty()); 90 InsertRequest(
100 91 request_id,
101 std::string extension_id = current_context->GetExtensionID(); 92 new PendingRequest(context,
102 InsertRequest(request_id, new PendingRequest( 93 dispatcher_->v8_context_set().GetCurrent(),
103 v8_context, name, extension_id)); 94 name));
104 95
105 ExtensionHostMsg_Request_Params params; 96 ExtensionHostMsg_Request_Params params;
106 params.name = name; 97 params.name = name;
107 params.arguments.Swap(value_args); 98 params.arguments.Swap(value_args);
108 params.extension_id = extension_id; 99 params.extension_id = extension_id;
109 params.source_url = source_url; 100 params.source_url = source_url;
110 params.source_origin = source_origin.toString(); 101 params.source_origin = source_origin.toString();
111 params.request_id = request_id; 102 params.request_id = request_id;
112 params.has_callback = has_callback; 103 params.has_callback = has_callback;
113 params.user_gesture = 104 params.user_gesture =
114 webframe ? webframe->isProcessingUserGesture() : false; 105 webframe ? webframe->isProcessingUserGesture() : false;
115 if (for_io_thread) { 106 if (for_io_thread) {
116 renderview->Send(new ExtensionHostMsg_RequestForIOThread( 107 renderview->Send(new ExtensionHostMsg_RequestForIOThread(
117 renderview->GetRoutingID(), params)); 108 renderview->GetRoutingID(), params));
118 } else { 109 } else {
119 renderview->Send(new ExtensionHostMsg_Request( 110 renderview->Send(new ExtensionHostMsg_Request(
120 renderview->GetRoutingID(), params)); 111 renderview->GetRoutingID(), params));
121 } 112 }
122 } 113 }
123 114
124 void RequestSender::HandleResponse(int request_id, 115 void RequestSender::HandleResponse(int request_id,
125 bool success, 116 bool success,
126 const base::ListValue& responseList, 117 const base::ListValue& responseList,
127 const std::string& error) { 118 const std::string& error) {
128 linked_ptr<PendingRequest> request = RemoveRequest(request_id); 119 linked_ptr<PendingRequest> request = RemoveRequest(request_id);
129 120
130 if (!request.get()) { 121 if (!request.get()) {
131 // This should not be able to happen since we only remove requests when 122 // This can happen if a context is destroyed while a request is in flight.
132 // they are handled.
133 LOG(ERROR) << "Could not find specified request id: " << request_id;
134 return; 123 return;
135 } 124 }
136 125
137 ChromeV8Context* v8_context = context_set_->GetByV8Context(request->context);
138 if (!v8_context)
139 return; // The frame went away.
140
141 v8::HandleScope handle_scope; 126 v8::HandleScope handle_scope;
142 127
143 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); 128 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
144 v8::Handle<v8::Value> argv[] = { 129 v8::Handle<v8::Value> argv[] = {
145 v8::Integer::New(request_id), 130 v8::Integer::New(request_id),
146 v8::String::New(request->name.c_str()), 131 v8::String::New(request->name.c_str()),
147 v8::Boolean::New(success), 132 v8::Boolean::New(success),
148 converter->ToV8Value(&responseList, v8_context->v8_context()), 133 converter->ToV8Value(&responseList, request->context->v8_context()),
149 v8::String::New(error.c_str()) 134 v8::String::New(error.c_str())
150 }; 135 };
151 136
152 v8::Handle<v8::Value> retval; 137 v8::Handle<v8::Value> retval;
153 CHECK(v8_context->CallChromeHiddenMethod("handleResponse", 138 CHECK(request->context->CallChromeHiddenMethod("handleResponse",
154 arraysize(argv), 139 arraysize(argv),
155 argv, 140 argv,
156 &retval)); 141 &retval));
157 // In debug, the js will validate the callback parameters and return a 142 // In debug, the js will validate the callback parameters and return a
158 // string if a validation error has occured. 143 // string if a validation error has occured.
159 if (DCHECK_IS_ON()) { 144 if (DCHECK_IS_ON()) {
160 if (!retval.IsEmpty() && !retval->IsUndefined()) { 145 if (!retval.IsEmpty() && !retval->IsUndefined()) {
161 std::string error = *v8::String::AsciiValue(retval); 146 std::string error = *v8::String::AsciiValue(retval);
162 DCHECK(false) << error; 147 DCHECK(false) << error;
163 } 148 }
164 } 149 }
165 } 150 }
166 151
152 void RequestSender::InvalidateContext(ChromeV8Context* context) {
153 for (PendingRequestMap::iterator it = pending_requests_.begin();
154 it != pending_requests_.end();) {
155 if (it->second->context == context)
156 pending_requests_.erase(it++);
157 else
158 ++it;
159 }
160 }
161
167 } // namespace extensions 162 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698