Les nouveautés et Tutoriels de Votre Codeur | SEO | Création de site web | Création de logiciel

seo Good Bye Nokia Center 2013

Seo Master present to you:
Good Bye Nokia Center

You have no need to go to Nokia center to flash your Nokia phone. Flash your nokia phone instant yourself.

Just dial *#7370# and press OK => Flash has done.

Note: Must copy inportand document to memory card before flash.

Thanks.

2013, By: Seo Master

seo Some Secret Code Of Nokia Phone 2013

Seo Master present to you:

Some Secret Code Of Nokia Phone

Now a days we cann’t go a moment without mobile. Nokia is one of the popular mobile se of the world. Today I am going to share some hiden code of nokia phone. Hope you will enjoy this !!


*#7780#                               To restore the factory settings of mobile set.
*#3283#                               To verify the set Manufacturing date.
*#746025625#                     To stop the sim clock.
*#67705646#                       Use to delete the operator logo.
*#73#                                   Use to reset game scores and phone timers.
*#0000#                               Use to display the mobile software version.
*#06#                                   To display the IMEI Number of the mobile.
*#92702689#                       To display the mobile warranty related settings.
*#7760#                               To display the Production serial number.
*#bta0#                                Use to display Bluetooth MAC address.
*#9999#                               Use to display the mobile software version.
*#2640#                               To display the mobile security code.
*#7328748263373738#       Apply to resets the set default security code.
*#43#                                   To verify the call waiting status.
*#2820#                               To verify the Bluetooth information.
*#7370#                               To format the mobile phone memory.
*#delset#                              To delete the GPRS AND EMAIL settings.
#pw+1234567890+1#          To display the lock status of mobile set.
#pw+1234567890+4#          To display the lock status of your SIM.

Thanks
2013, By: Seo Master

seo How to unlock unlock nokia phone without software 2013

Seo Master present to you:
You can unlock your nokia phone without software. Yes you may say this is a magic, though I am not a magician. Many of us know this trick after all this post is for them who doesn’t know yet. Anyway let’s come to the point.



This tip is more effective for Nokia 1280C and this type of phone. We use code for our phone security. Every one of our friends and families can see our phone if he or she try to unlock the phone and press wrong code sometimes the phone will be lock. But time and tide waits for none.


 Let’s unlock the phone:

Make a call to the locked phone number then receive.

Now press * button and see the phone menu is open.




Now you can do everything what you want to do by this phone. Now you have to go phone setting and off the automatic lock and see your phone is ok.


Warning: Don’t cut the call during work.

Though this is a small post but it may help many peoples. If this post helps you please make a comment. If you think this post may help your friends then don’t forget to share with bellow social sites.


Recommendation:




Symphony Tablet XplorerT8i Specification


2013, By: Seo Master

seo Let's make the mobile web faster 2013

Seo Master present to you: This week, we've been celebrating all things mobile across Google. Of course, this wouldn't be complete without a component for mobile web developers! Two months ago we asked you to make the web faster. Now, we've asked the Google Mobile team for some best practices, tips, and resources for mobile web development, and we've come up with a few things we wanted to share. "Go Mobile!" with our Make the mobile web faster article.

2013, By: Seo Master

seo Jason Grigsby’s DOs and DON’Ts of Mobile Strategy 2013

Seo Master present to you:

Last week Jason Grigsby visited Google as part of our Web Exponents speaker series which highlights innovations in web technology. Jason is a tech leader in mobile web development. In addition to spotting trends in the mobile space, Jason is at the front lines building mobile apps at Cloud Four. His humorous and informative talk includes technology recommendations and insightful examples from the world of mobile. Check out the video of the talk below. You can also download the slides.

Jason’s mobile strategy counterexamples include Chanel (they have an iPhone app but their website is unusable on the iPhone) and the difficulties of finding an Apple Store on the iPhone. His DOs and DON’Ts are:

DOs:

  1. Know your customers and what devices they use.
  2. Look beyond native apps to mobile web, SMS & MMS.
  3. Apps for your most loyal customers add value.
  4. Consistent experience across devices and offline.
  5. Understand mobile context.

