Friday, December 18, 2009

[Gd] Hello, Stack Overflow!

| More

Android Developers Blog: Hello, Stack Overflow!

Over the past year, an Android presence has been growing on a relatively new technical Q&A web site called Stack Overflow. The site was designed specifically for programmers, with features like syntax highlighting, tagging, user reputation, and community editing. It's attracted a loyal software developer community, and developers continue to express great praise for this new tool. Well, the Android team has been listening...and we agree.

Today, I'm happy to announce that we're working with Stack Overflow to improve developer support, especially for developers new to Android. In essence, the Android tag on Stack Overflow will become an official Android app development Q&A medium. We encourage you to post your beginner-level technical questions there. It's also important to point out that we don't plan to change the android-developers group, so intermediate and expert users should still feel free to post there.

I think that this will be a great new resource for novice Android developers, and our team is really excited to participate in the growth of the Android developer community on Stack Overflow. I hope to see you all there!


[Gd] Back and other hard keys: three stories

| More

Android Developers Blog: Back and other hard keys: three stories

Android 2.0 introduces new behavior and support for handling hard keys such as BACK and MENU, including some special features to support the virtual hard keys that are appearing on recent devices such as Droid.

This article will give you three stories on these changes: from the most simple to the gory details. Pick the one you prefer.

Story 1: Making things easier for developers

If you were to survey the base applications in the Android platform, you would notice a fairly common pattern: add a little bit of magic to intercept the BACK key and do something different. To do this right, the magic needs to look something like this:

public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
// do something on back.
return true;

return super.onKeyDown(keyCode, event);

How to intercept the BACK key in an Activity is also one of the common questions we see developers ask, so as of 2.0 we have a new little API to make this more simple and easier to discover and get right:

