Internet

Internet Privacy Rules: Why should Web professionals care?

The U.S. Congress repealed the FCC broadband/ Internet privacy rules established in the latter days of the Obama administration in late March, 2017. President Trump signed this repeal on April 3. Untouched, those rules would have gone into effect later this year. Those rules were an outgrowth of the Federal Communication Commission’s battle to protect net neutrality. You may be asking yourself – why does this matter, what will this change, and how will you and your clients be affected.

What you need to know:

  • Although most Internet Service Providers (ISPs) have said nothing has changed, they are free to change their policies at any time going forward. Consumers will not have a choice (to opt-in or opt-out).
  • It will be much easier for ISPs (think AT&T, Verizon, Comcast and similar corporations) to track your specific browsing history across all devices.
  • If an ISP decides to intercept search requests, they could send results from their own marketing databases (instead of the results someone might expect).
  • There is also a risk that such “injection” could be hijacked or compromised by malicious individuals. These large databases of consumer information would also be prime targets for hackers.
  • Previously, if you didn’t like the amount of data collected by a corporation (for example, Facebook), you could simply choose not to use their services and select some competitor. That will no longer be an option since your ISP will be the one tracking all your access (potentially).
  • There will not be any filters regarding your browsing history and how it can be used. You will have very limited control over what is shared with others (or sold).

Why this is important

In a nutshell, this is game changer (particularly in the U.S.). Up to this point, individual sites collected data (and used it to target ads). As a general rule, if a service appears free on the WWW, you are likely paying for it with your personal data. Facebook would be an excellent example of this. Using this company an example, Facebook wants you to visit Facebook so they can mine the data you share and can then sell targeted ads. These sorts of ads are likely to generate more revenue for the advertiser. That being said, each company wants to keep the data they collect about you to themselves. Frankly, information equals power these days. The more a company knows about you (and your browsing habits and searches), the better they can target ads.

That being said, there are limits. Most of us have smartphones, tablets, laptops and other devices. Trying to identify the common visitor across all these devices is a lot easier when the Internet Service Provider can be involved. One can no longer opt out by choosing an alternative company (perhaps DuckDuckGo instead of Google or Bing for Internet searches, for example).

Those of us who have been alive much longer than the WWW understand that limits were set in place for other technologies. For example, phone companies could not collect specific information that you were calling a physician or attorney and then target you with ads for similar types of services. The previous rules likened much Internet traffic to be similar to telephone traffic (and under the same guidelines).

Who voted for and against

Here are the details (who voted for and against this bill in the House of Representatives). For the senate version, votes followed party lines. We also found this overview of how we got to this point informative.

You will have less control of how your online history is used

With the elimination of these Internet Privacy rules, more of your online history will be available to more companies and you will have less control over how it is used. In addition to now being able to collect vast amounts of information from their customers, each company can use said information to provide targeted ads or can sell the collected data to others. Each company is free to change their policies at any time. That is why this is such an important change.

We found this NPR article to provide a solid overview of the situation and what your options are.

Help your customers understand these changes

Undoubtedly, some of your customers will have questions. More sophisticated customers will have detailed questions. At a minimum, we recommend mentioning these main points:

  • Internet Service Providers are able to change their policies at will. There is now much less oversight by the FCC and FTC.
  • It is likely there will be more tracking/ recording of your browser history and this data may be used for more targeted advertising. Much more data is likely to be collected (and shared or sold). As a consumer, you will likely not have the option to either opt-in or opt-out of such data collection. Many do not have the luxury of being able to easily select another ISP.
  • For additional information, you may wish to review this FAQ regarding what happens as these rules are cancelled.

For those who wish to pursue more privacy, here are some of the things you can do today:

  • Download and use the HTTPS everywhere extension for Firefox, Chrome, and Opera
  • Consider employing a tool like Privacy Badger to block spies and hidden trackers on sites you visit
  • Consider using a VPN
  • Consider using Tor as your browser
  • You might also want to introduce some Internet noise (a tool which loads random sites so your actual searches are obscured by large amounts of nonsense searches). This latter tool certainly will not protect your privacy; it will only generate additional “noise” which will obscure your actual search interests among a larger amount of random searches.

The bottom line is that there will be more data available for marketers. While this may be a plus for Web marketers, this is a giant step backwards for privacy advocates.

This has the potential to allow much more focused ads as big data and predictive analytics are brought to bear on an ever increasing amount of consumer information. If one is in marketing, they need to remain aware of consumer concerns.

Practicing web professionals should leverage this change as an opportunity to inform and educate their customers/ clients regarding what may be collected and how best to deal with this new reality (perhaps recommending using a VPN and plugins like those mentioned above).

