1 /* 2 * Copyright (C) 2008, 2010 Apple 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 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "config.h" 30 #include "core/page/Location.h" 31 32 #include "bindings/v8/ExceptionState.h" 33 #include "core/dom/Document.h" 34 #include "core/dom/ExceptionCode.h" 35 #include "core/loader/FrameLoader.h" 36 #include "core/page/DOMWindow.h" 37 #include "core/page/Frame.h" 38 #include "weborigin/KURL.h" 39 #include "weborigin/SecurityOrigin.h" 40 41 namespace WebCore { 42 43 Location::Location(Frame* frame) 44 : DOMWindowProperty(frame) 45 { 46 ScriptWrappable::init(this); 47 } 48 49 inline const KURL& Location::url() const 50 { 51 ASSERT(m_frame); 52 53 const KURL& url = m_frame->document()->url(); 54 if (!url.isValid()) 55 return blankURL(); // Use "about:blank" while the page is still loading (before we have a frame). 56 57 return url; 58 } 59 60 String Location::href() const 61 { 62 if (!m_frame) 63 return String(); 64 65 return url().string(); 66 } 67 68 String Location::protocol() const 69 { 70 if (!m_frame) 71 return String(); 72 73 return url().protocol() + ":"; 74 } 75 76 String Location::host() const 77 { 78 if (!m_frame) 79 return String(); 80 81 // Note: this is the IE spec. The NS spec swaps the two, it says 82 // "The hostname property is the concatenation of the host and port properties, separated by a colon." 83 const KURL& url = this->url(); 84 return url.hasPort() ? url.host() + ":" + String::number(url.port()) : url.host(); 85 } 86 87 String Location::hostname() const 88 { 89 if (!m_frame) 90 return String(); 91 92 return url().host(); 93 } 94 95 String Location::port() const 96 { 97 if (!m_frame) 98 return String(); 99 100 const KURL& url = this->url(); 101 return url.hasPort() ? String::number(url.port()) : ""; 102 } 103 104 String Location::pathname() const 105 { 106 if (!m_frame) 107 return String(); 108 109 const KURL& url = this->url(); 110 return url.path().isEmpty() ? "/" : url.path(); 111 } 112 113 String Location::search() const 114 { 115 if (!m_frame) 116 return String(); 117 118 const KURL& url = this->url(); 119 return url.query().isEmpty() ? emptyString() : "?" + url.query(); 120 } 121 122 String Location::origin() const 123 { 124 if (!m_frame) 125 return String(); 126 return SecurityOrigin::create(url())->toString(); 127 } 128 129 PassRefPtr<DOMStringList> Location::ancestorOrigins() const 130 { 131 RefPtr<DOMStringList> origins = DOMStringList::create(); 132 if (!m_frame) 133 return origins.release(); 134 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) 135 origins->append(frame->document()->securityOrigin()->toString()); 136 return origins.release(); 137 } 138 139 String Location::hash() const 140 { 141 if (!m_frame) 142 return String(); 143 144 const String& fragmentIdentifier = url().fragmentIdentifier(); 145 return fragmentIdentifier.isEmpty() ? emptyString() : "#" + fragmentIdentifier; 146 } 147 148 void Location::setHref(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& url) 149 { 150 if (!m_frame) 151 return; 152 setLocation(url, activeWindow, firstWindow); 153 } 154 155 void Location::setProtocol(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& protocol, ExceptionState& es) 156 { 157 if (!m_frame) 158 return; 159 KURL url = m_frame->document()->url(); 160 if (!url.setProtocol(protocol)) { 161 es.throwDOMException(SyntaxError); 162 return; 163 } 164 setLocation(url.string(), activeWindow, firstWindow); 165 } 166 167 void Location::setHost(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& host) 168 { 169 if (!m_frame) 170 return; 171 KURL url = m_frame->document()->url(); 172 url.setHostAndPort(host); 173 setLocation(url.string(), activeWindow, firstWindow); 174 } 175 176 void Location::setHostname(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& hostname) 177 { 178 if (!m_frame) 179 return; 180 KURL url = m_frame->document()->url(); 181 url.setHost(hostname); 182 setLocation(url.string(), activeWindow, firstWindow); 183 } 184 185 void Location::setPort(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& portString) 186 { 187 if (!m_frame) 188 return; 189 KURL url = m_frame->document()->url(); 190 int port = portString.toInt(); 191 if (port < 0 || port > 0xFFFF || portString.isEmpty()) 192 url.removePort(); 193 else 194 url.setPort(port); 195 setLocation(url.string(), activeWindow, firstWindow); 196 } 197 198 void Location::setPathname(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& pathname) 199 { 200 if (!m_frame) 201 return; 202 KURL url = m_frame->document()->url(); 203 url.setPath(pathname); 204 setLocation(url.string(), activeWindow, firstWindow); 205 } 206 207 void Location::setSearch(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& search) 208 { 209 if (!m_frame) 210 return; 211 KURL url = m_frame->document()->url(); 212 url.setQuery(search); 213 setLocation(url.string(), activeWindow, firstWindow); 214 } 215 216 void Location::setHash(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& hash) 217 { 218 if (!m_frame) 219 return; 220 KURL url = m_frame->document()->url(); 221 String oldFragmentIdentifier = url.fragmentIdentifier(); 222 String newFragmentIdentifier = hash; 223 if (hash[0] == '#') 224 newFragmentIdentifier = hash.substring(1); 225 url.setFragmentIdentifier(newFragmentIdentifier); 226 // Note that by parsing the URL and *then* comparing fragments, we are 227 // comparing fragments post-canonicalization, and so this handles the 228 // cases where fragment identifiers are ignored or invalid. 229 if (equalIgnoringNullity(oldFragmentIdentifier, url.fragmentIdentifier())) 230 return; 231 setLocation(url.string(), activeWindow, firstWindow); 232 } 233 234 void Location::assign(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& url) 235 { 236 if (!m_frame) 237 return; 238 setLocation(url, activeWindow, firstWindow); 239 } 240 241 void Location::replace(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& url) 242 { 243 if (!m_frame) 244 return; 245 // Note: We call DOMWindow::setLocation directly here because replace() always operates on the current frame. 246 m_frame->domWindow()->setLocation(url, activeWindow, firstWindow, LockHistoryAndBackForwardList); 247 } 248 249 void Location::reload(DOMWindow* activeWindow) 250 { 251 if (!m_frame) 252 return; 253 if (protocolIsJavaScript(m_frame->document()->url())) 254 return; 255 m_frame->navigationScheduler()->scheduleRefresh(); 256 } 257 258 void Location::setLocation(const String& url, DOMWindow* activeWindow, DOMWindow* firstWindow) 259 { 260 ASSERT(m_frame); 261 // We call findFrameForNavigation to handle the case of a seamless iframe correctly. 262 Frame* frame = m_frame->loader()->findFrameForNavigation(String(), activeWindow->document()); 263 if (!frame) 264 return; 265 frame->domWindow()->setLocation(url, activeWindow, firstWindow); 266 } 267 268 } // namespace WebCore 269