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