The Electronic Frontier Foundation recently posted a list of ISPs that respect your privacy. They also provided a solid overview of how to protect your privacy from your ISP. This article also included a number of questions to ask about any VPN (before you purchase). Examples include:

  • How long has the VPN been in business?
  • Does the VPN log your traffic?
  • Is the traffic encrypted? Is there a single shared password for all encryption?
  • Would the VPN leak your DNS queries to your ISP?
  • Does the VPN support IPv6?

We anticipate that this is only the beginning of the discussion regarding increased awareness of privacy issues on the part of consumers and professionals alike.

Best always,

Mark DuBois

Community Evangelist and Executive Director

The post Internet Privacy Rules: Why should Web professionals care? appeared first on Web Professionals.

View full post on Web Professional Minute

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Pixels, Politics and P2P – Internet Days Stockholm 2016

Internet Days Logo

I just got back from the Internet Days conference in Stockholm, Sweden. I was flattered when I was asked to speak at this prestigious event, but I had no idea until I arrived just how much fun it would be.

lanyard

I loved the branding of he conference as it was all about pixels and love. Things we now need more of – the latter more than the former. As a presenter, I felt incredibly pampered. I had a driver pick me up at the airport (which I didn’t know, so I took the train) and I was put up in the pretty amazing Waterfront hotel connected to the convention centre of the conference.

chris loves internet

This was the first time I heard about the internet days and for those who haven’t either, I can only recommend it. Imagine a mixture of a deep technical conference on all matters internet – connectivity, technologies and programming – mixed with a TED event on current political matters.

The technology setup was breathtaking. The stage tech was flawless and all the talks were streamed and live edited (mixed with slides). Thus they became available on YouTube about an hour after you delivered them. Wonderful work, and very rewarding as a presenter.

I talked in detail about my keynote in another post, so here are the others I enjoyed:

Juliana Rotich of BRCK and Ushahidi fame talked about connectivity for the world and how this is far from being a normal thing.

Erika Baker gave a heartfelt talk about how she doesn’t feel safe about anything that is happening in the web world right now and how we need to stop seeing each other as accounts but care more about us as people.

Incidentally, this reminded me a lot of my TEDx talk in Linz about making social media more social again:

The big bang to end the first day of the conference was of course the live skype interview with Edward Snowden. In the one hour interview he covered a lot of truths about security, privacy and surveillance and he had many calls to action anyone of us can do now.

What I liked most about him was how humble he was. His whole presentation was about how it doesn’t matter what will happen to him, how it is important to remember the others that went down with him, and how he wishes for us to use the information we have now to make sure our future is not one of silence and fear.

In addition to my keynote I also took part in a panel discussion on how to inspire creativity.

The whole conference was about activism of sorts. I had lots of conversations with privacy experts of all levels: developers, network engineers, journalists and lawyers. The only thing that is a bit of an issue is that most talks outside the keynotes were in Swedish, but having lots of people to chat with about important issues made up for this.

The speaker present was a certificate that all the CO2 our travel created was off-set by the conference and an Arduino-powered robot used to teach kids. In general, the conference was about preservation and donating to good courses. There was a place where you can touch your conference pass and coins will fall into a hat describing that your check-in just meant that the organisers donated a Euro to doctors without frontiers.

Foodrobotwater

The catering was stunning and with the omission of meat CO2 friendly. Instead of giving out water bottles the drinks were glasses of water, which in Stockholm is in some cases better quality than bottled water.

I am humbled and happy that I could play my part in this great event. It gave me hope that the web isn’t just run over by trolls, privileged complainers and people who don’t care if this great gift of information exchange is being taken from us bit by bit.

Make sure to check out all the talks, it is really worth your time. Thank you to everyone involved in this wonderful event!

View full post on Christian Heilmann

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Interviewing a depressed internet at The Internet Days

This morning I gave one of two keynotes at the Internet Days in Stockholm, Sweden. Suffice to say, I felt well chuffed to be presenting at such a prestigious event and opening up for a day that will be closed by an interview with Edward Snowden!

Presenting the keynote

Frankly, I freaked out and wanted to do something special. So, instead of doing a “state of the web” talk or some “here is what’s amazing right now”, I thought it would be fun to analyse how the web is doing. As such, I pretended to be a psychiatrist who interviews a slightly depressed internet on the verge of a midlife crisis.

A depressed internet

The keynote is already available on YouTube.

The slides are on Slideshare:

Here is the script, which – of course – I failed to stick to. The bits in strong are my questions, the rest the answers of a slightly depressed internet.

Hello again, Internet. How are we doing today?

Not good, and I don’t quite know why.

It’s not that you feel threatened again, is it?

No, no, that’s a thing of the past. It was a bit scary for a while when the tech press gave up on me and everybody talked to those other guys: Apps.

But it seems that this is well over. People don’t download apps anymore. I think the reason is that they were too pushy. Deep down, people don’t want to be locked in. They don’t want to have to deal with software issues all the time. A lot of apps felt like very needy Tamagochi – always wanting huge updates and asking for access to all kind of data. Others even flat out told you you’re in the wrong country or the phone you spent $500 on last month is not good enough any longer.

