This is exactly the kind of feedback we are expecting from a beta launch. We have invested a lot of effort into automating compatibility testing for large number of web pages but there is nothing like actual user feedback. We are impressed by the user response to the beta and the quality of bug reports filed. Nothing more motivating than a lot of users waiting for your work. :)
One of the big issues was support for PDF Fast WebView, which is the ability for a webserver to byte serve a PDF document. This allows a client to request specific byte ranges in the file while skipping pages that are not needed. This is supported generically by seekable streams specification in NPAPI, which Google Chrome now implements. This should improve performance with large PDF files or any other content served using Fast WebView.
We had a lot of fun fixing other issues too, and here are the stories behind a couple of them.
YouTube videos stop after six seek attempts:
We received several reports of YouTube videos failing to play. Many reports indicated that this symptom had something to do with using the slider while playing the video. However, we didn't have a reliable scenario to reproduce in this in-house.
Darin Fisher observed that if you move the slider many times, the video stopped playing. Furthermore, he found out that if the slider was moved exactly six times the video would stop playing. This was interesting, because Google Chrome uses a maximum of 6 HTTP connections per host.
A quick check of the 'I/O Status' in about:network revealed that all connections were active. The question then became one of why the existing connections weren't canceled when the slider was moved.
Darin found that the Flash plugin would return an error when we supplied it data while the slider was moved. In this case a browser is supposed to cancel the connection and that's what fixed it.
Google Finance chart dragging:
This report was very interesting, due to the fact that it only occurred on single core machines. Of course, in the end we found out that there wasn't any direct connection between the root cause and single core machines. In Google Chrome plugin windows live in a separate plugin process so a plugin has little or no influence on the browser thread, or so we thought.
After some inspection we found out that when a plugin is receiving mouse input, the browser main thread spins with 100% CPU for sometime. Now, the twist to the story is that since a plugin window is a child of the browser window, thread inputs of the browser and the plugin are attached.
We started looking at the browser message loop more closely. Soon we discovered that MsgWaitForMultipleObjects/PeekMessage APIs behaved strangely when thread inputs are attached. The MsgWaitForMultipleObjects API is typically used to block until an event or a windows message such as an input is available for processing. In this case, we found that it was returning an indication that an input event was available for processing, while PeekMessage indicated no event was available.
This behavior is probably due to the fact that thread inputs are attached and GetQueueStatus, called internally by MsgWaitForMultipleObjects, returned an indication that input is available in the browser thread, while in reality it was intended for the plugin. This caused the MsgWaitForMultipleObjects not do its intended function of waiting, and caused the browser thread to spin.
These are just a few examples of bugfixes we've made to Google Chrome to address performance issues related to plugins. We continue to look closely at the performance of Google Chrome, both as a whole and in relation to interaction with plugins, to make sure that users are getting the best browsing experience that we can deliver.
Posted by Anantanarayanan Iyengar and Amit Joshi, Software Engineers
WebKit is designed to work on multiple operating systems. It abstracts platform-specific functions into the "port," which an embedder application such as Google Chrome implements specifically for their system. This relatively clean abstraction has helped WebKit to be adopted on a wide variety of devices and systems. One of the parts of the port we had to consider when developing Google Chrome was the graphics layer, which is responsible for rendering text, images, and other graphics to the screen.
Which graphics library?
One question that people often ask is, why not use OpenGL or DirectX for accelerated rendering? First, on Windows, we use a sandbox that prevents us from displaying windows from our renderer processes. The image data must be transferred to the main browser process before it can be drawn to the screen, which limits the possible approaches we can take. If the images needs to be read off the video card only to be copied back to the video card in another process, it is usually not worthwhile using accelerated rendering in the first place.
Second, drawing graphics is actually a very small percentage of the time we spend rendering a page. Most of the time is spent in WebKit computing where things will be placed, what styles to apply to them, and using system routines to draw text. Accelerated 3D graphics would not give us enough overall improvement in speed to balance out the extra work and compatibility problems that we would encounter.
If we aren't going to be using OpenGL or DirectX, what about other graphics libraries? We considered a number of options when we first started work on our Windows port of WebKit:
Windows GDI: GDI is the basic, low-level graphics API in Microsoft Windows. It is used to draw buttons, window controls, and dialog boxes for every Windows application, so we know that it's tested and works well. However, it has relatively basic capabilities. Although most web pages can be drawn using only these basic primitives, parts of <canvas> or SVG would need to be implemented separately, either using a different graphics library, or our own custom code.
GDI+: GDI+ is a more advanced graphics API provided on newer versions of Windows. Its API is cleaner and it supports most 2D graphics operations you could think to use. However, we had concerns about GDI+ using device independent metrics, which means that text and letter spacing might look different in Google Chrome than in other Windows applications (which measure and draw text tailored to the screen device). Additionally, at the time we were making the decision, Microsoft was recommending developers use newer graphics APIs in Windows, so we weren't sure how much longer GDI+ would be supported and maintained.
Cairo: Cairo is an open-source 2D graphics library. It is successfully used in Firefox 3, and the Windows port of WebKit at that time already had a partially complete graphics implementation for WebKit. Cairo is also cross-platform, a key advantage over GDI and GDI+ when building a cross-platform browser.
We ended up choosing Skia over these options because it is cross-platform (meaning our work wouldn't have to be duplicated when porting to other systems), because there was already a high-quality WebKit port using it created for Android's browser, and because we had in-house expertise. The latter point is critical because we expected to (and did) need additional features added to the graphics library as well as some bugs fixed.
So far, we've been very happy with our choice. Skia has proved to be effective at handling all the graphics operations we've needed, has been fast enough despite being software-only, and we've gotten great support from the Skia team. Thanks!
System-specific features
Android has the advantage of controlling the entire operating system graphics layer. Skia's font layer implements all text rendering for the Android system, so all text looks consistent. However, we wanted to match the host OS's look and feel. This means using native text rendering routines so that, for example, we can get ClearType on Windows.
To solve this problem, we create a wrapper around Skia's SkDevice (an object representing a low-level drawing surface) which we call PlatformDevice. The object is both a bitmap in main memory that Skia can draw into, and a "Device Independent Bitmap" that the Windows GDI layer can draw into. Lines, images, and patters are all drawn by Skia into this bitmap, while text is drawn directly by Windows. As part of our porting efforts, we are currently working on creating similar abstractions for OS X and Linux.
This notion of "content, not chrome" was the mostly-quiet, sometimes-loud guiding principle behind our design; in combination with our tab-dragging work, it lead us to think of Google Chrome as a lightweight, tabbed window manager for the web. You may have noticed, for example, that Google Chrome doesn't use the traditional "browser titlebar - navigation toolbar - tabstrip" layout common in browsers today; in the Google Chrome world, we think of tabs as the equivalent of titlebars for web pages, and they deserve top-level placement and prominence, and should be the container for everything related to them - title, toolbar and content.
To achieve the streamlined feel we were after, we knew we would have to cut some things, and while we had our own intuitions about what was and wasn't useful in current browsers, we had no idea how those ideas matched to reality. So in typical Google fashion, we turned to data; we ran long studies of the browsing habits of thousands of volunteers, compiled giant charts of what features people did and didn't use, argued over and incorporated that data into our designs and prototypes, ran experiments, watched how our test users reacted, listened to their feedback, and then repeated the cycle over and over and over again.
Even the the more subtle parts of our first-level UI were subjected to similarly intense scrutiny - "what shade of blue best suits XP users", "should the tabs start 18 or 19 pixels below the top of the window?", "what's the correct offset between our buttons?". The answers to these questions were debated and tested for our entire development cycle, and we saw that opinions consistently differed greatly depending on whether we had been Windows 3.1, OS7 or even NeXT users and developers.
We realize that browser UI is controversial and that despite our data-driven approach, much of it remains subjective, so we've documented many of the major UI decisions and thought processes behind Google Chrome on our UX Site, we encourage you to read about our work, challenge our assumptions, and let us know how you think things could be improved.
As you may recall, Google Chrome is a multi-process application, with HTML rendering happening in separate processes we call the "renderers," and plugins running in separate "plugin" processes. Our priority is to always keep the browser process, and especially its main thread, running as smoothly as possible. If a plugin or renderer is interfering with the browser process, the user's interaction with all other tabs and plugins, as well as all the other features of Google Chrome, would also be interrupted. The user might even be prevented from terminating the offending sub-process, negating a key benefit of our multi-process architecture.
The first and most obvious approach is never to block while waiting for information from a renderer process, in case the renderer process happens to be busy or hung. And although the renderers may sometimes synchronously wait for the browser for some requests, there is not an easy way to express that the browser process should wait for the renderer on Windows. Unfortunately, this doesn't cover all cases.
The basic primitive of Microsoft Windows is the "window," which is much more general than just a top-level window with a title bar. Buttons, toolbars, and text controls are usually expressed as sub-windows of a floating top-level window. Windows in this hierarchy are not restricted to single processes, and early versions of Google Chrome used this feature to implement our cross-process rendering architecture. Each tab contained a sub-window owned by a renderer process. The renderer received input and painted into its child window just like any other. The browser and renderer processes each ran their own message processing for things like painting.
A problem arises for some types of Windows messages. The system will synchronously send them to all windows in a hierarchy, waiting for each window to process the message before sending it to parent or child windows. This introduces an implicit wait in the browser process on the renderer processes. If a renderer is hung and not responding to messages, the browser process will also hang as soon as one of these special messages is received. To solve this problem, we no longer allow the renderers to create any windows. Instead, the renderer paints the web page into an off-screen bitmap and sends it asynchronously to the browser process where it is copied to the screen.
Once we made this change, everything ran great. That is, until we implemented plugins. The NPAPI plugin standard that Google Chrome implements allows plugins to create sub-windows, and for compatibility, we can't avoid it. Sometimes a plugin may hang, or more commonly, block waiting on disk I/O. All the hard work we did to insulate the user interface from I/O latency is occasionally undone by our plugin architecture through this long chain of dependencies. To mitigate this problem, we periodically check plugins for responsiveness. If a plugin is unresponsive for too long, we know that the user-interface of Google Chrome might also be affected, and the user might not even be able to close the page that is hosting the plugin. To allow the user to regain control of the browser, we pop up a dialog that offers to terminate the plugin.
If you are doing something that saturates your hard drive (such as compiling Google Chrome), now you know one of the reasons why the interface may occasionally hang and give the "hung plugin" dialog box. Sometimes you may not even realize that a page has loaded plugins when you get this message. You can terminate the plugin immediately, but most of the time it also works to just wait longer for the plugin's I/O to complete.
To understand our holistic approach to performance in Google Chrome, it helps to know some background. Processing speed per dollar has rapidly increased over the last 40 years, but hard drives, which are based on moving parts, do not improve nearly as fast. As a result, a modern processor can execute millions of instructions in the same time that it takes to read just one byte off disk. We knew that building a fast, responsive browser for modern systems would require extra attention to disk I/O usage.
Developers are ideal testers for I/O performance since the load of compiling a very large application like Google Chrome will bog down even the most powerful system. This soon led us to a rule that the main thread of Google Chrome—the thread that runs the entire user interface—is not allowed to do any I/O. After fixing the obvious cases, we ran a program that thrashes the disk while we profiled common operations in Google Chrome to find latent I/O hotspots. We even ran a test where we removed the privileges of the main thread to read or write to disk, and made sure that nothing stopped working.
We moved the I/O onto a number of background threads which allow the user-interface to proceed asynchronously. We did this for large data sources like cookies, bookmarks, and the cache, and also for a myriad of smaller things. Writing a downloaded file to disk, or getting the icons for files in the download manager? The disk operations are being called from a special background thread. Indexing the contents of pages in history or saving a login password? All from background threads. Even the "Save As" dialog box is run from another thread because it can momentarily hang the application while it populates.
Startup poses a different type of problem. If all the subsystems simultaneously requested their data on startup, even if it was from different threads, the requests would quickly overwhelm the disk. As a result, we delay loading as much data as possible for as long as possible, so the most important work can get done first.
Our startup sequence works like this: First chrome.exe and chrome.dll are loaded. Then the preferences file is loaded (it may affect how things proceed). Then we immediately display the main window. The user now can interact with the UI and feels like Google Chrome has loaded, even though there has been remarkably little work done. Immediately after showing the window, we create the sub-process for rendering the first tab. Only once this process has loaded do subsystems like bookmarks proceed, since any I/O contention would slow down the display of that first tab (this is why you may see things like your bookmarks appear after a slight delay). The cache, cookies, and the Windows networking libraries are not loaded until even later when the first network request is issued.
We carefully monitor startup performance using an automated test that runs for almost every change to the code. This test was created very early in the project, when Google Chrome did almost nothing, and we have always followed a very simple rule: this test can never get any slower. Because it's much easier to address performance problems as they are created than fixing them later, we are quick to fix or revert any regressions. As a result, our very large application starts as fast today as the very lightweight application we started out with.
Our work on I/O performance sometimes complicates the code because so many operations have to be designed to be asynchronous: managing requests on different threads with data that comes in at different times is a lot of extra work. But we think it has been well worth it to help us achieve our goal of making Google Chrome not only the fastest, but the most responsive browser we could build.
In a nutshell, a sandbox is security mechanism used to run an application in a restricted environment. If an attacker is able to exploit the browser in a way that lets him run arbitrary code on the machine, the sandbox would help prevent this code from causing damage to the system. The sandbox would also help prevent this exploit from modifying and even reading your files or any information on the system.
We are very excited to be able to launch Google Chrome with the sandbox enabled on all the platforms we currently support. Even though the sandbox in Google Chrome uses some of the new security features on Windows Vista, it is fully compatible with Windows XP.
What part of chromium is sandboxed?
Google Chrome's multi process architecture allows for a lot of flexibility in the way we do security. The entire HTML rendering and JavaScript execution is isolated to its own class of processes; the renderers. These are the ones that live in the sandbox. We expect to work in the near future with the plug-in vendors to securely sandbox them as well.
How does the sandbox work?
The sandbox uses the security features of Windows extensively; it does not reinvent any security model.
To understand how it works, one needs a basic understanding of the Windows security model. With this model all processes have an access token. This access token is like an ID card, it contains information about the owner of the process, the list of groups that it belongs to and a list of privileges. Each process has its own token, and the system uses it to deny or grant access to resources.
These resources are called securable objects. They are securable because they are associated with an access control list, or security descriptor. It contains the security settings of the object. The list of all the users and groups having access to the resource, and what kind of access they have (read, write, execute, etc) can be found there. Files, registry keys, mutexes, pipes, events, semaphores are examples of securable objects.
The access check is the mechanism by which the system determines whether the security descriptor of an object grants the rights requested to an access token. It is performed every time a process tries to acquire a securable object.
The process access token is almost entirely customizable. It's possible to remove privileges and disable some groups. This is exactly what the sandbox does.
Before launching the renderer process we modify its token to remove all privileges and disable all groups. We then convert the token to a restricted token. A restricted token is like a normal token, but the access checks are performed twice, the first time with the normal information in the token, and the second one using a secondary list of groups. Both access checks have to succeed for the resources to be granted to the process. Google Chrome sets the secondary list of groups to contain only one item, the NULL user. Since this user is never given permissions to any objects, all access checks performed with the access token of the renderer process fail, making this process useless to an attacker.
Of course, not all resources on Windows follow this security model. The keyboard, the mouse, the screen and some user objects, like cursors, icons and windows are examples of resources that don't have security descriptors. There is no access check performed when trying to access them. To prevent the renderer from accessing those, the sandbox uses a combination of Job Objects and alternate desktops. A job object is used to apply some restrictions on a group of processes. Some of the restrictions we apply on the renderer process include accessing windows created outside the job, reading or writing to the clipboard, and exiting Windows. We also used an alternate desktop to prevent the renderer from seeing the screen (screen scrapping) or eavesdropping on the keyboard and mouse (key logging). Alternate desktops are commonly used for security. For example, on Windows, the login screen is on another desktop. It ensures that your password can't be stolen by applications running on your normal desktop.
What are the limitations?
As we said earlier, the sandbox itself is not a new security model; it relies on Windows to achieve its security. Therefore, it is impossible for us to prevent against a flaw in the OS security model itself. In addition, some legacy file systems, like FAT32, used on certain computers and USB keys don't support security descriptors. Files on these devices can't be protected by the sandbox. Finally, some third party vendors mistakenly configure files, registry keys and other objects in a way that bypasses the access check, giving everyone on the machine full access on them. Unfortunately, it's impossible for the sandbox to protect most of these misconfigured resources.
To conclude, it is important to mention that this sandbox was designed to be generic. It is not tied to Google Chrome. It can easily be used by any other projects with a compatible multi-process architecture. You can find more information about the sandbox in the design doc, and we will post here again about the details of our token manipulation and our policy framework to configure the level of security of the sandbox.
We hope you will feel safe browsing the web using Google Chrome, and we are looking forward to your feedback and code contribution!
Communications between Chromium (and Google Chrome) and service providers
Search Suggest: If you type a few letters into the address bar and pause, Google Chrome will send the letters you have typed to your default search provider so it can return a list of suggestions. These suggestions will appear in the drop-down that appears below the address bar. The letters you have typed are only sent if your search provider provides a suggest service. As an example, suppose your search provider is Google and you're located in the United States. If you type "presid" and pause, you might get suggestions like "Search Google for Presidential Polls", "Search Google for Presidents", as well as a suggested website (a page listing the Presidents of the United States on www.whitehouse.gov). Your provider for search suggestions may log these suggest queries. In the case of Google, we log 2% of these suggest queries, and anonymize these logs within approximately 24 hours as described in an earlier blog post.
If you choose to accept a search query suggestion, that query will be sent back to your search provider to return a results page. If you choose to accept a suggested website, the accepted suggestion is not sent back to your search provider unless you've opted-in to stats collection. If you have, Google may collect the suggestion you accepted along with the letters you had typed so far in order to improve the suggest service. If you are in a different part of the world, or are using a different search provider, you may get different suggestions.
If you do not wish this data to be sent to your search provider, you have a number of options. The first is to use incognito mode, in which the suggest feature is automatically disabled. You may still get suggestions from your local history stored on your computer, but no suggest queries are sent to your search provider. You can also turn off search suggestions permanently. Finally, you can change your search provider. If your new search provider supports suggest functionality (such as Yahoo!), suggest queries will be sent to this new provider. If it does not support suggest functionality then suggest queries will not be sent.
Safe Browsing: Safe Browsing is a feature designed to help protect users from phishing and malware. The way Safe Browsing works is that roughly every half hour, an updated list of suspected phishing and malware websites is downloaded from Google and stored locally on your computer. As you browse the web, URLs are checked against these lists that are maintained locally on your computer. If a match against the list is found, a request to Google is sent for more information. This request is formed by taking a 256-bit hash of the URL, and sending the first 32-bits of that hash. To be clear, requests are not sent for each page you visit, and we never send a URL in plain text to Google. More information on how this feature works is available in the Google Chrome help center. This feature can also be disabled, although disabling this feature means that you will not be warned before you visit a suspected phishing website, or a website suspected of downloading and installing malware onto your computer.
Suggestions for Navigation Errors: By default, Chromium (and Google Chrome) offer smarter error messages when you encounter unavailable websites. These error messages automatically generate suggestions for webpages with web addresses similar to the one you're trying to access. This feature involves sending the URL that failed to Google, to obtain suggested alternatives. This feature can be disabled in the options dialog.
Which Google Domain: Shortly after startup, Chromium (and Google Chrome) send a request to Google to determine which localized version of Google to use, e.g. whether to direct queries to google.com, google.de, google.co.uk, or another localized version of Google. This is important because sending queries to the right localized Google domain ensures that you get results that are more relevant. For instance, a user searching for "Football" on google.co.uk would get results for European football ("soccer"), while a search on google.com might favor results on American football. Currently (in Google Chrome version 0.2.149), this request is sent regardless of what your default search engine is set to. This was an oversight, and this information was never used to track users. In Google Chrome 0.3, this request will only be sent if your default search provider is set to Google. This change has already been made in the Chromium source code.
Communications between Google Chrome (but not Chromium) and service providers
Usage Statistics and Crash Reports: This option is opt-in, and is disabled by default. Users can elect to send Google their usage statistics and crash reports. This includes statistics on how often Google Chrome features, such as accepting a suggested query or URL in the address bar, are used. Google Chrome doesn't send other personal information, such as name, email address, or Google account information. This option can be enabled or disabled at any time.
GoogleUpdate: When you install Google Chrome, GoogleUpdate is also installed. GoogleUpdate makes sure that your copy of Google Chrome is kept up to date, so that when updates are released your version is automatically updated without any action required on your part. This is especially important to make sure that users are protected by the latest security fixes that Google releases. As part of these update checks, two unique, randomly generated IDs are sent, along with information such as version number, language, operating system, and other install or update-related details. This information helps us accurately count total users, and is not associated with you or your Google Account. More information is available in the Google Chrome help center. GoogleUpdate cannot be disabled from within Google Chrome. GoogleUpdate is automatically uninstalled on the next update check (typically every few hours) after the last Google product using it is uninstalled. The GoogleUpdate team is working on functionality to allow GoogleUpdate to be uninstalled immediately after the last app using it is uninstalled.
RLZ: When you do a Google search from the Google Chrome address bar, an "RLZ parameter" is included in the URL. It is also sent separately on days when Google Chrome has been used or when certain significant events occur such as a successful installation of Google Chrome. RLZ contains some encoded information, such as where you downloaded Google Chrome and where you got it from. This parameter does not uniquely identify you, nor is it used to target advertising. This information is used to understand the effectiveness of different distribution mechanisms, such as downloads directly from Google vs. other distribution channels. More information is available in the Google Chrome help center. This cannot be disabled so long as your search provider is Google. If your default search provider is not Google, then searches performed using the address bar will go to your default search provider, and will not include this RLZ parameter.
Updates to Google Chrome's privacy policy
In addition to explaining what communications take place between Google Chrome and service providers, we want to let you know that we are updating the Google Chrome privacy policy to reflect a change that we have made to the browser to protect user privacy.
Since the release of Google Chrome, we have modified the way its browsing history works so that the searchable index of pages you visit does not include sites with "https" web addresses. However, thumbnail-sized screenshots of these pages will be captured for local use, such as on the new tab page. The updated version of the privacy policy reflects this change. As before, your browsing history stays on your own computer for your convenience and is not sent back to Google. And remember: You can delete all or part of your browsing history at any time, or you can conduct your browsing in incognito mode, which does not store browsing history.