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 31#include "config.h" 32#include "V8Location.h" 33 34#include "Document.h" 35#include "Frame.h" 36#include "FrameLoader.h" 37#include "KURL.h" 38#include "Location.h" 39#include "PlatformString.h" 40#include "ScriptController.h" 41#include "V8Binding.h" 42#include "V8BindingState.h" 43#include "V8DOMWindow.h" 44#include "V8EventListener.h" 45#include "V8Location.h" 46#include "V8Utilities.h" 47#include "V8Proxy.h" 48 49namespace WebCore { 50 51void V8Location::hashAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 52{ 53 INC_STATS("DOM.Location.hash._set"); 54 Location* impl = V8Location::toNative(info.Holder()); 55 State<V8Binding>* state = V8BindingState::Only(); 56 57 // FIXME: Handle exceptions correctly. 58 String hash = toWebCoreString(value); 59 60 impl->setHash(hash, state->activeWindow(), state->firstWindow()); 61} 62 63void V8Location::hostAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 64{ 65 INC_STATS("DOM.Location.host._set"); 66 Location* impl = V8Location::toNative(info.Holder()); 67 State<V8Binding>* state = V8BindingState::Only(); 68 69 // FIXME: Handle exceptions correctly. 70 String host = toWebCoreString(value); 71 72 impl->setHost(host, state->activeWindow(), state->firstWindow()); 73} 74 75void V8Location::hostnameAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 76{ 77 INC_STATS("DOM.Location.hostname._set"); 78 Location* impl = V8Location::toNative(info.Holder()); 79 State<V8Binding>* state = V8BindingState::Only(); 80 81 // FIXME: Handle exceptions correctly. 82 String hostname = toWebCoreString(value); 83 84 impl->setHostname(hostname, state->activeWindow(), state->firstWindow()); 85} 86 87void V8Location::hrefAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 88{ 89 INC_STATS("DOM.Location.href._set"); 90 Location* impl = V8Location::toNative(info.Holder()); 91 State<V8Binding>* state = V8BindingState::Only(); 92 93 // FIXME: Handle exceptions correctly. 94 String href = toWebCoreString(value); 95 96 impl->setHref(href, state->activeWindow(), state->firstWindow()); 97} 98 99void V8Location::pathnameAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 100{ 101 INC_STATS("DOM.Location.pathname._set"); 102 Location* impl = V8Location::toNative(info.Holder()); 103 State<V8Binding>* state = V8BindingState::Only(); 104 105 // FIXME: Handle exceptions correctly. 106 String pathname = toWebCoreString(value); 107 108 impl->setPathname(pathname, state->activeWindow(), state->firstWindow()); 109} 110 111void V8Location::portAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 112{ 113 INC_STATS("DOM.Location.port._set"); 114 Location* impl = V8Location::toNative(info.Holder()); 115 State<V8Binding>* state = V8BindingState::Only(); 116 117 // FIXME: Handle exceptions correctly. 118 String port = toWebCoreString(value); 119 120 impl->setPort(port, state->activeWindow(), state->firstWindow()); 121} 122 123void V8Location::protocolAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 124{ 125 INC_STATS("DOM.Location.protocol._set"); 126 Location* impl = V8Location::toNative(info.Holder()); 127 State<V8Binding>* state = V8BindingState::Only(); 128 129 // FIXME: Handle exceptions correctly. 130 String protocol = toWebCoreString(value); 131 132 ExceptionCode ec = 0; 133 impl->setProtocol(protocol, state->activeWindow(), state->firstWindow(), ec); 134 if (UNLIKELY(ec)) 135 V8Proxy::setDOMException(ec); 136} 137 138void V8Location::searchAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 139{ 140 INC_STATS("DOM.Location.search._set"); 141 Location* impl = V8Location::toNative(info.Holder()); 142 State<V8Binding>* state = V8BindingState::Only(); 143 144 // FIXME: Handle exceptions correctly. 145 String search = toWebCoreString(value); 146 147 impl->setSearch(search, state->activeWindow(), state->firstWindow()); 148} 149 150v8::Handle<v8::Value> V8Location::reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 151{ 152 INC_STATS("DOM.Location.reload._get"); 153 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()))); 154 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8Location::GetTemplate(), info.This()); 155 if (holder.IsEmpty()) { 156 // can only reach here by 'object.__proto__.func', and it should passed 157 // domain security check already 158 return privateTemplate->GetFunction(); 159 } 160 Location* imp = V8Location::toNative(holder); 161 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { 162 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()))); 163 return sharedTemplate->GetFunction(); 164 } 165 return privateTemplate->GetFunction(); 166} 167 168v8::Handle<v8::Value> V8Location::replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 169{ 170 INC_STATS("DOM.Location.replace._get"); 171 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()))); 172 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8Location::GetTemplate(), info.This()); 173 if (holder.IsEmpty()) { 174 // can only reach here by 'object.__proto__.func', and it should passed 175 // domain security check already 176 return privateTemplate->GetFunction(); 177 } 178 Location* imp = V8Location::toNative(holder); 179 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { 180 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()))); 181 return sharedTemplate->GetFunction(); 182 } 183 return privateTemplate->GetFunction(); 184} 185 186v8::Handle<v8::Value> V8Location::assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 187{ 188 INC_STATS("DOM.Location.assign._get"); 189 static v8::Persistent<v8::FunctionTemplate> privateTemplate = 190 v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::assignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); 191 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8Location::GetTemplate(), info.This()); 192 if (holder.IsEmpty()) { 193 // can only reach here by 'object.__proto__.func', and it should passed 194 // domain security check already 195 return privateTemplate->GetFunction(); 196 } 197 Location* imp = V8Location::toNative(holder); 198 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { 199 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()))); 200 return sharedTemplate->GetFunction(); 201 } 202 return privateTemplate->GetFunction(); 203} 204 205v8::Handle<v8::Value> V8Location::reloadCallback(const v8::Arguments& args) 206{ 207 INC_STATS("DOM.Location.reload"); 208 Location* impl = V8Location::toNative(args.Holder()); 209 State<V8Binding>* state = V8BindingState::Only(); 210 211 impl->reload(state->activeWindow()); 212 return v8::Undefined(); 213} 214 215v8::Handle<v8::Value> V8Location::replaceCallback(const v8::Arguments& args) 216{ 217 INC_STATS("DOM.Location.replace"); 218 Location* impl = V8Location::toNative(args.Holder()); 219 State<V8Binding>* state = V8BindingState::Only(); 220 221 // FIXME: Handle exceptions correctly. 222 String urlString = toWebCoreString(args[0]); 223 224 impl->replace(urlString, state->activeWindow(), state->firstWindow()); 225 return v8::Undefined(); 226} 227 228v8::Handle<v8::Value> V8Location::assignCallback(const v8::Arguments& args) 229{ 230 INC_STATS("DOM.Location.assign"); 231 Location* impl = V8Location::toNative(args.Holder()); 232 State<V8Binding>* state = V8BindingState::Only(); 233 234 // FIXME: Handle exceptions correctly. 235 String urlString = toWebCoreString(args[0]); 236 237 impl->assign(urlString, state->activeWindow(), state->firstWindow()); 238 return v8::Undefined(); 239} 240 241v8::Handle<v8::Value> V8Location::valueOfCallback(const v8::Arguments& args) 242{ 243 // Just return the this object the way the normal valueOf function 244 // on the Object prototype would. The valueOf function is only 245 // added to make sure that it cannot be overwritten on location 246 // objects, since that would provide a hook to change the string 247 // conversion behavior of location objects. 248 return args.This(); 249} 250 251v8::Handle<v8::Value> V8Location::toStringCallback(const v8::Arguments& args) 252{ 253 INC_STATS("DOM.Location.toString"); 254 v8::Handle<v8::Object> holder = args.Holder(); 255 Location* imp = V8Location::toNative(holder); 256 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) 257 return v8::Undefined(); 258 String result = imp->href(); 259 return v8String(result); 260} 261 262bool V8Location::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) 263{ 264 // Only allow same origin access 265 Location* imp = V8Location::toNative(host); 266 return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false); 267} 268 269bool V8Location::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) 270{ 271 // Only allow same origin access 272 Location* imp = V8Location::toNative(host); 273 return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false); 274} 275 276v8::Handle<v8::Value> toV8(Location* impl) 277{ 278 if (!impl) 279 return v8::Null(); 280 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); 281 if (wrapper.IsEmpty()) { 282 wrapper = V8Location::wrap(impl); 283 if (!wrapper.IsEmpty()) 284 V8DOMWrapper::setNamedHiddenWindowReference(impl->frame(), "location", wrapper); 285 } 286 return wrapper; 287} 288 289} // namespace WebCore 290