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 "DOMMimeTypeArray.h"
     29 #include "DOMPluginArray.h"
     30 #include "ExceptionCode.h"
     31 #include "Frame.h"
     32 #include "FrameLoader.h"
     33 #include "FrameLoaderClient.h"
     34 #include "Geolocation.h"
     35 #include "KURL.h"
     36 #include "Language.h"
     37 #include "NavigatorUserMediaErrorCallback.h"
     38 #include "NavigatorUserMediaSuccessCallback.h"
     39 #include "Page.h"
     40 #include "PageGroup.h"
     41 #include "PlatformString.h"
     42 #include "PluginData.h"
     43 #include "ScriptController.h"
     44 #include "Settings.h"
     45 #include "StorageNamespace.h"
     46 #include <wtf/StdLibExtras.h>
     47 
     48 #if PLATFORM(ANDROID)
     49 #include "ApplicationInstalledCallback.h"
     50 #include "Connection.h"
     51 #include "PackageNotifier.h"
     52 #endif
     53 
     54 namespace WebCore {
     55 
     56 Navigator::Navigator(Frame* frame)
     57     : m_frame(frame)
     58 {
     59 }
     60 
     61 Navigator::~Navigator()
     62 {
     63     disconnectFrame();
     64 }
     65 
     66 void Navigator::resetGeolocation()
     67 {
     68     if (m_geolocation)
     69         m_geolocation->reset();
     70 }
     71 
     72 void Navigator::disconnectFrame()
     73 {
     74     if (m_plugins) {
     75         m_plugins->disconnectFrame();
     76         m_plugins = 0;
     77     }
     78     if (m_mimeTypes) {
     79         m_mimeTypes->disconnectFrame();
     80         m_mimeTypes = 0;
     81     }
     82     if (m_geolocation) {
     83         m_geolocation->disconnectFrame();
     84         m_geolocation = 0;
     85     }
     86     m_frame = 0;
     87 }
     88 
     89 // If this function returns true, we need to hide the substring "4." that would otherwise
     90 // appear in the appVersion string. This is to avoid problems with old versions of a
     91 // library called OpenCube QuickMenu, which as of this writing is still being used on
     92 // sites such as nwa.com -- the library thinks Safari is Netscape 4 if we don't do this!
     93 static bool shouldHideFourDot(Frame* frame)
     94 {
     95     const String* sourceURL = frame->script()->sourceURL();
     96     if (!sourceURL)
     97         return false;
     98     if (!(sourceURL->endsWith("/dqm_script.js") || sourceURL->endsWith("/dqm_loader.js") || sourceURL->endsWith("/tdqm_loader.js")))
     99         return false;
    100     Settings* settings = frame->settings();
    101     if (!settings)
    102         return false;
    103     return settings->needsSiteSpecificQuirks();
    104 }
    105 
    106 String Navigator::appVersion() const
    107 {
    108     if (!m_frame)
    109         return String();
    110     String appVersion = NavigatorBase::appVersion();
    111     if (shouldHideFourDot(m_frame))
    112         appVersion.replace("4.", "4_");
    113     return appVersion;
    114 }
    115 
    116 String Navigator::language() const
    117 {
    118     return defaultLanguage();
    119 }
    120 
    121 String Navigator::userAgent() const
    122 {
    123     if (!m_frame)
    124         return String();
    125 
    126     // If the frame is already detached, FrameLoader::userAgent may malfunction, because it calls a client method
    127     // that uses frame's WebView (at least, in Mac WebKit).
    128     if (!m_frame->page())
    129         return String();
    130 
    131     return m_frame->loader()->userAgent(m_frame->document()->url());
    132 }
    133 
    134 DOMPluginArray* Navigator::plugins() const
    135 {
    136     if (!m_plugins)
    137         m_plugins = DOMPluginArray::create(m_frame);
    138     return m_plugins.get();
    139 }
    140 
    141 DOMMimeTypeArray* Navigator::mimeTypes() const
    142 {
    143     if (!m_mimeTypes)
    144         m_mimeTypes = DOMMimeTypeArray::create(m_frame);
    145     return m_mimeTypes.get();
    146 }
    147 
    148 bool Navigator::cookieEnabled() const
    149 {
    150     if (!m_frame)
    151         return false;
    152 
    153     if (m_frame->page() && !m_frame->page()->cookieEnabled())
    154         return false;
    155 
    156     return cookiesEnabled(m_frame->document());
    157 }
    158 
    159 bool Navigator::javaEnabled() const
    160 {
    161     if (!m_frame || !m_frame->settings())
    162         return false;
    163 
    164     return m_frame->settings()->isJavaEnabled();
    165 }
    166 
    167 Geolocation* Navigator::geolocation() const
    168 {
    169     if (!m_geolocation)
    170         m_geolocation = Geolocation::create(m_frame);
    171     return m_geolocation.get();
    172 }
    173 
    174 #if PLATFORM(ANDROID)
    175 Connection* Navigator::connection() const
    176 {
    177     if (!m_connection)
    178         m_connection = Connection::create();
    179     return m_connection.get();
    180 }
    181 #endif
    182 
    183 #if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED)
    184 
    185 bool Navigator::isApplicationInstalled(const String& name, PassRefPtr<ApplicationInstalledCallback> callback)
    186 {
    187     if (m_applicationInstalledCallback)
    188         return false;
    189 
    190     m_applicationInstalledCallback = callback;
    191     m_applicationNameQuery = name;
    192 
    193     packageNotifier().requestPackageResult();
    194 
    195     return true;
    196 }
    197 
    198 void Navigator::onPackageResult()
    199 {
    200     if (m_applicationInstalledCallback) {
    201         m_applicationInstalledCallback->handleEvent(packageNotifier().isPackageInstalled(m_applicationNameQuery));
    202         m_applicationInstalledCallback = 0;
    203     }
    204 }
    205 #endif
    206 
    207 #if ENABLE(DOM_STORAGE)
    208 void Navigator::getStorageUpdates()
    209 {
    210     if (!m_frame)
    211         return;
    212 
    213     Page* page = m_frame->page();
    214     if (!page)
    215         return;
    216 
    217     StorageNamespace* localStorage = page->group().localStorage();
    218     if (localStorage)
    219         localStorage->unlock();
    220 }
    221 #endif
    222 
    223 #if ENABLE(REGISTER_PROTOCOL_HANDLER)
    224 static bool verifyCustomHandlerURL(const String& baseURL, const String& url, ExceptionCode& ec)
    225 {
    226     // The specification requires that it is a SYNTAX_ERR if the "%s" token is
    227     // not present.
    228     static const char token[] = "%s";
    229     int index = url.find(token);
    230     if (-1 == index) {
    231         ec = SYNTAX_ERR;
    232         return false;
    233     }
    234 
    235     // It is also a SYNTAX_ERR if the custom handler URL, as created by removing
    236     // the "%s" token and prepending the base url, does not resolve.
    237     String newURL = url;
    238     newURL.remove(index, WTF_ARRAY_LENGTH(token) - 1);
    239 
    240     KURL base(ParsedURLString, baseURL);
    241     KURL kurl(base, newURL);
    242 
    243     if (kurl.isEmpty() || !kurl.isValid()) {
    244         ec = SYNTAX_ERR;
    245         return false;
    246     }
    247 
    248     return true;
    249 }
    250 
    251 static bool verifyProtocolHandlerScheme(const String& scheme, ExceptionCode& ec)
    252 {
    253     // It is a SECURITY_ERR for these schemes to be handled by a custom handler.
    254     if (equalIgnoringCase(scheme, "http") || equalIgnoringCase(scheme, "https") || equalIgnoringCase(scheme, "file")) {
    255         ec = SECURITY_ERR;
    256         return false;
    257     }
    258     return true;
    259 }
    260 
    261 void Navigator::registerProtocolHandler(const String& scheme, const String& url, const String& title, ExceptionCode& ec)
    262 {
    263     if (!verifyProtocolHandlerScheme(scheme, ec))
    264         return;
    265 
    266     if (!m_frame)
    267         return;
    268 
    269     Document* document = m_frame->document();
    270     if (!document)
    271         return;
    272 
    273     String baseURL = document->baseURL().baseAsString();
    274 
    275     if (!verifyCustomHandlerURL(baseURL, url, ec))
    276         return;
    277 
    278     Page* page = m_frame->page();
    279     if (!page)
    280         return;
    281 
    282     page->chrome()->registerProtocolHandler(scheme, baseURL, url, m_frame->displayStringModifiedByEncoding(title));
    283 }
    284 #endif
    285 
    286 #if ENABLE(MEDIA_STREAM)
    287 void Navigator::webkitGetUserMedia(const String& options,
    288                                    PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback,
    289                                    PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback)
    290 {
    291     // FIXME: implement a call to the media stream context when available.
    292 }
    293 #endif
    294 
    295 } // namespace WebCore
    296