fingerprint.cc revision 010d83a9304c5a91596085d917d248abff47903a
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Generating a fingerprint consists of two major steps:
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//   (1) Gather all the necessary data.
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//   (2) Write it into a protocol buffer.
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Step (2) is as simple as it sounds -- it's really just a matter of copying
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// data.  Step (1) requires waiting on several asynchronous callbacks, which are
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// managed by the FingerprintDataLoader class.
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "components/autofill/content/browser/risk/fingerprint.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/cpu.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/memory/weak_ptr.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/scoped_observer.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/sys_info.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/timer/timer.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/font_list_async.h"
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/browser/geolocation_provider.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/gpu_data_manager.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/gpu_data_manager_observer.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/plugin_service.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_widget_host.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents.h"
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/common/geoposition.h"
38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/common/webplugininfo.h"
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/config/gpu_info.h"
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebRect.h"
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebScreenInfo.h"
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect.h"
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/screen.h"
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebScreenInfo;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace autofill {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace risk {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int32 kFingerprinterVersion = 1;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Maximum amount of time, in seconds, to wait for loading asynchronous
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// fingerprint data.
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const int kTimeoutSeconds = 4;
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the delta between the local timezone and UTC.
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::TimeDelta GetTimezoneOffset() {
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::Time utc = base::Time::Now();
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time::Exploded local;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  utc.LocalExplode(&local);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::Time::FromUTCExploded(local) - utc;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the concatenation of the operating system name and version, e.g.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// "Mac OS X 10.6.8".
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GetOperatingSystemVersion() {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::SysInfo::OperatingSystemName() + " " +
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::SysInfo::OperatingSystemVersion();
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Adds the list of |fonts| to the |machine|.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AddFontsToFingerprint(const base::ListValue& fonts,
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           Fingerprint::MachineCharacteristics* machine) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (base::ListValue::const_iterator it = fonts.begin();
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != fonts.end(); ++it) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Each item in the list is a two-element list such that the first element
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // is the font family and the second is the font name.
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::ListValue* font_description = NULL;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool success = (*it)->GetAsList(&font_description);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(success);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string font_name;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    success = font_description->GetString(1, &font_name);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(success);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    machine->add_font(font_name);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Adds the list of |plugins| to the |machine|.
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid AddPluginsToFingerprint(const std::vector<content::WebPluginInfo>& plugins,
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             Fingerprint::MachineCharacteristics* machine) {
97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (std::vector<content::WebPluginInfo>::const_iterator it = plugins.begin();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != plugins.end(); ++it) {
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Fingerprint::MachineCharacteristics::Plugin* plugin =
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        machine->add_plugin();
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    plugin->set_name(base::UTF16ToUTF8(it->name));
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    plugin->set_description(base::UTF16ToUTF8(it->desc));
103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    for (std::vector<content::WebPluginMimeType>::const_iterator mime_type =
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             it->mime_types.begin();
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         mime_type != it->mime_types.end(); ++mime_type) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      plugin->add_mime_type(mime_type->mime_type);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    plugin->set_version(base::UTF16ToUTF8(it->version));
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Adds the list of HTTP accept languages to the |machine|.
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AddAcceptLanguagesToFingerprint(
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& accept_languages_str,
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Fingerprint::MachineCharacteristics* machine) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> accept_languages;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SplitString(accept_languages_str, ',', &accept_languages);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<std::string>::const_iterator it = accept_languages.begin();
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != accept_languages.end(); ++it) {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    machine->add_requested_language(*it);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This function writes
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   (a) the number of screens,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   (b) the primary display's screen size,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   (c) the screen's color depth, and
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   (d) the size of the screen unavailable to web page content,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//       i.e. the Taskbar size on Windows
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// into the |machine|.
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AddScreenInfoToFingerprint(const WebScreenInfo& screen_info,
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                Fingerprint::MachineCharacteristics* machine) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(scottmg): NativeScreen maybe wrong. http://crbug.com/133312
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->set_screen_count(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Screen::GetNativeScreen()->GetNumDisplays());
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const gfx::Size screen_size =
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().GetSizeInPixel();
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->mutable_screen_size()->set_width(screen_size.width());
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->mutable_screen_size()->set_height(screen_size.height());
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->set_screen_color_depth(screen_info.depth);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const gfx::Rect screen_rect(screen_info.rect);
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const gfx::Rect available_rect(screen_info.availableRect);
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const gfx::Rect unavailable_rect =
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      gfx::SubtractRects(screen_rect, available_rect);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->mutable_unavailable_screen_size()->set_width(
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unavailable_rect.width());
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->mutable_unavailable_screen_size()->set_height(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unavailable_rect.height());
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Writes info about the machine's CPU into the |machine|.
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AddCpuInfoToFingerprint(Fingerprint::MachineCharacteristics* machine) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::CPU cpu;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->mutable_cpu()->set_vendor_name(cpu.vendor_name());
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->mutable_cpu()->set_brand(cpu.cpu_brand());
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Writes info about the machine's GPU into the |machine|.
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AddGpuInfoToFingerprint(Fingerprint::MachineCharacteristics* machine) {
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const gpu::GPUInfo& gpu_info =
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::GpuDataManager::GetInstance()->GetGPUInfo();
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!gpu_info.finalized)
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Fingerprint::MachineCharacteristics::Graphics* graphics =
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      machine->mutable_graphics_card();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  graphics->set_vendor_id(gpu_info.gpu.vendor_id);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  graphics->set_device_id(gpu_info.gpu.device_id);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  graphics->set_driver_version(gpu_info.driver_version);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  graphics->set_driver_date(gpu_info.driver_date);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Fingerprint::MachineCharacteristics::Graphics::PerformanceStatistics*
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gpu_performance = graphics->mutable_performance_statistics();
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gpu_performance->set_graphics_score(gpu_info.performance_stats.graphics);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gpu_performance->set_gaming_score(gpu_info.performance_stats.gaming);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gpu_performance->set_overall_score(gpu_info.performance_stats.overall);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Waits for geoposition data to be loaded.  Lives on the IO thread.
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class GeopositionLoader {
184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public:
185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |callback_| will be called on the UI thread with the loaded geoposition,
186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // once it is available.
187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  GeopositionLoader(
188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const base::TimeDelta& timeout,
189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const base::Callback<void(const content::Geoposition&)>& callback);
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ~GeopositionLoader() {}
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Methods to communicate with the GeolocationProvider.
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void OnGotGeoposition(const content::Geoposition& geoposition);
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // The callback that will be called once the geoposition is available.
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Will be called on the UI thread.
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const base::Callback<void(const content::Geoposition&)> callback_;
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // The callback used as an "observer" of the GeolocationProvider.
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  content::GeolocationProvider::LocationUpdateCallback geolocation_callback_;
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Timer to enforce a maximum timeout before the |callback_| is called, even
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // if the geoposition has not been loaded.
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::OneShotTimer<GeopositionLoader> timeout_timer_;
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)GeopositionLoader::GeopositionLoader(
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const base::TimeDelta& timeout,
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const base::Callback<void(const content::Geoposition&)>& callback)
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  : callback_(callback) {
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  timeout_timer_.Start(FROM_HERE, timeout,
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                       base::Bind(&GeopositionLoader::OnGotGeoposition,
214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                  base::Unretained(this),
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                  content::Geoposition()));
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  geolocation_callback_ =
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(&GeopositionLoader::OnGotGeoposition, base::Unretained(this));
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  content::GeolocationProvider::GetInstance()->AddLocationUpdateCallback(
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      geolocation_callback_, false);
221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void GeopositionLoader::OnGotGeoposition(
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const content::Geoposition& geoposition) {
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                   base::Bind(callback_, geoposition));
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Unregister as an observer, since this class instance might be destroyed
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // after this callback.  Note: It's important to unregister *after* posting
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // the task above.  Unregistering as an observer can have the side-effect of
231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // modifying the value of |geoposition|.
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool removed =
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      content::GeolocationProvider::GetInstance()->RemoveLocationUpdateCallback(
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          geolocation_callback_);
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(removed);
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  delete this;
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Asynchronously loads the user's current geoposition and calls |callback_| on
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// the UI thread with the loaded geoposition, once it is available. Expected to
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// be called on the IO thread.
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void LoadGeoposition(
244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const base::TimeDelta& timeout,
245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const base::Callback<void(const content::Geoposition&)>& callback) {
246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // The loader is responsible for freeing its own memory.
247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  new GeopositionLoader(timeout, callback);
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Waits for all asynchronous data required for the fingerprint to be loaded,
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// then fills out the fingerprint.
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FingerprintDataLoader : public content::GpuDataManagerObserver {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FingerprintDataLoader(
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      uint64 obfuscated_gaia_id,
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const gfx::Rect& window_bounds,
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const gfx::Rect& content_bounds,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const WebScreenInfo& screen_info,
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& version,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& charset,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& accept_languages,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Time& install_time,
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const std::string& app_locale,
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const std::string& user_agent,
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const base::TimeDelta& timeout,
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Callback<void(scoped_ptr<Fingerprint>)>& callback);
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual ~FingerprintDataLoader() {}
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // content::GpuDataManagerObserver:
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnGpuInfoUpdate() OVERRIDE;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Callbacks for asynchronously loaded data.
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnGotFonts(scoped_ptr<base::ListValue> fonts);
276ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void OnGotPlugins(const std::vector<content::WebPluginInfo>& plugins);
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void OnGotGeoposition(const content::Geoposition& geoposition);
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If all of the asynchronous data has been loaded, calls |callback_| with
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the fingerprint data.
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MaybeFillFingerprint();
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calls |callback_| with the fingerprint data.
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void FillFingerprint();
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The GPU data provider.
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Weak reference because the GpuDataManager class is a singleton.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::GpuDataManager* const gpu_data_manager_;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Ensures that any observer registrations for the GPU data are cleaned up by
2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // the time this object is destroyed.
2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedObserver<content::GpuDataManager, FingerprintDataLoader> gpu_observer_;
2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Data that will be passed on to the next loading phase.  See the comment for
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // GetFingerprint() for a description of these variables.
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const uint64 obfuscated_gaia_id_;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Rect window_bounds_;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Rect content_bounds_;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const WebScreenInfo screen_info_;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string version_;
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string charset_;
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string accept_languages_;
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string app_locale_;
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string user_agent_;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Time install_time_;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Data that will be loaded asynchronously.
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> fonts_;
309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::vector<content::WebPluginInfo> plugins_;
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool waiting_on_plugins_;
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  content::Geoposition geoposition_;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Timer to enforce a maximum timeout before the |callback_| is called, even
314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // if not all asynchronous data has been loaded.
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::OneShotTimer<FingerprintDataLoader> timeout_timer_;
316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // For invalidating asynchronous callbacks that might arrive after |this|
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // instance is destroyed.
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::WeakPtrFactory<FingerprintDataLoader> weak_ptr_factory_;
320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The callback that will be called once all the data is available.
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Callback<void(scoped_ptr<Fingerprint>)> callback_;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FingerprintDataLoader);
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FingerprintDataLoader::FingerprintDataLoader(
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint64 obfuscated_gaia_id,
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& window_bounds,
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& content_bounds,
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const WebScreenInfo& screen_info,
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& version,
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& charset,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& accept_languages,
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Time& install_time,
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& app_locale,
337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& user_agent,
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const base::TimeDelta& timeout,
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Callback<void(scoped_ptr<Fingerprint>)>& callback)
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : gpu_data_manager_(content::GpuDataManager::GetInstance()),
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      gpu_observer_(this),
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      obfuscated_gaia_id_(obfuscated_gaia_id),
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      window_bounds_(window_bounds),
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_bounds_(content_bounds),
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      screen_info_(screen_info),
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      version_(version),
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      charset_(charset),
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      accept_languages_(accept_languages),
349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      app_locale_(app_locale),
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      user_agent_(user_agent),
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      install_time_(install_time),
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      waiting_on_plugins_(true),
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      weak_ptr_factory_(this),
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_(callback) {
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!install_time_.is_null());
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  timeout_timer_.Start(FROM_HERE, timeout,
358d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                       base::Bind(&FingerprintDataLoader::MaybeFillFingerprint,
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                  weak_ptr_factory_.GetWeakPtr()));
360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Load GPU data if needed.
362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (gpu_data_manager_->GpuAccessAllowed(NULL) &&
363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !gpu_data_manager_->IsCompleteGpuInfoAvailable()) {
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    gpu_observer_.Add(gpu_data_manager_);
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gpu_data_manager_->RequestCompleteGpuInfoIfNeeded();
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(ENABLE_PLUGINS)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Load plugin data.
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::PluginService::GetInstance()->GetPlugins(
371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(&FingerprintDataLoader::OnGotPlugins,
372d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  waiting_on_plugins_ = false;
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Load font data.
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::GetFontListAsync(
379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(&FingerprintDataLoader::OnGotFonts,
380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Load geolocation data.
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  content::BrowserThread::PostTask(
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      content::BrowserThread::IO, FROM_HERE,
385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(&LoadGeoposition,
386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 timeout,
387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 base::Bind(&FingerprintDataLoader::OnGotGeoposition,
388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr())));
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FingerprintDataLoader::OnGpuInfoUpdate() {
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!gpu_data_manager_->IsCompleteGpuInfoAvailable())
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gpu_observer_.Remove(gpu_data_manager_);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaybeFillFingerprint();
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FingerprintDataLoader::OnGotFonts(scoped_ptr<base::ListValue> fonts) {
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!fonts_);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fonts_.reset(fonts.release());
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaybeFillFingerprint();
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FingerprintDataLoader::OnGotPlugins(
406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::vector<content::WebPluginInfo>& plugins) {
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(waiting_on_plugins_);
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  waiting_on_plugins_ = false;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  plugins_ = plugins;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MaybeFillFingerprint();
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FingerprintDataLoader::OnGotGeoposition(
41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const content::Geoposition& geoposition) {
41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!geoposition_.Validate());
41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  geoposition_ = geoposition;
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(geoposition_.Validate() ||
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         geoposition_.error_code != content::Geoposition::ERROR_CODE_NONE);
42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MaybeFillFingerprint();
42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FingerprintDataLoader::MaybeFillFingerprint() {
425d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // If all of the data has been loaded, or if the |timeout_timer_| has expired,
426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // fill the fingerprint and clean up.
427d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!timeout_timer_.IsRunning() ||
428effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      ((!gpu_data_manager_->GpuAccessAllowed(NULL) ||
429effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        gpu_data_manager_->IsCompleteGpuInfoAvailable()) &&
430d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)       fonts_ &&
431d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)       !waiting_on_plugins_ &&
432d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)       (geoposition_.Validate() ||
433d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        geoposition_.error_code != content::Geoposition::ERROR_CODE_NONE))) {
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FillFingerprint();
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete this;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FingerprintDataLoader::FillFingerprint() {
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Fingerprint> fingerprint(new Fingerprint);
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Fingerprint::MachineCharacteristics* machine =
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fingerprint->mutable_machine_characteristics();
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->set_operating_system_build(GetOperatingSystemVersion());
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We use the delta between the install time and the Unix epoch, in hours.
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->set_browser_install_time_hours(
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (install_time_ - base::Time::UnixEpoch()).InHours());
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->set_utc_offset_ms(GetTimezoneOffset().InMilliseconds());
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  machine->set_browser_language(app_locale_);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->set_charset(charset_);
451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  machine->set_user_agent(user_agent_);
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->set_ram(base::SysInfo::AmountOfPhysicalMemory());
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  machine->set_browser_build(version_);
45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  machine->set_browser_feature(
45558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      Fingerprint::MachineCharacteristics::FEATURE_REQUEST_AUTOCOMPLETE);
456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (fonts_)
457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    AddFontsToFingerprint(*fonts_, machine);
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddPluginsToFingerprint(plugins_, machine);
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddAcceptLanguagesToFingerprint(accept_languages_, machine);
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddScreenInfoToFingerprint(screen_info_, machine);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddCpuInfoToFingerprint(machine);
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddGpuInfoToFingerprint(machine);
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(isherman): Record the user_and_device_name_hash.
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(isherman): Record the partition size of the hard drives?
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Fingerprint::TransientState* transient_state =
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fingerprint->mutable_transient_state();
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Fingerprint::Dimension* inner_window_size =
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      transient_state->mutable_inner_window_size();
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inner_window_size->set_width(content_bounds_.width());
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inner_window_size->set_height(content_bounds_.height());
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Fingerprint::Dimension* outer_window_size =
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      transient_state->mutable_outer_window_size();
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  outer_window_size->set_width(window_bounds_.width());
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  outer_window_size->set_height(window_bounds_.height());
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(isherman): Record network performance data, which is theoretically
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // available to JS.
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
48190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(isherman): Record more user behavior data.
482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (geoposition_.Validate() &&
483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      geoposition_.error_code == content::Geoposition::ERROR_CODE_NONE) {
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Fingerprint::UserCharacteristics::Location* location =
48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        fingerprint->mutable_user_characteristics()->mutable_location();
48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    location->set_altitude(geoposition_.altitude);
48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    location->set_latitude(geoposition_.latitude);
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    location->set_longitude(geoposition_.longitude);
48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    location->set_accuracy(geoposition_.accuracy);
49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    location->set_time_in_ms(
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        (geoposition_.timestamp - base::Time::UnixEpoch()).InMilliseconds());
49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Fingerprint::Metadata* metadata = fingerprint->mutable_metadata();
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  metadata->set_timestamp_ms(
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds());
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  metadata->set_obfuscated_gaia_id(obfuscated_gaia_id_);
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  metadata->set_fingerprinter_version(kFingerprinterVersion);
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_.Run(fingerprint.Pass());
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace internal {
506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void GetFingerprintInternal(
508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint64 obfuscated_gaia_id,
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const gfx::Rect& window_bounds,
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const gfx::Rect& content_bounds,
511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const blink::WebScreenInfo& screen_info,
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& version,
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& charset,
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& accept_languages,
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::Time& install_time,
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& app_locale,
517a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& user_agent,
518d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const base::TimeDelta& timeout,
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::Callback<void(scoped_ptr<Fingerprint>)>& callback) {
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Begin loading all of the data that we need to load asynchronously.
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This class is responsible for freeing its own memory.
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  new FingerprintDataLoader(obfuscated_gaia_id, window_bounds, content_bounds,
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            screen_info, version, charset, accept_languages,
524a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            install_time, app_locale, user_agent, timeout,
525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            callback);
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace internal
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetFingerprint(
53190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint64 obfuscated_gaia_id,
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& window_bounds,
533010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::WebContents* web_contents,
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& version,
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& charset,
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& accept_languages,
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Time& install_time,
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& app_locale,
539a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& user_agent,
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Callback<void(scoped_ptr<Fingerprint>)>& callback) {
541010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Rect content_bounds = web_contents->GetContainerBounds();
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
543f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blink::WebScreenInfo screen_info;
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::RenderWidgetHostView* host_view =
545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      web_contents->GetRenderWidgetHostView();
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (host_view)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    host_view->GetRenderWidgetHost()->GetWebScreenInfo(&screen_info);
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  internal::GetFingerprintInternal(
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      obfuscated_gaia_id, window_bounds, content_bounds, screen_info, version,
551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      charset, accept_languages, install_time, app_locale, user_agent,
552d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::TimeDelta::FromSeconds(kTimeoutSeconds), callback);
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace risk
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace autofill
557