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

Unified Diff: chrome/renderer/extensions/chrome_webstore_bindings.cc

Issue 7621032: Initial inline web store install bindings. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review feedback. Created 9 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/extensions/chrome_webstore_bindings.cc
diff --git a/chrome/renderer/extensions/chrome_webstore_bindings.cc b/chrome/renderer/extensions/chrome_webstore_bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9c58d15c1b8c4519e188af813f63cfcaa5dfef11
--- /dev/null
+++ b/chrome/renderer/extensions/chrome_webstore_bindings.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/extensions/chrome_webstore_bindings.h"
+
+#include "base/string_util.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/renderer/extensions/bindings_utils.h"
+#include "chrome/renderer/extensions/extension_helper.h"
+#include "content/renderer/render_view.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h"
+#include "v8/include/v8.h"
+
+using WebKit::WebDocument;
+using WebKit::WebElement;
+using WebKit::WebFrame;
+using WebKit::WebNode;
+using WebKit::WebNodeList;
+
+const char kWebstoreLinkRelation[] = "chrome-webstore-item";
+
+const char kNotInTopFrameError[] =
+ "Chrome Web Store installations can only be started by the top frame.";
+const char kNotUserGestureError[] =
+ "Chrome Web Store installations can only be initated by a user gesture.";
+const char kNoWebstoreItemLinkFoundError[] =
+ "No Chrome Web Store item link found.";
+const char kInvalidWebstoreItemUrlError[] =
+ "Invalid Chrome Web Store item URL.";
+
+namespace extensions_v8 {
+
+static const char* const kWebstoreExtensionName = "v8/ChromeWebstore";
+
+class ChromeWebstoreExtensionWrapper : public v8::Extension {
+ public:
+ ChromeWebstoreExtensionWrapper() :
+ v8::Extension(
+ kWebstoreExtensionName,
+ "var chrome;"
+ "if (!chrome)"
+ " chrome = {};"
+ "if (!chrome.webstore) {"
+ " chrome.webstore = new function() {"
+ " native function Install();"
+ " this.install = Install;"
+ " };"
+ "}") {
+ }
+
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ v8::Handle<v8::String> name) {
+ if (name->Equals(v8::String::New("Install"))) {
+ return v8::FunctionTemplate::New(Install);
+ } else {
+ return v8::Handle<v8::FunctionTemplate>();
+ }
+ }
+
+ static v8::Handle<v8::Value> Install(const v8::Arguments& args) {
+ WebFrame* frame = WebFrame::frameForCurrentContext();
+ RenderView* render_view = bindings_utils::GetRenderViewForCurrentContext();
+ if (frame && render_view) {
+ std::string webstore_item_id;
+ std::string error;
+ if (GetWebstoreItemIdFromFrame(frame, &webstore_item_id, &error)) {
+ ExtensionHelper* helper = ExtensionHelper::Get(render_view);
+ helper->InlineWebstoreInstall(webstore_item_id);
+ } else {
+ v8::ThrowException(v8::String::New(error.c_str()));
+ }
+ }
+
+ return v8::Undefined();
+ }
+
+ private:
+ // Extracts a Web Store item ID from a <link rel="chrome-webstore-item"
+ // href="https://chrome.google.com/webstore/detail/id"> node found in the
+ // frame. On success, true will be returned and the |webstore_item_id|
+ // parameter will be populated with the ID. On failure, false will be returned
+ // and |error| will be populated with the error.
+ static bool GetWebstoreItemIdFromFrame(
+ WebFrame* frame, std::string* webstore_item_id, std::string* error) {
+ if (frame != frame->top()) {
+ *error = kNotInTopFrameError;
+ return false;
+ }
+
+ if (!frame->isProcessingUserGesture()) {
+ *error = kNotUserGestureError;
+ return false;
+ }
+
+ WebDocument document = frame->document();
+ if (document.isNull()) {
+ *error = kNoWebstoreItemLinkFoundError;
+ return false;
+ }
+
+ WebElement head = document.head();
+ if (head.isNull()) {
+ *error = kNoWebstoreItemLinkFoundError;
+ return false;
+ }
+
+ GURL webstore_base_url =
+ GURL(extension_misc::GetWebstoreItemDetailURLPrefix());
+ WebNodeList children = head.childNodes();
+ for (unsigned i = 0; i < children.length(); ++i) {
+ WebNode child = children.item(i);
+ if (!child.isElementNode())
+ continue;
+ WebElement elem = child.to<WebElement>();
+
+ if (!elem.hasTagName("link") || !elem.hasAttribute("rel") ||
+ !elem.hasAttribute("href"))
+ continue;
+
+ std::string rel = elem.getAttribute("rel").utf8();
+ if (!LowerCaseEqualsASCII(rel, kWebstoreLinkRelation))
+ continue;
+
+ std::string webstore_url_string(elem.getAttribute("href").utf8());
+ GURL webstore_url = GURL(webstore_url_string);
+ if (!webstore_url.is_valid()) {
+ *error = kInvalidWebstoreItemUrlError;
+ return false;
+ }
+
+ if (webstore_url.scheme() != webstore_base_url.scheme() ||
+ webstore_url.host() != webstore_base_url.host() ||
+ !StartsWithASCII(
+ webstore_url.path(), webstore_base_url.path(), true)) {
+ *error = kInvalidWebstoreItemUrlError;
+ return false;
+ }
+
+ std::string candidate_webstore_item_id = webstore_url.path().substr(
+ webstore_base_url.path().length());
+ std::string reconstructed_webstore_item_url_string =
+ extension_misc::GetWebstoreItemDetailURLPrefix() +
+ candidate_webstore_item_id;
+ if (reconstructed_webstore_item_url_string != webstore_url_string) {
+ *error = kInvalidWebstoreItemUrlError;
+ return false;
+ }
+
+ *webstore_item_id = candidate_webstore_item_id;
+ return true;
+ }
+
+ *error = kNoWebstoreItemLinkFoundError;
+ return false;
+ }
+};
+
+v8::Extension* ChromeWebstoreExtension::Get() {
+ return new ChromeWebstoreExtensionWrapper();
+}
+
+} // namespace extensions_v8
« no previous file with comments | « chrome/renderer/extensions/chrome_webstore_bindings.h ('k') | chrome/renderer/extensions/extension_dispatcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698