No, I really think people are coming back to me.

That’s a good thing, isn’t it?

Yes, I suppose. But, I feel bad. I don’t think I make a difference any longer. People see me as a given. They see me as plumbing and aren’t interested in how I work. They don’t see me as someone to talk to and create things with me. They just want to consume what others do. And – much like running clear water – they don’t understand that it isn’t a normal thing for everybody. It is actually a privilege to be able to talk to me freely. And I feel people are not using this privilege.

I want to matter, I want to be known as a great person to talk to.

Oh dear, this sounds like you’re heading into a midlife crisis. Promise me you won’t do something stupid like buying a fancy sports car to feel better…

It’s funny you say that. I don’t want to, but I have no choice. People keep pushing me into things. Things I never thought I needed to be in.

But, surely that must feel good. Change is good, right?

Yes, and no. Of course it feels great that people realise I’m flexible enough to power whatever. But there are a few issues with that. First of all, I don’t want to power things that don’t solve issues but are blatant consumerism. When people talk about “internet of things” it is mostly about solving inconveniences of the rich and bored -instead of solving real problems. There are a few things that I love to power. I’m great at monitoring things and telling you if something is prone to breaking before it does. But these are rare. Most things I am pushed into are borderline silly and made to break. Consume more, do less. Constant accumulation of data with no real insight or outcome. Someone wants that data. It doesn’t go back to the owner of the things in most cases – or only a small part of it as a cute graph. I don’t keep that data either. But I get dizzy with the amount of traffic I need to deal with.

And the worst is that people connect things to me without considering the consequences. Just lately a lot of these things ganged up on me and took down a large bit of me for a while. The reason was that none of those things ever challenged their owners to set them up properly. A lack of strong passwords allowed a whole army of things that shouldn’t need to communicate much to shout and start a riot.

So, you feel misused and not appreciated?

Yes, many are bored of how I look now and want me to be flashier than before. It’s all about escaping into an own world. A world that is created for you and can be consumed without effort. I am not like this. I’m here to connect people. To help collaborative work. I want to empower people to communicate on a human level.

But, that’s what people do, isn’t it? People create more data than ever.

Maybe. Yes, I could be, but I don’t think I am. Sure, people talk to me. People look into cameras and take photos and send them to me. But I don’t get explanations. People don’t describe what they do and they don’t care if they can find it again later. Being first and getting quick likes is more important. It’s just adding more stuff, over and over.

So, people talk to you and it is meaningless? You feel like all you get is small talk?

I wished it were small. People have no idea how I work and have no empathy for how well connected the people they talk to are. I get huge files that could be small. And they don’t contain any information on what they are. I need to rely on others to find that information for me.

When it comes down to it, I am stupid. That’s why I am still around. I am so simple, I can’t break.

The ones using me to get information from humans use intelligent systems to try to decipher what it all means. Take the chat systems you talked about. These analyse images and turn them into words. They detect faces, emotions and text. This data goes somewhere, I don’t know where and most of the users don’t care. These systems then mimic human communication and give the recipient intelligent answers to choose from. Isn’t that cool?

People use me to communicate with other people and use language created for them by machines. Instead of using us, humans are becoming the transport mechanism for machines to talk to each other and mine data in between.

This applies to almost all content on the web – it is crazy. Algorithms write the news feeds; not humans.

Why do you think that is?

Speed. Constant change. Always new, always more, always more optimised. People don’t take time to verify things. It sickens me.

Why do you care?

You’re right, I shouldn’t be bothered. But I don’t feel good. I feel slow and sluggish.

Take a tweet. 140 letters, right?

Loading a URL that is a tweet on a computer downloads 3 megabytes of code. I feel – let’s name it – fat. I want to talk to everybody, but I am fed too much extra sugar and digital carbs. Most of the new people who are eager to meet me will never get me.

This is because this company want to give users their site functionality as soon as possible. But it feels more sinister to me. It is not about using me, it is about replacing me and keeping people inside of one system.

I am meant to be a loosely connected network of on-demand solutions. These used to be small, not a whopping 3 Megabytes to read 140 characters.

People still don’t get that about me. Maybe it is because I got two fathers and no mother. Some people get angry about this and don’t understand it. Maybe a woman’s touch would have made a better system.

But the worst is that I am almost in my 30s and I still haven’t got an income.

What do you mean by that?

There seems to be no way to make money with me. All everybody does is show ads for products and services people may or may not buy.

Ask for money to access something on me and people will not use it. Or find an illegal copy of the same thing. We raised a whole generation of people who don’t understand that creating on me is free, but not everything that I show is free to use and to consume.

Ads are making me sick and obese. Many of them don’t stop at showing people products. They spy on the people who use me, mine how they interact with things and sell that data to others. In the past, only people who use me for criminal purposes did that. Blackmail and such.

