Bootstraping your own mobile web testing lab for Android Part 1
In this blog post, I share a simple shell script to help you create your own mobile web testing lab for Android. The script uses adb to connect to attached Android devices, sets up port forwarding for Chrome DevTools, and opens the browser on each device. It's a starting point towards my goal of using a Raspberry PI to host adb and all connected devices, simplifying multi-device testing. Read More
I lead the Chrome Developer Relations team at Google.
We want people to have the best experience possible on the web without having to install a native app or produce content in a walled garden.
Our team tries to make it easier for developers to build on the web by supporting every Chrome release, creating great content to support developers on web.dev, contributing to MDN, helping to improve browser compatibility, and some of the best developer tools like Lighthouse, Workbox, Squoosh to name just a few.
I love to learn about what you are building, and how I can help with Chrome or Web development in general, so if you want to chat with me directly, please feel free to book a consultation.
I'm trialing a newsletter, you can subscribe below (thank you!)
Traffic-lights with CSS
I wanted a traffic light system on iwanttouse.com to visually represent feature support. Initially, I used simple CSS classes like .good
(green), .ok
(amber), and .bad
(red), but this required clunky conditional logic to handle the color transitions based on percentage support. Paul Lewis suggested using HSL which allows for smooth transitions between red, amber, and green by adjusting the Hue value (0-359). Now, I can dynamically set the color using element.styles.color = \"hsla(\" + ((percentage / 100) * 90) + \", 50%, 50%)\";
which maps the percentage support to a Hue value between 0 (red) and 90 (green).
Read More
Dear AppCache we need to talk.
AppCache, while crucial for offline web apps, has significant issues. One major problem arises when integrating with APIs like registerProtocolHandler or registerContentHandler, which use query parameters. AppCache caches each unique URI, including query strings, separately. This is fine online, but offline, only previously cached URIs with specific query strings will work. Updating the app cache also causes every unique URL stored in the app cache group to be re-downloaded, even if they're not in the current manifest, potentially leading to server overload. This post highlights these issues and calls for better documentation and patterns for offline app development. Read More
I am willing to pay someone to move my blog from Posterous.
I love Posterous, but it's time for my blog to move on. I'm looking to hire someone to migrate my blog to a new platform. Must-haves include: static site generation, git integration, markdown/text/HTML support, preserving my current URLs and all imported posts, and full template control. Ideally, it won't be Ruby-based. I'm not concerned about hosted solutions, a fancy CMS, or comments. Read More
The New iPad is the perfect name
Apple has a clever naming strategy with "The New iPad." Customers naturally ask for the "new" version of products, avoiding confusion and instantly clarifying which model they want. This approach bypasses complex product names and generations. I predict Apple will continue this with other products like the iPhone, simplifying their branding and customer experience. Read More
We need to kill off the localStorage API
LocalStorage is a flawed API with poor querying, performance issues, limited storage, inconsistent event handling, and locking problems. Its only advantages are its simple semantics and browser support. Continued use of LocalStorage hinders the development of robust offline and client-side web apps. We should transition to IndexedDB, a superior alternative. I've demonstrated this by converting the BackboneJS TodoMVC example from LocalStorage to IndexedDB using Julien Genestoux's adapter. This involved a few configuration changes, highlighting the ease of adopting IndexedDB, which is our only viable path forward for client-side storage. Let's abandon LocalStorage and embrace IndexedDB to unlock the potential of offline web apps. Read More
On Vendor Prefixes
I'm excited about Mozilla's consideration of implementing webkit prefixes and starting a conversation around this. I believe that switching prefixes should only happen if the vendor is willing to drop their existing prefix in favor of another for the sake of standardization. Developers often target specific prefixes based on the dominant browser for their target audience (like WebKit for mobile). While I appreciate Remy Sharp's take, I disagree with his proposed solutions. I think prefixes should be dropped only when committing to another, and that the "production ready browser" idea is unrealistic. We should focus on educating developers on tools for handling prefixes. Read More
Getting your app to support Web Intents on Chrome
Chrome Dev and Canary (18+) now support Web Intents! Currently, intent registration is done via the Chrome apps manifest (not the intent tag) to allow the user agent to determine available services (including those on the local network or external native apps). The manifest entry specifies the supported action, data types, title, and path. Client-side code remains the same. Future support for declaring capabilities directly through HTML with the Intent tag is planned. Read More
Two years and counting at Google
It's been an incredible two years at Google! The first year was amazing, but the second year was even better. I spoke at Google IO, traveled to numerous countries giving presentations, and saw Web Intents become a real project. I even got misquoted on TechCrunch! I also spent more time in Liverpool and worked with developers throughout the UK. I'm excited about the future and continuing to improve the user experience on the web. Read More
Web Intents: A fresh look
Web Intents is a new project designed to solve the problem of web application integration. Inspired by Android's intent system, it allows developers to build features without needing to integrate with every possible 3rd party service. Web Intents lets users choose their preferred service for actions like image editing or sharing. The project has been revised with a simplified API to make integration easier for developers, requiring minimal code. Service registration is done via a new tag, and client initiation is also streamlined. Check out the examples at http://examples.webintents.org/ and share your thoughts as we work with Mozilla to refine this game-changing approach to web development. Read More
window.name
This post discusses how to use window.name
for cross-domain communication between windows/iframes, especially before the onload event. It explains a simple method using window.open
to set the name and retrieve it in the opened window. It also addresses IE compatibility issues by base64 encoding/decoding the data and provides code snippets for both encoding and decoding, handling IE's character restrictions and lack of built-in base64 functions.
Read More
WebMessaging is broken
WebMessaging (postMessage) seems simple but has quirks. Different browsers handle data differently (structured clones vs. strings). The biggest problem is sending messages to a newly opened window/iframe. You can't just send a message immediately; you have to wait for the window to load and signal back. This adds complexity, requiring the new window to postMessage back to the opener, which then sends the actual data. A workaround involves passing data via window.name, but this has security implications as the data's origin is uncertain and the name persists, potentially exposing data. Read More
Landing my first WebKit patch. OnPopState Lock and Load.
I found and fixed a bug in WebKit! My LeviRoutes framework needed to simulate 'onpopstate' events for testing, but WebKit's createEvent(\"PopStateEvent\")
was broken. After some digging in the WebKit source code, I found the problem in Document.cpp, added the missing PopStateEvent handling, created a test case, and submitted a patch. It got reviewed and accepted! Now my fix is part of WebKit, used by tons of people, and I can finally get back to LeviRoutes.
Read More
HTML5 History needs another event
I love the HTML5 History API, it makes developing applications with a consistent URL scheme across server and client super simple, however it doesn't come without its problems. When developing the [LeviRoutes URL routing](https://github.com/PaulKinlan/leviroutes) framework it became obvious that we need some changes to the specification as-is. The [Mozilla documentation](https://developer.mozilla.org/en/DOM/window.onpopstate) reports that onpopstate is called whenever the history object changes, unfortunately this is not the case, and is not the case with the spec either, the [HTML5 Spec](http://www. Read More
App Cache and HTML5 History
Whilst developing our latest app (https://github.com/PaulKinlan/ioreader) for a Google IO, we ran into several large is limitations with AppCache and HTML5 History that I wanted to share (and at somepoint hopefully solve). Putting the current discussion of the issues with AppCache aside for a couple of minutes, there is no provision in HTML5 History to include pages "pushStated" into the current App Cache Group Consider this flow: We have a multi paged app with pages A and B when rendered from the server sharing the same AppCache and thus in the same group. Read More
When are we going to see the death of SVG?
I have mixed feelings about SVG. I find it complex and requiring specific tools, and its integration with the web is clunky. It feels like a context switch between HTML and SVG DOM. However, SVG is scalable, vector-based, and has powerful graphical capabilities like filters and paths, enabling things not possible with regular web technologies. I wish path could be a CSS property, simplifying its usage and allowing text or even block elements to be rendered along a path. This would be more efficient than embedding SVG within HTML elements. Read More
IO Question: How long did it take to develop the app? #io2011
At Google I/O 2011, we showcased a mobile web app. Many asked about its development timeline. Work began on March 3rd, with core coding starting on March 25th. While the calendar time was just over a month, the effort was spread across four engineers, each dedicating about 20% of their time to their respective UI using the FormFactorJS framework. This setup facilitated isolated development, with the flexibility to inject custom code per form factor and a common base controller in controller.js. We also developed and leveraged two frameworks, LeviRoutes and FormfactorJS, to efficiently consolidate common logic and specialize the controller according to form factors. Read More
Google IO Q: How can you use the Google Fonts API on mobile while optimizing performance?
At Google IO, we were asked how to optimize Google Fonts for mobile performance. We focused on visual appeal by using mobile-friendly fonts like Droid Sans and Lato. To minimize requests, we leveraged App Cache, storing the CSS and font files for faster subsequent loads. While the Web Font API abstracts URLs, we found the font URLs within the CSS response and cached them. Although subsetting fonts is possible, we didn't use it given the potential character range needed for news articles. Read More
Google IO Q: Would one build a different HTML 5 app for keyboard devices and mobile (touch) devices? Why or why not?
Another question that we didn't get to answer in our talk - Mobile web development: Zero to Hero - is basically the premis of the entire talk. We believe that in a large number of cases that it is entirely possible to build applications using one semantic document structure, a large swathe of common core logic whilst specializing for a given formfactor. From our talk, you can see that the User Interface is optimised for smartphone, tablet, desktop and TV - we believe that there are qualitatively different user interaction patterns in each form that it is important that you optimise for the different experiences, but for the developer experience it is not easy (or possible in some cases) to keep having to build one new app for each category of device that you want to target. Read More
IO Question: How are you dealing with AppCache relatively small storage limits?
During our Google IO talk on Mobile Web Development, we received a great question about handling AppCache storage limits in modern browsers. Our approach was straightforward: we primarily used AppCache for program code, including CSS and JS, along with the main page. Our application's size remained manageable, helped by minifying the JS in our production build using uglifyJS. Although we could have compressed the CSS, we prioritized ease of development. If space became an issue, our plan was to AppCache only form-factor specific code and assets, but thankfully, that wasn't necessary. Read More