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