How to enable Safari App Extension programmatically? - safari

I'm developing a Safari App Extension inside a macOS app. When a user installs this app, the extension is added to Safari, but it's disabled by default. We can detect the state of extension by using SFSafariExtensionManager class via its getStateOfSafariExtension method.
Now I want to enable the extension state programmatically if it is disabled. How can I achieve that?
Or do anyone have any idea where the preferences / app extensions settings are stored in macOS?

You can create a button such as "Open extension preferences" to show Safari preferences directly for your extension then the user could enable it.
The code for your app:
import SafariServices
func enableExtension () {
SFSafariApplication.showPreferencesForExtension(withIdentifier: YOUR_EXTENSION_IDENTIFIER) { (error) in
NSLog("Error \(String(describing: error))")
}
}
SFSafariApplication could be used in Cocoa app only (not extension).

Related

ionic3 open external url without address bar and toolbar and close button

My app needs a login page from external url.
The login logic that I thought is :
Steps
Open external url when ionic is launched
Once user logged in, move back to internal app using deep link (ex : myapp://main)
I tested step 2 which is deep link. Works well.
So, I have to make step 1 now.
First, I tested with iframe.
And got Refused to display 'https:....' in a frame because it set 'X-Frame-Options' to 'deny'. error. Seems this needs a server-side configuration. But anyway we don't want to use this way. iframe feels like a hack.
Second, I tried location.href = this.loginUrl;.
Worked well in chrome browser but when I built in iOS simulator, I see address bar, tool bar, and close button.
I don't like this because I don't want user to close login page or to change url address.
Third, tried window.open(this.loginUrl, '_self', 'location=no').
Same result as second.
Fourth, tried to use ionic version of in-app-browserplugin.
But the result is same as second and third.
It still opens a browser with address bar, tool bar even it shows 'back to myApp'. So user would feel this is out of app.
Check here, people are looking for the solution still.
After spending a day, I don't even know if there is option I can try.
I could resolve by doing this. But in real device.
Xcode iPhone emulators don't have open in-app-browser but built-in browser.
browser:any;
this.platform.ready().then(() => {
this.browser = this.iab.create(this.loginUrl, '_blank', 'location=no,toolbar=no');
});
You can solve this by installing a cordova plugin called cordova-plugin-inappbrowser. Execute the following commands:
ionic plugin add cordova-plugin-inappbrowser
npm install --save #ionic-native/in-app-browser
On your app.module.ts add
import { InAppBrowser } from '#ionic-native/in-app-browser';
and also add the following to your providers in app.module.ts
providers: [
StatusBar,
SplashScreen,
InAppBrowser,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
Then on your home.ts add
import { InAppBrowser } from '#ionic-native/in-app-browser';
and inject it into the constructor like this
constructor(public navCtrl: NavController, private iab: InAppBrowser) {
}
then add the following method
ionViewDidLoad(){
this.iab.create('url', '_self', { location: 'no' }); }
Check the different options you have for this plugin here
For removing the address bar just use the option:
location: Set to yes or no to turn the InAppBrowser's location bar on or off.

Worklight 6.1: How to add EULA to hybrid app

Environment:
Worklight 6.1.0.2
dojo 1.9.4
We have created a hybrid app using Worklight 6.1 for android, iOS and windows8 platform. Now we would like to add and show End User License Agreement (EULA) window to the user, when the app first time launch. It should have Accept and Decline button. If user tap on Accept button, then he should be able to use the app.
I would like to know, how can we achieve this using Worklight 6.1.
Any help on this, will be much appreciated.
FYI there is nothing specific here to Worklight.
You could implement this in any number of ways w/out ever using any Worklight API whatsoever.
You could achieve it for example like this (untested code - you'll need to experiment):
In main.js create some global variable eulaAccepted:
var eulaAccepted;
// You will need to handle this property using HTML5 Local Storage so that it will persist for the next time the app is launched, and have the app act accordingly.
Then, in wlCommonInit():
function wlCommonInit() {
if (!eulaAccepted) {
displayEula();
} else {
displayApp();
}
}
In displayEula():
function displayEula() {
// either display a dialog using `WL.SimpleDialog`...
// Or maybe custom HTML with "accept" and "not accept" buttons
WL.SimpleDialog.show(
"Eula Agreement", "your-eula-text-here",
[{text: "Accept", handler: acceptEula },
{text: "Reject", handler: rejectEula}]
);
}
Handle the result:
function acceptEula() {
eulaAccepted = true;
... // Some code that will store the `eulaAccepted` variable using HTML5 Local Storage API
displayApp();
}
function rejectEula() {
// Display some other custom HTML instead of your app.
// Maybe also additional logic to try again to accept the Eula...
}

window.open addEventListener does not work on "Mobile Browser Simulator"

I'm using IBM Worklight 6.2
I'm using window.open to load some external pages for OAuth and I configure event listeners for the opened window.
var authWindow = window.open(authUrl, '_blank', 'location=yes');
authWindow.addEventListener('loaderror', function(e) {
console.log(">> load error. event: " + JSON.stringify(e));
});
also for "load" and "loadstart" events.
This works in Android and iOS but when I preview the app in the "Mobile Browser Simulator" the eventListeners are not executed.
I have also tested creating a "desktopbrowser" application.
Any idea?
Loaderror, loadstart, and loadstop are specific to Cordova and not supported in the Mobile Browser Simulator. It would be best to test these on emulator or device. Please see: http://cordova.apache.org/docs/en/3.0.0/cordova_inappbrowser_inappbrowser.md.html#addEventListener

What is the substitute for WL.App.close?

WL.App.close is deprecated. I know that this is not supported for iOS. But why is it deprecated for Android as well? At the moment, it is still functioning fine, even on 6.2, but since it is deprecated, what is the alternative/substitute for this?
In Android as well, this is not the recommended approach. You should let the user quit the app, and this is done by manually bringing up the "applications view" and swiping the app in order to quit it.
Can be corroborated by these answers by Googlers:
http://android.nextapp.com/site/fx/doc/exit
Additionally, there are these approaches:
Close application and launch home screen on Android
https://groups.google.com/forum/#!topic/android-developers/Y96KnN_6RqM
You could write a Cordova plug-in that will force-quit the app and trigger it by overriding whatever you'd like (like the Back button), or create a dedicated Quit button, etc.
In MobileFirst 7.0, this method seems to be deprecated in both iOS and Android, but when I call this "deprecated" method in Android, it really works.
I think overriding Android's back button might be a best practice in Android webapp as back button may cause strange page navigating issues (if you use UI frameworks like JQM). This is what I done in WL's main.js.
WL.App.overrideBackButton(backFunc);
function backFunc(){
WL.SimpleDialog.show(
"Alert",
"Sure to quit the app ?",
[ {text : 'Cancel', handler: function() {
}},
{text : 'Yes', handler: function() {
if(WL.Client.getEnvironment() == WL.Environment.ANDROID) {
WL.App.close();
}
}}]
);
}

How do I allow downloads from a WebView using the standard download system on a Mac app?

I am building a mac app and would like to able to include the ability to browse the web and download files from the sites using the standard downloads system like you see when using safari.
At the moment when I click a link to a .zip or .nzb in the app it does nothing! Is there a way of allowing this from the app?
Thanks in advance for any help :)
The download manager in Safari is implemented by Safari, not by WebKit, so you don't get that functionality "for free", just the tools to build it.
In order to be able to download files, you need to assign an object as the WebPolicyDelegate of the WebView and implement the webView:decidePolicyForMIMEType:request:frame:decisionListener: delegate method.
In that method, you must call one of the WebPolicyDecisionListener protocol methods on the object that is passed as the decisionlistener parameter to the method. The three WebPolicyDecisionListener protocol methods are ignore, use or download. For any MIME types that you want to download, you must call download on the object passed as the listener parameter:
- (void)webView:(WebView *)webView
decidePolicyForMIMEType:(NSString *)type
request:(NSURLRequest *)request
frame:(WebFrame *)frame
decisionListener:(id < WebPolicyDecisionListener >)listener
{
if([type isEqualToString:#"application/zip"])
{
[listener download];
}
//just ignore all other types; the default behaviour will be used
}
You then need to assign an object as the download delegate of your WebView. This object will be sent all of the NSURLDownloadDelegate protocol messages as well as the WebDownload
delegate messages. You can use these messages to choose where the file is downloaded, as well as to implement a download manager UI like Safari.
Off the top of my head I would think you could implement the WebView's delegates to detect when a user clicks on a link - then check the extension and if it's not html/php/whatever then manually download the file yourself
Here's a link to a question (and answer) for how to capture the link pressing:
Cocoa WebKit/WebView delegate for location change? (User clicked link, javascript action, etc)
Another option is to open the link in external browser. And the file will be downloaded using external browser's download manager.
Sample code in Swift 2.2 with XCode 7.3:
func webView(webView: WebView!, decidePolicyForNavigationAction actionInformation: [NSObject : AnyObject]!, request: NSURLRequest!, frame: WebFrame!, decisionListener listener: WebPolicyDecisionListener!) {
let url = request.URL!.absoluteString
if url.hasSuffix(".zip") || url.hasSuffix(".nzb") {
listener.ignore()
NSWorkspace.sharedWorkspace().openURL(request.URL!)
} else {
listener.use()
}
}
PS. method above comes from WebPolicyDelegate.