Can’t you do anything about that?

I can’t, but some people try. There’s ad blockers, new browsers that remove ads and proxy services. But to me these are just laxatives. I still need to consume the whole lot and then I need to get rid of it again. That’s not a healthy way to lose weight.

Some of them have nasty side effects, as you never know who watches the watchmen.

What do you need to feel better?

I want to communicate with humans again. I want to see real content, human interactions and real emotions. I don’t want to have predictable creativity and quick chuckles. I want people to use me for what I was meant to do – real communication and creativity.

Yes, you said that. What’s stopping you?

Two kinds of people. The ones who know my weaknesses and use me to attack others and bully them. This makes me really sick, and I find it disappointing that those who act out of malice are better at using me than others.

The second kind of people are those who don’t care. They have me, but they don’t understand that I could bring prosperity, information and creativity to everyone on the planet.

I need to lose some weight and I need to be more open to everybody out there again. Not dependent on a shiny and well-connected consumption device.

So, you’re stuck in between bullies and sheep?

Your words. Not mine. I like people. Some of my best friends are people. I want to keep empowering them.

However, if we don’t act now, those who always tried to control me will have won. Not because they are good at it, but because the intelligent, kind and good people of the web allowed the hooligans to take over. And that allows those who want to censor and limit me to do so in the name of “security”.

You sound worried…

I am. We all should be. This is not a time to be silent. This is not a time to behave. This is a time that needs rebels.

People who use their words, their kindness and their willingness to teach others the benefits of using me rather than consuming through me. Hey, maybe there are quite a few here who listened to me and help me get fit and happy again.

The feedback so far was amazing. People loved the idea and I had a whole day of interviews, chats, podcasts and more. Tomorrow will be fun, too, I am sure.

View full post on Christian Heilmann

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Building a Firefox OS App for my favorite Internet radio station

I recently created a Firefox OS app for my favourite radio station — radio paradise. It was a lot of fun making this app, so I thought it would be good to share some notes about how I built it.

The audio tag

It started by implementing the main functionality of the app, playing an ogg stream I got from the Internet radio station, using the HTML5 audio element

<audio src="http://stream-sd.radioparadise.com/rp_192m.ogg" controls preload></audio>

That was easy! At this point our app is completely functional. If you don’t believe me, checkout this jsfiddle. But please continue reading, since there will be a few more sweet features added. In fact, checkout the short video below to see how it will turn out.

Because this content belongs to radio paradise, before implementing the app, I contacted them to ask for their permission to make a Firefox OS app for their radio station; they responded:

Thanks. We’d be happy to have you do that. Our existing web player is html5-based. That might be a place to start. Firefox should have native support for our Ogg Vorbis streams.

I couldn’t have asked for a more encouraging response, and that was enough to set things in motion.

Features of the app

I wanted the app to be very minimal and simple — both in terms of user experience and the code backing it. Here is a list of the features I decided to include:

  • A single, easy to access, button to play and pause the music
  • Artist name, song title and album cover for the current song playing should fill up the interface
  • Setting option to select song quality (for situation when bandwidth is not enough to handle highest quality)
  • Setting option to start app with music playing or paused
  • Continue playing even when the app is sent to the background
  • Keep the screen on when the app is running in the forground

Instead of using the HTML tag, I decided to create the audio element and configure it in JavaScript. Then I hooked up an event listener for a button to play or stop music.

  var btn = document.getElementById('play-btn');
  var state = 'stop';
  btn.addEventListener('click', stop_play);
 
  // create an audio element that can be played in the background
  var audio = new Audio();
  audio.preload = 'auto';
  audio.mozAudioChannelType = 'content';
 
  function play() {
    audio.play();
    state = 'playing';
    btn.classList.remove('stop');
    btn.classList.add('playing');
  }
 
  function stop() {
    audio.pause();
    state = 'stop';
    btn.classList.add('stop');
    btn.classList.remove('playing');
  }
 
  // toggle between play and stop state
  function stop_play() {
    (state == 'stop') ? play() : stop();
  }

Accessing current song information

The first challenge I faced was accessing the current song information. Normally we should not need any special privilege to access third party API’s as long as they provide correct header information. However, the link radio paradise provided me for getting the current song information did not allow for cross origin access. Luckily FirefoxOS has a special power reserved for this kind of situation — systemXHR comes to the rescue.

function get_current_songinfo() {
  var cache_killer = Math.floor(Math.random() * 10000);
  var playlist_url =
    'http://www.radioparadise.com/ajax_rp2_playlist.php?' +
    cache_killer;
  var song_info = document.getElementById('song-info-holder');
  var crossxhr = new XMLHttpRequest({mozSystem: true});
  crossxhr.onload = function() {
    var infoArray = crossxhr.responseText.split('|');
    song_info.innerHTML = infoArray[1];
    next_song = setInterval(get_current_songinfo, infoArray[0]);
    update_info();
  };
  crossxhr.onerror = function() {
    console.log('Error getting current song info', crossxhr);
    nex_song = setInterval(get_current_singinfo, 200000);
  };
  crossxhr.open('GET', playlist_url);
  crossxhr.send();
  clearInterval(next_song);
}

