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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/renderer/extensions/chrome_webstore_bindings.h"
6
7 #include "base/string_util.h"
8 #include "chrome/common/extensions/extension.h"
9 #include "chrome/renderer/extensions/bindings_utils.h"
10 #include "chrome/renderer/extensions/extension_helper.h"
11 #include "content/renderer/render_view.h"
12 #include "googleurl/src/gurl.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h"
18 #include "v8/include/v8.h"
19
20 using WebKit::WebDocument;
21 using WebKit::WebElement;
22 using WebKit::WebFrame;
23 using WebKit::WebNode;
24 using WebKit::WebNodeList;
25
26 const char kWebstoreLinkRelation[] = "chrome-webstore-item";
27
28 const char kNotInTopFrameError[] =
29 "Chrome Web Store installations can only be started by the top frame.";
30 const char kNotUserGestureError[] =
31 "Chrome Web Store installations can only be initated by a user gesture.";
32 const char kNoWebstoreItemLinkFoundError[] =
33 "No Chrome Web Store item link found.";
34 const char kInvalidWebstoreItemUrlError[] =
35 "Invalid Chrome Web Store item URL.";
36
37 namespace extensions_v8 {
38
39 static const char* const kWebstoreExtensionName = "v8/ChromeWebstore";
40
41 class ChromeWebstoreExtensionWrapper : public v8::Extension {
42 public:
43 ChromeWebstoreExtensionWrapper() :
44 v8::Extension(
45 kWebstoreExtensionName,
46 "var chrome;"
47 "if (!chrome)"
48 " chrome = {};"
49 "if (!chrome.webstore) {"
50 " chrome.webstore = new function() {"
51 " native function Install();"
52 " this.install = Install;"
53 " };"
54 "}") {
55 }
56
57 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
58 v8::Handle<v8::String> name) {
59 if (name->Equals(v8::String::New("Install"))) {
60 return v8::FunctionTemplate::New(Install);
61 } else {
62 return v8::Handle<v8::FunctionTemplate>();
63 }
64 }
65
66 static v8::Handle<v8::Value> Install(const v8::Arguments& args) {
67 WebFrame* frame = WebFrame::frameForCurrentContext();
68 RenderView* render_view = bindings_utils::GetRenderViewForCurrentContext();
69 if (frame && render_view) {
70 std::string webstore_item_id;
71 std::string error;
72 if (GetWebstoreItemIdFromFrame(frame, &webstore_item_id, &error)) {
73 ExtensionHelper* helper = ExtensionHelper::Get(render_view);
74 helper->InlineWebstoreInstall(webstore_item_id);
75 } else {
76 v8::ThrowException(v8::String::New(error.c_str()));
77 }
78 }
79
80 return v8::Undefined();
81 }
82
83 private:
84 // Extracts a Web Store item ID from a <link rel="chrome-webstore-item"
85 // href="https://chrome.google.com/webstore/detail/id"> node found in the
86 // frame. On success, true will be returned and the |webstore_item_id|
87 // parameter will be populated with the ID. On failure, false will be returned
88 // and |error| will be populated with the error.
89 static bool GetWebstoreItemIdFromFrame(
90 WebFrame* frame, std::string* webstore_item_id, std::string* error) {
91 if (frame != frame->top()) {
92 *error = kNotInTopFrameError;
93 return false;
94 }
95
96 if (!frame->isProcessingUserGesture()) {
97 *error = kNotUserGestureError;
98 return false;
99 }
100
101 WebDocument document = frame->document();
102 if (document.isNull()) {
103 *error = kNoWebstoreItemLinkFoundError;
104 return false;
105 }
106
107 WebElement head = document.head();
108 if (head.isNull()) {
109 *error = kNoWebstoreItemLinkFoundError;
110 return false;
111 }
112
113 GURL webstore_base_url =
114 GURL(extension_misc::GetWebstoreItemDetailURLPrefix());
115 WebNodeList children = head.childNodes();
116 for (unsigned i = 0; i < children.length(); ++i) {
117 WebNode child = children.item(i);
118 if (!child.isElementNode())
119 continue;
120 WebElement elem = child.to<WebElement>();
121
122 if (!elem.hasTagName("link") || !elem.hasAttribute("rel") ||
123 !elem.hasAttribute("href"))
124 continue;
125
126 std::string rel = elem.getAttribute("rel").utf8();
127 if (!LowerCaseEqualsASCII(rel, kWebstoreLinkRelation))
128 continue;
129
130 std::string webstore_url_string(elem.getAttribute("href").utf8());
131 GURL webstore_url = GURL(webstore_url_string);
132 if (!webstore_url.is_valid()) {
133 *error = kInvalidWebstoreItemUrlError;
134 return false;
135 }
136
137 if (webstore_url.scheme() != webstore_base_url.scheme() ||
138 webstore_url.host() != webstore_base_url.host() ||
139 !StartsWithASCII(
140 webstore_url.path(), webstore_base_url.path(), true)) {
141 *error = kInvalidWebstoreItemUrlError;
142 return false;
143 }
144
145 std::string candidate_webstore_item_id = webstore_url.path().substr(
146 webstore_base_url.path().length());
147 std::string reconstructed_webstore_item_url_string =
148 extension_misc::GetWebstoreItemDetailURLPrefix() +
149 candidate_webstore_item_id;
150 if (reconstructed_webstore_item_url_string != webstore_url_string) {
151 *error = kInvalidWebstoreItemUrlError;
152 return false;
153 }
154
155 *webstore_item_id = candidate_webstore_item_id;
156 return true;
157 }
158
159 *error = kNoWebstoreItemLinkFoundError;
160 return false;
161 }
162 };
163
164 v8::Extension* ChromeWebstoreExtension::Get() {
165 return new ChromeWebstoreExtensionWrapper();
166 }
167
168 } // namespace extensions_v8
OLDNEW
« 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