When opening the 3D model in Augmented Reality on Safari, the model initially displays correctly. However, when attempting to move, resize, or rotate it, the device screen freezes along with the Augmented Reality view, and sometimes it crashes the application. This same model does not have any issues when opened in Chrome.
Has anyone experienced something similar, and if so, do you know how to resolve it?
General
RSS for tagExplore the integration of web technologies within your app. Discuss building web-based apps, leveraging Safari functionalities, and integrating with web services.
Post
Replies
Boosts
Views
Activity
Testing Sequoia public beta. The latest Safari should now support Extensions in web apps.
https://developer.apple.com/documentation/safari-release-notes/safari-18-release-notes#Safari-Extensions
But even I have extensions in the main Safari, there is none showing up in any of the web apps. What can be done to resolve this?
Hi,
I have developed my extension using React and MUI. The extension works with other browsers but it does not work with Safari. Is there any workaround to make it work with Safari or It is not possible to use React build on Safari.
Thank you.
Are there any Apple Pencil Pro specific events in Mobile Safari? The interesting ones are
hover, so we can know that it is about to touch the screen
squeeze, ideally where we can provide a list of icons and actions to take. Failing that, providing a filter so we can show just the Apple-approved actions that a given web app supports
I have simulators downloaded to my 14" M2 Pro Macbook Pro, and for some reason, I cannot see any simulators as an option in Safari's Responsive Design Mode.
Am I missing something obvious, or is my computer bugged?
Above is an image of the Responsive Design Mode showing no simulators. I would offer more screenshots to prove that I have simulators installed, but it won't let me upload any more photos for some reason.
I have a merchantId which from Buckaroo.
it is return false when I call canMakePaymentsWithActiveCard
I also have an merchantId which from Apple directly.
it is return true on sandbox test account.
The merchantId from buckaroo return true. when we test it on Mobile with real account.
I tried to create a content blocker for Safari and did it through Safari App Extension and Safari Web Extension.
The XCode project for Safari Extension creates 2 applications: the “Main Application” (which is compiled into ".app") and the “Safari Extension” itself (which is compiled into ".appex").
If you want to create a content blocker, you must add “Content Blocker Extension” from the “File → New → Target” menu. This will be the third application in the group, which is also compiled into "*.appex".
And now about differences...
The first difference is that Web Extension does not have the right to work on any domains by default, unlike App Extension. For the App Extension, in the "info.plist" in the "SFSafariWebsiteAccess" section, we can remove "Allowed Domains" and in "Level" replace "Some" to "All". This is important because the content blocker should work on any domain, and not be turned on manually for each individual. This will not work in Web Extension and will have to be activated for each domain separately.
The second significant difference between Web Extension and App Extension is that for security reasons it is more limited in page management.
Web Extensions are supposedly focused on a common API for all browsers (Firefox, Chrome, Opera, Edge, Safari), but if I use Safari and want maximum integration with it, then I don't care about all those browsers. In this case, I don't need Web Extension.
App Extension functions as a client-server even within the “Main Application”. This is quite expensive and can be fixed. You can remove the “webView” component from storyBoard and remove this files: “script.js”, “main.html”, “style.css”. After this you will get the pure storyBoard without any tinsel and communication between these layers. That’s will work perfectly because these are native Swift applications.
p.s. To show the "Safari Extension" window after clicking on the icon on the toolbar, you need to change key from "Command" to "Popover" in the "info.plist" in the section "SFSafariToolbarItem" in the "Action".
write your additions...
Hi, here's an example: https://codepen.io/gyurmey2/pen/abgNQdE
Is this even a known issue?
Hello all, I am have an issue in Safari both for iOS and MacOS where when uploading a file with XMLHttpRequest() progress is not sent in a nice even interval that allows for a smooth upload progress, it is set randomly at large intervals. This means you do not get a smooth nice progress but rather large jumps because the amount of data sent is in large intervals. can see data being constantly sent from the device and at the server level so I know the upload is working.
You can see the problem here: https://imgur.com/a/Qhh3Q8u
I am pretty sure this has to do with the server config and something that is unique to Safari, I am running Nginx 1.27.0 and Php 8.2. This problem does not happen in Chrome or Firefox on my desktop, in those browsers I get a smooth progress and data sent amount. If you have a fast connection you do not notice this problem, slow connections and it's very apparent.
Has anyone figured out what is needed to get this to work properly?
Hi everyone.
I'm reaching out to you to get some help about the issue that I'm facing for last couple of weeks.
The problem is when I have HTML canvas element which is rendering some text which is including some emojis and I'm setting gradient color to that text. I'm expecting that after setting gradient emojis should not change their color, but the reality is that they also become colored. The issue is not reproducible in other major browsers. I'm attaching some screenshots and HTML code for you to have better understanding what I'm trying to achieve.
Thanks in advance.
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style></style>
</head>
<body>
<div id="emojis"></div>
<script>
const emojis = [
0x1f600, 0x1f601, 0x1f603, 0x1f603, 0x1f604, 0x1f605, 0x1f606, 0x1f607, 0x1f609, 0x1f60a, 0x1f642,
0x1f643, 0x1f355, 0x1f354,
];
const emoji = [];
const size = 80;
const factor = 2;
const placeholder = document.getElementById("emojis");
for (let i = 0; i < 3; i++) {
emoji.push({
x: size,
y: size,
src: getEmoji(),
});
}
function loadCanvas(id, emo) {
const canvas = document.createElement("canvas");
canvas.id = id;
placeholder.appendChild(canvas);
const ctx = canvas.getContext("2d");
loadEmoji(canvas, ctx, emo);
}
function loadEmoji(canvas, ctx, emo) {
// Use the intrinsic size of image in CSS pixels for the canvas element
canvas.width = w = size * factor;
canvas.height = h = size * factor;
const fontSize = size * (factor - 0.5);
const offset = Math.floor((h - fontSize) / 4);
ctx.font = `${size * (factor - 0.5)}px Arial`;
ctx.textBaseline = "middle";
ctx.textAlign = "center";
emo.x = w / 2;
emo.y = h - size + offset;
const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop("0", "magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
ctx.fillStyle = gradient;
ctx.fillText(emo.src, emo.x, emo.y);
}
function getEmoji() {
const len = emojis.length;
const emos = Math.floor(Math.random() * len);
return String.fromCodePoint(emojis[emos]);
}
window.onload = function () {
emoji.forEach((emo, i) => {
const id = `canvas-0${i}`;
loadCanvas(id, emo);
});
};
</script>
</body>
</html>
I am currently working on a web application where I need a container/textarea with overflow on the y-axis. I've managed to achieve the desired scrollbar customization in Chrome by dynamically adding a class to the DOM when a scroll event occurs. This class modifies the "::-webkit-scrollbar" pseudo-element, allowing me to toggle between different styles as needed.
However, I'm facing an issue with Safari. Despite my custom styles being visible in the DOM when inspected, the scrollbar styles do not update dynamically as they do in Chrome.
Expected Behavior: The custom scroll bar should be hidden when the user is not scrolling. When the user begins to scroll, the scroll bar should become visible.
Hi:
I saw the post WWDC WebKit release notes said Safari will support largeblob extension from version 17. But when I create a credential with largeblob extension, different action takes according what authenticator used.
The credential options is:
"credCreateOptions": {
"rp": {
"name": "WebAuthn demo",
"id": "webauthn.turinggear.com"
},
"user": {
"name": "Jonathon.Runte97@gmail.com",
"displayName": "Jonathon.Runte97@gmail.com",
"id": "bqShD9YGRicjM-1foXiBqrdCzTHTuG1bkmKaxzn7oEM"
},
"challenge": "9BP4y2epk2b3MhRCRRS5tt4bdWYLPJcKBLMMiB_7p7E",
"pubKeyCredParams": [
{
"alg": -7,
"type": "public-key"
},
{
"alg": -257,
"type": "public-key"
}
],
"excludeCredentials": [],
"authenticatorSelection": {
"requireResidentKey": true,
"residentKey": "required",
"userVerification": "discouraged"
},
"attestation": "none",
"extensions": {
"credProps": true,
"largeBlob": {
"support": "preferred"
}
}
}
When i choose use iPhone be my authenticator, it seems that largeblob act as it should be:
"credential" : {
"id": "ZRxBdH4LKE4eiVxbwcA4Kmn9VZk",
"rawId": "ZRxBdH4LKE4eiVxbwcA4Kmn9VZk",
"response": {
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViYSETDPyxegNfyH_fI_8t9iVRDn34LxYd8YH1k2u4xSk5dAAAAAPv8MAcVTk7MjAtuAgVX170AFGUcQXR-CyhOHolcW8HAOCpp_VWZpQECAyYgASFYICY6gkqg6OG_v1BlGCPj7gSwsu_c0vTmVzmfd7TsqEh5Ilgg_Cn0mAiO8QCx7J1xw809VBq8iI-U5pgY0I947B7XF9g",
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiOVcta3RMbEswemZDSXpFb2hNd3E3OTgxQXJlRzV0aEVBdmRHdXNHcUsxcyIsIm9yaWdpbiI6Imh0dHBzOi8vd2ViYXV0aG4udHVyaW5nZ2Vhci5jb20ifQ",
"transports": [
"internal",
"hybrid"
],
"publicKeyAlgorithm": -7,
"publicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJjqCSqDo4b-_UGUYI-PuBLCy79zS9OZXOZ93tOyoSHn8KfSYCI7xALHsnXHDzT1UGryIj5TmmBjQj3jsHtcX2A",
"authenticatorData": "SETDPyxegNfyH_fI_8t9iVRDn34LxYd8YH1k2u4xSk5dAAAAAPv8MAcVTk7MjAtuAgVX170AFGUcQXR-CyhOHolcW8HAOCpp_VWZpQECAyYgASFYICY6gkqg6OG_v1BlGCPj7gSwsu_c0vTmVzmfd7TsqEh5Ilgg_Cn0mAiO8QCx7J1xw809VBq8iI-U5pgY0I947B7XF9g"
},
"type": "public-key",
"clientExtensionResults": {
"largeBlob": {
"supported": true
}
},
"authenticatorAttachment": "platform"
}
Safari returns clientExtensionResults.largeBlob.supported= ture.
But when I use an NFC authenticator with the same credCreateOptions, safari didnot return clientExtensionResults section. Response as follows(ignore the challenge and others random data):
"credential" : {
"id": "uEVMzgsINXj7bHFD5Z5xbMGJ7k6tnrMQSLjB4yB8_0GxbUPoWYUYX8E3D9XB24Cv-PMh6cRpCFt5klUHqsot2Yc48BVu5TN8sbabTgped2x46ljdsxFzaNCA8D2y9FZK8BHLLZTKHNuzJw4SCYUkzg",
"rawId": "uEVMzgsINXj7bHFD5Z5xbMGJ7k6tnrMQSLjB4yB8_0GxbUPoWYUYX8E3D9XB24Cv-PMh6cRpCFt5klUHqsot2Yc48BVu5TN8sbabTgped2x46ljdsxFzaNCA8D2y9FZK8BHLLZTKHNuzJw4SCYUkzg",
"response": {
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVj0SETDPyxegNfyH_fI_8t9iVRDn34LxYd8YH1k2u4xSk5FAAABeAAAAAAAAAAAAAAAAAAAAAAAcLhFTM4LCDV4-2xxQ-WecWzBie5OrZ6zEEi4weMgfP9BsW1D6FmFGF_BNw_VwduAr_jzIenEaQhbeZJVB6rKLdmHOPAVbuUzfLG2m04KXndseOpY3bMRc2jQgPA9svRWSvARyy2UyhzbsycOEgmFJM6lAQIDJiABIVggg2LXO5Q2U0ETrSxrLKxCfKKCTCitTCx9bpxD1Gw917ciWCDsxnw4Wd7M_UTiGQJ7swCMXN83nprsT8wkTlftXRizmw",
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiOUJQNHkyZXBrMmIzTWhSQ1JSUzV0dDRiZFdZTFBKY0tCTE1NaUJfN3A3RSIsIm9yaWdpbiI6Imh0dHBzOi8vd2ViYXV0aG4udHVyaW5nZ2Vhci5jb20ifQ",
"transports": [
"nfc"
],
"publicKeyAlgorithm": -7,
"publicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg2LXO5Q2U0ETrSxrLKxCfKKCTCitTCx9bpxD1Gw917fsxnw4Wd7M_UTiGQJ7swCMXN83nprsT8wkTlftXRizmw",
"authenticatorData": "SETDPyxegNfyH_fI_8t9iVRDn34LxYd8YH1k2u4xSk5FAAABeAAAAAAAAAAAAAAAAAAAAAAAcLhFTM4LCDV4-2xxQ-WecWzBie5OrZ6zEEi4weMgfP9BsW1D6FmFGF_BNw_VwduAr_jzIenEaQhbeZJVB6rKLdmHOPAVbuUzfLG2m04KXndseOpY3bMRc2jQgPA9svRWSvARyy2UyhzbsycOEgmFJM6lAQIDJiABIVggg2LXO5Q2U0ETrSxrLKxCfKKCTCitTCx9bpxD1Gw917ciWCDsxnw4Wd7M_UTiGQJ7swCMXN83nprsT8wkTlftXRizmw"
},
"type": "public-key",
"clientExtensionResults": {},
"authenticatorAttachment": "cross-platform"
}
Even without a clientExtensionResults.largeBlob.supported= false.
According to w3c, it should return clientExtensionResults.largeBlob.supported= false ?
The NFC authenticaor do support largeblob extensions and act write with the same credCreateOptions on edge on windows.
Does safari need some extra parameters?
My safari is the newest version of 17.5 (19618.2.12.11.6), mac version is Sonoma 14.5(23F79).
Thank you very much.
Here is my manifest.json:
"permissions": [
"<all_urls>",
"storage",
"unlimitedStorage",
"activeTab"
]
Despite declaring "unlimitedStorage" in permissions, I encounter the following error when trying to save files exceeding approximately 3MB:
Invalid call to browser.storage.local.set(). Exceeded storage quota.
This issue did not occur in iOS 17. Is this behavior intentional or is it a bug? If it is intentional, is there an alternative method to handle large file?
I am trying to load a URL in webView, and have it exclude the website Header and Footer from displaying within the view.
Hi,
We are having issues trying to get the Web Push API working in Safari 17.4/5 and 18 beta (both on ios and macos).
Below you can find a basic vanilla web app that tests push subscription (its not wired up to actual service but does allow testing the client side).
It has been configured as per the push api requirements..
Runs over https (using self signed certificate).
Runs a service worker.
Asks for permissions via button click before subscribing.
Running this on macos chrome/firefox works fine, after providing permissions the promise returns a populated subscription object (Endpoint / p256dh values etc). When reloading the site, the subscription is persisted.
In Safari, the permissions are requested as per other browsers but the returned subscription promise object (see code below) (https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription), although the keys are present, contains all empty values. Calling GetKeys for any of the values, also returns empty.
On reload, it is clear that a subscription was not actually created.
serviceWorkerRegistration.pushManager.subscribe(subscribeOptions).then(function (subscription) {
return subscription;
}).catch(function (error) {
console.log('Error:', error);
throw error;
});
The subscription promise does not catch, so why these values are empty is a mistry. The same code works fine on other browsers on the same OS, so it seems there is an underlying issue in safari's implementation of the web push api.
Can you please run the sample app and confirm if you see the same issue, together with any required changes if it's a coding issue, or, confirm that this is a safari bug? If its a limitation due to config etc, then the catch should be thrown with a useful error.
Github repo..
https://github.com/andyball89/web-push-testing
Thanks,
Andy
HI,
Just discovered...
If I update - change function arguments the JavaScript on my website fails as Safari keeps the previous version and doesn't notice that the JavaScript is new (only a very small change - one function now has two arguments instead of one, then calls AJAX). Is there a way to force a reloading of the JavaScript?
This is really annoying. After much checking around (and not much sleep) on various other devices and browsers I finally cleared iOS Safari's history, and all is well.
I don't know if others have had this problem, but I thought I'd post it here anyway. I always automatically clear the browser history when closing or re-launching the browser during development of web stuff.
Regards,
Paul
In my project, I'm using the WKWebView to display the Google OAuth popup. And after it appears, the JS window.opener is null, and because of that the original window cannot receive an auth token in a callback. This works perfectly fine in iOS 17.0 and earlier, but broken starting from 17.5. I've tested on the 18.0 too - same results the opener is always null no matter what I try.
Web Part:
<html>
<head>
<script src="https://accounts.google.com/gsi/client" async></script>
</head>
<script type="text/javascript">
var global = {};
window.addEventListener("message", function (ev) {
console.log("=== Event Listener ===");
console.log(ev);
});
function client() {
if (global.client === undefined) {
global.client = google.accounts.oauth2.initTokenClient({
client_id: '<client_id>',
scope: 'https://www.googleapis.com/auth/userinfo.email \
https://www.googleapis.com/auth/userinfo.profile',
callback: function (responseToken) {
console.log("=== Callback ===");
console.log(responseToken);
let auth = document.getElementById("auth");
auth.textContent = 'Token: ' + responseToken.access_token
}
});
}
return global.client;
}
function googleOauthClient() {
console.log("Trying to login");
let auth = document.getElementById("auth");
auth.textContent = 'In Progress...';
client().requestAccessToken();
}
</script>
<body>
<div id="center">
<a onclick="googleOauthClient()"><h1>Google Login Attempt</h1></a>
<h2 id="auth"></h2>
</div>
</body>
</html>
In iOS showing popup is implemented as:
#import "WebViewController.h"
#import "SafariServices/SafariServices.h"
@interface WebViewController () <WKNavigationDelegate, WKUIDelegate> {
WKWebView *web;
WKWebView *popupWebView;
}
@end
@implementation WebViewController
- (void)loadView {
[super loadView];
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
[[config preferences] setJavaScriptEnabled:YES];
[[config preferences] setJavaScriptCanOpenWindowsAutomatically:NO];
[[config defaultWebpagePreferences] setAllowsContentJavaScript:YES];
[config setAllowsInlineMediaPlayback:YES];
web = [[WKWebView alloc] initWithFrame:self.view.frame configuration:config];
[web setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[web setAllowsLinkPreview:YES];
[web setNavigationDelegate:self];
[web setUIDelegate:self];
[web setInspectable:YES];
[web setCustomUserAgent:[[web valueForKey:@"userAgent"] stringByAppendingString:@" Safari"]];
[[self view] addSubview:web];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString *url = @"http://localhost:8080/oauth"; // A simple Spring Boot App where HTML is hosted
[web loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
}
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
decisionHandler(WKNavigationActionPolicyAllow);
}
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
if (navigationAction.targetFrame == nil) {
popupWebView = [[WKWebView alloc] initWithFrame:webView.frame configuration:configuration];
[popupWebView setCustomUserAgent: [webView customUserAgent]];
[popupWebView setUIDelegate:self];
[popupWebView setNavigationDelegate:self];
[popupWebView setInspectable:true];
[[[popupWebView configuration] defaultWebpagePreferences] setAllowsContentJavaScript:YES];
[[[popupWebView configuration] preferences] setJavaScriptCanOpenWindowsAutomatically:NO];
[[[popupWebView configuration] preferences] setJavaScriptEnabled:YES];
[[popupWebView configuration] setSuppressesIncrementalRendering:YES];
[webView addSubview:popupWebView];
[popupWebView loadRequest:[navigationAction.request copy]];
return popupWebView;
}
return nil;
}
- (void)webViewDidClose:(WKWebView *)webView {
[webView removeFromSuperview];
popupWebView = nil;
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"didFailProvisionalNavigation: %@", [error description]);
}
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"didFailNavigation: %@", [error description]);
}
- (void)webView:(WKWebView *)webView requestMediaCapturePermissionForOrigin:(WKSecurityOrigin *)origin initiatedByFrame:(WKFrameInfo *)frame
type:(WKMediaCaptureType)type decisionHandler:(void (^)(WKPermissionDecision decision))decisionHandler {
decisionHandler(WKPermissionDecisionGrant);
}
- (void)webView:(WKWebView *)webView requestDeviceOrientationAndMotionPermissionForOrigin:(WKSecurityOrigin *)origin
initiatedByFrame:(WKFrameInfo *)frame decisionHandler:(void (^)(WKPermissionDecision decision))decisionHandler {
decisionHandler(WKPermissionDecisionGrant);
}
- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters
initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray<NSURL *> * _Nullable URLs))completionHandler {
completionHandler(nil);
}
@end
What I tried so far:
Disabled in the Settings -> Safari -> Cross-Origin-Opener-Policy;
Disabled popup blocking;
Added Allow Arbitrary Loads to Info.plist (actually added all possible security policies);
This actually works in the SFSafariViewController, but I cannot use it because I need to hide the Navigation and Status bar panels.
How it looks in 17.0
vs 17.5
And ideas about what I might be doing wrong? Or maybe some workaround I can utilize to get the Google OAuth token from the popup. Thanks in advance.
Here's my code:
font-weight: bold;
font-family: 'PingFangSC-Regular';
when i use font-family:system-ui on the web, i found the text will be smaller on ios 18 beta, the problem also appear on ios 17 when using iphone 15 pro max.
It looks ok if i use font-family:PingFang SC instead of system-ui.
when use the css below, the text will be smaller than iOS17.
font-family:system-ui
If i use font-family: PingFang SC, that will be ok.
If system-ui was modified by system?