This meant that the app would have to be privileged and thus packaged. I normally would try to keep my apps hosted, because that is very natural for a web app and has several benefits including the added bonus of being accessible to search engines. However, in cases such as this we have no other option but to package the app and give it the special privileges it needs.

{
  "version": "1.1",
  "name": "Radio Paradise",
  "launch_path": "/index.html",
  "description": "An unofficial app for radio paradise",
  "type": "privileged",
  "icons": {
    "32": "/img/rp_logo32.png",
    "60": "/img/rp_logo60.png",
    "64": "/img/rp_logo64.png",
    "128": "/img/rp_logo128.png"
  },
  "developer": {
    "name": "Aras Balali Moghaddam",
    "url": "http://arasbm.com"
  },
  "permissions": {
    "systemXHR": {
      "description" : "Access current song info on radioparadise.com"
    },
    "audio-channel-content": {
      "description" : "Play music when app goes into background"
    }
  },
  "installs_allowed_from": ["*"],
  "default_locale": "en"
}

Updating song info and album cover

That XHR call to radio paradise proides me with three important pieces of information:

  • Name of the current song playing and it’s artist
  • An image tag containing the album cover
  • Time left to the end of current song in miliseconds

Time left to the end of current song is very nice to have. It means that I can execute the XHR call and update the song information only once for every song. I first tried using the setTimeout function like this:

//NOT working example. Can you spot the error?
crossxhr.onload = function() {
  var infoArray = crossxhr.responseText.split('|');
  song_info.innerHTML = infoArray[1];
  setTimeout('get_current_songinfo()', infoArray[0]);
  update_info();
};

To my surprise, that did not work, and I got a nice error in logcat about a CSP restriction. It turns out that any attempt at dynamically executing code is banned for security reasons. All we have to do in this scenario to avoid the CSP issue is to pass a callable object, instead of a string.

  // instead of passing a string to setTimout we pass
  // a callable object to it
  setTimeout(get_current_songinfo, infoArray[0]);

radio paradise mobile web app running on FirefoxOS

With a bit of CSS magic, things started to fall into place pretty quickly

Adding a unique touch

One of the great advantages of developing mobile applications for the web is that you are completely free to design your app in any way you want. There is no enforcement of style or restriction on interaction design innovation. Knowing that, it was hard to hold myself back from trying to explore new ideas and have some fun with the app. I decided to hide the settings behind the main content and then add a feature so user can literally cut open the app in the middle to get to setting. That way they are tucked away, but still can be discovered in an intuitive way. For UI elements in the setting page to toggle options I decided to give Brick a try., with a bit of custom styling added.

radio paradise app settings

User can slide open the cover image to access app settings behind it

Using the swipe gesture

As you saw in the video above, to open and close the cover image I use pan and swipe gestures. To implement that, I took gesture detector from Gaia. It was very easy to integrated the gesture code as a module into my app and hook it up to the cover image.

Organizing the code

For an app this small, we do not have to use modular code. However, since I have recently started to learn about AMD practices, I decided to use a module system. I asked James Burke about implications of using requirejs in an app like this. He suggested I use Alameda instead, since it is geared toward modern browsers.

Saving app settings

I wanted to let users choose stream quality as well as whether they want the app to start playing music as soon as it opens. Both of these options need to be persisted somewhere and retrieved when the app starts. I just needed to save a couple of key/value pairs. I went to #openwebapps irc channel and asked for advice. Fabrice pointed me to a nice piece of code in Gaia (again!) that is used for asynchronous storing of key/value pairs and even whole objects. That was perfect for my use case, so I took it as well. Gaia appears to be a goldmine. Here is the module I created for settings.

define(['helper/async_storage'], function(asyncStorage) {
  var setting = {
    values: {
      quality: 'high',
      play_on_start: false
    },
    get_quality: function() {
      return setting.values.quality;
    },
    set_quality: function(q) {
      setting.values.quality = q;
      setting.save();
    },
    get_play_on_start: function() {
      return setting.values.play_on_start;
    },
    set_play_on_start: function(p) {
      setting.values.play_on_start = p;
      setting.save();
    },
    save: function() {
      asyncStorage.setItem('setting', setting.values);
    },
    load: function(callback) {
      asyncStorage.getItem('setting', function(values_obj) {
        if (values_obj) setting.values = values_obj;
        callback();
      });
    }
  };
  return setting;
});

Splitting the cover image

