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