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 "Location.h" 31 32#include "DOMWindow.h" 33#include "ExceptionCode.h" 34#include "Frame.h" 35#include "FrameLoader.h" 36#include "KURL.h" 37 38namespace WebCore { 39 40Location::Location(Frame* frame) 41 : m_frame(frame) 42{ 43} 44 45void Location::disconnectFrame() 46{ 47 m_frame = 0; 48} 49 50inline const KURL& Location::url() const 51{ 52 ASSERT(m_frame); 53 54 const KURL& url = m_frame->document()->url(); 55 if (!url.isValid()) 56 return blankURL(); // Use "about:blank" while the page is still loading (before we have a frame). 57 58 return url; 59} 60 61String Location::href() const 62{ 63 if (!m_frame) 64 return String(); 65 66 return url().string(); 67} 68 69String Location::protocol() const 70{ 71 if (!m_frame) 72 return String(); 73 74 return url().protocol() + ":"; 75} 76 77String Location::host() const 78{ 79 if (!m_frame) 80 return String(); 81 82 // Note: this is the IE spec. The NS spec swaps the two, it says 83 // "The hostname property is the concatenation of the host and port properties, separated by a colon." 84 const KURL& url = this->url(); 85 return url.hasPort() ? url.host() + ":" + String::number(url.port()) : url.host(); 86} 87 88String Location::hostname() const 89{ 90 if (!m_frame) 91 return String(); 92 93 return url().host(); 94} 95 96String Location::port() const 97{ 98 if (!m_frame) 99 return String(); 100 101 const KURL& url = this->url(); 102 return url.hasPort() ? String::number(url.port()) : ""; 103} 104 105String Location::pathname() const 106{ 107 if (!m_frame) 108 return String(); 109 110 const KURL& url = this->url(); 111 return url.path().isEmpty() ? "/" : url.path(); 112} 113 114String Location::search() const 115{ 116 if (!m_frame) 117 return String(); 118 119 const KURL& url = this->url(); 120 return url.query().isEmpty() ? "" : "?" + url.query(); 121} 122 123String Location::origin() const 124{ 125 if (!m_frame) 126 return String(); 127 return SecurityOrigin::create(url())->toString(); 128} 129 130String Location::hash() const 131{ 132 if (!m_frame) 133 return String(); 134 135 const String& fragmentIdentifier = url().fragmentIdentifier(); 136 return fragmentIdentifier.isEmpty() ? "" : "#" + fragmentIdentifier; 137} 138 139String Location::getParameter(const String& name) const 140{ 141 if (!m_frame) 142 return String(); 143 144 ParsedURLParameters parameters; 145 url().copyParsedQueryTo(parameters); 146 return parameters.get(name); 147} 148 149void Location::setHref(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow) 150{ 151 if (!m_frame) 152 return; 153 m_frame->domWindow()->setLocation(urlString, activeWindow, firstWindow); 154} 155 156void Location::setProtocol(const String& protocol, DOMWindow* activeWindow, DOMWindow* firstWindow, ExceptionCode& ec) 157{ 158 if (!m_frame) 159 return; 160 KURL url = m_frame->document()->url(); 161 if (!url.setProtocol(protocol)) { 162 ec = SYNTAX_ERR; 163 return; 164 } 165 m_frame->domWindow()->setLocation(url.string(), activeWindow, firstWindow); 166} 167 168void Location::setHost(const String& host, DOMWindow* activeWindow, DOMWindow* firstWindow) 169{ 170 if (!m_frame) 171 return; 172 KURL url = m_frame->document()->url(); 173 url.setHostAndPort(host); 174 m_frame->domWindow()->setLocation(url.string(), activeWindow, firstWindow); 175} 176 177void Location::setHostname(const String& hostname, DOMWindow* activeWindow, DOMWindow* firstWindow) 178{ 179 if (!m_frame) 180 return; 181 KURL url = m_frame->document()->url(); 182 url.setHost(hostname); 183 m_frame->domWindow()->setLocation(url.string(), activeWindow, firstWindow); 184} 185 186void Location::setPort(const String& portString, DOMWindow* activeWindow, DOMWindow* firstWindow) 187{ 188 if (!m_frame) 189 return; 190 KURL url = m_frame->document()->url(); 191 int port = portString.toInt(); 192 if (port < 0 || port > 0xFFFF || portString.isEmpty()) 193 url.removePort(); 194 else 195 url.setPort(port); 196 m_frame->domWindow()->setLocation(url.string(), activeWindow, firstWindow); 197} 198 199void Location::setPathname(const String& pathname, DOMWindow* activeWindow, DOMWindow* firstWindow) 200{ 201 if (!m_frame) 202 return; 203 KURL url = m_frame->document()->url(); 204 url.setPath(pathname); 205 m_frame->domWindow()->setLocation(url.string(), activeWindow, firstWindow); 206} 207 208void Location::setSearch(const String& search, DOMWindow* activeWindow, DOMWindow* firstWindow) 209{ 210 if (!m_frame) 211 return; 212 KURL url = m_frame->document()->url(); 213 url.setQuery(search); 214 m_frame->domWindow()->setLocation(url.string(), activeWindow, firstWindow); 215} 216 217void Location::setHash(const String& hash, DOMWindow* activeWindow, DOMWindow* firstWindow) 218{ 219 if (!m_frame) 220 return; 221 KURL url = m_frame->document()->url(); 222 String oldFragmentIdentifier = url.fragmentIdentifier(); 223 String newFragmentIdentifier = hash; 224 if (hash[0] == '#') 225 newFragmentIdentifier = hash.substring(1); 226 url.setFragmentIdentifier(newFragmentIdentifier); 227 // Note that by parsing the URL and *then* comparing fragments, we are 228 // comparing fragments post-canonicalization, and so this handles the 229 // cases where fragment identifiers are ignored or invalid. 230 if (equalIgnoringNullity(oldFragmentIdentifier, url.fragmentIdentifier())) 231 return; 232 m_frame->domWindow()->setLocation(url.string(), activeWindow, firstWindow); 233} 234 235void Location::assign(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow) 236{ 237 if (!m_frame) 238 return; 239 m_frame->domWindow()->setLocation(urlString, activeWindow, firstWindow); 240} 241 242void Location::replace(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow) 243{ 244 if (!m_frame) 245 return; 246 m_frame->domWindow()->setLocation(urlString, activeWindow, firstWindow, LockHistoryAndBackForwardList); 247} 248 249void Location::reload(DOMWindow* activeWindow) 250{ 251 if (!m_frame) 252 return; 253 // FIXME: It's not clear this cross-origin security check is valuable. 254 // We allow one page to change the location of another. Why block attempts to reload? 255 // Other location operations simply block use of JavaScript URLs cross origin. 256 DOMWindow* targetWindow = m_frame->domWindow(); 257 if (!activeWindow->securityOrigin()->canAccess(targetWindow->securityOrigin())) { 258 targetWindow->printErrorMessage(targetWindow->crossDomainAccessErrorMessage(activeWindow)); 259 return; 260 } 261 if (protocolIsJavaScript(m_frame->document()->url())) 262 return; 263 m_frame->navigationScheduler()->scheduleRefresh(); 264} 265 266} // namespace WebCore 267