Home | History | Annotate | Download | only in page
      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