• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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