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

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

Issue 175263003: Add chrome.webstore API methods to allow sites to see progress of installation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: separate pure-virtual change Created 6 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
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/webstore_bindings.h" 5 #include "chrome/renderer/extensions/webstore_bindings.h"
6 6
7 #include "base/strings/string_util.h" 7 #include "base/strings/string_util.h"
8 #include "chrome/common/extensions/api/webstore/webstore_api_constants.h"
8 #include "chrome/common/extensions/extension_constants.h" 9 #include "chrome/common/extensions/extension_constants.h"
9 #include "chrome/common/extensions/extension_messages.h" 10 #include "chrome/common/extensions/extension_messages.h"
10 #include "chrome/renderer/extensions/chrome_v8_context.h" 11 #include "chrome/renderer/extensions/chrome_v8_context.h"
11 #include "content/public/renderer/render_view.h" 12 #include "content/public/renderer/render_view.h"
12 #include "extensions/common/extension.h" 13 #include "extensions/common/extension.h"
13 #include "grit/renderer_resources.h" 14 #include "grit/renderer_resources.h"
14 #include "third_party/WebKit/public/web/WebDocument.h" 15 #include "third_party/WebKit/public/web/WebDocument.h"
15 #include "third_party/WebKit/public/web/WebElement.h" 16 #include "third_party/WebKit/public/web/WebElement.h"
16 #include "third_party/WebKit/public/web/WebNode.h" 17 #include "third_party/WebKit/public/web/WebNode.h"
17 #include "third_party/WebKit/public/web/WebNodeList.h" 18 #include "third_party/WebKit/public/web/WebNodeList.h"
(...skipping 21 matching lines...) Expand all
39 const char kFailureCallbackNotAFunctionError[] = 40 const char kFailureCallbackNotAFunctionError[] =
40 "The failure callback parameter must be a function."; 41 "The failure callback parameter must be a function.";
41 const char kNotInTopFrameError[] = 42 const char kNotInTopFrameError[] =
42 "Chrome Web Store installations can only be started by the top frame."; 43 "Chrome Web Store installations can only be started by the top frame.";
43 const char kNotUserGestureError[] = 44 const char kNotUserGestureError[] =
44 "Chrome Web Store installations can only be initated by a user gesture."; 45 "Chrome Web Store installations can only be initated by a user gesture.";
45 const char kNoWebstoreItemLinkFoundError[] = 46 const char kNoWebstoreItemLinkFoundError[] =
46 "No Chrome Web Store item link found."; 47 "No Chrome Web Store item link found.";
47 const char kInvalidWebstoreItemUrlError[] = 48 const char kInvalidWebstoreItemUrlError[] =
48 "Invalid Chrome Web Store item URL."; 49 "Invalid Chrome Web Store item URL.";
50 const char kInstallStageListenerCallbackNotAFunctionError[] =
51 "The listener callback for install stage change must be a function.";
52 const char kDownloadProgressListenerCallbackNotAFunctionError[] =
53 "The listener callback for download progress must be a function.";
not at google - send to devlin 2014/02/27 21:49:56 these sort of checks can be handled by the Event o
Devlin 2014/02/28 18:04:51 Done.
49 54
50 // chrome.webstore.install() calls generate an install ID so that the install's 55 // chrome.webstore.install() calls generate an install ID so that the install's
51 // callbacks may be fired when the browser notifies us of install completion 56 // callbacks may be fired when the browser notifies us of install completion
52 // (successful or not) via OnInlineWebstoreInstallResponse. 57 // (successful or not) via OnInlineWebstoreInstallResponse.
53 int g_next_install_id = 0; 58 int g_next_install_id = 0;
54 59
60 // Parses the given |args| to determine if a valid listener function argument
61 // was passed. NULL is considered valid, since it is used to unset the current
62 // listener.
63 // Returns true on success, false on failure. If successful,
64 // populates |is_listener_set| with whether or not the listener should be set.
65 bool GetIsListenerSet(const v8::FunctionCallbackInfo<v8::Value>& args,
66 bool* is_listener_set) {
67 if (args[0]->IsNull()) {
68 *is_listener_set = false;
69 return true;
70 }
71
72 if (args[0]->IsFunction()) {
73 *is_listener_set = true;
74 return true;
75 }
76
77 return false;
78 }
79
55 } // anonymous namespace 80 } // anonymous namespace
56 81
57 WebstoreBindings::WebstoreBindings(Dispatcher* dispatcher, 82 WebstoreBindings::WebstoreBindings(Dispatcher* dispatcher,
58 ChromeV8Context* context) 83 ChromeV8Context* context)
59 : ChromeV8Extension(dispatcher, context), 84 : ChromeV8Extension(dispatcher, context),
60 ChromeV8ExtensionHandler(context) { 85 ChromeV8ExtensionHandler(context) {
61 RouteFunction("Install", 86 RouteFunction("Install",
62 base::Bind(&WebstoreBindings::Install, base::Unretained(this))); 87 base::Bind(&WebstoreBindings::Install, base::Unretained(this)));
88 RouteFunction("ValidateInstallStageListener",
89 base::Bind(&WebstoreBindings::ValidateInstallStageListener,
90 base::Unretained(this)));
91 RouteFunction("ValidateDownloadProgressListener",
92 base::Bind(&WebstoreBindings::ValidateDownloadProgressListener,
93 base::Unretained(this)));
94 }
95
96 content::RenderView* WebstoreBindings::GetRenderView() {
97 WebFrame* frame = WebFrame::frameForContext(context()->v8_context());
98 if (!frame || !frame->view())
99 return NULL;
100 content::RenderView* render_view =
101 content::RenderView::FromWebView(frame->view());
102 return render_view;
63 } 103 }
64 104
65 void WebstoreBindings::Install( 105 void WebstoreBindings::Install(
66 const v8::FunctionCallbackInfo<v8::Value>& args) { 106 const v8::FunctionCallbackInfo<v8::Value>& args) {
67 WebFrame* frame = WebFrame::frameForContext(context()->v8_context()); 107 content::RenderView* render_view = GetRenderView();
68 if (!frame || !frame->view())
69 return;
70
71 content::RenderView* render_view =
72 content::RenderView::FromWebView(frame->view());
73 if (!render_view) 108 if (!render_view)
74 return; 109 return;
75 110
111 // The first two arguments, which indicate whether or not there are install
112 // stage and download progress listeners, are provided directly by the
113 // custom bindings, so should always be valid.
114 int listener_mask = 0;
115 if (args[0]->IsBoolean()) {
not at google - send to devlin 2014/02/27 21:49:56 so - *you* are calling the Install method. Rather
Devlin 2014/02/28 18:04:51 Done!
116 if (args[0]->BooleanValue())
117 listener_mask |= api::webstore::INSTALL_STAGE_LISTENER;
118 } else {
119 NOTREACHED();
120 return;
121 }
122 if (args[1]->IsBoolean()) {
123 if (args[1]->BooleanValue())
124 listener_mask |= api::webstore::DOWNLOAD_PROGRESS_LISTENER;
125 } else {
126 NOTREACHED();
127 return;
128 }
129
76 std::string preferred_store_link_url; 130 std::string preferred_store_link_url;
77 if (!args[0]->IsUndefined()) { 131 if (!args[2]->IsUndefined()) {
78 if (args[0]->IsString()) { 132 if (args[2]->IsString()) {
79 preferred_store_link_url = std::string(*v8::String::Utf8Value(args[0])); 133 preferred_store_link_url = std::string(*v8::String::Utf8Value(args[2]));
80 } else { 134 } else {
81 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 135 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
82 args.GetIsolate(), kPreferredStoreLinkUrlNotAString)); 136 args.GetIsolate(), kPreferredStoreLinkUrlNotAString));
83 return; 137 return;
84 } 138 }
85 } 139 }
86 140
87 std::string webstore_item_id; 141 std::string webstore_item_id;
88 std::string error; 142 std::string error;
143 WebFrame* frame = WebFrame::frameForContext(context()->v8_context());
144
89 if (!GetWebstoreItemIdFromFrame( 145 if (!GetWebstoreItemIdFromFrame(
90 frame, preferred_store_link_url, &webstore_item_id, &error)) { 146 frame, preferred_store_link_url, &webstore_item_id, &error)) {
91 args.GetIsolate()->ThrowException( 147 args.GetIsolate()->ThrowException(
92 v8::String::NewFromUtf8(args.GetIsolate(), error.c_str())); 148 v8::String::NewFromUtf8(args.GetIsolate(), error.c_str()));
93 return; 149 return;
94 } 150 }
95 151
96 int install_id = g_next_install_id++; 152 int install_id = g_next_install_id++;
97 if (!args[1]->IsUndefined() && !args[1]->IsFunction()) { 153 if (!args[3]->IsUndefined() && !args[3]->IsFunction()) {
98 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 154 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
99 args.GetIsolate(), kSuccessCallbackNotAFunctionError)); 155 args.GetIsolate(), kSuccessCallbackNotAFunctionError));
100 return; 156 return;
101 } 157 }
102 158
103 if (!args[2]->IsUndefined() && !args[2]->IsFunction()) { 159 if (!args[4]->IsUndefined() && !args[4]->IsFunction()) {
104 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 160 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
105 args.GetIsolate(), kFailureCallbackNotAFunctionError)); 161 args.GetIsolate(), kFailureCallbackNotAFunctionError));
106 return; 162 return;
107 } 163 }
108 164
109 Send(new ExtensionHostMsg_InlineWebstoreInstall( 165 Send(new ExtensionHostMsg_InlineWebstoreInstall(render_view->GetRoutingID(),
110 render_view->GetRoutingID(), 166 install_id,
111 install_id, 167 GetRoutingID(),
112 GetRoutingID(), 168 webstore_item_id,
113 webstore_item_id, 169 frame->document().url(),
114 frame->document().url())); 170 listener_mask));
115 171
116 args.GetReturnValue().Set(static_cast<int32_t>(install_id)); 172 args.GetReturnValue().Set(static_cast<int32_t>(install_id));
117 } 173 }
118 174
175 void WebstoreBindings::ValidateInstallStageListener(
176 const v8::FunctionCallbackInfo<v8::Value>& args) {
177 content::RenderView* render_view = GetRenderView();
178 if (!render_view)
179 return;
180
181 bool is_listener_set = false;
182 if (!GetIsListenerSet(args, &is_listener_set)) {
183 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
184 args.GetIsolate(), kInstallStageListenerCallbackNotAFunctionError));
185 args.GetReturnValue().Set(false);
186 }
187 args.GetReturnValue().Set(true);
188 }
189
190 void WebstoreBindings::ValidateDownloadProgressListener(
191 const v8::FunctionCallbackInfo<v8::Value>& args) {
192 content::RenderView* render_view = GetRenderView();
193 if (!render_view)
194 return;
195
196 bool is_listener_set = false;
197 if (!GetIsListenerSet(args, &is_listener_set)) {
198 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
199 args.GetIsolate(), kDownloadProgressListenerCallbackNotAFunctionError));
200 args.GetReturnValue().Set(false);
201 }
202 args.GetReturnValue().Set(true);
203 }
204
119 // static 205 // static
120 bool WebstoreBindings::GetWebstoreItemIdFromFrame( 206 bool WebstoreBindings::GetWebstoreItemIdFromFrame(
121 WebFrame* frame, const std::string& preferred_store_link_url, 207 WebFrame* frame, const std::string& preferred_store_link_url,
122 std::string* webstore_item_id, std::string* error) { 208 std::string* webstore_item_id, std::string* error) {
123 if (frame != frame->top()) { 209 if (frame != frame->top()) {
124 *error = kNotInTopFrameError; 210 *error = kNotInTopFrameError;
125 return false; 211 return false;
126 } 212 }
127 213
128 if (!WebUserGestureIndicator::isProcessingUserGesture()) { 214 if (!WebUserGestureIndicator::isProcessingUserGesture()) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 } 286 }
201 287
202 *error = kNoWebstoreItemLinkFoundError; 288 *error = kNoWebstoreItemLinkFoundError;
203 return false; 289 return false;
204 } 290 }
205 291
206 bool WebstoreBindings::OnMessageReceived(const IPC::Message& message) { 292 bool WebstoreBindings::OnMessageReceived(const IPC::Message& message) {
207 IPC_BEGIN_MESSAGE_MAP(WebstoreBindings, message) 293 IPC_BEGIN_MESSAGE_MAP(WebstoreBindings, message)
208 IPC_MESSAGE_HANDLER(ExtensionMsg_InlineWebstoreInstallResponse, 294 IPC_MESSAGE_HANDLER(ExtensionMsg_InlineWebstoreInstallResponse,
209 OnInlineWebstoreInstallResponse) 295 OnInlineWebstoreInstallResponse)
296 IPC_MESSAGE_HANDLER(ExtensionMsg_InlineInstallStageChanged,
297 OnInlineInstallStageChanged)
298 IPC_MESSAGE_HANDLER(ExtensionMsg_InlineInstallDownloadProgress,
299 OnInlineInstallDownloadProgress)
210 IPC_MESSAGE_UNHANDLED(CHECK(false) << "Unhandled IPC message") 300 IPC_MESSAGE_UNHANDLED(CHECK(false) << "Unhandled IPC message")
211 IPC_END_MESSAGE_MAP() 301 IPC_END_MESSAGE_MAP()
212 return true; 302 return true;
213 } 303 }
214 304
215 void WebstoreBindings::OnInlineWebstoreInstallResponse( 305 void WebstoreBindings::OnInlineWebstoreInstallResponse(
216 int install_id, 306 int install_id,
217 bool success, 307 bool success,
218 const std::string& error) { 308 const std::string& error) {
219 v8::Isolate* isolate = context()->isolate(); 309 v8::Isolate* isolate = context()->isolate();
220 v8::HandleScope handle_scope(isolate); 310 v8::HandleScope handle_scope(isolate);
221 v8::Context::Scope context_scope(context()->v8_context()); 311 v8::Context::Scope context_scope(context()->v8_context());
222 v8::Handle<v8::Value> argv[] = { 312 v8::Handle<v8::Value> argv[] = {
223 v8::Integer::New(isolate, install_id), 313 v8::Integer::New(isolate, install_id),
224 v8::Boolean::New(isolate, success), 314 v8::Boolean::New(isolate, success),
225 v8::String::NewFromUtf8(isolate, error.c_str()) 315 v8::String::NewFromUtf8(isolate, error.c_str())
226 }; 316 };
227 context()->module_system()->CallModuleMethod( 317 context()->module_system()->CallModuleMethod(
228 "webstore", "onInstallResponse", arraysize(argv), argv); 318 "webstore", "onInstallResponse", arraysize(argv), argv);
229 } 319 }
230 320
321 void WebstoreBindings::OnInlineInstallStageChanged(const std::string& stage) {
322 v8::Isolate* isolate = context()->isolate();
323 v8::HandleScope handle_scope(isolate);
324 v8::Context::Scope context_scope(context()->v8_context());
325 v8::Handle<v8::Value> argv[] = {
326 v8::String::NewFromUtf8(isolate, stage.c_str())};
327 context()->module_system()->CallModuleMethod(
328 "webstore", "onInstallStageChanged", arraysize(argv), argv);
329 }
330
331 void WebstoreBindings::OnInlineInstallDownloadProgress(int percent_downloaded) {
332 v8::Isolate* isolate = context()->isolate();
333 v8::HandleScope handle_scope(isolate);
334 v8::Context::Scope context_scope(context()->v8_context());
335 v8::Handle<v8::Value> argv[] = {
336 v8::Number::New(isolate, percent_downloaded / 100.0)};
337 context()->module_system()->CallModuleMethod(
338 "webstore", "onDownloadProgress", arraysize(argv), argv);
339 }
340
231 } // namespace extensions 341 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698