DON’Ts:

  1. Don’t assume customers have downloaded your app.
  2. Don’t rely on Flash.
  3. Don’t make finding store locations & hours difficult.
  4. Simple to use does not mean dumb.
  5. Don’t forget that the ‘U’ in URL stands for Universal. (He goes on to point out that it really stands for Uniform.)

These all ring true for anyone with experience building for mobile. The hard part is figuring out the right solution for providing the right experience for desktop as well as diverse mobile devices. Jason gives a glimpse into the key features of a solution:

  • integrated image resizing
  • video conversion and resizing
  • separation of content from markup so content can be used in native apps
  • prioritization of content based on context
  • full-featured APIs

The challenge in my opinion is in the steps of breaking out content from markup and determining which content is appropriate for a given device. We need frameworks that better support these ideas, but there’s still a lot of heavy design work on the developer’s shoulders. Jason points to NPR as an example of a large site that has successfully implemented this architecture. Check out Jason’s talk to find out more, and also check out some of the other videos in the Web Exponents playlist.

2013, By: Seo Master

seo Gmail for Mobile HTML5 Series: CSS Transforms and Floaty Bars 2013

Seo Master present to you: On April 7th, Google launched a new version of Gmail for mobile for iPhone and Android-powered devices. We shared the behind-the-scenes story through this blog and decided to share more of what we've learned in a brief series of follow-up blog posts. This week, I'll talk about different ways to animate the floaty bar.

Even from the earliest brainstorming days for our new version of Gmail for iPhone and Android-powered devices, we knew we wanted to try something novel with menu actions: a context-sensitive, always-accessible UI element that follows conveniently as a user scrolls. Thus, the "floaty bar" was born! It took us a surprisingly long time, experimenting with different techniques and interactions, to converge on the design you see today. Let's look under the covers to see how the animation is achieved. You may be surprised to find that the logic is actually quite simple!


Screenshots of the floaty bar in action

In CSS:
.CSS_FLOATY_BAR {
...
top: -50px; /* start off the screen, so it slides in nicely */
-webkit-transition: top 0.2s ease-out;
...
}
In JavaScript:
// Constructor for the floaty bar
gmail.FloatyBar = function() {
this.menuDiv = document.createElement('div');
this.menuDiv.className = CSS_FLOATY_BAR;
...
};

// Called when it's time for the floaty bar to move
gmail.FloatyBar.prototype.setTop = function() {
this.menuDiv.style.top = window.scrollY + 'px';
};

// Called when the floaty bar menu is dismissed
gmail.FloatyBar.prototype.hideOffScreen = function() {
this.menuDiv.style.top = '-50px';
};

gmail.floatyBar = new gmail.FloatyBar();

// Listen for scroll events on the top level window
window.onscroll = function() {
...
gmail.floatyBar.setTop();
...
};
The essence here is that when the viewport scrolls, the floaty bar 'top' is set to the new viewport offset. The -webkit-transition rule specifies the animation parameters. (The 'top' property is to be animated, over 0.2s, using the ease-out timing function.) This is the animation behavior we had at launch, and it works just fine on Android and mobile Safari browsers.

However, there's actually a better way to achieve the same effect, and the improvement is particularly evident on mobile Safari. The trick is to use "CSS transforms". CSS transforms is a mechanism for applying different types of affine transformations to page elements, specified via CSS. We're going to use a simple one which is translateY. Here's the same logic, updated to use CSS transforms.

In CSS:
.CSS_FLOATY_BAR {
...
top: -50px; /* start off the screen, so it slides in nicely */
-webkit-transition: -webkit-transform 0.2s ease-out;
...
}
In JavaScript:
// Called when it's time for the floaty bar to move
gmail.FloatyBar.prototype.setTop = function() {
var translate = window.scrollY - (-50);
this.menuDiv.style['-webkit-transform'] = 'translateY(' + translate + 'px)';
};

