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