Now we get to the really fun part that is splitting the cover image in half. To achieve this effect, I made two identical overlapping canvas element both of which are sized to fit the device width. One canvas clips the image and keeps the left portion of it while the other keeps the right side.

Each canvas clips and renders half of the image

Each canvas clips and renders half of the image

Here is the code for draw function where most of the action is happening. Note that this function runs only once for each song, or when user changes the orientation of the device from portrait to landscape and vice versa.

function draw(img_src) {
  width = cover.clientWidth;
  height = cover.clientHeight;
  draw_half(left_canvas, 'left');
  draw_half(right_canvas, 'right');
  function draw_half(canvas, side) {
    canvas.setAttribute('width', width);
    canvas.setAttribute('height', height);
    var ctx = canvas.getContext('2d');
    var img = new Image();
    var clip_img = new Image();
    // opacity 0.01 is used to make any glitch in clip invisible
    ctx.fillStyle = 'rgba(255,255,255,0.01)';
 
    ctx.beginPath();
    if (side == 'left') {
      ctx.moveTo(0, 0);
      // add one pixel to ensure there is no gap
      var center = (width / 2) + 1;
    } else {
      ctx.moveTo(width, 0);
      var center = (width / 2) - 1;
    }
 
    ctx.lineTo(width / 2, 0);
 
    // Draw a wavy pattern down the center
    var step = 40;
    var count = parseInt(height / step);
    for (var i = 0; i < count; i++) {
      ctx.lineTo(center, i * step);
 
      // alternate curve control point 20 pixels, every other time
      ctx.quadraticCurveTo((i % 2) ? center - 20 :
        center + 20, i * step + step * 0.5, center, (i + 1) * step);
    }
    ctx.lineTo(center, height);
    if (side == 'left') {
      ctx.lineTo(0, height);
      ctx.lineTo(0, 0);
    } else {
      ctx.lineTo(width, height);
      ctx.lineTo(width, 0);
    }
 
    ctx.closePath();
    ctx.fill();
    ctx.clip();
 
    img.onload = function() {
      var h = width * img.height / img.width;
      ctx.drawImage(img, 0, 0, width, h);
    };
    img.src = img_src;
  }
}

Keeping the screen on

The last feature I needed to add was keeping the screen on when the app is running in foreground and that turned out to be very easy to implement as well. We need to request a screen wake lock

  var lock = window.navigator.requestWakeLock(resourceName);

The screen wake lock is actually pretty smart. It will be automatically released when app is sent to the background, and then will given back to your app when it comes to the foreground. Currently in this app I have not provided an option to release the lock. If in future I get requests to add that option, all I have to do is release the lock that has been obtained before setting the option to false

  lock.unlock();

Getting the app

If you have a FirefoxOS device and like great music, you can now install this app on your device. Search for “radio paradise” in the marketplace, or install it directly from this link. You can also checkout the full source code from github. Feel free to fork and modify the app as you wish, to create your own Internet Radio apps! I would love it if you report issues, ask for features or send pull requests.

Conclusion

I am more and more impressed by how quickly we can create very functional and unique mobile apps using web technologies. If you have not build a mobile web app for Firefox OS yet, you should definitely give it a try. The future of open web apps is very exciting, and Firefox OS provides a great platform to get a taste of that excitement.

Now it is your turn to leave a comment. What is your favourite feature of this app? What things would you have done differently if you developed this app? How could we make this app better (both code and UX)?

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Building a FirefoxOS App for my favorite Internet radio station

I recently created a Firefox OS app for my favourite radio station — radio paradise. It was a lot of fun making this app, so I thought it would be good to share some notes about how I built it.

The audio tag

It started by implementing the main functionality of the app, playing an ogg stream I got from the Internet radio station, using the HTML5 audio element

<audio src="http://stream-sd.radioparadise.com/rp_192m.ogg" controls preload></audio>

That was easy! At this point our app is completely functional. If you don’t believe me, checkout this jsfiddle. But please continue reading, since there will be a few more sweet features added. In fact, checkout the short video below to see how it will turn out.

Because this content belongs to radio paradise, before implementing the app, I contacted them to ask for their permission to make a Firefox OS app for their radio station; they responded:

Thanks. We’d be happy to have you do that. Our existing web player is html5-based. That might be a place to start. Firefox should have native support for our Ogg Vorbis streams.

I couldn’t have asked for a more encouraging response, and that was enough to set things in motion.

Features of the app

I wanted the app to be very minimal and simple — both in terms of user experience and the code backing it. Here is a list of the features I decided to include:

  • A single, easy to access, button to play and pause the music
  • Artist name, song title and album cover for the current song playing should fill up the interface
  • Setting option to select song quality (for situation when bandwidth is not enough to handle highest quality)
  • Setting option to start app with music playing or paused
  • Continue playing even when the app is sent to the background
  • Keep the screen on when the app is running in the forground