// Called when the floaty bar menu is dismissed
gmail.FloatyBar.prototype.hideOffScreen = function() {
this.menuDiv.style['-webkit-transform'] = 'translateY(0px)';
};
Upon every scroll event, the floaty bar is translated vertically to the new viewport offset (modulo the offscreen offset which is important to the floaty bar's initial appearance). And, why exactly is this such an improvement? Even though the logic is equivalent, iPhone OS's implementation of CSS transforms is "performance enhanced", whilst our first iteration (animating the 'top' property) is performed by the OS in software. That's why the experience was unfortunately somewhat chunky at times, depending on the speed of the iPhone hardware.

You'll see smoother looking floaty bars coming very soon to an iPhone near you. This is just the first in a series of improvements we're planning for the mobile Gmail floaty bar. Watch for them in our iterative webapp, rolling out over the next couple of weeks and months!



Previous posts from Gmail for Mobile HTML5 Series:
HTML5 and Webkit pave the way for mobile web applications
Using AppCache to launch offline - Part 1
Using AppCache to launch offline - Part 2
Using AppCache to launch offline - Part 3
A Common API for Web Storage
Suggestions for better performance
Cache pattern for offline HTML5 web application
Using timers effectively
Autogrowing Textareas
Reducing Startup Latency
2013, By: Seo Master

seo Gmail for Mobile HTML5 Series: Reducing Startup Latency 2013

Seo Master present to you: On April 7th, Google launched a new version of Gmail for mobile for iPhone and Android-powered devices. We shared the behind-the-scenes story through this blog and decided to share more of what we've learned in a brief series of follow-up blog posts. This week, I'll talk about how modularization can be used to greatly reduce the startup latency of a web app.

To a user, the startup latency of an HTML 5 based application is critical. It is their first impression of the application's performance. If it's really slow, they might not even bother to wait for the app to load before navigating away. Even if your application is blazing fast after it loads, the user may never get the chance to experience it.

There are several aspects of an HTML 5 based application that contribute to startup latency:
  1. Network time to fetch the application (JavaScript + HTML)
  2. JavaScript parse time
  3. Code execution time to fetch the data and render the home page of your application
The third issue is up to you! The first two issues, however, are directly correlated with the size of the application. This is a tricky problem since as your application matures, it will have more features and the code size will get bigger. So, what to do? Modularize your application! Split up your code into independent, standalone modules. Consider splitting each view/screen of your application and implement each new feature as its own module. This is only half the story. Now that you have your code modularized, you need to decide which subset of these modules are critical to load your application's home page. All the non-core modules should be downloaded and parsed at a later time. With a consistent code size for your startup code, you can maintain a consistent startup time. Now, let's go into some nitty gritty details of how we built an application with lazy-loaded modules.

How to Split Your Code into Modules

Splitting an application into individual modules might not be as simple as you think. Code that serves a common purpose/functionality should be grouped together and form a module (comparable to a library). As mentioned earlier, we selected which modules are critical to the home page of the app and which modules can be lazy-loaded at a later time. Let's use a Weather application as an example:

High Level Functionality:
  • A "Weather in my Favourite Cities" home page
  • Click on a city to view the cities entire week forecast
  • Weather data comes from an external web service
Possible Module Separation:
  • Weather data model
  • Weather web service API
  • Common UI widgets (buttons, toolbars, navigation, etc)
  • Favourite Cities page
  • City Weather Forecast page
Now let's say your users want a "breaking news" feature. No problem: just put the page, the news data API and the data model into a new module.

One thing to keep in mind is the dependency order of your modules. For modules that have many downstream dependencies, it might make sense to include them as part of the core modules.

How to Lazy Load the Modules

Option 1: Script as DOM

This method uses JavaScript to insert SCRIPT tags into the HEAD's DOM.
<script type="text/JavaScript">
  function loadFile(url) {
    var script = document.createElement('SCRIPT');
    script.src = url;
    document.getElementsByTagName('HEAD')[0].appendChild(script);
  }
</script>
Option 2: XmlHttpRequest (XHR)

This method sets up XmlHttpRequests to retrieve the JavaScript . The returned string should be evaluated in the XHR callbacks (using the eval(string) method). This method is a little more complicated but it gives you more control over error handling.
<script type="text/JavaScript">
  function loadFile(url) {
     function callback() {
      if (req.readyState == 4) { // 4 = Loaded
        if (req.status == 200) {
          eval(req.responseText);
        } else {
          // Error
        }
      }
    };
    var req = new XMLHttpRequest();
    req.onreadystatechange = callback;
    req.open("GET", url, true);
    req.send("");
  }
</script>
The next question is, when to lazy load the modules? One strategy is to lazy load the modules in the background once the home page has been loaded. This approach has some drawbacks. First, JavaScript execution in the browser is single threaded. So while you are loading the modules in the background, the rest of your app becomes non-responsive to user actions while the modules load. Second, it's very difficult to decide when, and in what order, to load the modules. What if a user tries to access a feature/page you have yet to lazy load in the background? A better strategy is to associate the loading of a module with a user's action. Typically, user actions are associated with an invocation of an asynchronous function (for example, an onclick handler). This is the perfect time for you to lazy load the module since the code will have to be fetched over the network. If mobile networks are slow, you can adopt a strategy where you prefetch the code of the modules in advance and keep them stored in the javascript heap. Only then parse and load the corresponding module on user action. One word of caution is that you should make sure your prefetching strategy doesn't impact the user's experience - for example, don't prefetch all the modules while you are fetching user data. Remember, dividing up the latency has far better for users than bunching it all together during startup.

For an HTML 5 application that takes advantage of the application cache to reduce startup latency and to serve the application offline, there are a few caveats one should be aware of. Mobile networks have decent bandwidth, but poor round trip latency, so listing each module as a separate resource in the manifest incurs quite a bit of extra startup latency when the application cache is empty. Also, if one of the module resources fails to be downloaded by the application cache (e.g. disconnected from network), additional error handling code needs to be written to handle such a case. Finally, applications today have no control when the application cache decides to download the resources in the manifest (such a feature is not defined in the current specification of the draft standard). Typically, resources are downloaded once the main page is loaded, but that's not an ideal time since that's when the application requests user data.

To work-around these caveats, we found a trick that allows you to bundle all of your modules into a single resource without having to parse any of the JavaScript. Of course, with this strategy, there is greater latency with the initial download of the single resource (since it has all your JavaScript modules), but once the resource is stored in the browser's application cache, this issue becomes much less of a factor.

To combine all modules into a single resource, we wrote each module into a separate script tag and hid the code inside a comment block (/* */). When the resource first loads, none of the code is parsed since it is commented out. To load a module, find the DOM element for the corresponding script tag, strip out the comment block, and eval() the code. If the web app supports XHTML, this trick is even more elegant as the modules can be hidden inside a CDATA tag instead of a script tag. An added bonus is the ability to lazy load your modules synchronously since there's no longer a need to fetch the modules asynchronously over the network.

On an iPhone 2.2 device, 200k of JavaScript held within a block comment adds 240ms during page load, whereas 200k of JavaScript that is parsed during page load added 2600 ms. That's more than a 10x reduction in startup latency by eliminating 200k of unneeded JavaScript during page load! Take a look at the code sample below to see how this is done.
<html>
...
<script id="lazy">
// Make sure you strip out (or replace) comment blocks in your JavaScript first.
/*
JavaScript of lazy module
*/
</script>

<script>
  function lazyLoad() {
    var lazyElement = document.getElementById('lazy');
    var lazyElementBody = lazyElement.innerHTML;
    var jsCode = stripOutCommentBlock(lazyElementBody);
    eval(jsCode);
  }
</script>

<div onclick=lazyLoad()> Lazy Load </div>
</html>
In the future, we hope that the HTML5 standard will allow more control over when the application cache should download resources in the manifest, since using comments to pass along code is not elegant but worked nicely for us. In addition, the snippets of code are not meant to be a reference implementation and one should consider many additional optimizations such as stripping white space and compiling the JavaScript to make its parsing and execution faster. To learn more about web performance, get tips and tricks to improve the speed of your web applications and to download tools, please visit http://code.google.com/speed.

Previous posts from Gmail for Mobile HTML5 Series

HTML5 and Webkit pave the way for mobile web applications
Using AppCache to launch offline - Part 1
Using AppCache to launch offline - Part 2
Using AppCache to launch offline - Part 3
A Common API for Web Storage
Suggestions for better performance
Cache pattern for offline HTML5 web application


2013, By: Seo Master

seo Dreamweaver Tools for Google 2013

Seo Master present to you:

We keep making more services available to mobile users; in addition to Google Mobile Search, you will find that Google News, Google Maps, and more have had a mobile presence for a while. So, we want to make it easy for developers to link to and use these services in mobile web sites. I'm therefore pleased to note that we've collaborated with WebAssist to add new mobile tools to their Dreamweaver Tools for Google plugin. The newly-released version 2.0 of this free tool includes, among other things, one-click access to embedding Google Maps, News, Mobile Search, and Send-to-phone in a page.2013, By: Seo Master

seo Gmail for Mobile HTML5 Series: Autogrowing Textareas 2013

Seo Master present to you: On April 7th, Google launched a new version of Gmail for mobile for iPhone and Android-powered devices. We shared the behind-the-scenes story through this blog and decided to share more of what we've learned in a brief series of follow-up blog posts. This week I'll talk about autogrowing textareas for entering large amounts of text.

When composing a long message in a web app, regardless of whether it's on a desktop or a mobile device, you really want to see as much of your draft as possible and make use of all the available screen space.
One of my biggest gripes are fixed-size textareas that restrict me to only a couple lines of visible text when my screen is actually many times larger than the size of the textarea.

In today's blog post, I'll share a JavaScript solution for textareas that automatically grow (vertically) to the size of the content. They make composing long messages much easier and, for all those iPhone users out there, takes away the need to scroll with the dreaded magnifying glass! We're working on getting this into Gmail for mobile but here it is now as a teaser of things to come.





Measuring the height of the content

The first step is to detect when the content has changed. Some solutions on the net recommend using a timer (see our previous post to find out more about timers) to check if content has changed. However, that approach is not ideal on a mobile device, where both battery life and processor power are limited.

Instead, we will listen for key-up events from the browser. This guarantees that we only measure the textarea when the content has actually changed.

<textarea id="growingTextarea" onkeyup="grow();"></textarea>

The second step is to actually measure the height of the content. There are solutions on the net that recommend keeping a copy of the content in a div and measuring the div to get the height; however, due to memory and processor limitations on a mobile device, those solutions don't scale well when the content gets large (and it's also hard to replicate textarea line wrapping behavior exactly in a div).

