Home | History | Annotate | Download | only in page
      1 /*
      2  *  Copyright (C) 2000 Harri Porten (porten (at) kde.org)
      3  *  Copyright (c) 2000 Daniel Molkentin (molkentin (at) kde.org)
      4  *  Copyright (c) 2000 Stefan Schimanski (schimmi (at) kde.org)
      5  *  Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
      6  *  Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      7  *
      8  *  This library is free software; you can redistribute it and/or
      9  *  modify it under the terms of the GNU Lesser General Public
     10  *  License as published by the Free Software Foundation; either
     11  *  version 2 of the License, or (at your option) any later version.
     12  *
     13  *  This library is distributed in the hope that it will be useful,
     14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  *  Lesser General Public License for more details.
     17  *
     18  *  You should have received a copy of the GNU Lesser General Public
     19  *  License along with this library; if not, write to the Free Software
     20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     21  */
     22 
     23 #include "config.h"
     24 #include "Navigator.h"
     25 
     26 #include "Chrome.h"
     27 #include "CookieJar.h"
     28 #include "ExceptionCode.h"
     29 #include "Frame.h"
     30 #include "FrameLoader.h"
     31 #include "FrameLoaderClient.h"
     32 #include "Geolocation.h"
     33 #include "KURL.h"
     34 #include "Language.h"
     35 #include "MimeTypeArray.h"
     36 #include "Page.h"
     37 #include "PageGroup.h"
     38 #include "PlatformString.h"
     39 #include "PluginArray.h"
     40 #include "PluginData.h"
     41 #include "ScriptController.h"
     42 #include "Settings.h"
     43 #include "StorageNamespace.h"
     44 
     45 #if PLATFORM(ANDROID)
     46 #include "ApplicationInstalledCallback.h"
     47 #include "Connection.h"
     48 #include "PackageNotifier.h"
     49 #endif
     50 
     51 namespace WebCore {
     52 
     53 Navigator::Navigator(Frame* frame)
     54     : m_frame(frame)
     55 {
     56 }
     57 
     58 Navigator::~Navigator()
     59 {
     60     disconnectFrame();
     61 }
     62 
     63 void Navigator::disconnectFrame()
     64 {
     65     if (m_plugins) {
     66         m_plugins->disconnectFrame();
     67         m_plugins = 0;
     68     }
     69     if (m_mimeTypes) {
     70         m_mimeTypes->disconnectFrame();
     71         m_mimeTypes = 0;
     72     }
     73     if (m_geolocation) {
     74         m_geolocation->disconnectFrame();
     75         m_geolocation = 0;
     76     }
     77     m_frame = 0;
     78 }
     79 
     80 // If this function returns true, we need to hide the substring "4." that would otherwise
     81 // appear in the appVersion string. This is to avoid problems with old versions of a
     82 // library called OpenCube QuickMenu, which as of this writing is still being used on
     83 // sites such as nwa.com -- the library thinks Safari is Netscape 4 if we don't do this!
     84 static bool shouldHideFourDot(Frame* frame)
     85 {
     86     const String* sourceURL = frame->script()->sourceURL();
     87     if (!sourceURL)
     88         return false;
     89     if (!(sourceURL->endsWith("/dqm_script.js") || sourceURL->endsWith("/dqm_loader.js") || sourceURL->endsWith("/tdqm_loader.js")))
     90         return false;
     91     Settings* settings = frame->settings();
     92     if (!settings)
     93         return false;
     94     return settings->needsSiteSpecificQuirks();
     95 }
     96 
     97 String Navigator::appVersion() const
     98 {
     99     if (!m_frame)
    100         return String();
    101     String appVersion = NavigatorBase::appVersion();
    102     if (shouldHideFourDot(m_frame))
    103         appVersion.replace("4.", "4_");
    104     return appVersion;
    105 }
    106 
    107 String Navigator::language() const
    108 {
    109     return defaultLanguage();
    110 }
    111 
    112 String Navigator::userAgent() const
    113 {
    114     if (!m_frame)
    115         return String();
    116 
    117     // If the frame is already detached, FrameLoader::userAgent may malfunction, because it calls a client method
    118     // that uses frame's WebView (at least, in Mac WebKit).
    119     if (!m_frame->page())
    120         return String();
    121 
    122     return m_frame->loader()->userAgent(m_frame->document()->url());
    123 }
    124 
    125 PluginArray* Navigator::plugins() const
    126 {
    127     if (!m_plugins)
    128         m_plugins = PluginArray::create(m_frame);
    129     return m_plugins.get();
    130 }
    131 
    132 MimeTypeArray* Navigator::mimeTypes() const
    133 {
    134     if (!m_mimeTypes)
    135         m_mimeTypes = MimeTypeArray::create(m_frame);
    136     return m_mimeTypes.get();
    137 }
    138 
    139 bool Navigator::cookieEnabled() const
    140 {
    141     if (!m_frame)
    142         return false;
    143 
    144     if (m_frame->page() && !m_frame->page()->cookieEnabled())
    145         return false;
    146 
    147     return cookiesEnabled(m_frame->document());
    148 }
    149 
    150 bool Navigator::javaEnabled() const
    151 {
    152     if (!m_frame || !m_frame->settings())
    153         return false;
    154 
    155     return m_frame->settings()->isJavaEnabled();
    156 }
    157 
    158 Geolocation* Navigator::geolocation() const
    159 {
    160     if (!m_geolocation)
    161         m_geolocation = Geolocation::create(m_frame);
    162     return m_geolocation.get();
    163 }
    164 
    165 #if PLATFORM(ANDROID)
    166 Connection* Navigator::connection() const
    167 {
    168     if (!m_connection)
    169         m_connection = Connection::create();
    170     return m_connection.get();
    171 }
    172 #endif
    173 
    174 #if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED)
    175 
    176 bool Navigator::isApplicationInstalled(const String& name, PassRefPtr<ApplicationInstalledCallback> callback)
    177 {
    178     if (m_applicationInstalledCallback)
    179         return false;
    180 
    181     m_applicationInstalledCallback = callback;
    182     m_applicationNameQuery = name;
    183 
    184     packageNotifier().requestPackageResult();
    185 
    186     return true;
    187 }
    188 
    189 void Navigator::onPackageResult()
    190 {
    191     if (m_applicationInstalledCallback) {
    192         m_applicationInstalledCallback->handleEvent(packageNotifier().isPackageInstalled(m_applicationNameQuery));
    193         m_applicationInstalledCallback = 0;
    194     }
    195 }
    196 #endif
    197 
    198 #if ENABLE(DOM_STORAGE)
    199 void Navigator::getStorageUpdates()
    200 {
    201     if (!m_frame)
    202         return;
    203 
    204     Page* page = m_frame->page();
    205     if (!page)
    206         return;
    207 
    208     StorageNamespace* localStorage = page->group().localStorage();
    209     if (localStorage)
    210         localStorage->unlock();
    211 }
    212 #endif
    213 
    214 static bool verifyCustomHandlerURL(const String& baseURL, const String& url, ExceptionCode& ec)
    215 {
    216     // The specification requires that it is a SYNTAX_ERR if the the "%s" token is not present.
    217     static const char token[] = "%s";
    218     int index = url.find(token);
    219     if (-1 == index) {
    220         ec = SYNTAX_ERR;
    221         return false;
    222     }
    223 
    224     // It is also a SYNTAX_ERR if the custom handler URL, as created by removing
    225     // the "%s" token and prepending the base url, does not resolve.
    226     String newURL = url;
    227     newURL.remove(index, sizeof(token) / sizeof(token[0]));
    228 
    229     KURL base(ParsedURLString, baseURL);
    230     KURL kurl(base, newURL);
    231 
    232     if (kurl.isEmpty() || !kurl.isValid()) {
    233         ec = SYNTAX_ERR;
    234         return false;
    235     }
    236 
    237     return true;
    238 }
    239 
    240 static bool verifyProtocolHandlerScheme(const String& scheme, ExceptionCode& ec)
    241 {
    242     // It is a SECURITY_ERR for these schemes to be handled by a custom handler.
    243     if (equalIgnoringCase(scheme, "http") || equalIgnoringCase(scheme, "https") || equalIgnoringCase(scheme, "file")) {
    244         ec = SECURITY_ERR;
    245         return false;
    246     }
    247     return true;
    248 }
    249 
    250 void Navigator::registerProtocolHandler(const String& scheme, const String& url, const String& title, ExceptionCode& ec)
    251 {
    252     if (!verifyProtocolHandlerScheme(scheme, ec))
    253         return;
    254 
    255     if (!m_frame)
    256         return;
    257 
    258     Document* document = m_frame->document();
    259     if (!document)
    260         return;
    261 
    262     String baseURL = document->baseURL().baseAsString();
    263 
    264     if (!verifyCustomHandlerURL(baseURL, url, ec))
    265         return;
    266 
    267     if (Page* page = m_frame->page())
    268         page->chrome()->registerProtocolHandler(scheme, baseURL, url, m_frame->displayStringModifiedByEncoding(title));
    269 }
    270 
    271 static bool verifyProtocolHandlerMimeType(const String& type, ExceptionCode& ec)
    272 {
    273     // It is a SECURITY_ERR for these mime types to be assigned to a custom
    274     // handler.
    275     if (equalIgnoringCase(type, "text/html") || equalIgnoringCase(type, "text/css") || equalIgnoringCase(type, "application/x-javascript")) {
    276         ec = SECURITY_ERR;
    277         return false;
    278     }
    279     return true;
    280 }
    281 
    282 void Navigator::registerContentHandler(const String& mimeType, const String& url, const String& title, ExceptionCode& ec)
    283 {
    284     if (!verifyProtocolHandlerMimeType(mimeType, ec))
    285         return;
    286 
    287     if (!m_frame)
    288         return;
    289 
    290     Document* document = m_frame->document();
    291     if (!document)
    292         return;
    293 
    294     String baseURL = document->baseURL().baseAsString();
    295 
    296     if (!verifyCustomHandlerURL(baseURL, url, ec))
    297         return;
    298 
    299     if (Page* page = m_frame->page())
    300         page->chrome()->registerContentHandler(mimeType, baseURL, url, m_frame->displayStringModifiedByEncoding(title));
    301 }
    302 
    303 } // namespace WebCore
    304