Chromium Code Reviews| Index: chrome/renderer/extensions/webstore_bindings.cc |
| diff --git a/chrome/renderer/extensions/webstore_bindings.cc b/chrome/renderer/extensions/webstore_bindings.cc |
| index 85ecbf21a4ad205b3c787f008ffa8f669348d232..2009b43a17ac69bd2faec6b94042eb91a878d611 100644 |
| --- a/chrome/renderer/extensions/webstore_bindings.cc |
| +++ b/chrome/renderer/extensions/webstore_bindings.cc |
| @@ -5,6 +5,7 @@ |
| #include "chrome/renderer/extensions/webstore_bindings.h" |
| #include "base/strings/string_util.h" |
| +#include "chrome/common/extensions/api/webstore/webstore_api_constants.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "chrome/common/extensions/extension_messages.h" |
| #include "chrome/renderer/extensions/chrome_v8_context.h" |
| @@ -46,12 +47,36 @@ const char kNoWebstoreItemLinkFoundError[] = |
| "No Chrome Web Store item link found."; |
| const char kInvalidWebstoreItemUrlError[] = |
| "Invalid Chrome Web Store item URL."; |
| +const char kInstallStageListenerCallbackNotAFunctionError[] = |
| + "The listener callback for install stage change must be a function."; |
| +const char kDownloadProgressListenerCallbackNotAFunctionError[] = |
| + "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.
|
| // chrome.webstore.install() calls generate an install ID so that the install's |
| // callbacks may be fired when the browser notifies us of install completion |
| // (successful or not) via OnInlineWebstoreInstallResponse. |
| int g_next_install_id = 0; |
| +// Parses the given |args| to determine if a valid listener function argument |
| +// was passed. NULL is considered valid, since it is used to unset the current |
| +// listener. |
| +// Returns true on success, false on failure. If successful, |
| +// populates |is_listener_set| with whether or not the listener should be set. |
| +bool GetIsListenerSet(const v8::FunctionCallbackInfo<v8::Value>& args, |
| + bool* is_listener_set) { |
| + if (args[0]->IsNull()) { |
| + *is_listener_set = false; |
| + return true; |
| + } |
| + |
| + if (args[0]->IsFunction()) { |
| + *is_listener_set = true; |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| } // anonymous namespace |
| WebstoreBindings::WebstoreBindings(Dispatcher* dispatcher, |
| @@ -60,23 +85,52 @@ WebstoreBindings::WebstoreBindings(Dispatcher* dispatcher, |
| ChromeV8ExtensionHandler(context) { |
| RouteFunction("Install", |
| base::Bind(&WebstoreBindings::Install, base::Unretained(this))); |
| + RouteFunction("ValidateInstallStageListener", |
| + base::Bind(&WebstoreBindings::ValidateInstallStageListener, |
| + base::Unretained(this))); |
| + RouteFunction("ValidateDownloadProgressListener", |
| + base::Bind(&WebstoreBindings::ValidateDownloadProgressListener, |
| + base::Unretained(this))); |
| } |
| -void WebstoreBindings::Install( |
| - const v8::FunctionCallbackInfo<v8::Value>& args) { |
| +content::RenderView* WebstoreBindings::GetRenderView() { |
| WebFrame* frame = WebFrame::frameForContext(context()->v8_context()); |
| if (!frame || !frame->view()) |
| - return; |
| - |
| + return NULL; |
| content::RenderView* render_view = |
| content::RenderView::FromWebView(frame->view()); |
| + return render_view; |
|
not at google - send to devlin
2014/02/27 21:49:56
https://code.google.com/p/chromium/codesearch#chro
Devlin
2014/02/28 18:04:51
Done.
|
| +} |
| + |
| +void WebstoreBindings::Install( |
| + const v8::FunctionCallbackInfo<v8::Value>& args) { |
| + content::RenderView* render_view = GetRenderView(); |
| if (!render_view) |
| return; |
| + // The first two arguments, which indicate whether or not there are install |
| + // stage and download progress listeners, are provided directly by the |
| + // custom bindings, so should always be valid. |
| + int listener_mask = 0; |
| + 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!
|
| + if (args[0]->BooleanValue()) |
| + listener_mask |= api::webstore::INSTALL_STAGE_LISTENER; |
| + } else { |
| + NOTREACHED(); |
| + return; |
| + } |
| + if (args[1]->IsBoolean()) { |
| + if (args[1]->BooleanValue()) |
| + listener_mask |= api::webstore::DOWNLOAD_PROGRESS_LISTENER; |
| + } else { |
| + NOTREACHED(); |
| + return; |
| + } |
| + |
| std::string preferred_store_link_url; |
| - if (!args[0]->IsUndefined()) { |
| - if (args[0]->IsString()) { |
| - preferred_store_link_url = std::string(*v8::String::Utf8Value(args[0])); |
| + if (!args[2]->IsUndefined()) { |
| + if (args[2]->IsString()) { |
| + preferred_store_link_url = std::string(*v8::String::Utf8Value(args[2])); |
| } else { |
| args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( |
| args.GetIsolate(), kPreferredStoreLinkUrlNotAString)); |
| @@ -86,6 +140,8 @@ void WebstoreBindings::Install( |
| std::string webstore_item_id; |
| std::string error; |
| + WebFrame* frame = WebFrame::frameForContext(context()->v8_context()); |
| + |
| if (!GetWebstoreItemIdFromFrame( |
| frame, preferred_store_link_url, &webstore_item_id, &error)) { |
| args.GetIsolate()->ThrowException( |
| @@ -94,28 +150,58 @@ void WebstoreBindings::Install( |
| } |
| int install_id = g_next_install_id++; |
| - if (!args[1]->IsUndefined() && !args[1]->IsFunction()) { |
| + if (!args[3]->IsUndefined() && !args[3]->IsFunction()) { |
| args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( |
| args.GetIsolate(), kSuccessCallbackNotAFunctionError)); |
| return; |
| } |
| - if (!args[2]->IsUndefined() && !args[2]->IsFunction()) { |
| + if (!args[4]->IsUndefined() && !args[4]->IsFunction()) { |
| args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( |
| args.GetIsolate(), kFailureCallbackNotAFunctionError)); |
| return; |
| } |
| - Send(new ExtensionHostMsg_InlineWebstoreInstall( |
| - render_view->GetRoutingID(), |
| - install_id, |
| - GetRoutingID(), |
| - webstore_item_id, |
| - frame->document().url())); |
| + Send(new ExtensionHostMsg_InlineWebstoreInstall(render_view->GetRoutingID(), |
| + install_id, |
| + GetRoutingID(), |
| + webstore_item_id, |
| + frame->document().url(), |
| + listener_mask)); |
| args.GetReturnValue().Set(static_cast<int32_t>(install_id)); |
| } |
| +void WebstoreBindings::ValidateInstallStageListener( |
| + const v8::FunctionCallbackInfo<v8::Value>& args) { |
| + content::RenderView* render_view = GetRenderView(); |
| + if (!render_view) |
| + return; |
| + |
| + bool is_listener_set = false; |
| + if (!GetIsListenerSet(args, &is_listener_set)) { |
| + args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( |
| + args.GetIsolate(), kInstallStageListenerCallbackNotAFunctionError)); |
| + args.GetReturnValue().Set(false); |
| + } |
| + args.GetReturnValue().Set(true); |
| +} |
| + |
| +void WebstoreBindings::ValidateDownloadProgressListener( |
| + const v8::FunctionCallbackInfo<v8::Value>& args) { |
| + content::RenderView* render_view = GetRenderView(); |
| + if (!render_view) |
| + return; |
| + |
| + bool is_listener_set = false; |
| + if (!GetIsListenerSet(args, &is_listener_set)) { |
| + args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( |
| + args.GetIsolate(), kDownloadProgressListenerCallbackNotAFunctionError)); |
| + args.GetReturnValue().Set(false); |
| + } |
| + args.GetReturnValue().Set(true); |
| +} |
| + |
| // static |
| bool WebstoreBindings::GetWebstoreItemIdFromFrame( |
| WebFrame* frame, const std::string& preferred_store_link_url, |
| @@ -207,6 +293,10 @@ bool WebstoreBindings::OnMessageReceived(const IPC::Message& message) { |
| IPC_BEGIN_MESSAGE_MAP(WebstoreBindings, message) |
| IPC_MESSAGE_HANDLER(ExtensionMsg_InlineWebstoreInstallResponse, |
| OnInlineWebstoreInstallResponse) |
| + IPC_MESSAGE_HANDLER(ExtensionMsg_InlineInstallStageChanged, |
| + OnInlineInstallStageChanged) |
| + IPC_MESSAGE_HANDLER(ExtensionMsg_InlineInstallDownloadProgress, |
| + OnInlineInstallDownloadProgress) |
| IPC_MESSAGE_UNHANDLED(CHECK(false) << "Unhandled IPC message") |
| IPC_END_MESSAGE_MAP() |
| return true; |
| @@ -228,4 +318,24 @@ void WebstoreBindings::OnInlineWebstoreInstallResponse( |
| "webstore", "onInstallResponse", arraysize(argv), argv); |
| } |
| +void WebstoreBindings::OnInlineInstallStageChanged(const std::string& stage) { |
| + v8::Isolate* isolate = context()->isolate(); |
| + v8::HandleScope handle_scope(isolate); |
| + v8::Context::Scope context_scope(context()->v8_context()); |
| + v8::Handle<v8::Value> argv[] = { |
| + v8::String::NewFromUtf8(isolate, stage.c_str())}; |
| + context()->module_system()->CallModuleMethod( |
| + "webstore", "onInstallStageChanged", arraysize(argv), argv); |
| +} |
| + |
| +void WebstoreBindings::OnInlineInstallDownloadProgress(int percent_downloaded) { |
| + v8::Isolate* isolate = context()->isolate(); |
| + v8::HandleScope handle_scope(isolate); |
| + v8::Context::Scope context_scope(context()->v8_context()); |
| + v8::Handle<v8::Value> argv[] = { |
| + v8::Number::New(isolate, percent_downloaded / 100.0)}; |
| + context()->module_system()->CallModuleMethod( |
| + "webstore", "onDownloadProgress", arraysize(argv), argv); |
| +} |
| + |
| } // namespace extensions |