1/* 2 * Copyright (C) 2000 Harri Porten (porten@kde.org) 3 * Copyright (c) 2000 Daniel Molkentin (molkentin@kde.org) 4 * Copyright (c) 2000 Stefan Schimanski (schimmi@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 54namespace WebCore { 55 56Navigator::Navigator(Frame* frame) 57 : m_frame(frame) 58{ 59} 60 61Navigator::~Navigator() 62{ 63 disconnectFrame(); 64} 65 66void Navigator::resetGeolocation() 67{ 68 if (m_geolocation) 69 m_geolocation->reset(); 70} 71 72void 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! 93static 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 106String 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 116String Navigator::language() const 117{ 118 return defaultLanguage(); 119} 120 121String 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 134DOMPluginArray* Navigator::plugins() const 135{ 136 if (!m_plugins) 137 m_plugins = DOMPluginArray::create(m_frame); 138 return m_plugins.get(); 139} 140 141DOMMimeTypeArray* Navigator::mimeTypes() const 142{ 143 if (!m_mimeTypes) 144 m_mimeTypes = DOMMimeTypeArray::create(m_frame); 145 return m_mimeTypes.get(); 146} 147 148bool 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 159bool Navigator::javaEnabled() const 160{ 161 if (!m_frame || !m_frame->settings()) 162 return false; 163 164 return m_frame->settings()->isJavaEnabled(); 165} 166 167Geolocation* 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) 175Connection* 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 185bool 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 198void 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) 208void 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) 224static 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 251static 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 261void 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) 287void 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