Move gamepad to Modules/ (+ some cleanup)
[WebKit-https.git] / Source / WebCore / page / Navigator.cpp
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 "Document.h"
31 #include "ExceptionCode.h"
32 #include "Frame.h"
33 #include "FrameLoader.h"
34 #include "FrameLoaderClient.h"
35 #include "Geolocation.h"
36 #include "PointerLock.h"
37 #include "KURL.h"
38 #include "Language.h"
39 #include "Page.h"
40 #include "PageGroup.h"
41 #include "PlatformString.h"
42 #include "PluginData.h"
43 #include "Settings.h"
44 #include "StorageNamespace.h"
45 #include <wtf/HashSet.h>
46 #include <wtf/StdLibExtras.h>
47
48 #if ENABLE(GAMEPAD)
49 #include "GamepadList.h"
50 #endif
51
52 #if ENABLE(MEDIA_STREAM)
53 #include "NavigatorUserMediaErrorCallback.h"
54 #include "NavigatorUserMediaSuccessCallback.h"
55 #include "UserMediaRequest.h"
56 #endif
57
58 namespace WebCore {
59
60 Navigator::Navigator(Frame* frame)
61     : m_frame(frame)
62 {
63 }
64
65 Navigator::~Navigator()
66 {
67     disconnectFrame();
68 }
69
70 void Navigator::resetGeolocation()
71 {
72     if (m_geolocation)
73         m_geolocation->reset();
74 }
75
76 void Navigator::disconnectFrame()
77 {
78     if (m_plugins) {
79         m_plugins->disconnectFrame();
80         m_plugins = 0;
81     }
82     if (m_mimeTypes) {
83         m_mimeTypes->disconnectFrame();
84         m_mimeTypes = 0;
85     }
86     if (m_geolocation) {
87         m_geolocation->disconnectFrame();
88         m_geolocation = 0;
89     }
90     m_frame = 0;
91 }
92
93 // If this function returns true, we need to hide the substring "4." that would otherwise
94 // appear in the appVersion string. This is to avoid problems with old versions of a
95 // library called OpenCube QuickMenu, which as of this writing is still being used on
96 // sites such as nwa.com -- the library thinks Safari is Netscape 4 if we don't do this!
97 static bool shouldHideFourDot(Frame* frame)
98 {
99     const String* sourceURL = frame->script()->sourceURL();
100     if (!sourceURL)
101         return false;
102     if (!(sourceURL->endsWith("/dqm_script.js") || sourceURL->endsWith("/dqm_loader.js") || sourceURL->endsWith("/tdqm_loader.js")))
103         return false;
104     Settings* settings = frame->settings();
105     if (!settings)
106         return false;
107     return settings->needsSiteSpecificQuirks();
108 }
109
110 String Navigator::appVersion() const
111 {
112     if (!m_frame)
113         return String();
114     String appVersion = NavigatorBase::appVersion();
115     if (shouldHideFourDot(m_frame))
116         appVersion.replace("4.", "4_");
117     return appVersion;
118 }
119
120 String Navigator::language() const
121 {
122     return defaultLanguage();
123 }
124
125 String Navigator::userAgent() const
126 {
127     if (!m_frame)
128         return String();
129         
130     // If the frame is already detached, FrameLoader::userAgent may malfunction, because it calls a client method
131     // that uses frame's WebView (at least, in Mac WebKit).
132     if (!m_frame->page())
133         return String();
134         
135     return m_frame->loader()->userAgent(m_frame->document()->url());
136 }
137
138 DOMPluginArray* Navigator::plugins() const
139 {
140     if (!m_plugins)
141         m_plugins = DOMPluginArray::create(m_frame);
142     return m_plugins.get();
143 }
144
145 DOMMimeTypeArray* Navigator::mimeTypes() const
146 {
147     if (!m_mimeTypes)
148         m_mimeTypes = DOMMimeTypeArray::create(m_frame);
149     return m_mimeTypes.get();
150 }
151
152 bool Navigator::cookieEnabled() const
153 {
154     if (!m_frame)
155         return false;
156         
157     if (m_frame->page() && !m_frame->page()->cookieEnabled())
158         return false;
159
160     return cookiesEnabled(m_frame->document());
161 }
162
163 bool Navigator::javaEnabled() const
164 {
165     if (!m_frame || !m_frame->settings())
166         return false;
167
168     return m_frame->settings()->isJavaEnabled();
169 }
170
171 Geolocation* Navigator::geolocation() const
172 {
173     if (!m_geolocation)
174         m_geolocation = Geolocation::create(m_frame);
175     return m_geolocation.get();
176 }
177
178 #if ENABLE(POINTER_LOCK)
179 PointerLock* Navigator::webkitPointer() const
180 {
181     if (!m_pointer)
182         m_pointer = PointerLock::create();
183     return m_pointer.get();
184 }
185 #endif
186
187 void Navigator::getStorageUpdates()
188 {
189     // FIXME: Remove this method or rename to yieldForStorageUpdates.
190 }
191
192 #if ENABLE(REGISTER_PROTOCOL_HANDLER)
193 static HashSet<String>* protocolWhitelist;
194
195 static void initProtocolHandlerWhitelist()
196 {
197     protocolWhitelist = new HashSet<String>;
198     static const char* protocols[] = {
199         "irc",
200         "mailto",
201         "mms",
202         "news",
203         "nntp",
204         "sms",
205         "smsto",
206         "tel",
207         "urn",
208         "webcal",
209     };
210     for (size_t i = 0; i < WTF_ARRAY_LENGTH(protocols); ++i)
211         protocolWhitelist->add(protocols[i]);
212 }
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 "%s" token is
217     // not present.
218     static const char token[] = "%s";
219     int index = url.find(token);
220     if (-1 == index) {
221         ec = SYNTAX_ERR;
222         return false;
223     }
224
225     // It is also a SYNTAX_ERR if the custom handler URL, as created by removing
226     // the "%s" token and prepending the base url, does not resolve.
227     String newURL = url;
228     newURL.remove(index, WTF_ARRAY_LENGTH(token) - 1);
229
230     KURL base(ParsedURLString, baseURL);
231     KURL kurl(base, newURL);
232
233     if (kurl.isEmpty() || !kurl.isValid()) {
234         ec = SYNTAX_ERR;
235         return false;
236     }
237
238     return true;
239 }
240
241 static bool isProtocolWhitelisted(const String& scheme)
242 {
243     if (!protocolWhitelist)
244         initProtocolHandlerWhitelist();
245     return protocolWhitelist->contains(scheme);
246 }
247
248 static bool verifyProtocolHandlerScheme(const String& scheme, ExceptionCode& ec)
249 {
250     if (scheme.startsWith("web+")) {
251         if (isValidProtocol(scheme))
252             return true;
253         ec = SECURITY_ERR;
254         return false;
255     }
256
257     if (isProtocolWhitelisted(scheme))
258         return true;
259     ec = SECURITY_ERR;
260     return false;
261 }
262
263 void Navigator::registerProtocolHandler(const String& scheme, const String& url, const String& title, ExceptionCode& ec)
264 {
265     if (!m_frame)
266         return;
267
268     Document* document = m_frame->document();
269     if (!document)
270         return;
271
272     String baseURL = document->baseURL().baseAsString();
273
274     if (!verifyCustomHandlerURL(baseURL, url, ec))
275         return;
276
277     if (!verifyProtocolHandlerScheme(scheme, ec))
278         return;
279
280     Page* page = m_frame->page();
281     if (!page)
282         return;
283
284     page->chrome()->registerProtocolHandler(scheme, baseURL, url, m_frame->displayStringModifiedByEncoding(title));
285 }
286 #endif
287
288 #if ENABLE(MEDIA_STREAM)
289 void Navigator::webkitGetUserMedia(const String& options, PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback, PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback, ExceptionCode& ec)
290 {
291     if (!successCallback)
292         return;
293
294     if (!m_frame)
295         return;
296
297     Page* page = m_frame->page();
298     if (!page)
299         return;
300
301     RefPtr<UserMediaRequest> request = UserMediaRequest::create(m_frame->document(), page->userMediaClient(), options, successCallback, errorCallback);
302     if (!request) {
303         ec = NOT_SUPPORTED_ERR;
304         return;
305     }
306
307     request->start();
308 }
309 #endif
310
311 #if ENABLE(GAMEPAD)
312 GamepadList* Navigator::webkitGamepads()
313 {
314     // Stubbed until platform/ changes landed.
315     return 0;
316 }
317 #endif
318
319 } // namespace WebCore