Need a mechanism to override navigator.userAgent
[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 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 "Frame.h"
32 #include "FrameLoader.h"
33 #include "FrameLoaderClient.h"
34 #include "Geolocation.h"
35 #include "JSDOMPromiseDeferred.h"
36 #include "LoaderStrategy.h"
37 #include "Page.h"
38 #include "PlatformStrategies.h"
39 #include "PluginData.h"
40 #include "ResourceLoadObserver.h"
41 #include "RuntimeEnabledFeatures.h"
42 #include "ScriptController.h"
43 #include "SecurityOrigin.h"
44 #include "Settings.h"
45 #include <wtf/Language.h>
46 #include <wtf/StdLibExtras.h>
47 #include <wtf/WeakPtr.h>
48
49 namespace WebCore {
50 using namespace WTF;
51
52 Navigator::Navigator(ScriptExecutionContext* context, DOMWindow& window)
53     : NavigatorBase(context)
54     , DOMWindowProperty(&window)
55 {
56 }
57
58 Navigator::~Navigator() = default;
59
60 // If this function returns true, we need to hide the substring "4." that would otherwise
61 // appear in the appVersion string. This is to avoid problems with old versions of a
62 // library called OpenCube QuickMenu, which as of this writing is still being used on
63 // sites such as nwa.com -- the library thinks Safari is Netscape 4 if we don't do this!
64 static bool shouldHideFourDot(Frame& frame)
65 {
66     auto* sourceURL = frame.script().sourceURL();
67     if (!sourceURL)
68         return false;
69     if (!(sourceURL->endsWith("/dqm_script.js") || sourceURL->endsWith("/dqm_loader.js") || sourceURL->endsWith("/tdqm_loader.js")))
70         return false;
71     return frame.settings().needsSiteSpecificQuirks();
72 }
73
74 String Navigator::appVersion() const
75 {
76     auto* frame = this->frame();
77     if (!frame)
78         return String();
79     if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
80         ResourceLoadObserver::shared().logNavigatorAPIAccessed(*frame->document(), ResourceLoadStatistics::NavigatorAPI::AppVersion);
81     String appVersion = NavigatorBase::appVersion();
82     if (shouldHideFourDot(*frame))
83         appVersion.replace("4.", "4_");
84     return appVersion;
85 }
86
87 const String& Navigator::userAgent() const
88 {
89     auto* frame = this->frame();
90     if (!frame || !frame->page())
91         return m_userAgent;
92     if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
93         ResourceLoadObserver::shared().logNavigatorAPIAccessed(*frame->document(), ResourceLoadStatistics::NavigatorAPI::UserAgent);
94     if (m_userAgent.isNull())
95         m_userAgent = frame->loader().userAgentForJavaScript(frame->document()->url());
96     return m_userAgent;
97 }
98     
99 const String& Navigator::platform() const
100 {
101     auto* frame = this->frame();
102     if (!frame || !frame->page())
103         return m_platform;
104
105     if (m_platform.isNull())
106         m_platform = frame->loader().navigatorPlatform();
107     
108     if (m_platform.isNull())
109         m_platform = NavigatorBase::platform();
110     return m_platform;
111 }
112
113 void Navigator::userAgentChanged()
114 {
115     m_userAgent = String();
116 }
117
118 bool Navigator::onLine() const
119 {
120     return platformStrategies()->loaderStrategy()->isOnLine();
121 }
122
123 void Navigator::share(ScriptExecutionContext& context, ShareData data, Ref<DeferredPromise>&& promise)
124 {
125     auto* frame = this->frame();
126     if (!frame || !frame->page()) {
127         promise->reject(TypeError);
128         return;
129     }
130     
131     if (data.title.isEmpty() && data.url.isEmpty() && data.text.isEmpty()) {
132         promise->reject(TypeError);
133         return;
134     }
135
136     Optional<URL> url;
137     if (!data.url.isEmpty()) {
138         url = context.completeURL(data.url);
139         if (!url->isValid()) {
140             promise->reject(TypeError);
141             return;
142         }
143     }
144     
145     if (!UserGestureIndicator::processingUserGesture()) {
146         promise->reject(NotAllowedError);
147         return;
148     }
149     
150     ShareDataWithParsedURL shareData = {
151         data,
152         url,
153     };
154
155     frame->page()->chrome().showShareSheet(shareData, [promise = WTFMove(promise)] (bool completed) {
156         if (completed) {
157             promise->resolve();
158             return;
159         }
160         promise->reject(Exception { AbortError, "Abort due to cancellation of share."_s });
161     });
162 }
163
164 DOMPluginArray& Navigator::plugins()
165 {
166     if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) {
167         if (auto* frame = this->frame())
168             ResourceLoadObserver::shared().logNavigatorAPIAccessed(*frame->document(), ResourceLoadStatistics::NavigatorAPI::Plugins);
169     }
170     if (!m_plugins)
171         m_plugins = DOMPluginArray::create(m_window);
172     return *m_plugins;
173 }
174
175 DOMMimeTypeArray& Navigator::mimeTypes()
176 {
177     if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) {
178         if (auto* frame = this->frame())
179             ResourceLoadObserver::shared().logNavigatorAPIAccessed(*frame->document(), ResourceLoadStatistics::NavigatorAPI::MimeTypes);
180     }
181     if (!m_mimeTypes)
182         m_mimeTypes = DOMMimeTypeArray::create(m_window);
183     return *m_mimeTypes;
184 }
185
186 bool Navigator::cookieEnabled() const
187 {
188     auto* frame = this->frame();
189     if (!frame)
190         return false;
191
192     if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
193         ResourceLoadObserver::shared().logNavigatorAPIAccessed(*frame->document(), ResourceLoadStatistics::NavigatorAPI::CookieEnabled);
194
195     auto* page = frame->page();
196     if (!page)
197         return false;
198     
199     if (!page->settings().cookieEnabled())
200         return false;
201
202     auto* document = frame->document();
203     if (!document)
204         return false;
205
206     return page->cookieJar().cookiesEnabled(*document);
207 }
208
209 bool Navigator::javaEnabled() const
210 {
211     auto* frame = this->frame();
212     if (!frame)
213         return false;
214
215     if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
216         ResourceLoadObserver::shared().logNavigatorAPIAccessed(*frame->document(), ResourceLoadStatistics::NavigatorAPI::JavaEnabled);
217
218     if (!frame->settings().isJavaEnabled())
219         return false;
220     if (frame->document()->securityOrigin().isLocal() && !frame->settings().isJavaEnabledForLocalFiles())
221         return false;
222
223     return true;
224 }
225
226 #if PLATFORM(IOS_FAMILY)
227
228 bool Navigator::standalone() const
229 {
230     auto* frame = this->frame();
231     return frame && frame->settings().standalone();
232 }
233
234 #endif
235
236 void Navigator::getStorageUpdates()
237 {
238 }
239
240 } // namespace WebCore