Instead of using the HTML tag, I decided to create the audio element and configure it in JavaScript. Then I hooked up an event listener for a button to play or stop music.

  var btn = document.getElementById('play-btn');
  var state = 'stop';
  btn.addEventListener('click', stop_play);
 
  // create an audio element that can be played in the background
  var audio = new Audio();
  audio.preload = 'auto';
  audio.mozAudioChannelType = 'content';
 
  function play() {
    audio.play();
    state = 'playing';
    btn.classList.remove('stop');
    btn.classList.add('playing');
  }
 
  function stop() {
    audio.pause();
    state = 'stop';
    btn.classList.add('stop');
    btn.classList.remove('playing');
  }
 
  // toggle between play and stop state
  function stop_play() {
    (state == 'stop') ? play() : stop();
  }

Accessing current song information

The first challenge I faced was accessing the current song information. Normally we should not need any special privilege to access third party API’s as long as they provide correct header information. However, the link radio paradise provided me for getting the current song information did not allow for cross origin access. Luckily FirefoxOS has a special power reserved for this kind of situation — systemXHR comes to the rescue.

function get_current_songinfo() {
  var cache_killer = Math.floor(Math.random() * 10000);
  var playlist_url =
    'http://www.radioparadise.com/ajax_rp2_playlist.php?' +
    cache_killer;
  var song_info = document.getElementById('song-info-holder');
  var crossxhr = new XMLHttpRequest({mozSystem: true});
  crossxhr.onload = function() {
    var infoArray = crossxhr.responseText.split('|');
    song_info.innerHTML = infoArray[1];
    next_song = setInterval(get_current_songinfo, infoArray[0]);
    update_info();
  };
  crossxhr.onerror = function() {
    console.log('Error getting current song info', crossxhr);
    nex_song = setInterval(get_current_singinfo, 200000);
  };
  crossxhr.open('GET', playlist_url);
  crossxhr.send();
  clearInterval(next_song);
}

This meant that the app would have to be privileged and thus packaged. I normally would try to keep my apps hosted, because that is very natural for a web app and has several benefits including the added bonus of being accessible to search engines. However, in cases such as this we have no other option but to package the app and give it the special privileges it needs.

{
  "version": "1.1",
  "name": "Radio Paradise",
  "launch_path": "/index.html",
  "description": "An unofficial app for radio paradise",
  "type": "privileged",
  "icons": {
    "32": "/img/rp_logo32.png",
    "60": "/img/rp_logo60.png",
    "64": "/img/rp_logo64.png",
    "128": "/img/rp_logo128.png"
  },
  "developer": {
    "name": "Aras Balali Moghaddam",
    "url": "http://arasbm.com"
  },
  "permissions": {
    "systemXHR": {
      "description" : "Access current song info on radioparadise.com"
    },
    "audio-channel-content": {
      "description" : "Play music when app goes into background"
    }
  },
  "installs_allowed_from": ["*"],
  "default_locale": "en"
}

Updating song info and album cover

That XHR call to radio paradise proides me with three important pieces of information:

  • Name of the current song playing and it’s artist
  • An image tag containing the album cover
  • Time left to the end of current song in miliseconds

Time left to the end of current song is very nice to have. It means that I can execute the XHR call and update the song information only once for every song. I first tried using the setTimeout function like this:

//NOT working example. Can you spot the error?
crossxhr.onload = function() {
  var infoArray = crossxhr.responseText.split('|');
  song_info.innerHTML = infoArray[1];
  setTimeout('get_current_songinfo()', infoArray[0]);
  update_info();
};

To my surprise, that did not work, and I got a nice error in logcat about a CSP restriction. It turns out that any attempt at dynamically executing code is banned for security reasons. All we have to do in this scenario to avoid the CSP issue is to pass a callable object, instead of a string.

  // instead of passing a string to setTimout we pass
  // a callable object to it
  setTimeout(get_current_songinfo, infoArray[0]);

radio paradise mobile web app running on FirefoxOS

With a bit of CSS magic, things started to fall into place pretty quickly

Adding a unique touch

One of the great advantages of developing mobile applications for the web is that you are completely free to design your app in any way you want. There is no enforcement of style or restriction on interaction design innovation. Knowing that, it was hard to hold myself back from trying to explore new ideas and have some fun with the app. I decided to hide the settings behind the main content and then add a feature so user can literally cut open the app in the middle to get to setting. That way they are tucked away, but still can be discovered in an intuitive way. For UI elements in the setting page to toggle options I decided to give Brick a try., with a bit of custom styling added.

radio paradise app settings

User can slide open the cover image to access app settings behind it

Using the swipe gesture

As you saw in the video above, to open and close the cover image I use pan and swipe gestures. To implement that, I took gesture detector from Gaia. It was very easy to integrated the gesture code as a module into my app and hook it up to the cover image.

Organizing the code

