/platform/external/webkit/WebCore/bindings/v8/custom/V8LocationCustom.cpp

https://github.com/aharish/totoro-gb-opensource-update2 · C++ · 375 lines · 261 code · 62 blank · 52 comment · 36 complexity · 1cece2f84aad2f9f2d09d9f4324fd61d MD5 · raw file

  1. /*
  2. * Copyright (C) 2009 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above
  11. * copyright notice, this list of conditions and the following disclaimer
  12. * in the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Google Inc. nor the names of its
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "config.h"
  31. #include "V8Location.h"
  32. #include "CSSHelper.h"
  33. #include "Document.h"
  34. #include "Frame.h"
  35. #include "FrameLoader.h"
  36. #include "KURL.h"
  37. #include "Location.h"
  38. #include "PlatformString.h"
  39. #include "ScriptController.h"
  40. #include "V8Binding.h"
  41. #include "V8BindingState.h"
  42. #include "V8CustomEventListener.h"
  43. #include "V8DOMWindow.h"
  44. #include "V8Location.h"
  45. #include "V8Utilities.h"
  46. #include "V8Proxy.h"
  47. namespace WebCore {
  48. // Notes about V8/JSC porting of this file.
  49. // This class is not very JS-engine specific. If we can move a couple of
  50. // methods to the scriptController, we should be able to unify the code
  51. // between JSC and V8:
  52. // toCallingFrame() - in JSC, this needs an ExecState.
  53. // isSafeScript()
  54. // Since JSC and V8 have different mechanisms for getting at the calling frame,
  55. // we're just making all these custom for now. The functionality is simple
  56. // and mirrors JSLocationCustom.cpp.
  57. void V8Location::hashAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
  58. {
  59. INC_STATS("DOM.Location.hash._set");
  60. v8::Handle<v8::Object> holder = info.Holder();
  61. Location* imp = V8Location::toNative(holder);
  62. String hash = toWebCoreString(value);
  63. Frame* frame = imp->frame();
  64. if (!frame)
  65. return;
  66. KURL url = frame->loader()->url();
  67. String oldRef = url.fragmentIdentifier();
  68. if (hash.startsWith("#"))
  69. hash = hash.substring(1);
  70. if (oldRef == hash || (oldRef.isNull() && hash.isEmpty()))
  71. return;
  72. url.setFragmentIdentifier(hash);
  73. navigateIfAllowed(frame, url, false, false);
  74. }
  75. void V8Location::hostAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
  76. {
  77. INC_STATS("DOM.Location.host._set");
  78. v8::Handle<v8::Object> holder = info.Holder();
  79. Location* imp = V8Location::toNative(holder);
  80. String host = toWebCoreString(value);
  81. Frame* frame = imp->frame();
  82. if (!frame)
  83. return;
  84. KURL url = frame->loader()->url();
  85. String newHost = host.left(host.find(":"));
  86. String newPort = host.substring(host.find(":") + 1);
  87. url.setHost(newHost);
  88. url.setPort(newPort.toUInt());
  89. navigateIfAllowed(frame, url, false, false);
  90. }
  91. void V8Location::hostnameAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
  92. {
  93. INC_STATS("DOM.Location.hostname._set");
  94. v8::Handle<v8::Object> holder = info.Holder();
  95. Location* imp = V8Location::toNative(holder);
  96. String hostname = toWebCoreString(value);
  97. Frame* frame = imp->frame();
  98. if (!frame)
  99. return;
  100. KURL url = frame->loader()->url();
  101. url.setHost(hostname);
  102. navigateIfAllowed(frame, url, false, false);
  103. }
  104. void V8Location::hrefAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
  105. {
  106. INC_STATS("DOM.Location.href._set");
  107. v8::Handle<v8::Object> holder = info.Holder();
  108. Location* imp = V8Location::toNative(holder);
  109. Frame* frame = imp->frame();
  110. if (!frame)
  111. return;
  112. KURL url = completeURL(toWebCoreString(value));
  113. if (url.isNull())
  114. return;
  115. if (!shouldAllowNavigation(frame))
  116. return;
  117. navigateIfAllowed(frame, url, false, false);
  118. }
  119. void V8Location::pathnameAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
  120. {
  121. INC_STATS("DOM.Location.pathname._set");
  122. v8::Handle<v8::Object> holder = info.Holder();
  123. Location* imp = V8Location::toNative(holder);
  124. String pathname = toWebCoreString(value);
  125. Frame* frame = imp->frame();
  126. if (!frame)
  127. return;
  128. KURL url = frame->loader()->url();
  129. url.setPath(pathname);
  130. navigateIfAllowed(frame, url, false, false);
  131. }
  132. void V8Location::portAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
  133. {
  134. INC_STATS("DOM.Location.port._set");
  135. v8::Handle<v8::Object> holder = info.Holder();
  136. Location* imp = V8Location::toNative(holder);
  137. String port = toWebCoreString(value);
  138. Frame* frame = imp->frame();
  139. if (!frame)
  140. return;
  141. KURL url = frame->loader()->url();
  142. url.setPort(port.toUInt());
  143. navigateIfAllowed(frame, url, false, false);
  144. }
  145. void V8Location::protocolAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
  146. {
  147. INC_STATS("DOM.Location.protocol._set");
  148. v8::Handle<v8::Object> holder = info.Holder();
  149. Location* imp = V8Location::toNative(holder);
  150. String protocol = toWebCoreString(value);
  151. Frame* frame = imp->frame();
  152. if (!frame)
  153. return;
  154. KURL url = frame->loader()->url();
  155. url.setProtocol(protocol);
  156. navigateIfAllowed(frame, url, false, false);
  157. }
  158. void V8Location::searchAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
  159. {
  160. INC_STATS("DOM.Location.search._set");
  161. v8::Handle<v8::Object> holder = info.Holder();
  162. Location* imp = V8Location::toNative(holder);
  163. String query = toWebCoreString(value);
  164. Frame* frame = imp->frame();
  165. if (!frame)
  166. return;
  167. KURL url = frame->loader()->url();
  168. url.setQuery(query);
  169. navigateIfAllowed(frame, url, false, false);
  170. }
  171. v8::Handle<v8::Value> V8Location::reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
  172. {
  173. INC_STATS("DOM.Location.reload._get");
  174. static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::reloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate())));
  175. v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8Location::GetTemplate(), info.This());
  176. if (holder.IsEmpty()) {
  177. // can only reach here by 'object.__proto__.func', and it should passed
  178. // domain security check already
  179. return privateTemplate->GetFunction();
  180. }
  181. Location* imp = V8Location::toNative(holder);
  182. if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
  183. static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::reloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate())));
  184. return sharedTemplate->GetFunction();
  185. }
  186. return privateTemplate->GetFunction();
  187. }
  188. v8::Handle<v8::Value> V8Location::replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
  189. {
  190. INC_STATS("DOM.Location.replace._get");
  191. static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::replaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate())));
  192. v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8Location::GetTemplate(), info.This());
  193. if (holder.IsEmpty()) {
  194. // can only reach here by 'object.__proto__.func', and it should passed
  195. // domain security check already
  196. return privateTemplate->GetFunction();
  197. }
  198. Location* imp = V8Location::toNative(holder);
  199. if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
  200. static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::replaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate())));
  201. return sharedTemplate->GetFunction();
  202. }
  203. return privateTemplate->GetFunction();
  204. }
  205. v8::Handle<v8::Value> V8Location::assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
  206. {
  207. INC_STATS("DOM.Location.assign._get");
  208. static v8::Persistent<v8::FunctionTemplate> privateTemplate =
  209. v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::assignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate())));
  210. v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8Location::GetTemplate(), info.This());
  211. if (holder.IsEmpty()) {
  212. // can only reach here by 'object.__proto__.func', and it should passed
  213. // domain security check already
  214. return privateTemplate->GetFunction();
  215. }
  216. Location* imp = V8Location::toNative(holder);
  217. if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) {
  218. static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::assignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate())));
  219. return sharedTemplate->GetFunction();
  220. }
  221. return privateTemplate->GetFunction();
  222. }
  223. v8::Handle<v8::Value> V8Location::reloadCallback(const v8::Arguments& args)
  224. {
  225. // FIXME: we ignore the "forceget" parameter.
  226. INC_STATS("DOM.Location.reload");
  227. v8::Handle<v8::Object> holder = args.Holder();
  228. Location* imp = V8Location::toNative(holder);
  229. Frame* frame = imp->frame();
  230. if (!frame || !ScriptController::isSafeScript(frame))
  231. return v8::Undefined();
  232. if (!protocolIsJavaScript(frame->loader()->url()))
  233. frame->redirectScheduler()->scheduleRefresh(processingUserGesture());
  234. return v8::Undefined();
  235. }
  236. v8::Handle<v8::Value> V8Location::replaceCallback(const v8::Arguments& args)
  237. {
  238. INC_STATS("DOM.Location.replace");
  239. v8::Handle<v8::Object> holder = args.Holder();
  240. Location* imp = V8Location::toNative(holder);
  241. Frame* frame = imp->frame();
  242. if (!frame)
  243. return v8::Undefined();
  244. KURL url = completeURL(toWebCoreString(args[0]));
  245. if (url.isNull())
  246. return v8::Undefined();
  247. if (!shouldAllowNavigation(frame))
  248. return v8::Undefined();
  249. navigateIfAllowed(frame, url, true, true);
  250. return v8::Undefined();
  251. }
  252. v8::Handle<v8::Value> V8Location::assignCallback(const v8::Arguments& args)
  253. {
  254. INC_STATS("DOM.Location.assign");
  255. v8::Handle<v8::Object> holder = args.Holder();
  256. Location* imp = V8Location::toNative(holder);
  257. Frame* frame = imp->frame();
  258. if (!frame)
  259. return v8::Undefined();
  260. KURL url = completeURL(toWebCoreString(args[0]));
  261. if (url.isNull())
  262. return v8::Undefined();
  263. if (!shouldAllowNavigation(frame))
  264. return v8::Undefined();
  265. navigateIfAllowed(frame, url, false, false);
  266. return v8::Undefined();
  267. }
  268. v8::Handle<v8::Value> V8Location::valueOfCallback(const v8::Arguments& args)
  269. {
  270. // Just return the this object the way the normal valueOf function
  271. // on the Object prototype would. The valueOf function is only
  272. // added to make sure that it cannot be overwritten on location
  273. // objects, since that would provide a hook to change the string
  274. // conversion behavior of location objects.
  275. return args.This();
  276. }
  277. v8::Handle<v8::Value> V8Location::toStringCallback(const v8::Arguments& args)
  278. {
  279. INC_STATS("DOM.Location.toString");
  280. v8::Handle<v8::Object> holder = args.Holder();
  281. Location* imp = V8Location::toNative(holder);
  282. if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
  283. return v8::Undefined();
  284. String result = imp->href();
  285. return v8String(result);
  286. }
  287. bool V8Location::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data)
  288. {
  289. ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION);
  290. // Only allow same origin access
  291. Location* imp = V8Location::toNative(host);
  292. return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false);
  293. }
  294. bool V8Location::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data)
  295. {
  296. ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION);
  297. // Only allow same origin access
  298. Location* imp = V8Location::toNative(host);
  299. return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false);
  300. }
  301. v8::Handle<v8::Value> toV8(Location* impl)
  302. {
  303. if (!impl)
  304. return v8::Null();
  305. v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl);
  306. if (wrapper.IsEmpty()) {
  307. wrapper = V8Location::wrap(impl);
  308. if (!wrapper.IsEmpty())
  309. V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::locationIndex, wrapper);
  310. }
  311. return wrapper;
  312. }
  313. } // namespace WebCore