I have a packaged Chrome app that is trying to read from a serial port. However, everytime I call chrome.serial.getDevices(), it doesn't return (nor does my function get called).
My code is as simple as reacting to a click on my browser action button:
chrome.browserAction.onClicked.addListener(function(tab) {
var onGetDevices = function(ports) {
alert("Devices");
for (var i=0; i<ports.length; i++) {
alert(ports[i].path);
}
}
alert("before");
chrome.serial.getDevices(onGetDevices);
alert("after");
});
The before message gets displayed, but the after one doesn't. I've similarly tried invoking connect() directly, but it too doesn't return.
chrome.serial.connect("/dev/tty.usbserial-AI02KQN0", {bitrate: 9600}, onConnect);
I've read a number of posts that suggest that Chrome on a Mac isn't able to read from the serial port properly, but I'm not sure if I'm suffering from this problem, or something else.
Any ideas? Do I need to move to a Windows machine? Thanks.
man... I should know better. Turns out that I was still shipping it as an extension, not as an app. Once I make it an app, the list of devices are successfully returned.
Related
GOAL
The application needs to constantly read from a socket - and when it receives a line that is not empty it needs to do an appropriate action.
Issue
From what I researched you can't do services in Xamarin Forms, since each service is platform dependent. (IOS, Andoird, Windows). So what I am looking for as a way to constantly monitor inputs from a Bluetooth port in this case, simply by calling a already defined function.
Tried
I tried using a Refresh view. But there were issues with that from a code point of view and a visual point of view.
Current Code
This is what I have tried, but unfortuntately it has mixed results. The socket seems to connect when first pairing but then closed if I try to read:
Device.StartTimer(TimeSpan.FromMilliseconds(miliseconds), () =>
{
command.Execute(null);
return true;
});
I'm troubleshooting a location-based app launch cycle that works fine on iOS simulator, but apparently does not launch the app on an actual device.
I've set up UNNotifications for both enter and exit events. Both the simulator and the device(s) register and display these notifications.
The next thing that is supposed to happen is that the app goes through a launch process, setting the app's state in such a way that I can tell without being connected to the debugger whether the app has launched or not when I open it from the home screen.
On simulator, the didEnterRegion code gets called and I can step through the subsequent launch code using the debugger - success.
However when I take the device out (for a walk) all I get are UNNotifications, and no app launch (which I can tell from the UI in the app on the real device)
I'm sure I need to improve my testing strategy (welcome to suggestions!), but at this point I should be able to expect that the app should behave the same on the simulator and the actual device - it is not.
Why is the expected outcome happening on the simulator but not on the device?
LocationService.swift
func handleRegionEnterEvent (for region: CLRegion) {
ApplicationController.sharedInstance.didEnterRegion(region)
}
func handleRegionExitEvent (for region: CLRegion) {
ApplicationController.sharedInstance.didExitRegion(region)
}
ApplicationController.swift
func didEnterRegion (_ region: CLRegion) {
// Present Alert
delegate?.handleUNEvent(note: "ENTER: \(region.identifier)")
// Start launch cycle
}
AppDelegate.swift
extension AppDelegate: AppControllerDelegate {
func handleUNEvent(note: String?) {
// Show an alert if application is active
if UIApplication.shared.applicationState == .active {
guard let message = note else { return }
Alert().showAlert(withMessage: "Application received UN while active: \(message)", title: "UNNotification")
} else {
// Otherwise present a local notification
guard let body = note else { return }
let notificationContent = UNMutableNotificationContent()
notificationContent.body = body
notificationContent.sound = UNNotificationSound.default
notificationContent.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let request = UNNotificationRequest(identifier: "location_change",
content: notificationContent,
trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
print("Error: \(error)")
}
}
}
}
}
The simulator sadly has a lot of differences from a device both in terms of data reported (you will not get speed for example) and also as you saw call flow may be different...
Something to check is to make sure you have the descriptions for the specific location permissions you are asking for in relation to location set up. For entering regions you probably want to make sure you have "always" access.
It may also be worth enabling wireless debugging, and walking around with laptop tethered to the device to verify with the debugger the didEnterRegion is truly not called, and there is a bug in the code that is supposed to display the UI you are expecting. At the very least perhaps you could get better logging as to the status of various location callbacks.
What happened: Code that executed on simulator was indeed crashing on the device and I was not reviewing crash logs from the device. This question arose from an issue that is neither ios, or core-location specific.
It has everything to do with choosing appropriate testing strategies and using all available information at one's disposal before coming to what may turn out to be premature conclusions.
However when I take the device out (for a walk) all I get are UNNotifications, and no app launch (which I can tell from the UI in the app on the real device)
I was mistaken to think that a) User Notifications that appear when the App is not running are presented by the system (as banners) and b) the App launches in another process. In fact my own code specifically executes the code that makes those notifications appear. Face-to-palm: Copying code from tutorials to achieve quick test results without even trying to understand what the code does can lead to that I suppose.
In Xcode, plug in your device and hit command-shift-2 to open Devices & Simulators window. Select your device on the left and hit "View Logs" button to bring up your crash log.
Is there any way to remove a record from Launch Services database which was added using LSRegisterURL?
I have several apps that can open the same URL and I want to manage which one of them should open it. Unfortunately now I face a problem that at some point LSRegisterURL stop working. E.g. it works until some point, then, I guess, Launch Services database (or cache) gets overflown and subsequent calls to LSRegisterURL don't have any effect.
So my idea is to clean up Launch Services database by removing old records, but I can't find any related function.
I came across a private API in LaunchServices today that appears to do the trick. It seems to work on Mac OS X 10.7 thru 10.11. I've barely tested it yet, so YMMV:
extern void _LSUnregisterURL(CFURLRef url) __attribute__((weak_import));
- (void) unregisterAppAtURL:(NSURL *)appURL
{
if( _LSUnregisterURL != NULL )
{
CFURLRef urlRef = (__bridge CFURLRef)appURL;
if( urlRef )
{
_LSUnregisterURL( urlRef );
}
}
}
There are several other private API's similar to this (which you can find by using nm). Keep in mind that if you go private, you can't submit to the App Store. Hope that helps someone.
As it comes from the further tests OS X frees the Launch Services database itself. The exact algorithm is not clear, but rebooting Mac in most cases helps to remove the records to the missed applications and/or make the app specified by the most recent call to LSRegisterURL to become the default one.
How can you detect the url that I am browsing in chrome/safari/firefox via cocoa (desktop app)?
As a side but related note, are there any security restrictions when developing a desktop app that the user will be alerted and asked if they want to allow? e.g. if the app accesses their contact information etc.
Looking for a cocoa based solution, not javascript.
I would do this as an extension, and because you would like to target Chrome, Safari, and Firefox, I'd use a cross-browser extension framework like Crossrider.
So go to crossrider.com, set up an account and create a new extension. Then open the background.js file and paste in code like this:
appAPI.ready(function($) {
appAPI.message.addListener({channel: "notifyPageUrl"}, function(msg) {
//Do something, like send an xhr post somewhere
// notifying you of the pageUrl that the user visited.
// The url is contained within msg.pageUrl
});
var opts = { listen: true};
// Note: When defining the callback function, the first parameter is an object that
// contains the page URL, and the second parameter contains the data passed
// to the context of the callback function.
appAPI.webRequest.onBeforeNavigate.addListener(function(details, opaqueData) {
// Where:
// * details.pageUrl is the URL of the tab requesting the page
// * opaqueData is the data passed to the context of the callback function
if(opaqueData.listen){
appAPI.message.toBackground({
msg: details.pageUrl
}, {channel: "notifyPageUrl"});
}
}, opts ); // opts is the opaque parameter that is passed to the callback function
});
Then install the extension! In the example above, nothing is being done with the detected pageUrl that the user is visiting, but you can do whatever you like here - you could send a message to the user, you could restrict access utilizing the cancel or redirectTo return parameters, you could log it locally utilizing the crossrider appAPI.db API or you could send the notification elsewhere, cross-domain, to wherever you like utilizing an XHR request from the background directly.
Hope that helps!
And to answer the question on security issues desktop-side, just note that desktop applications will have the permissions of the user under which they run. So if you are thinking of providing a desktop app that your users will run locally, say something that will detect urls they access by tapping into the network stream using something like winpcap on windows or libpcap on *nix varieties, then just be aware of that - and also that libpcap and friends would have to have access to a network card that can be placed in promiscuous mode in the first place, by the user in question.
the pcap / installed desktop app solutions are pretty invasive - most folks don't want you listening in on literally everything and may actually violate some security policies depending on where your users work - their network administrators may not appreciate you "sniffing", whether that is the actual purpose or not. Security guys can get real spooky so-to-speak on these kinds of topics.
The extension via Crossrider is probably the easiest and least intrusive way of accomplishing your goal if I understand the goal correctly.
One last note, you can get the current tab urls for all tabs using Crossrider's tabs API:
// retrieves the array of tabs
appAPI.tabs.getAllTabs(function(allTabInfo) {
// Display the array
for (var i=0; i<allTabInfo.length; i++) {
console.log(
'tabId: ' + allTabInfo[i].tabId +
' tabUrl: ' + allTabInfo[i].tabUrl
);
}
});
For the tab API, refer to:
http://docs.crossrider.com/#!/api/appAPI.tabs
For the background navigation API:
http://docs.crossrider.com/#!/api/appAPI.webRequest.onBeforeNavigate
And for the messaging:
http://docs.crossrider.com/#!/api/appAPI.message
And for the appAPI.db stuff:
http://docs.crossrider.com/#!/api/appAPI.db
Have you looked into the Scripting Bridge? You could have an app that launches, say, an Applescript which verifies if any of the well known browser is opened and ask them which documents (URL) they are viewing.
Note: It doesn't necessarily need to be an applescript; you can access the Scripting Bridge through cocoa.
It would, however, require the browser to support it. I know Safari supports it but ignore if the others do.
Just as a quick note:
There are ways to do it via AppleScript, and you can easily wrap this code into NSAppleScript calls.
Here's gist with AppleScript commands for Safari and Chrome. Firefox seems to not support AE.
Well obviously this is what I had come across on google.
chrome.tabs.
getSelected
(null,
function
(tab) {
alert
(tab.url);
}) ;
in pure javascript we can use
alert(document.URL);
alert(window.location.href)
function to get current url
I am running several tests with WebDriver and Firefox.
I'm running into a problem with the following command:
WebDriver.get(www.google.com);
With this command, WebDriver blocks till the onload event is fired. While this can normally takes seconds, it can take hours on websites which never finish loading.
What I'd like to do is stop loading the page after a certain timeout, somehow simulating Firefox's stop button.
I first tried execute the following JS code every time that I tried loading a page:
var loadTimeout=setTimeout(\"window.stop();\", 10000);
Unfortunately this doesn't work, probably because :
Because of the order in which scripts are loaded, the stop() method cannot stop the document in which it is contained from loading 1
UPDATE 1: I tried to use SquidProxy in order to add connect and request timeouts, but the problem persisted.
One weird thing that I found today is that one web site that never stopped loading on my machine (FF3.6 - 4.0 and Mac Os 10.6.7) loaded normally on other browsers and/or computers.
UPDATE 2: The problem apparently can be solved by telling Firefox not to load images. hopefully, everything will work after that...
I wish WebDriver had a better Chrome driver in order to use it. Firefox is disappointing me every day!
UPDATE 3: Selenium 2.9 added a new feature to handle cases where the driver appears to hang. This can be used with FirefoxProfile as follows:
FirefoxProfile firefoxProfile = new ProfilesIni().getProfile("web");
firefoxProfile.setPreference("webdriver.load.strategy", "fast");
I'll post whether this works after I try it.
UPDATE 4: at the end none of the above methods worked. I end up "killing" the threads that are taking to long to finish. I am planing to try Ghostdriver which is a Remote WebDriver that uses PhantomJS as back-end. PhantomJS is a headless WebKit scriptable, so i expect not to have the problems of a real browser such as firefox. For people that are not obligate to use firefox(crawling purposes) i will update with the results
UPDATE 5: Time for an update. Using for 5 months the ghostdriver 1.1 instead FirefoxDriver i can say that i am really happy with his performance and stability. I got some cases where we have not the appropriate behaviour but looks like in general ghostdriver is stable enough. So if you need, like me, a browser for crawling/web scraping purposes i recomend you use ghostdriver instead firefox and xvfb which will give you several headaches...
I was able to get around this doing a few things.
First, set a timeout for the webdriver. E.g.,
WebDriver wd;
... initialize wd ...
wd.manage().timeouts().pageLoadTimeout(5000, TimeUnit.MILLISECONDS);
Second, when doing your get, wrap it around a TimeoutException. (I added a UnhandledAlertException catch there just for good measure.) E.g.,
for (int i = 0; i < 10; i++) {
try {
wd.get(url);
break;
} catch (org.openqa.selenium.TimeoutException te) {
((JavascriptExecutor)wd).executeScript("window.stop();");
} catch (UnhandledAlertException uae) {
Alert alert = wd.switchTo().alert();
alert.accept();
}
}
This basically tries to load the page, but if it times out, it forces the page to stop loading via javascript, then tries to get the page again. It might not help in your case, but it definitely helped in mine, particularly when doing a webdriver's getCurrentUrl() command, which can also take too long, have an alert, and require the page to stop loading before you get the url.
I've run into the same problem, and there's no general solution it seems. There is, however, a bug about it in their bug tracking system which you could 'star' to vote for it.
http://code.google.com/p/selenium/issues/detail?id=687
One of the comments on that bug has a workaround which may work for you - Basically, it creates a separate thread which waits for the required time, and then tries to simulate pressing escape in the browser, but that requires the browser window to be frontmost, which may be a problem.
http://code.google.com/p/selenium/issues/detail?id=687#c4
My solution is to use this class:
WebDriverBackedSelenium;
//When creating a new browser:
WebDriver driver = _initBrowser(); //Just returns firefox WebDriver
WebDriverBackedSelenium backedSelenuium =
new WebDriverBackedSelenium(driver,"about:blank");
//This code has to be put where a TimeOut is detected
//I use ExecutorService and Future<?> Object
void onTimeOut()
{
backedSelenuium.runScript("window.stop();");
}
It was a really tedious issue to solve. However, I am wondering why people are complicating it. I just did the following and the problem got resolved (perhaps got supported recently):
driver= webdriver.Firefox()
driver.set_page_load_timeout(5)
driver.get('somewebpage')
It worked for me using Firefox driver (and Chrome driver as well).
One weird thing that i found today is that one web site that never stop loading on my machine (FF3.6 - 4.0 and Mac Os 10.6.7), is stop loading NORMALy in Chrome in my machine and also in another Mac Os and Windows machines of some colleague of mine!
I think the problem is closely related to Firefox bugs. See this blog post for details. Maybe upgrade of FireFox to the latest version will solve your problem. Anyway I wish to see Selenium update that simulates the "stop" button...
Basically I set the browser timeout lower than my selenium hub, and then catch the error. And then stop the browser from loading, then continue the test.
webdriver.manage().timeouts().pageLoadTimeout(55000);
function handleError(err){
console.log(err.stack);
};
return webdriver.get(url).then(null,handleError).then(function () {
return webdriver.executeScript("return window.stop()");
});
Well , the following concept worked with me on Chrome , try the same:
1) Navigate to "about:blank"
2) get element "body"
3) on the elemënt , just Send Keys Ësc
Just in case someone else might be stuck with the same forever loading annoyance, you can use simple add-ons such as Killspinners for Firefox to do the job effortlessly.
Edit : This solution doesn't work if javascript is the problem. Then you could go for a Greasemonkey script such as :
// ==UserScript==
// #name auto kill
// #namespace default
// #description auto kill
// #include *
// #version 1
// #grant none
// ==/UserScript==
function sleep1() {
window.stop();
setTimeout(sleep1, 1500);
}
setTimeout(sleep1, 5000);