For an app this small, we do not have to use modular code. However, since I have recently started to learn about AMD practices, I decided to use a module system. I asked James Burke about implications of using requirejs in an app like this. He suggested I use Alameda instead, since it is geared toward modern browsers.

Saving app settings

I wanted to let users choose stream quality as well as whether they want the app to start playing music as soon as it opens. Both of these options need to be persisted somewhere and retrieved when the app starts. I just needed to save a couple of key/value pairs. I went to #openwebapps irc channel and asked for advice. Fabrice pointed me to a nice piece of code in Gaia (again!) that is used for asynchronous storing of key/value pairs and even whole objects. That was perfect for my use case, so I took it as well. Gaia appears to be a goldmine. Here is the module I created for settings.

define(['helper/async_storage'], function(asyncStorage) {
  var setting = {
    values: {
      quality: 'high',
      play_on_start: false
    },
    get_quality: function() {
      return setting.values.quality;
    },
    set_quality: function(q) {
      setting.values.quality = q;
      setting.save();
    },
    get_play_on_start: function() {
      return setting.values.play_on_start;
    },
    set_play_on_start: function(p) {
      setting.values.play_on_start = p;
      setting.save();
    },
    save: function() {
      asyncStorage.setItem('setting', setting.values);
    },
    load: function(callback) {
      asyncStorage.getItem('setting', function(values_obj) {
        if (values_obj) setting.values = values_obj;
        callback();
      });
    }
  };
  return setting;
});

Splitting the cover image

Now we get to the really fun part that is splitting the cover image in half. To achieve this effect, I made two identical overlapping canvas element both of which are sized to fit the device width. One canvas clips the image and keeps the left portion of it while the other keeps the right side.

Each canvas clips and renders half of the image

Each canvas clips and renders half of the image

Here is the code for draw function where most of the action is happening. Note that this function runs only once for each song, or when user changes the orientation of the device from portrait to landscape and vice versa.

function draw(img_src) {
  width = cover.clientWidth;
  height = cover.clientHeight;
  draw_half(left_canvas, 'left');
  draw_half(right_canvas, 'right');
  function draw_half(canvas, side) {
    canvas.setAttribute('width', width);
    canvas.setAttribute('height', height);
    var ctx = canvas.getContext('2d');
    var img = new Image();
    var clip_img = new Image();
    // opacity 0.01 is used to make any glitch in clip invisible
    ctx.fillStyle = 'rgba(255,255,255,0.01)';
 
    ctx.beginPath();
    if (side == 'left') {
      ctx.moveTo(0, 0);
      // add one pixel to ensure there is no gap
      var center = (width / 2) + 1;
    } else {
      ctx.moveTo(width, 0);
      var center = (width / 2) - 1;
    }
 
    ctx.lineTo(width / 2, 0);
 
    // Draw a wavy pattern down the center
    var step = 40;
    var count = parseInt(height / step);
    for (var i = 0; i < count; i++) {
      ctx.lineTo(center, i * step);
 
      // alternate curve control point 20 pixels, every other time
      ctx.quadraticCurveTo((i % 2) ? center - 20 :
        center + 20, i * step + step * 0.5, center, (i + 1) * step);
    }
    ctx.lineTo(center, height);
    if (side == 'left') {
      ctx.lineTo(0, height);
      ctx.lineTo(0, 0);
    } else {
      ctx.lineTo(width, height);
      ctx.lineTo(width, 0);
    }
 
    ctx.closePath();
    ctx.fill();
    ctx.clip();
 
    img.onload = function() {
      var h = width * img.height / img.width;
      ctx.drawImage(img, 0, 0, width, h);
    };
    img.src = img_src;
  }
}

Keeping the screen on

The last feature I needed to add was keeping the screen on when the app is running in foreground and that turned out to be very easy to implement as well. We need to request a screen wake lock

  var lock = window.navigator.requestWakeLock(resourceName);

The screen wake lock is actually pretty smart. It will be automatically released when app is sent to the background, and then will given back to your app when it comes to the foreground. Currently in this app I have not provided an option to release the lock. If in future I get requests to add that option, all I have to do is release the lock that has been obtained before setting the option to false

  lock.unlock();

Getting the app

If you have a FirefoxOS device and like great music, you can now install this app on your device. Search for “radio paradise” in the marketplace, or install it directly from this link. You can also checkout the full source code from github. Feel free to fork and modify the app as you wish, to create your own Internet Radio apps! I would love it if you report issues, ask for features or send pull requests.

Conclusion

I am more and more impressed by how quickly we can create very functional and unique mobile apps using web technologies. If you have not build a mobile web app for Firefox OS yet, you should definitely give it a try. The future of open web apps is very exciting, and Firefox OS provides a great platform to get a taste of that excitement.

Now it is your turn to leave a comment. What is your favourite feature of this app? What things would you have done differently if you developed this app? How could we make this app better (both code and UX)?

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)