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 return url().string(); 67 } 68 69 String Location::protocol() const 70 { 71 if (!m_frame) 72 return String(); 73 74 return url().protocol() + ":"; 75 } 76 77 String 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 88 String Location::hostname() const 89 { 90 if (!m_frame) 91 return String(); 92 93 return url().host(); 94 } 95 96 String 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 105 String 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 114 String 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 123 String Location::origin() const 124 { 125 if (!m_frame) 126 return String(); 127 return SecurityOrigin::create(url())->toString(); 128 } 129 130 String 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 139 String 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 149 void 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 156 void 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 168 void 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 177 void 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 186 void 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 199 void 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 208 void 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 217 void 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 235 void 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 242 void 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 249 void 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