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 49 namespace WebCore { 50 51 void 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 63 void 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 75 void 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 87 void 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 99 void 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 111 void 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 123 void 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 138 void 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 150 v8::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 168 v8::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 186 v8::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 205 v8::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 215 v8::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 228 v8::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 241 v8::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 251 v8::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 262 bool 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 269 bool 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 276 v8::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::setHiddenWindowReference(impl->frame(), wrapper); 285 } 286 return wrapper; 287 } 288 289 } // namespace WebCore 290