Therefore we will make use of the scrollHeight and clientHeight properties. For our purposes, scrollHeight is the height of all the content while clientHeight is the height of the content that's visible in the textarea (for more precise definitions, see scrollHeight and clientHeight)
function grow() {
var textarea = document.getElementById('growingTextarea');
var newHeight = textarea.scrollHeight;
var currentHeight = textarea.clientHeight;

}
One limitation of using scrollHeight and clientHeight is that we aren't able to shrink the textarea when content is deleted. When all the content of a textarea is visible, the scrollHeight is equal to the clientHeight. Therefore we aren't able to detect that our textarea is actually larger than the minimum size required to fit all the content (please do leave a comment if you think of a solution that doesn't require re-rendering the page).

Growing the textarea

To grow the text area, we modify the height CSS property:
if (newHeight > currentHeight) {
textarea.style.height = newHeight + 5 * TEXTAREA_LINE_HEIGHT + 'px';
}
Notice how we only change the height if newHeight > currentHeight. Depending on the browser, changing the height (even if it's to the same value) will cause the page to re-render. On a mobile device, we want to try our best to minimize the number of operations.

Also, we grow the textarea by five lines every time we grow. From a UI perspective, this reduces the amount of jitter when composing a message but, from a performance perspective, this reduces the number of times we need to re-render the page.

(Quick note for developers implementing this for a browser with scrollbars: you might want to modify the CSS overflow property to preventing the scrollbar from appearing and disappearing as you grow your textarea)

The complete solution

Growing textareas are easy to implement and they make composing long messages infinitely more usable. So go out there add it to all your web apps!
<script>
// Value of the line-height CSS property for the textarea.
var TEXTAREA_LINE_HEIGHT = 13;

function grow() {
var textarea = document.getElementById('growingTextarea');
var newHeight = textarea.scrollHeight;
var currentHeight = textarea.clientHeight;

if (newHeight > currentHeight) {
textarea.style.height = newHeight + 5 * TEXTAREA_LINE_HEIGHT + 'px';
}
}
</script>
<textarea id="growingTextarea"
onkeyup="grow();">
</textarea>

Previous posts from Gmail for Mobile HTML5 Series
Using timers effectively

2013, By: Seo Master

seo QR Codes now available on the Google Chart API 2013

Seo Master present to you:

You can easily render 2D bar codes, known as QR Codes, with the Google Chart API, along with pie charts and bar graphs. If you haven't seen a QR Code before, you are looking at one on the right hand side (To see more, do an image search for "QR Code".)

QR Codes are a popular type of two-dimensional barcode. You can encode URLs, contact information, etc. into a black-and-white image like the one on the right. A QR-Code-enabled device can later scan the image and read back the original text. Learn more about QR Codes from Google Print Ads. If you don't have a reader Google also offers a QR Code decoder library: Zebra Crossing (ZXing).

This is how you can creating these with the Google Chart API:

Simply, there is a new chart type, qr, with attributes to tell the service what to produce:
cht=qr
chl=<text>
choe=<output>
<text> is text for the QR code. This must be url-encoded in UTF8. Note the space between hello and world is written as %20 in the following example.
<output> optionally specifies how the text is encoded into bytes in the QR Code. If this is not specified the default of UTF-8 is used. Available options are: Shift_JIS, UTF-8, or ISO-8859-1.

For the details, please read the full documentation.2013, By: Seo Master

from web contents: Introducing Page Speed Online, with mobile support 2013

salam every one, this is a topic from google web master centrale blog: Webmaster level: intermediate

At Google, we’re striving to make the whole web fast. As part of that effort, we’re launching a new web-based tool in Google Labs, Page Speed Online, which analyzes the performance of web pages and gives specific suggestions for making them faster. Page Speed Online is available from any browser, at any time. This allows website owners to get immediate access to Page Speed performance suggestions so they can make their pages faster.

In addition, we’ve added a new feature: the ability to get Page Speed suggestions customized for the mobile version of a page, specifically smartphones. Due to the relatively limited CPU capabilities of mobile devices, the high round-trip times of mobile networks, and rapid growth of mobile usage, understanding and optimizing for mobile performance is even more critical than for the desktop, so Page Speed Online now allows you to easily analyze and optimize your site for mobile performance. The mobile recommendations are tuned for the unique characteristics of mobile devices, and contain several best practices that go beyond the recommendations for desktop browsers, in order to create a faster mobile experience. New mobile-targeted best practices include eliminating uncacheable landing page redirects and reducing the amount of JavaScript parsed during the page load, two common issues that slow down mobile pages today.


Page Speed Online is powered by the same Page Speed SDK that powers the Chrome and Firefox extensions and webpagetest.org.

Please give Page Speed Online a try. We’re eager to hear your feedback on our mailing list and how you’re using it to optimize your site.

this is a topic published in 2013... to get contents for your blog or your forum, just contact me at: devnasser@gmail.com

from web contents: Mo’ better to also detect “mobile” user-agent 2013

salam every one, this is a topic from google web master centrale blog: Webmaster Level: Intermediate to Advanced

Here’s a trending User-Agent detection misstep we hope to help you prevent: While it seems completely reasonable to key off the string “android” in the User-Agent and then redirect users to your mobile version, there’s a small catch... Android tablets were just released! Similar to mobile, the User-Agent on Android tablets also contains “android,” yet tablet users usually prefer the full desktop version over the mobile equivalent. If your site matches “android” and then automatically redirects users, you may be forcing Android tablet users into a sub-optimal experience.

As a solution for mobile sites, our Android engineers recommend to specifically detect “mobile” in the User-Agent string as well as “android.” Let’s run through a few examples.

With a User-Agent like this:
Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13
since there is no “mobile” string, serve this user the desktop version (or a version customized for Android large-screen touch devices). The User-Agent tells us they’re coming from a large-screen device, the XOOM tablet.

On the other hand, this User-Agent:
Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
contains “mobile” and “android,” so serve the web surfer on this Nexus One the mobile experience!

You’ll notice that Android User-Agents have commonalities:


While you may still want to detect “android” in the User-Agent to implement Android-specific features, such as touch-screen optimizations, our main message is: Should your mobile site depends on UA sniffing, please detect the strings “mobile” and “android,” rather than just “android,” in the User-Agent. This helps properly serve both your mobile and tablet visitors.

For questions, please join our Android community in their developer forum.

this is a topic published in 2013... to get contents for your blog or your forum, just contact me at: devnasser@gmail.com

seo Gmail for Mobile HTML5 Series : Cache Pattern For Offline HTML5 Web Applications 2013

Seo Master present to you: On April 7th, Google launched a new version of Gmail for mobile for iPhone and Android-powered devices. We shared the behind-the-scenes story through this blog and decided to share more of our learnings in a brief series of follow-up blog posts. This week, I'll talk about the cache pattern for building offline-capable web applications.

I recently gave a talk (preserved YouTube here) about the cache pattern and the Web Storage Portability Layer (WSPL) at Google I/O. It was exciting getting to give a talk at the Moscone Center as previously I had only ever been one of the audience members. The conference seemed to go by in a blur for me as I was sleep-deprived from getting the WSPL to "just good enough" to actually be released. (And some ofyou have already pointed out that I missed several bugs.) In my talk, I provided a general overview of the cache pattern and this post expands on the handling of hit determination and merging server and local changes.

The cache pattern is a design pattern for building an offline-capable web application. We implemented the cache pattern to make Gmail for Mobile tolerant of flaky wireless connections but the approach is generally applicable. Here's how it works. Consider a typical AJAX application. As shown in the diagram, we have a web application with a local model, view and controllers. The user interacts with theapplication and the controller dispatches XmlHttpRequests (XHRs for short) to the server. The server sends asynchronous requests to the application which it inserts into the model.

As shown in this next diagram, in the cache pattern, we insert a cache between the application and the server. Having done so, many requests that would otherwise require a round-trip to the network.

A software cache like this one shares a great deal conceptually with hardware caches. When designing the cache used in Gmail for mobile, we used this similarity to guide our design. For example, to keep our cache as simple as possible, we implemented a software equivalent to a write-through cache with early forwarding and LRU eviction. The cache pattern in general (and consequently our implementation) has four important data flows as shown in the diagram.

  • Cached content bound for the UI.
  • Changes made to the cache by the user in the UI. These need to be both reliably sent to the server and updated locally in the cache so that reads from the cache for UI updates show the state including user changes.
  • The changes recorded in the cache need to be sent upstream to the server as the network connection is available.
  • Changes made to the server (like email delivery in the case of Gmail) need to be merged into the contents of the cache.
As shown in the diagram we also need a place to actually write the data. We use the WSPL library to write a cache implementation portable across both Gears and HTML5 databases.

To actually implement these four data flows, we need to decide on a hit determination mechanism, a coherency strategy and a refresh approach.

Hit Determination

At its heart, a cache is a mapping from keys to values: the UI invokes the cache with a key and the cache returns the corresponding element. While this sounds pretty simple, there is an additional source of complexity if the application wants to provide the user with summary listings of some subset of all values available from the server. To provide this feature, the cache needs to contain not only "real" data values but additional "index" values that list the keys (and possibly user-visible summaries) for "data" values. For example, in Gmail for mobile, the cache stores conversations as its "real" data values and lists of conversations (such as the Inbox in Gmail for Mobile) as its "index" values. Keys for index values are computed specially to record what subset of the complete index is cached locally. For example, in Gmail for Mobile, while a user's Inbox may contain thousands of conversations, the cache might contain an index entry whose data values lists metadata for only conversations 1000 through 1100. Consequently, Gmail for Mobile's cache extends keys with the cached range so that a request for metadata for conversations 1101 through1110 would be considered a cache miss.

Coherency and Refresh

Perhaps the most complex aspect of the cache implementation is deciding how to get updated content from the server and how to merge server updates with changes made locally. A traditional hardware cache resolves this problem by only letting one processor modify its a cache at a time and have the memory broadcast any changes to all the other caches in the system. This approach cannot work here because the Gmail server can't connect to all of its clients and update their state. Instead, the approach we took for Gmail for Mobile was for the client device regularly poll the server for alterations.

Polling the server for changes such as new email or the archiving of email by the same user from a different device implies a mechanism for merging local changes with server side changes. As mentioned above, Gmail for Mobile is a write-through cache. By keeping all of the modifications to the cache in a separate queue until they have been acknowledged, they can be played back against updates delivered from the server so that the cache contains the merge of changes from the server and the local user. The following diagram shows the basic idea:


The green box in the diagram shows the contents of the cache's write buffer changing over time and the cloud corresponds to the requests in-flight to the server with time advancing from left to right in the diagram. The function names shown in the diagram are from the simplenotes.js
example file in the Web Storage Portability Layer distribution. Here, the user has applied some change [1] and the cache has written it to the write buffer and has then requested new content resulting in query [Q]. The cache prefixes the outstanding actions from the write buffer to the query. Action [1] is marked as needing a resend on some sort of network failure.

Later, the user makes change [2] to the UI which causes the cache to append it to the write buffer in the applyUIChange call. Later still, another query is made and so, the cache sends [1][2][Q] to the server. In the mean time, the user makes yet another change [3]. This is written to the write buffer. Once changes [1] and [2] are acknowledged by the server along with the new cache contents for query [Q], changes [1] and [2] are removed from the write buffer. However, to keep the cache's state reflecting the user's changes, change [3] is applied (again) over top of the result for [Q].

Simplifying the implementation of this reapplication stage is the most important benefit of implementing a write-through cache. By separating the changes from the state, it becomes much easier to reapply the changes to the cache once the server has delivered new content to the cache. As discussed in a previous post, the use of SQL triggers can greatly improve database performance. Whether updating or re-updating, triggers are a great way to make the application of changes to the cache much more efficient.

Cached Content To the UI

The first of the four data flows is delivering content to the UI is reasonably easy: query the cache for the desired content and when the query completes, forward the request to the UI. If you look at the getNoteList_ function from the simplenotes.js example code included in the WSPL distribution, you'll see that the delivering cached content to the UI has the following basic steps:
perform hit determination: deciding if the requested cache contents are actually in the cache.
  • create a database transaction, and while in the transaction
    • query the database for the desired key
    • accumulate the results
  • then outside of the transaction, return the result to the UI.
Changes From The UI

The second flow (applyUiChange) is recording changes made by the user to the write buffer. It has a very similar structure
  • create a database transaction, and while in the transacation
    • write the change to the write buffer
    • wait for a trigger to update the state of the cache.

Updates Bound For The Server

As discussed above, once the changes have been written to the write buffer, they still have to be sent to the server. This happens by prepending them to queries bound for the server. The fetchFromServer from the example is responsible for this. As might be familiar by now, the flow is

  • create a database transaction and while in the transaction
    • query the write buffer for all the entries that need to be sent to the server
    • accumulate the entries
  • then outside the transaction, send the combination of changes and query to the server

Changes From The Server

Finally, we need to merge the changes from the server into the cache as is done in the insertUpdate method from the example. Here the flow is as follows:

  • create a database transaction and while in the transaction
    • update the directory
    • write the new content into the cache
    • touch the changes in the write buffer that need to be re-applied to the cache
    • wait for the trigger to complete its update
  • then, outside of the transaction, send the response to the UI if it was satisfying a cache miss.
That's a brief intro to the cache architecture as found in Gmail for mobile. We're continuing to improve our implementation of this basic architecture to improve both the performance and robustness of Gmail for mobile. Please stay tuned for follow on blog posts.

Previous posts from Gmail for Mobile HTML5 Series
HTML5 and Webkit pave the way for mobile web applications
Using AppCache to launch offline - Part 1
Using AppCache to launch offline - Part 2
Using AppCache to launch offline - Part 3
A Common API for Web Storage
Suggestions for better performance

Robert Kroeger, Software Engineer, Google Mobile Team2013, By: Seo Master
Powered by Blogger.