public void onBackPressed() {
// do something on back.

If this is all you care about doing, and you're not worried about supporting versions of the platform before 2.0, then you can stop here. Otherwise, read on.

Story 2: Embracing long press

One of the fairly late addition to the Android platform was the use of long press on hard keys to perform alternative actions. In 1.0 this was long press on HOME for the recent apps switcher and long press on CALL for the voice dialer. In 1.1 we introduced long press on SEARCH for voice search, and 1.5 introduced long press on MENU to force the soft keyboard to be displayed as a backwards compatibility feature for applications that were not yet IME-aware.

(As an aside: long press on MENU was only intended for backwards compatibility, and thus has some perhaps surprising behavior in how strongly the soft keyboard stays up when it is used. This is not intended to be a standard way to access the soft keyboards, and all apps written today should have a more standard and visible way to bring up the IME if they need it.)

Unfortunately the evolution of this feature resulted in a less than optimal implementation: all of the long press detection was implemented in the client-side framework's default key handling code, using timed messages. This resulted in a lot of duplication of code and some behavior problems; since the actual event dispatching code had no concept of long presses and all timing for them was done on the main thread of the application, the application could be slow enough to not update within the long press timeout.

In Android 2.0 this all changes, with a real KeyEvent API and callback functions for long presses. These greatly simplify long press handling for applications, and allow them to interact correctly with the framework. For example: you can override Activity.onKeyLongPress() to supply your own action for a long press on one of the hard keys, overriding the default action provided by the framework.

Perhaps most significant for developers is a corresponding change in the semantics of the BACK key. Previously the default key handling executed the action for this key when it was pressed, unlike the other hard keys. In 2.0 the BACK key is now execute on key up. However, for existing apps, the framework will continue to execute the action on key down for compatibility reasons. To enable the new behavior in your app you must set android:targetSdkVersion in your manifest to 5 or greater.

Here is an example of code an Activity subclass can use to implement special actions for a long press and short press of the CALL key:

public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_CALL) {
// a long press of the call key.
// do our work, returning true to consume it. by
// returning true, the framework knows an action has
// been performed on the long press, so will set the
// canceled flag for the following up event.
return true;
return super.onKeyLongPress(keyCode, event);
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_CALL && event.isTracking()
&& !event.isCanceled()) {
// if the call key is being released, AND we are tracking
// it from an initial key down, AND it is not canceled,
// then handle it.
return true;
return super.onKeyUp(keyCode, event);

Note that the above code assumes we are implementing different behavior for a key that is normally processed by the framework. If you want to implement long presses for another key, you will also need to override onKeyDown to have the framework track it:

public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_0) {
// this tells the framework to start tracking for
// a long press and eventual key up. it will only
// do so if this is the first down (not a repeat).
return true;
return super.onKeyDown(keyCode, event);

Story 3: Making a mess with virtual keys

Now we come to the story of our original motivation for all of these changes: support for virtual hard keys, as seen on the Droid and other upcoming devices. Instead of physical buttons, these devices have a touch sensor that extends outside of the visible screen, creating an area for the "hard" keys to live as touch sensitive areas. The low-level input system looks for touches on the screen in this area, and turns these into "virtual" hard key events as appropriate.

To applications these basically look like real hard keys, though the generated events will have a new FLAG_VIRTUAL_HARD_KEY bit set to identify them. Regardless of that flag, in nearly all cases an application can handle these "hard" key events in the same way it has always done for real hard keys.

However, these keys introduce some wrinkles in user interaction. Most important is that the keys exist on the same surface as the rest of the user interface, and they can be easily pressed with the same kind of touches. This can become an issue, for example, when the virtual keys are along the bottom of the screen: a common gesture is to swipe up the screen for scrolling, and it can be very easy to accidentally touch a virtual key at the bottom when doing this.

The solution for this in 2.0 is to introduce a concept of a "canceled" key event. We've already seen this in the previous story, where handling a long press would cancel the following up event. In a similar way, moving from a virtual key press on to the screen will cause the virtual key to be canceled when it goes up.

In fact the previous code already takes care of this — by checking isCanceled() on the key up, canceled virtual keys and long presses will be ignored. There are also individual flags for these two cases, but they should rarely be used by applications and always with the understanding that in the future there may be more reasons for a key event to be canceled.

For existing application, where BACK key compatibility is turned on to execute the action on down, there is still the problem of accidentally detecting a back press when intending to perform a swipe. Though there is no solution for this except to update an application to specify it targets SDK version 5 or later, fortunately the back key is generally positioned on a far side of the virtual key area, so the user is much less likely to accidentally hit it than some of the other keys.

Writing an application that works well on pre-2.0 as well as 2.0 and later versions of the platform is also fairly easy for most common cases. For example, here is code that allows you to handle the back key in an activity correctly on all versions of the platform:

public boolean onKeyDown(int keyCode, KeyEvent event) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ECLAIR
&& keyCode == KeyEvent.KEYCODE_BACK
&& event.getRepeatCount() == 0) {
// Take care of calling this method on earlier versions of
// the platform where it doesn't exist.

return super.onKeyDown(keyCode, event);

public void onBackPressed() {
// This will be called either automatically for you on 2.0
// or later, or by the code above on earlier versions of the
// platform.

For the hard core: correctly dispatching events

One final topic that is worth covering is how to correctly handle events in the raw dispatch functions such as onDispatchEvent() or onPreIme(). These require a little more care, since you can't rely on some of the help the framework provides when it calls the higher-level functions such as onKeyDown(). The code below shows how you can intercept the dispatching of the BACK key such that you correctly execute your action when it is release.

public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {

// Tell the framework to start tracking this event.
getKeyDispatcherState().startTracking(event, this);
return true;

} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (event.isTracking() && !event.isCanceled()) {

return true;

return super.dispatchKeyEvent(event);
} else {
return super.dispatchKeyEvent(event);

The call to getKeyDispatcherState() returns an object that is used to track the current key state in your window. It is generally available on the View class, and an Activity can use any of its views to retrieve the object if needed.


Thursday, December 17, 2009

[Gd] An update on the legacy API deprecation

| More

iGoogle Developer Blog: An update on the legacy API deprecation

Three months ago we announced the deprecation of the legacy gadgets API. Since then we've released a legacy migration guide for converting legacy gadgets to "gadgets.*" by hand, and we're continuing to work on a migration tool to help perform this conversion automatically.

Since the migration tool isn't yet available, we've decided to delay the next step of the migration process, the requirement that all new gadgets be written using gadgets.*, for an indefinite period. So, while we still recommend using the gadgets.* API, as it will save you time later, we're holding off on this requirement. Stay tuned for another update on the migration process, with a link to the migration tool, in early 2010.

Posted by Dan Holevoet, Developer Programs

[Gd] AdWords API v2009 Hack Days

| More

AdWords API Blog: ​AdWords API v2009 Hack Days

​Have you been putting off migrating to v2009? Not sure where to start? Been way too busy? Well it's time to jump start your v2009 development with some in-person help from Google. Join us in San Francisco (January 7th) or New York (January 14th) for a full day of non-stop v2009 hacking.

To keep things interesting throughout the day, we'll do some coding demos of the cool things you can do with v2009 that weren't possible in v13, like asynchronous calls, dynamic ad parameters, and more.

Non-engineers beware! This is a developer-only event, and there will be no content or activities for attendees who don't plan to write code.

Space is very limited, and signups are on a first come, first serve basis. We ask that you limit attendance to two people per company. If you are based in Europe, please don't register yet, as a separate event for you is in the works and will be announced shortly.

More information and the signup form are available here:

- Aaron Karp, AdWords API Team

[Gd] Google Analytics API v2 Python Client Library

| More

Google Code Blog: Google Analytics API v2 Python Client Library

We know it's easier for developers to program in the languages they know. So we updated the Google Analytics API Python Client library with all the new API version 2 features and added reference exampels for both the Account Feed and Data Feed. Now it's easier than ever to automate your analysis workflow using our API.

Taking The Library For a Spin

With the updated library, we thought it would be a great time to highlight the power of the new v2 features. So we created a sample application to do just that. The application uses the new Google Analytics Python client library to retrieve metrics for a series of segments. It then performs some calculations on the data and creates bar charts using the GChartWrapper package, an open source Python wrapper for the Google Charts API. Finally, it uses the Python Imaging Library to add a title and legend, and stitches all the charts together into a single image. We decided to release this application as open source so you can create visualizations with your own data.

Solving Business Problems

With social media all the rage, we wanted to use this new application to help Avinash Kaushik, our Analytics Evangelist, to measure "engagement" on his popular Occam's Razor blog. We also wanted to determine if the time he spends participating in social media sites is valuable and sends new readers to his blog.

First we created segments to pull all the referrals from Facebook and Twitter. Second, we chose five calculations and corresponding metrics to compare the performance of thee two segments. We then compared the segments to each other and, for context, to all the visits to the site as a control.

They say a picture is worth a thousand words, here are the results:

Let's Analyze

Some interesting observations become apparent.
  • Far more visits originate from Twitter (3.6x) when compared to Facebook, perhaps not surprising given Avinash's Twitter followers (~16,120)
  • Visitors from Twitter tend to be new visitors, a good thing, but they view fewer pages and spend significantly less time on the blog.
  • On the other hand Facebook delivers an audience that is loyal. These visitors come back to the site more often and spend a significant time on the blog (compared to Twitter and all other visitors).
The bottom line? Even though social networking sites are all the rage, they actually contribute very little to Avinash's blog. If this blog were a company, it would be wise to ensure the time and effort put into driving traffic from social media is proportionate to the actual volume of traffic and goal conversions from those sites.

Hopefully this example shows how powerful our new features can be.

If you're interested in running this report against your own data, the application is free and open sourced. Additionally, we made it really easy to change the metrics, segments, calculations and all the other visual properties to power your own visualizations. So please download it here and give it a whirl, we would love to hear your feedback.

By Nick Mihailovski, Google Analytics API Team

[Gd] New resources and sample code on

| More

Android Developers Blog: New resources and sample code on

Hey Android developers—if you've visited the online Android SDK documentation recently, you may have noticed a few changes. That's right, there's a new Resources tab, which was designed to take some of the load off the Developer's Guide. We've moved a number of existing resources to the Resources tab, including tutorials, sample code, and FAQs. We've also formalized a few of our most popular developer blog posts into technical articles; watch for more of these to appear in the future.

In addition, we just released a new batch of sample code, available now as a ZIP file download on the samples index page. And we're working on updating the way in which we distribute official sample code; more on that some other time.

New sample screenshots

The new sample code includes:

  • Multiple Resolutions: a simple example showing how to use resource directory qualifiers to support multiple screen configurations and Android SDK versions.
  • Wiktionary and WiktionarySimple: sample applications that illustrate how to create an interactive home screen widget.
  • Contact Manager: an example on using the new ContactsContract interface to query and manipulate a user's various accounts and contact providers.
  • Bluetooth Chat: a fun little demo that allows two users to have a 1 on 1 chat over Bluetooth. It demonstrates how to discover devices, initiate a connection, and transfer data.
  • API Demos > App > Activity > QuickContactsDemo: a demo showing how to use the android.widget.QuickContactsBadge class, new in Android 2.0.
  • API Demos > App > Activity > SetWallpaper: a demo showing how to use the new class to allow users to change the system wallpaper.
  • API Demos > App > Text-To-Speech: a sample using Text-To-Speech (speech synthesis) to make your application talk.
  • NotePad (now with Live Folders): this sample now includes code for creating Live Folders.

We hope these new samples can be a valuable resource for learning some of the newer features in Android 1.6 and 2.0. Let us know in the android-developers Google Group if you have any questions about these new samples or about the new Resources tab.

Thanks for tuning in, and 'til next time, happy coding!


[Gd] Knowing is half the battle

| More

Android Developers Blog: Knowing is half the battle

As a developer, I often wonder which Android platforms my applications should support,especially as the number of Android-powered devices grows. Should my application only focus on the latest version of the platform or should it support older ones as well?

To help with this kind of decision, I am excited to announce the new
device dashboard. It provides information about deployed Android-powered devices that is helpful to developers as they build and update their apps. The dashboard provides the relative distribution of Android platform versions on devices running Android Market.

Android PlatformPercentage of Devices

The above graph shows the relative number of Android devices that have accessed Android Market during the first 14 days of December 2009.

From a developer's perspective, there are a number of interesting points on this graph:

  • At this point, there's little incentive to make sure a new application is
    backward compatible with Android 1.0 and Android 1.1.
  • Close to 30% of the devices are running Android 1.5. To take advantage of this significant install base, you may consider support for Android 1.5.
  • Starting with Android 1.6, devices can have different screen densities & sizes. There are several devices out there that fall in this category, so make sure to adapt your application to support different screen sizes and take advantage of devices with small, low density (e.g QVGA) and normal, high density (e.g. WVGA) screens. Note that Android Market will not list your application on small screen devices unless its manifest explicitly indicates support for "small" screen sizes. Make sure you properly configure the emulator and test your application on different screen sizes before uploading to Market.
  • A new SDK for Android 2.0.1 was released last week. All Android 2.0 devices will be updated to 2.0.1 before the end of the year, so if your application uses features specific to Android 2.0, you are encouraged to update it to take advantage of the latest Android 2.0.1 API instead.

In summary, Android 1.5, 1.6, and 2.0.1 are the 3 versions of the platform that are deployed in volume. Our goal is to provide you with the tools and information to make it easy for you to target specific versions of the platform or all the versions that are deployed in volume.

We plan to update the dashboard regularly to reflect deployment of new Android platforms. We also plan to expand the dashboard to include other information like devices per screen size and so on.


[Gd] Tab-Modality and You

| More

Chromium Blog: Tab-Modality and You

Years ago, I remember watching a webcast of the introduction of the Aqua user interface when Mac OS X Public Beta was first demoed. The part I distinctly remember was realizing the brilliance of sheets. Like many great innovations, they were simple in retrospect and solved a problem you didn't realize you had: the modality problem — the fact that dialog boxes blocked interacting with the whole application even though only one window needed the information that you, as the user, had to provide. I watched in wonder as a save dialog blocked only the one window that needed saving, leaving all the other windows free. Finally, a solution to limit the modality.

Because modality sucks.

Back in 2000, sheets worked well because the smallest unit of user interaction with an application was a window. Soon after, though, things started to change. Web browsers in particular were among the first to start using tabs to put more than one document in a window. This caused a snag. A web page can require modal interaction from the user: picking a file, or supplying a username and password. Yet we don't want to prevent the user from switching to a different tab and continuing to interact with other websites. If the finest-grained modality control we have is per-window, how can we achieve that outcome?

Chromium's current answer comes from combining Cocoa's child window support with sheets to get tab-modal sheets:

While this looks like a normal sheet, you can switch between open tabs while the password request is up. You can't, however, interact with the web page.

The implementation, like all of the code used in Chromium, is open source, and can be found in the Google Toolbox for Mac, a collection of reusable components from the Mac developers at Google. The technical details of the GTMWindowSheetController can be found on the Google Mac blog. The other thing to note is that right now tab-modal sheets are only used for website authentication. The other sheets we use (for file selection, etc) are currently window-modal; we hope to convert them over soon.

The fate of tab modal sheets, however, isn't certain. A way to enforce tab-modal interaction is certainly needed. But is attaching sheets to the tabs the right way to achieve that goal? At the last WWDC, I talked to some graphic designers who were opposed to the idea. "Reusing sheets in a context that isn't window modality will only confuse the user!" On the other hand, my position is that the concept of modality is the same, and the context is similar enough that users will find that sheets help them understand the modality in which they must interact.

So the story isn't over. Tab-modal sheets are our contribution to the ongoing discussion, an experiment to see what works and what doesn't. Together we can work out the best way to help users interact with their computers.

Posted by Avi Drissman, Software Engineer

[Gd] 2 days of ideas, hacks, and pufferfish in Tokyo

| More

Google Wave Developer Blog: 2 days of ideas, hacks, and pufferfish in Tokyo

I am never one to turn down a trip to Japan. Firstly, because a friend of mine has become entirely dependent on a constantly flowing supply of authentic Pocky (a surprisingly addictive chocolate-covered pretzel snack that I once ate for breakfast every day for 2 weeks). Secondly, because the Japanese developer community has a creativity and energy that both infects and inspires me.

I stopped by Japan on my way back to Australia, for 2 days of Google Wave developer events. I arrived on the first night in a strangely alert jet-lagged state to find myself amidst what they called an "Idea-a-thon". This was basically a pre-party for the hackathon the next day, where groups of developers would brainstorm ideas and then present them. I didn't understand much of what they said, but luckily, they sketched out logos and diagrams on sheets of paper. I saw a Wave/Twitter logo, where the "w" was Wave's "w", and a diagram involving a flow between Eclipse and SVN... enough info to get me excited.

After the idea-a-thon, we all headed upstairs to a real party (beer = party, right?), where a mix of developers and journalists gathered to hear the latest about Google Wave. Ando Yasushi started off the night with an introduction of the APIs, and a demo of his own Animal Chess ("Dobutsu Shogi") gadget (which is now near and dear to my heart, as I was actually able to win the game.. that never happens). I then showed off a series of my favorite demos - using Napkin Gadget to collaboratively draw a demon love-child, AJAX Animator to show my flight across the Pacific, and AmazonBot to aid my purchase of an inflatable castle and a pony (childhood dreams never die). Googler Hiroshi Ichikawa demo'd his own extensions - an HTML5 drawing gadget and a Kanjy robot, and then blazed through a wave of Japanese-created games, like Donpachi, Reversi, Tetris, Tictactoe, and yet another Shogi implementaton. After a few more talks and rounds of beer, we headed home to rest up for a full day of hacking the next day (well, that would have been the plan, if I hadn't sold my soul to the jet lag devil).

Bright and early, at 10am, I kicked off the hackathon with several debugging tips, and presented "Making Wave-y Extensions", a talk about how to make gadgets and robots that take full advantage of the collaborative & real-time experience of Google Wave. For the next 8 hours, the developers dilligently worked together to make their idea come to life, each group huddled around a 30inch monitor.

Finally, my favorite part: demos! The first team showed "Weclipse", a plugin for Eclipse that embedded the Google Wave client as a tab in the IDE, with the hope of making coding more social. In that embedded wave, they also showed a robot that received messages from an Android and posted them as blips. Then, Maripo Goda, author of the Brainstorming gadget and tDiary plug-in, showed her team's project: an end-to-end message translation system. One of her team members is on the Debian JP project, and wanted an extension to expedite translations for the operating system. The extension starts with a gadget that loads in translation files, lets the participants set the translations, and then it commits them to an SVN repository. There have been multiple translation helper extensions created by international developers over the last few months, but this is the first I've seen that tackles the software message translation problem.

Atsushi Nakamura, who also attended the Tokyo Chrome Extensions hackathon the week before, then demo'd his Chrome+Google Wave hack, a bookmarklet which pops down an embedded Wave - "ChroMemo." I can see that being really useful for storing little notes, a to-do list, or a schedule. Ando Yasushi demoed his own prototype of operational transforms - in JavaScript. Well, that's certainly one way of learning how Wave works. :)

My trip ended with a dinner of traditional "Fugu" - pufferfish, cooked (and not cooked) in every way possible: sashimi, grilled, boiled, and my favorite: deep fried. I learnt over dinner that a dish of pufferfish can cause instantaneous death, if the internal organs aren't plucked out properly. Well, luckily, my new Japanese friends took me to a properly licensed restaurant, and I'm alive now to tell you about the trip and enjoy my souvenirs - 10 flavors of Pocky and 3 flavors of Mochi.

The Japanese developers are going full speed ahead into Wave development, with another two events planned in the next month: Kyoto GTUG Wave Hackathon, and a Tokyo "Demo Tournament". I'm too bloated on my pocky to make it out there for those events, but I expect to hear about more innovative ideas and exciting extensions coming from my new developer friends in Japan. Until next time, Tokyo!

Posted by Pamela Fox, Developer Relations

Wednesday, December 16, 2009

[Gd] Beta Update: Linux and Windows

| More

Google Chrome Releases: Beta Update: Linux and Windows

The Beta channel has been updated to for Linux, Windows and Mac. It was cut at r34532.

The release includes stability improvements for Linux and Linux, Windows and Mac.


-- Fixed several common crashes

Windows & Linux
-- Fix bug 28795 - Added a notification says "xxx is synched." if you are already synced and click that button.

-- Fixed bug 28061 - Add popup support for page action extensions.

Known issues:
-Mac only: bug 29121 - You'll get an error when checking for updates using the About Google Chrome dialog. 'Update server not available' (error : 12). Regardless of the error message, the update is successful.

Orit Mazor, Google Chrome

[Gd] Introducing Google Browser Size

| More

Google Code Blog: Introducing Google Browser Size

When I started work at Google, I visited the Google Earth team, hoping to find a 20% project on my favorite Google product. There I met Bruno Bowden, who introduced me to a problem I had never thought much about: how to take browser sizes into account when designing a page.

Bruno had noticed that many people who visit the “Download Google Earth” page never actually download, even though, as you can see, the button is pretty hard to miss:

He wondered if a significant number of users might have their browser windows too small to see the button:

To analyze this, Bruno looked at how large people's browser windows were when they visited this page. His first key idea was to measure not the entire browser window, but just the client area -- no toolbars, status bars, or other chrome.

Bruno's second key idea was to render several weeks' worth of page visitor browser sizes in a contour visualization:

Using this visualization, Bruno confirmed that about 10% of users couldn't see the download button without scrolling, and thus never noticed it. 10% may not sound like a lot, but in this context it turns out to mean a significant number of people weren't downloading Google Earth. Using this data, the team was able to redesign the page to good effect.

Bruno and I realized that Web designers might benefit from this information if it could be made more generally available. We constructed a page that could overlay a DIV containing the contour visualization atop an IFRAME containing any other Web page:

This turned out to be a good way to see which controls were and weren't visible at typical browser sizes. The only problem was, the overlay DIV prevented mouse events from getting to the page IFRAME, so it wasn't possible to interact with the page.

To solve this, we split the overlay DIV into four:

Each of the outlines above (red, yellow, blue, green) represents a separate DIV. As the mouse pointer moves, we resize and reposition the DIVs to leave a small window of blank space around the pointer, and adjust background offsets for each DIV to make the overlay look like one seamless graphic. (We originally did this on a timer, but we found a simpler way: when the mouse touches any of the DIVs, resize/reposition all of the DIVs.) End result: a designer can click and otherwise interact with the page with the mouse, and thus interact with the site normally instead of repeatedly typing in URLs.

We are now making this tool available to the public on Google Labs. To try it, simply visit and enter the URL of a page you'd like to examine. The size overlay you see is using latest data from visitors to, so this should give you a pretty good indication of what parts of your UI are generally visible and what aren't.

We look forward to receiving your comments at browser-size-external-feedback!

By Arthur Blume on behalf of the Google Browser Size team

[Gd] Google Chrome Extensions: A quick recap of our first week in beta

| More

Chromium Blog: Google Chrome Extensions: A quick recap of our first week in beta

The seven days since our beta launch have been busy and exciting for the Google Chrome Extensions team.

Besides having fun trying out some of the 800+ new extensions in our gallery, we hosted an event for developers on our Mountain View campus to discuss the design principles of the Google Chrome's extensions system and to present the team's roadmap. Approximately 140 developers attended, representing more than 50 companies. Aaron Boodman and Erik Kay, technical leads for the extensions platform, provided insights across several topics, including the UI design and the security model for the extensions system. They also demonstrated the platform's flexibility by building and publishing an "Email this page" extension in less than 5 minutes.

Aaron and Erik were joined on stage by the Xmarks, eBay and Google Translate teams, who discussed their own experiences with Google Chrome Extensions, highlighting the ease of development and the advanced capabilities that HTML5 provides to extension developers. Finally, Nick Baum, product manager for Google Chrome Extensions, closed the event by walking through the extensions gallery approval process, tips for successful extensions, as well as the team's near-term goals.

To learn more on these topics you can check out the videos from the event below:

We also met many extensions developers last week at Add-on Con, an annual conference for browser add-ons. Erik and Aaron presented a quick overview of the extension system's design for those who had missed our earlier event. In addition, Aaron shared his thoughts on a panel about cross-browser extension development while Linus Upson, Google's engineering lead for client products, presented his views on a panel about the future of the browser.

We'd like to thank developers for building and uploading some great extensions in our gallery and for giving us plenty of feedback. This week, we plan to continue our discussions with the developer community by hosting several online tutorial sessions. You can still sign up for one of these sessions, but if you aren't able to attend, we encourage you to submit your questions through our discussion group.

Posted by Arne Kurrik, Developer Advocate, Google Chrome Extensions

Tuesday, December 15, 2009

[Gd] Handling legitimate cross-domain content duplication

| More

Official Google Webmaster Central Blog: Handling legitimate cross-domain content duplication

Webmaster level: Intermediate

We've recently discussed several ways of handling duplicate content on a single website; today we'll look at ways of handling similar duplication across different websites, across different domains. For some sites, there are legitimate reasons to duplicate content across different websites — for instance, to migrate to a new domain name using a web server that cannot create server-side redirects. To help with issues that arise on such sites, we're announcing our support of the cross-domain rel="canonical" link element.

Ways of handling cross-domain content duplication:
  • Choose your preferred domain
    When confronted with duplicate content, search engines will generally take one version and filter the others out. This can also happen when multiple domain names are involved, so while search engines are generally pretty good at choosing something reasonable, many webmasters prefer to make that decision themselves.
  • Enable crawling and use 301 (permanent) redirects where possible
    Where possible, the most important step is often to use appropriate 301 redirects. These redirects send visitors and search engine crawlers to your preferred domain and make it very clear which URL should be indexed. This is generally the preferred method as it gives clear guidance to everyone who accesses the content. Keep in mind that in order for search engine crawlers to discover these redirects, none of the URLs in the redirect chain can be disallowed via a robots.txt file. Don't forget to handle your www / non-www preference with appropriate redirects and in Webmaster Tools.
  • Use the cross-domain rel="canonical" link element
    There are situations where it's not easily possible to set up redirects. This could be the case when you need to move your website from a server that does not feature server-side redirects. In a situation like this, you can use the rel="canonical" link element across domains to specify the exact URL of whichever domain is preferred for indexing. While the rel="canonical" link element is seen as a hint and not an absolute directive, we do try to follow it where possible.

Still have questions?

Q: Do the pages have to be identical?
A: No, but they should be similar. Slight differences are fine.

Q: For technical reasons I can't include a 1:1 mapping for the URLs on my sites. Can I just point the rel="canonical" at the homepage of my preferred site?
A: No; this could result in problems. A mapping from old URL to new URL for each URL on the old site is the best way to use rel="canonical".

Q: I'm offering my content / product descriptions for syndication. Do my publishers need to use rel="canonical"?
A: We leave this up to you and your publishers. If the content is similar enough, it might make sense to use rel="canonical", if both parties agree.

Q: My server can't do a 301 (permanent) redirect. Can I use rel="canonical" to move my site?
A: If it's at all possible, you should work with your webhost or web server to do a 301 redirect. Keep in mind that we treat rel="canonical" as a hint, and other search engines may handle it differently. But if a 301 redirect is impossible for some reason, then a rel="canonical" may work for you. For more information, see our guidelines on moving your site.

Q: Should I use a noindex robots meta tag on pages with a rel="canonical" link element?
A: No, since those pages would not be equivalent with regards to indexing - one would be allowed while the other would be blocked. Additionally, it's important that these pages are not disallowed from crawling through a robots.txt file, otherwise search engine crawlers will not be able to discover the rel="canonical" link element.

We hope this makes it easier for you to handle duplicate content in a user-friendly way. Are there still places where you feel that duplicate content is causing your sites problems? Let us know in the Webmaster Help Forum!

Posted by John Mueller, Webmaster Trends Analyst, Google Z├╝rich

[Gd] Security in Depth: The Extension System

| More

Chromium Blog: Security in Depth: The Extension System

In our earliest discussions about the extension system, we knew we wanted to raise the bar for security, but how can we secure the platform while still letting developers create awesome extensions that have rich interactions with web pages? During our threat analysis, we realized there were two main security concerns: malicious extensions and "benign-but-buggy" extensions.

A malicious extension is an extension written by an ill-intentioned developer. For example, a malicious extension might record your passwords and send them to back to a central server. The tricky part about defending against malicious extensions is that there are well-intentioned extensions that do exactly the same thing. Our defenses against malicious extensions focus on helping the user avoid installing malicious extensions in the first place:
  1. We expect most users to install extensions from the gallery, where each extension has a reputation. We expect malicious extensions will have a low reputation and will have difficulty attracting many users. If a malicious extension is discovered in the gallery, we will remove it from the gallery.

  2. When installing extensions outside the gallery, the user experience for installing an extension is very similar to the experience for running a native executable. If an attacker can trick the user into installing a malicious extension, the attacker might as well trick the user into running a malicious executable. In this way, the extension system avoids increasing the attack surface.
To help protect against vulnerabilities in benign-but-buggy extensions, we employ the time-tested principles of least privilege and privilege separation. Each extension declares the privileges it needs in its manifest. If the extension is later compromised, the attacker will be limited to those privileges. For example, the Gmail Checker extension declares that it wishes to interact with Gmail. If the extension is somehow compromised, the attacker will not be granted the privilege to access your bank.

To achieve privilege separation, each extension is divided into two pieces, a background page and content scripts. The background page has the lion's share of the extensions privileges but is isolated from direct contact with web pages. Content scripts can interact directly with web pages but are granted few additional privileges. Of course, the two can communicate, but dividing extensions into these components means a vulnerability in a content script does not necessarily leak all the extension's privileges to the attacker.

Finally, we utilize our multi-process architecture and sandboxing technology to provide strong isolation between web content, extensions, and the browser. Extensions run in a separate operating system process from the browser kernel and from web content, helping prevent malicious web sites from compromising extensions and malicious extensions from compromising the browser kernel. To facilitate rich interaction, content scripts run in-process with web content, but we run content scripts in an "isolated world" where they are protected from the page's JavaScript.

Of course, attackers will write malicious extensions and well-intentioned developers will write buggy extensions. The extension system improves security by making it easier for developers to write secure extensions. If you would like to learn more about the security of the extension system, you can watch our video or read our academic paper describing all the details.

Posted by Adam Barth, Software Engineer

Monday, December 14, 2009

[Gd] App Engine SDK 1.3.0 Released Including Support for Larger User Uploads

| More

Google App Engine Blog: App Engine SDK 1.3.0 Released Including Support for Larger User Uploads

Today, we've very excited to release version 1.3.0 of the App Engine SDK, now available to both Java and Python developers. The newest SDK includes a new experimental Blobstore API for storage of files up to 50MB.

Store and Serve - Files can be uploaded and stored as blobs, to be served later in response to user requests. Developers can build their own organizational structures and access controls on top of blobs.

Pricing and Quotas - We include blob storage and transfer under the same datastore pricing and quotas you're already familiar with. For more information, see the App Engine quotas page.

The new Blobstore API is now available in both App Engine SDKs for local development. At this time it can only be used by applications that have enabled billing. There's a lot more information about the API and how it works in the Blobstore documentation (Python, Java) so please check that out and post any questions to the groups.

This release also includes some performance tweaks to the Java runtime. For example, we've sped up many reflective operations by up to 10x resulting in improvements on the order of 10% for applications based on dynamic languages. As always, there are a few other minor changes and bug fixes in this release, so make sure to read our release notes (Python, Java).

Posted by the App Engine Team

[Gd] New Google Analytics API Features

| More

Google Code Blog: New Google Analytics API Features

Over the past few months we've received a lot of great feedback from our developers about what they wanted to see in the Google Analytics API. Today we're excited to announce new powerful and flexible features to the Google Analytics Data Export API including:

Support for Advanced Segments

With advanced segmentation, you can look beyond the totals and into the nuances of the data for your site. For example, the average time on site for all visits could be 60 seconds, but when you segment by country, you might learn that average time on site of visits from Poland is over 2 minutes.

So we've added two new ways to use advanced segments through the API:
  1. Create them on the fly by specifying their expression directly through an API query.
  2. Use advanced segments created in the Google Analytics web interface through the API.
This video describes exactly what advanced segments do and how you can use them with the API.

Goal 5-20 and Configuration Data

With the recent Google Analytics v4 launch enabling up to 20 goals, many of you asked for access to this valuable data, and we listened. Now there are 48 new metrics to access goal performance. We've also added all the goal configuration data, including name, type, step names for each profile.

Here's a great video describing the depth of the goal configuration data.

Custom Variables

Custom variables are powerful new ways to describe visitors, visits and pages within Google Analytics. In this new release, we've added 10 new dimensions to access custom variable data. In addition, every custom variable that you've used is now available through the Account Feed.

All the details of this release can be found on our public changelog and public notify group. We've updated all our documentatation at Please continue to give us feedback to improve our product through our public google group.


By Nick Mihailovski on behalf of the Google Analytics API Team

[Gd] New Tech Talks Posted

| More

Chromium Blog: New Tech Talks Posted

I'm excited to announce four new tech talks on the guts of Chromium have been posted to YouTube! These should be especially useful for developers who work on Chromium whether they're fairly new to the project or have been around the block.

We've done tech talks before, but this time we asked Chromium developers what they'd most like to hear about. Once we knew what was most in demand, we found experts on each subject and asked them to make a presentation. The talks were given before a live studio audience of Googlers last Friday with extra attention paid to creating high quality recordings. Now we're excited to make these widely available to all Chromium contributors!

The WebKit API
with Darin Fisher

Darin Fisher talks about the recently upstreamed Chromium WebKit API. The API is a critical step in our path to becoming completely integrated into the WebKit project. Like the other WebKit APIs, ours is a veneer which shields developers (including many of our own) from the internal details of WebKit (named WebCore). Darin talks at a high level about the API, dives into some code examples, and talks about the history and future of the API.

Layout Tests
with Pam Greene

Layout Tests are the tests we inherit from the WebKit project and are a very important part of the Chromium's testing infrastructure. Pam Greene talks about what they are, how to run them, how to debug problems within them, and even touches on how to write your own. She also covers advanced (but easy to use) tools for rebaselining and tracking flakyness. Any Chromium developer that works on WebKit really should check this out!

Painting in Chromium
with Brett Wilson

Because of Chromium's multi-process architecture, painting within Chromium is far from typical. In this talk, Brett Wilson starts from Skia and the WebKit render tree, follows the bits across the process boundaries, and continues all the way to your screen. He also details many of the differences in painting between platforms, how things work in test shell, and interesting corner cases like resizing.

WebKit's Guts
with Eric Seidel

A large percentage of Chromium's code (and part of what makes it so fast) is WebKit. In this talk, Eric Seidel gives us a 30,000 foot view of how WebKit actually renders a page. He starts with how resources are loaded, explains how they're parsed into a DOM tree, and then talks about the various trees involved in rendering. In addition, he touches on many other important topics like hit testing (figuring out what you're hovering over and clicking on). This is a must-see for anyone working on the guts of WebKit.

Also note that all the tech talks are posted to the Chromium developer website.

Posted by Jeremy Orlow, Software Engineer

[Gd] Google Fusion Tables API

| More

Google Code Blog: Google Fusion Tables API

Today I'm excited to announce that Google Fusion Tables is releasing its own API.

What is Fusion Tables? A product launched recently in Google Labs, Fusion Tables is a free service for sharing and visualizing data online. It allows you to upload data, share and mark up your data with collaborators, merge data from multiple tables, and create visualizations like charts and maps.

Do you have data you need to share with other organizations? In Fusion Tables, you can share all or part of a table with other people. Does your data mean more when seen together with other datasets you don't own? By merging your data with other people's shared tables, you can see the whole picture in one place, discuss the data in embedded comments, and mark up the data with your collaborators. Fusion Tables keeps track of who contributed each part of the data and who has permission to edit.

Watch Circle of Blue's video description of how they use Fusion Tables to combine and visualize water data.

Often the real meaning and potential impact of a database can be hidden behind all the raw names and numbers, but a well-chosen visualization can bring the data to life. Fusion Tables has automatic data visualization built in: we've integrated with the Google Maps API and the Google Visualization API so you can view your data in maps, motion charts, and graphs. All of these can be embedded in your webpage, your Google Site, your blog...any Web page you want! The visualizations even update automatically as data is updated or corrected. Embed the visualization once, and the latest version will always be shown automatically.

Let other people help spot outliers and unexpected values in your dataset by linking them directly to data that is filtered, aggregated, and visualized for various angles of examination. Fusion Tables' data discussion features help you gather feedback from your community.

Is your dataset active, always changing? Is it being collected right now on cell phones or websites? With the new Fusion Tables API, you can update and query your dataset in Fusion Tables programmatically, without ever logging in to the Fusion Tables website. The API means you can import data from whatever data source you may have, whether a text file or a full-powered data base. On the more exotic side, imagine you're collecting data via survey software on GPS-enabled cell phones, as the Open Data Kit project is doing. Open Data Kit uses Google App Engine and the Fusion Tables API to instantly map locations of survey results.

Are you a data exhibitionist? Put your data in Fusion Tables and make it available for the world to see! Fusion Tables will maintain your attribution as your data participates in other tables, enforce your choices about sharing and exporting the data, and invite Google Web Search to index the table.

Fusion Tables allows datasets to play together in a safe, collaborative, and privacy-controlled environment. We can't wait to hear about the amazing things you will make happen with Fusion Tables.

By Anno Langen, Jayant Madhavan and Rebecca Shapley, Google Fusion Tables Team

[Gd] Stable update: Crash fixes

| More

Google Chrome Releases: Stable update: Crash fixes

Google Chrome's Stable channel has been updated to version (The Stable channel is still Windows-only.)

This release fixes a couple of browser crashes:
  • r31694 fixes a crash while typing in the omnibox (issue 20511).
  • r32474 fixes a crash while playing mp4 videos with odd sizes, such as 1366x768 (issue 27675).
--Mark Larson, Google Chrome Team


| More

Google Testing Blog:

Google Testing Blog is now live on twitter. Follow us here:

By Patrick Copeland