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
54 namespace WebCore {
55
Navigator(Frame * frame)56 Navigator::Navigator(Frame* frame)
57 : m_frame(frame)
58 {
59 }
60
~Navigator()61 Navigator::~Navigator()
62 {
63 disconnectFrame();
64 }
65
resetGeolocation()66 void Navigator::resetGeolocation()
67 {
68 if (m_geolocation)
69 m_geolocation->reset();
70 }
71
disconnectFrame()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!
shouldHideFourDot(Frame * frame)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
appVersion() const106 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
language() const116 String Navigator::language() const
117 {
118 return defaultLanguage();
119 }
120
userAgent() const121 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
plugins() const134 DOMPluginArray* Navigator::plugins() const
135 {
136 if (!m_plugins)
137 m_plugins = DOMPluginArray::create(m_frame);
138 return m_plugins.get();
139 }
140
mimeTypes() const141 DOMMimeTypeArray* Navigator::mimeTypes() const
142 {
143 if (!m_mimeTypes)
144 m_mimeTypes = DOMMimeTypeArray::create(m_frame);
145 return m_mimeTypes.get();
146 }
147
cookieEnabled() const148 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
javaEnabled() const159 bool Navigator::javaEnabled() const
160 {
161 if (!m_frame || !m_frame->settings())
162 return false;
163
164 return m_frame->settings()->isJavaEnabled();
165 }
166
geolocation() const167 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)
connection() const175 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
isApplicationInstalled(const String & name,PassRefPtr<ApplicationInstalledCallback> callback)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
onPackageResult()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)
getStorageUpdates()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)
verifyCustomHandlerURL(const String & baseURL,const String & url,ExceptionCode & ec)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
verifyProtocolHandlerScheme(const String & scheme,ExceptionCode & ec)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
registerProtocolHandler(const String & scheme,const String & url,const String & title,ExceptionCode & ec)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)
webkitGetUserMedia(const String & options,PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback,PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback)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