Home | History | Annotate | Download | only in child
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/child/blink_platform_impl.h"
      6 
      7 #include <math.h>
      8 
      9 #include <vector>
     10 
     11 #include "base/allocator/allocator_extension.h"
     12 #include "base/bind.h"
     13 #include "base/files/file_path.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/memory/singleton.h"
     16 #include "base/message_loop/message_loop.h"
     17 #include "base/metrics/histogram.h"
     18 #include "base/metrics/sparse_histogram.h"
     19 #include "base/metrics/stats_counters.h"
     20 #include "base/process/process_metrics.h"
     21 #include "base/rand_util.h"
     22 #include "base/strings/string_number_conversions.h"
     23 #include "base/strings/string_util.h"
     24 #include "base/strings/utf_string_conversions.h"
     25 #include "base/synchronization/lock.h"
     26 #include "base/synchronization/waitable_event.h"
     27 #include "base/sys_info.h"
     28 #include "base/time/time.h"
     29 #include "content/child/content_child_helpers.h"
     30 #include "content/child/fling_curve_configuration.h"
     31 #include "content/child/web_discardable_memory_impl.h"
     32 #include "content/child/web_socket_stream_handle_impl.h"
     33 #include "content/child/web_url_loader_impl.h"
     34 #include "content/child/websocket_bridge.h"
     35 #include "content/child/webthread_impl.h"
     36 #include "content/child/worker_task_runner.h"
     37 #include "content/public/common/content_client.h"
     38 #include "grit/blink_resources.h"
     39 #include "grit/webkit_resources.h"
     40 #include "grit/webkit_strings.h"
     41 #include "net/base/data_url.h"
     42 #include "net/base/mime_util.h"
     43 #include "net/base/net_errors.h"
     44 #include "third_party/WebKit/public/platform/WebConvertableToTraceFormat.h"
     45 #include "third_party/WebKit/public/platform/WebData.h"
     46 #include "third_party/WebKit/public/platform/WebString.h"
     47 #include "third_party/WebKit/public/platform/WebWaitableEvent.h"
     48 #include "ui/base/layout.h"
     49 
     50 #if defined(OS_ANDROID)
     51 #include "base/android/sys_utils.h"
     52 #include "content/child/fling_animator_impl_android.h"
     53 #endif
     54 
     55 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
     56 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
     57 #endif
     58 
     59 using blink::WebData;
     60 using blink::WebFallbackThemeEngine;
     61 using blink::WebLocalizedString;
     62 using blink::WebString;
     63 using blink::WebSocketStreamHandle;
     64 using blink::WebThemeEngine;
     65 using blink::WebURL;
     66 using blink::WebURLError;
     67 using blink::WebURLLoader;
     68 
     69 namespace content {
     70 
     71 namespace {
     72 
     73 class WebWaitableEventImpl : public blink::WebWaitableEvent {
     74  public:
     75   WebWaitableEventImpl() : impl_(new base::WaitableEvent(false, false)) {}
     76   virtual ~WebWaitableEventImpl() {}
     77 
     78   virtual void wait() { impl_->Wait(); }
     79   virtual void signal() { impl_->Signal(); }
     80 
     81   base::WaitableEvent* impl() {
     82     return impl_.get();
     83   }
     84 
     85  private:
     86   scoped_ptr<base::WaitableEvent> impl_;
     87   DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl);
     88 };
     89 
     90 // A simple class to cache the memory usage for a given amount of time.
     91 class MemoryUsageCache {
     92  public:
     93   // Retrieves the Singleton.
     94   static MemoryUsageCache* GetInstance() {
     95     return Singleton<MemoryUsageCache>::get();
     96   }
     97 
     98   MemoryUsageCache() : memory_value_(0) { Init(); }
     99   ~MemoryUsageCache() {}
    100 
    101   void Init() {
    102     const unsigned int kCacheSeconds = 1;
    103     cache_valid_time_ = base::TimeDelta::FromSeconds(kCacheSeconds);
    104   }
    105 
    106   // Returns true if the cached value is fresh.
    107   // Returns false if the cached value is stale, or if |cached_value| is NULL.
    108   bool IsCachedValueValid(size_t* cached_value) {
    109     base::AutoLock scoped_lock(lock_);
    110     if (!cached_value)
    111       return false;
    112     if (base::Time::Now() - last_updated_time_ > cache_valid_time_)
    113       return false;
    114     *cached_value = memory_value_;
    115     return true;
    116   };
    117 
    118   // Setter for |memory_value_|, refreshes |last_updated_time_|.
    119   void SetMemoryValue(const size_t value) {
    120     base::AutoLock scoped_lock(lock_);
    121     memory_value_ = value;
    122     last_updated_time_ = base::Time::Now();
    123   }
    124 
    125  private:
    126   // The cached memory value.
    127   size_t memory_value_;
    128 
    129   // How long the cached value should remain valid.
    130   base::TimeDelta cache_valid_time_;
    131 
    132   // The last time the cached value was updated.
    133   base::Time last_updated_time_;
    134 
    135   base::Lock lock_;
    136 };
    137 
    138 class ConvertableToTraceFormatWrapper
    139     : public base::debug::ConvertableToTraceFormat {
    140  public:
    141   explicit ConvertableToTraceFormatWrapper(
    142       const blink::WebConvertableToTraceFormat& convertable)
    143       : convertable_(convertable) {}
    144   virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
    145     *out += convertable_.asTraceFormat().utf8();
    146   }
    147 
    148  private:
    149   virtual ~ConvertableToTraceFormatWrapper() {}
    150 
    151   blink::WebConvertableToTraceFormat convertable_;
    152 };
    153 
    154 }  // namespace
    155 
    156 static int ToMessageID(WebLocalizedString::Name name) {
    157   switch (name) {
    158     case WebLocalizedString::AXAMPMFieldText:
    159       return IDS_AX_AM_PM_FIELD_TEXT;
    160     case WebLocalizedString::AXButtonActionVerb:
    161       return IDS_AX_BUTTON_ACTION_VERB;
    162     case WebLocalizedString::AXCheckedCheckBoxActionVerb:
    163       return IDS_AX_CHECKED_CHECK_BOX_ACTION_VERB;
    164     case WebLocalizedString::AXDateTimeFieldEmptyValueText:
    165       return IDS_AX_DATE_TIME_FIELD_EMPTY_VALUE_TEXT;
    166     case WebLocalizedString::AXDayOfMonthFieldText:
    167       return IDS_AX_DAY_OF_MONTH_FIELD_TEXT;
    168     case WebLocalizedString::AXHeadingText:
    169       return IDS_AX_ROLE_HEADING;
    170     case WebLocalizedString::AXHourFieldText:
    171       return IDS_AX_HOUR_FIELD_TEXT;
    172     case WebLocalizedString::AXImageMapText:
    173       return IDS_AX_ROLE_IMAGE_MAP;
    174     case WebLocalizedString::AXLinkActionVerb:
    175       return IDS_AX_LINK_ACTION_VERB;
    176     case WebLocalizedString::AXLinkText:
    177       return IDS_AX_ROLE_LINK;
    178     case WebLocalizedString::AXListMarkerText:
    179       return IDS_AX_ROLE_LIST_MARKER;
    180     case WebLocalizedString::AXMediaDefault:
    181       return IDS_AX_MEDIA_DEFAULT;
    182     case WebLocalizedString::AXMediaAudioElement:
    183       return IDS_AX_MEDIA_AUDIO_ELEMENT;
    184     case WebLocalizedString::AXMediaVideoElement:
    185       return IDS_AX_MEDIA_VIDEO_ELEMENT;
    186     case WebLocalizedString::AXMediaMuteButton:
    187       return IDS_AX_MEDIA_MUTE_BUTTON;
    188     case WebLocalizedString::AXMediaUnMuteButton:
    189       return IDS_AX_MEDIA_UNMUTE_BUTTON;
    190     case WebLocalizedString::AXMediaPlayButton:
    191       return IDS_AX_MEDIA_PLAY_BUTTON;
    192     case WebLocalizedString::AXMediaPauseButton:
    193       return IDS_AX_MEDIA_PAUSE_BUTTON;
    194     case WebLocalizedString::AXMediaSlider:
    195       return IDS_AX_MEDIA_SLIDER;
    196     case WebLocalizedString::AXMediaSliderThumb:
    197       return IDS_AX_MEDIA_SLIDER_THUMB;
    198     case WebLocalizedString::AXMediaCurrentTimeDisplay:
    199       return IDS_AX_MEDIA_CURRENT_TIME_DISPLAY;
    200     case WebLocalizedString::AXMediaTimeRemainingDisplay:
    201       return IDS_AX_MEDIA_TIME_REMAINING_DISPLAY;
    202     case WebLocalizedString::AXMediaStatusDisplay:
    203       return IDS_AX_MEDIA_STATUS_DISPLAY;
    204     case WebLocalizedString::AXMediaEnterFullscreenButton:
    205       return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON;
    206     case WebLocalizedString::AXMediaExitFullscreenButton:
    207       return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON;
    208     case WebLocalizedString::AXMediaShowClosedCaptionsButton:
    209       return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON;
    210     case WebLocalizedString::AXMediaHideClosedCaptionsButton:
    211       return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON;
    212     case WebLocalizedString::AXMediaAudioElementHelp:
    213       return IDS_AX_MEDIA_AUDIO_ELEMENT_HELP;
    214     case WebLocalizedString::AXMediaVideoElementHelp:
    215       return IDS_AX_MEDIA_VIDEO_ELEMENT_HELP;
    216     case WebLocalizedString::AXMediaMuteButtonHelp:
    217       return IDS_AX_MEDIA_MUTE_BUTTON_HELP;
    218     case WebLocalizedString::AXMediaUnMuteButtonHelp:
    219       return IDS_AX_MEDIA_UNMUTE_BUTTON_HELP;
    220     case WebLocalizedString::AXMediaPlayButtonHelp:
    221       return IDS_AX_MEDIA_PLAY_BUTTON_HELP;
    222     case WebLocalizedString::AXMediaPauseButtonHelp:
    223       return IDS_AX_MEDIA_PAUSE_BUTTON_HELP;
    224     case WebLocalizedString::AXMediaSliderHelp:
    225       return IDS_AX_MEDIA_SLIDER_HELP;
    226     case WebLocalizedString::AXMediaSliderThumbHelp:
    227       return IDS_AX_MEDIA_SLIDER_THUMB_HELP;
    228     case WebLocalizedString::AXMediaCurrentTimeDisplayHelp:
    229       return IDS_AX_MEDIA_CURRENT_TIME_DISPLAY_HELP;
    230     case WebLocalizedString::AXMediaTimeRemainingDisplayHelp:
    231       return IDS_AX_MEDIA_TIME_REMAINING_DISPLAY_HELP;
    232     case WebLocalizedString::AXMediaStatusDisplayHelp:
    233       return IDS_AX_MEDIA_STATUS_DISPLAY_HELP;
    234     case WebLocalizedString::AXMediaEnterFullscreenButtonHelp:
    235       return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON_HELP;
    236     case WebLocalizedString::AXMediaExitFullscreenButtonHelp:
    237       return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON_HELP;
    238     case WebLocalizedString::AXMediaShowClosedCaptionsButtonHelp:
    239       return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON_HELP;
    240     case WebLocalizedString::AXMediaHideClosedCaptionsButtonHelp:
    241       return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON_HELP;
    242     case WebLocalizedString::AXMillisecondFieldText:
    243       return IDS_AX_MILLISECOND_FIELD_TEXT;
    244     case WebLocalizedString::AXMinuteFieldText:
    245       return IDS_AX_MINUTE_FIELD_TEXT;
    246     case WebLocalizedString::AXMonthFieldText:
    247       return IDS_AX_MONTH_FIELD_TEXT;
    248     case WebLocalizedString::AXRadioButtonActionVerb:
    249       return IDS_AX_RADIO_BUTTON_ACTION_VERB;
    250     case WebLocalizedString::AXSecondFieldText:
    251       return IDS_AX_SECOND_FIELD_TEXT;
    252     case WebLocalizedString::AXTextFieldActionVerb:
    253       return IDS_AX_TEXT_FIELD_ACTION_VERB;
    254     case WebLocalizedString::AXUncheckedCheckBoxActionVerb:
    255       return IDS_AX_UNCHECKED_CHECK_BOX_ACTION_VERB;
    256     case WebLocalizedString::AXWebAreaText:
    257       return IDS_AX_ROLE_WEB_AREA;
    258     case WebLocalizedString::AXWeekOfYearFieldText:
    259       return IDS_AX_WEEK_OF_YEAR_FIELD_TEXT;
    260     case WebLocalizedString::AXYearFieldText:
    261       return IDS_AX_YEAR_FIELD_TEXT;
    262     case WebLocalizedString::CalendarClear:
    263       return IDS_FORM_CALENDAR_CLEAR;
    264     case WebLocalizedString::CalendarToday:
    265       return IDS_FORM_CALENDAR_TODAY;
    266     case WebLocalizedString::DateFormatDayInMonthLabel:
    267       return IDS_FORM_DATE_FORMAT_DAY_IN_MONTH;
    268     case WebLocalizedString::DateFormatMonthLabel:
    269       return IDS_FORM_DATE_FORMAT_MONTH;
    270     case WebLocalizedString::DateFormatYearLabel:
    271       return IDS_FORM_DATE_FORMAT_YEAR;
    272     case WebLocalizedString::DetailsLabel:
    273       return IDS_DETAILS_WITHOUT_SUMMARY_LABEL;
    274     case WebLocalizedString::FileButtonChooseFileLabel:
    275       return IDS_FORM_FILE_BUTTON_LABEL;
    276     case WebLocalizedString::FileButtonChooseMultipleFilesLabel:
    277       return IDS_FORM_MULTIPLE_FILES_BUTTON_LABEL;
    278     case WebLocalizedString::FileButtonNoFileSelectedLabel:
    279       return IDS_FORM_FILE_NO_FILE_LABEL;
    280     case WebLocalizedString::InputElementAltText:
    281       return IDS_FORM_INPUT_ALT;
    282     case WebLocalizedString::KeygenMenuHighGradeKeySize:
    283       return IDS_KEYGEN_HIGH_GRADE_KEY;
    284     case WebLocalizedString::KeygenMenuMediumGradeKeySize:
    285       return IDS_KEYGEN_MED_GRADE_KEY;
    286     case WebLocalizedString::MissingPluginText:
    287       return IDS_PLUGIN_INITIALIZATION_ERROR;
    288     case WebLocalizedString::MultipleFileUploadText:
    289       return IDS_FORM_FILE_MULTIPLE_UPLOAD;
    290     case WebLocalizedString::OtherColorLabel:
    291       return IDS_FORM_OTHER_COLOR_LABEL;
    292     case WebLocalizedString::OtherDateLabel:
    293         return IDS_FORM_OTHER_DATE_LABEL;
    294     case WebLocalizedString::OtherMonthLabel:
    295       return IDS_FORM_OTHER_MONTH_LABEL;
    296     case WebLocalizedString::OtherTimeLabel:
    297       return IDS_FORM_OTHER_TIME_LABEL;
    298     case WebLocalizedString::OtherWeekLabel:
    299       return IDS_FORM_OTHER_WEEK_LABEL;
    300     case WebLocalizedString::PlaceholderForDayOfMonthField:
    301       return IDS_FORM_PLACEHOLDER_FOR_DAY_OF_MONTH_FIELD;
    302     case WebLocalizedString::PlaceholderForMonthField:
    303       return IDS_FORM_PLACEHOLDER_FOR_MONTH_FIELD;
    304     case WebLocalizedString::PlaceholderForYearField:
    305       return IDS_FORM_PLACEHOLDER_FOR_YEAR_FIELD;
    306     case WebLocalizedString::ResetButtonDefaultLabel:
    307       return IDS_FORM_RESET_LABEL;
    308     case WebLocalizedString::SearchableIndexIntroduction:
    309       return IDS_SEARCHABLE_INDEX_INTRO;
    310     case WebLocalizedString::SearchMenuClearRecentSearchesText:
    311       return IDS_RECENT_SEARCHES_CLEAR;
    312     case WebLocalizedString::SearchMenuNoRecentSearchesText:
    313       return IDS_RECENT_SEARCHES_NONE;
    314     case WebLocalizedString::SearchMenuRecentSearchesText:
    315       return IDS_RECENT_SEARCHES;
    316     case WebLocalizedString::SelectMenuListText:
    317       return IDS_FORM_SELECT_MENU_LIST_TEXT;
    318     case WebLocalizedString::SubmitButtonDefaultLabel:
    319       return IDS_FORM_SUBMIT_LABEL;
    320     case WebLocalizedString::ThisMonthButtonLabel:
    321       return IDS_FORM_THIS_MONTH_LABEL;
    322     case WebLocalizedString::ThisWeekButtonLabel:
    323       return IDS_FORM_THIS_WEEK_LABEL;
    324     case WebLocalizedString::ValidationBadInputForDateTime:
    325       return IDS_FORM_VALIDATION_BAD_INPUT_DATETIME;
    326     case WebLocalizedString::ValidationBadInputForNumber:
    327       return IDS_FORM_VALIDATION_BAD_INPUT_NUMBER;
    328     case WebLocalizedString::ValidationPatternMismatch:
    329       return IDS_FORM_VALIDATION_PATTERN_MISMATCH;
    330     case WebLocalizedString::ValidationRangeOverflow:
    331       return IDS_FORM_VALIDATION_RANGE_OVERFLOW;
    332     case WebLocalizedString::ValidationRangeOverflowDateTime:
    333       return IDS_FORM_VALIDATION_RANGE_OVERFLOW_DATETIME;
    334     case WebLocalizedString::ValidationRangeUnderflow:
    335       return IDS_FORM_VALIDATION_RANGE_UNDERFLOW;
    336     case WebLocalizedString::ValidationRangeUnderflowDateTime:
    337       return IDS_FORM_VALIDATION_RANGE_UNDERFLOW_DATETIME;
    338     case WebLocalizedString::ValidationStepMismatch:
    339       return IDS_FORM_VALIDATION_STEP_MISMATCH;
    340     case WebLocalizedString::ValidationStepMismatchCloseToLimit:
    341       return IDS_FORM_VALIDATION_STEP_MISMATCH_CLOSE_TO_LIMIT;
    342     case WebLocalizedString::ValidationTooLong:
    343       return IDS_FORM_VALIDATION_TOO_LONG;
    344     case WebLocalizedString::ValidationTypeMismatch:
    345       return IDS_FORM_VALIDATION_TYPE_MISMATCH;
    346     case WebLocalizedString::ValidationTypeMismatchForEmail:
    347       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL;
    348     case WebLocalizedString::ValidationTypeMismatchForEmailEmpty:
    349       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY;
    350     case WebLocalizedString::ValidationTypeMismatchForEmailEmptyDomain:
    351       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_DOMAIN;
    352     case WebLocalizedString::ValidationTypeMismatchForEmailEmptyLocal:
    353       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_LOCAL;
    354     case WebLocalizedString::ValidationTypeMismatchForEmailInvalidDomain:
    355       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOMAIN;
    356     case WebLocalizedString::ValidationTypeMismatchForEmailInvalidDots:
    357       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOTS;
    358     case WebLocalizedString::ValidationTypeMismatchForEmailInvalidLocal:
    359       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_LOCAL;
    360     case WebLocalizedString::ValidationTypeMismatchForEmailNoAtSign:
    361       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_NO_AT_SIGN;
    362     case WebLocalizedString::ValidationTypeMismatchForMultipleEmail:
    363       return IDS_FORM_VALIDATION_TYPE_MISMATCH_MULTIPLE_EMAIL;
    364     case WebLocalizedString::ValidationTypeMismatchForURL:
    365       return IDS_FORM_VALIDATION_TYPE_MISMATCH_URL;
    366     case WebLocalizedString::ValidationValueMissing:
    367       return IDS_FORM_VALIDATION_VALUE_MISSING;
    368     case WebLocalizedString::ValidationValueMissingForCheckbox:
    369       return IDS_FORM_VALIDATION_VALUE_MISSING_CHECKBOX;
    370     case WebLocalizedString::ValidationValueMissingForFile:
    371       return IDS_FORM_VALIDATION_VALUE_MISSING_FILE;
    372     case WebLocalizedString::ValidationValueMissingForMultipleFile:
    373       return IDS_FORM_VALIDATION_VALUE_MISSING_MULTIPLE_FILE;
    374     case WebLocalizedString::ValidationValueMissingForRadio:
    375       return IDS_FORM_VALIDATION_VALUE_MISSING_RADIO;
    376     case WebLocalizedString::ValidationValueMissingForSelect:
    377       return IDS_FORM_VALIDATION_VALUE_MISSING_SELECT;
    378     case WebLocalizedString::WeekFormatTemplate:
    379       return IDS_FORM_INPUT_WEEK_TEMPLATE;
    380     case WebLocalizedString::WeekNumberLabel:
    381       return IDS_FORM_WEEK_NUMBER_LABEL;
    382     // This "default:" line exists to avoid compile warnings about enum
    383     // coverage when we add a new symbol to WebLocalizedString.h in WebKit.
    384     // After a planned WebKit patch is landed, we need to add a case statement
    385     // for the added symbol here.
    386     default:
    387       break;
    388   }
    389   return -1;
    390 }
    391 
    392 BlinkPlatformImpl::BlinkPlatformImpl()
    393     : main_loop_(base::MessageLoop::current()),
    394       shared_timer_func_(NULL),
    395       shared_timer_fire_time_(0.0),
    396       shared_timer_fire_time_was_set_while_suspended_(false),
    397       shared_timer_suspended_(0),
    398       fling_curve_configuration_(new FlingCurveConfiguration),
    399       current_thread_slot_(&DestroyCurrentThread) {}
    400 
    401 BlinkPlatformImpl::~BlinkPlatformImpl() {
    402 }
    403 
    404 WebURLLoader* BlinkPlatformImpl::createURLLoader() {
    405   return new WebURLLoaderImpl;
    406 }
    407 
    408 WebSocketStreamHandle* BlinkPlatformImpl::createSocketStreamHandle() {
    409   return new WebSocketStreamHandleImpl;
    410 }
    411 
    412 blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
    413   return new WebSocketBridge;
    414 }
    415 
    416 WebString BlinkPlatformImpl::userAgent() {
    417   return WebString::fromUTF8(GetContentClient()->GetUserAgent());
    418 }
    419 
    420 WebData BlinkPlatformImpl::parseDataURL(const WebURL& url,
    421                                         WebString& mimetype_out,
    422                                         WebString& charset_out) {
    423   std::string mime_type, char_set, data;
    424   if (net::DataURL::Parse(url, &mime_type, &char_set, &data)
    425       && net::IsSupportedMimeType(mime_type)) {
    426     mimetype_out = WebString::fromUTF8(mime_type);
    427     charset_out = WebString::fromUTF8(char_set);
    428     return data;
    429   }
    430   return WebData();
    431 }
    432 
    433 WebURLError BlinkPlatformImpl::cancelledError(
    434     const WebURL& unreachableURL) const {
    435   return WebURLLoaderImpl::CreateError(unreachableURL, false, net::ERR_ABORTED);
    436 }
    437 
    438 blink::WebThread* BlinkPlatformImpl::createThread(const char* name) {
    439   return new WebThreadImpl(name);
    440 }
    441 
    442 blink::WebThread* BlinkPlatformImpl::currentThread() {
    443   WebThreadImplForMessageLoop* thread =
    444       static_cast<WebThreadImplForMessageLoop*>(current_thread_slot_.Get());
    445   if (thread)
    446     return (thread);
    447 
    448   scoped_refptr<base::MessageLoopProxy> message_loop =
    449       base::MessageLoopProxy::current();
    450   if (!message_loop.get())
    451     return NULL;
    452 
    453   thread = new WebThreadImplForMessageLoop(message_loop.get());
    454   current_thread_slot_.Set(thread);
    455   return thread;
    456 }
    457 
    458 blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() {
    459   return new WebWaitableEventImpl();
    460 }
    461 
    462 blink::WebWaitableEvent* BlinkPlatformImpl::waitMultipleEvents(
    463     const blink::WebVector<blink::WebWaitableEvent*>& web_events) {
    464   std::vector<base::WaitableEvent*> events;
    465   for (size_t i = 0; i < web_events.size(); ++i)
    466     events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl());
    467   size_t idx = base::WaitableEvent::WaitMany(
    468       vector_as_array(&events), events.size());
    469   DCHECK_LT(idx, web_events.size());
    470   return web_events[idx];
    471 }
    472 
    473 void BlinkPlatformImpl::decrementStatsCounter(const char* name) {
    474   base::StatsCounter(name).Decrement();
    475 }
    476 
    477 void BlinkPlatformImpl::incrementStatsCounter(const char* name) {
    478   base::StatsCounter(name).Increment();
    479 }
    480 
    481 void BlinkPlatformImpl::histogramCustomCounts(
    482     const char* name, int sample, int min, int max, int bucket_count) {
    483   // Copied from histogram macro, but without the static variable caching
    484   // the histogram because name is dynamic.
    485   base::HistogramBase* counter =
    486       base::Histogram::FactoryGet(name, min, max, bucket_count,
    487           base::HistogramBase::kUmaTargetedHistogramFlag);
    488   DCHECK_EQ(name, counter->histogram_name());
    489   counter->Add(sample);
    490 }
    491 
    492 void BlinkPlatformImpl::histogramEnumeration(
    493     const char* name, int sample, int boundary_value) {
    494   // Copied from histogram macro, but without the static variable caching
    495   // the histogram because name is dynamic.
    496   base::HistogramBase* counter =
    497       base::LinearHistogram::FactoryGet(name, 1, boundary_value,
    498           boundary_value + 1, base::HistogramBase::kUmaTargetedHistogramFlag);
    499   DCHECK_EQ(name, counter->histogram_name());
    500   counter->Add(sample);
    501 }
    502 
    503 void BlinkPlatformImpl::histogramSparse(const char* name, int sample) {
    504   // For sparse histograms, we can use the macro, as it does not incorporate a
    505   // static.
    506   UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample);
    507 }
    508 
    509 const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag(
    510     const char* category_group) {
    511   return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
    512 }
    513 
    514 long* BlinkPlatformImpl::getTraceSamplingState(
    515     const unsigned thread_bucket) {
    516   switch (thread_bucket) {
    517     case 0:
    518       return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(0));
    519     case 1:
    520       return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(1));
    521     case 2:
    522       return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(2));
    523     default:
    524       NOTREACHED() << "Unknown thread bucket type.";
    525   }
    526   return NULL;
    527 }
    528 
    529 COMPILE_ASSERT(
    530     sizeof(blink::Platform::TraceEventHandle) ==
    531         sizeof(base::debug::TraceEventHandle),
    532     TraceEventHandle_types_must_be_same_size);
    533 
    534 blink::Platform::TraceEventHandle BlinkPlatformImpl::addTraceEvent(
    535     char phase,
    536     const unsigned char* category_group_enabled,
    537     const char* name,
    538     unsigned long long id,
    539     int num_args,
    540     const char** arg_names,
    541     const unsigned char* arg_types,
    542     const unsigned long long* arg_values,
    543     unsigned char flags) {
    544   base::debug::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT(
    545       phase, category_group_enabled, name, id,
    546       num_args, arg_names, arg_types, arg_values, NULL, flags);
    547   blink::Platform::TraceEventHandle result;
    548   memcpy(&result, &handle, sizeof(result));
    549   return result;
    550 }
    551 
    552 blink::Platform::TraceEventHandle BlinkPlatformImpl::addTraceEvent(
    553     char phase,
    554     const unsigned char* category_group_enabled,
    555     const char* name,
    556     unsigned long long id,
    557     int num_args,
    558     const char** arg_names,
    559     const unsigned char* arg_types,
    560     const unsigned long long* arg_values,
    561     const blink::WebConvertableToTraceFormat* convertable_values,
    562     unsigned char flags) {
    563   scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_wrappers[2];
    564   if (convertable_values) {
    565     size_t size = std::min(static_cast<size_t>(num_args),
    566                            arraysize(convertable_wrappers));
    567     for (size_t i = 0; i < size; ++i) {
    568       if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
    569         convertable_wrappers[i] =
    570             new ConvertableToTraceFormatWrapper(convertable_values[i]);
    571       }
    572     }
    573   }
    574   base::debug::TraceEventHandle handle =
    575       TRACE_EVENT_API_ADD_TRACE_EVENT(phase,
    576                                       category_group_enabled,
    577                                       name,
    578                                       id,
    579                                       num_args,
    580                                       arg_names,
    581                                       arg_types,
    582                                       arg_values,
    583                                       convertable_wrappers,
    584                                       flags);
    585   blink::Platform::TraceEventHandle result;
    586   memcpy(&result, &handle, sizeof(result));
    587   return result;
    588 }
    589 
    590 void BlinkPlatformImpl::updateTraceEventDuration(
    591     const unsigned char* category_group_enabled,
    592     const char* name,
    593     TraceEventHandle handle) {
    594   base::debug::TraceEventHandle traceEventHandle;
    595   memcpy(&traceEventHandle, &handle, sizeof(handle));
    596   TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
    597       category_group_enabled, name, traceEventHandle);
    598 }
    599 
    600 namespace {
    601 
    602 WebData loadAudioSpatializationResource(const char* name) {
    603 #ifdef IDR_AUDIO_SPATIALIZATION_COMPOSITE
    604   if (!strcmp(name, "Composite")) {
    605     base::StringPiece resource = GetContentClient()->GetDataResource(
    606         IDR_AUDIO_SPATIALIZATION_COMPOSITE, ui::SCALE_FACTOR_NONE);
    607     return WebData(resource.data(), resource.size());
    608   }
    609 #endif
    610 
    611 #ifdef IDR_AUDIO_SPATIALIZATION_T000_P000
    612   const size_t kExpectedSpatializationNameLength = 31;
    613   if (strlen(name) != kExpectedSpatializationNameLength) {
    614     return WebData();
    615   }
    616 
    617   // Extract the azimuth and elevation from the resource name.
    618   int azimuth = 0;
    619   int elevation = 0;
    620   int values_parsed =
    621       sscanf(name, "IRC_Composite_C_R0195_T%3d_P%3d", &azimuth, &elevation);
    622   if (values_parsed != 2) {
    623     return WebData();
    624   }
    625 
    626   // The resource index values go through the elevations first, then azimuths.
    627   const int kAngleSpacing = 15;
    628 
    629   // 0 <= elevation <= 90 (or 315 <= elevation <= 345)
    630   // in increments of 15 degrees.
    631   int elevation_index =
    632       elevation <= 90 ? elevation / kAngleSpacing :
    633       7 + (elevation - 315) / kAngleSpacing;
    634   bool is_elevation_index_good = 0 <= elevation_index && elevation_index < 10;
    635 
    636   // 0 <= azimuth < 360 in increments of 15 degrees.
    637   int azimuth_index = azimuth / kAngleSpacing;
    638   bool is_azimuth_index_good = 0 <= azimuth_index && azimuth_index < 24;
    639 
    640   const int kNumberOfElevations = 10;
    641   const int kNumberOfAudioResources = 240;
    642   int resource_index = kNumberOfElevations * azimuth_index + elevation_index;
    643   bool is_resource_index_good = 0 <= resource_index &&
    644       resource_index < kNumberOfAudioResources;
    645 
    646   if (is_azimuth_index_good && is_elevation_index_good &&
    647       is_resource_index_good) {
    648     const int kFirstAudioResourceIndex = IDR_AUDIO_SPATIALIZATION_T000_P000;
    649     base::StringPiece resource = GetContentClient()->GetDataResource(
    650         kFirstAudioResourceIndex + resource_index, ui::SCALE_FACTOR_NONE);
    651     return WebData(resource.data(), resource.size());
    652   }
    653 #endif  // IDR_AUDIO_SPATIALIZATION_T000_P000
    654 
    655   NOTREACHED();
    656   return WebData();
    657 }
    658 
    659 struct DataResource {
    660   const char* name;
    661   int id;
    662   ui::ScaleFactor scale_factor;
    663 };
    664 
    665 const DataResource kDataResources[] = {
    666   { "missingImage", IDR_BROKENIMAGE, ui::SCALE_FACTOR_100P },
    667   { "missingImage@2x", IDR_BROKENIMAGE, ui::SCALE_FACTOR_200P },
    668   { "mediaplayerPause", IDR_MEDIAPLAYER_PAUSE_BUTTON, ui::SCALE_FACTOR_100P },
    669   { "mediaplayerPauseHover",
    670     IDR_MEDIAPLAYER_PAUSE_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    671   { "mediaplayerPauseDown",
    672     IDR_MEDIAPLAYER_PAUSE_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    673   { "mediaplayerPlay", IDR_MEDIAPLAYER_PLAY_BUTTON, ui::SCALE_FACTOR_100P },
    674   { "mediaplayerPlayHover",
    675     IDR_MEDIAPLAYER_PLAY_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    676   { "mediaplayerPlayDown",
    677     IDR_MEDIAPLAYER_PLAY_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    678   { "mediaplayerPlayDisabled",
    679     IDR_MEDIAPLAYER_PLAY_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
    680   { "mediaplayerSoundLevel3",
    681     IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON, ui::SCALE_FACTOR_100P },
    682   { "mediaplayerSoundLevel3Hover",
    683     IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    684   { "mediaplayerSoundLevel3Down",
    685     IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    686   { "mediaplayerSoundLevel2",
    687     IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON, ui::SCALE_FACTOR_100P },
    688   { "mediaplayerSoundLevel2Hover",
    689     IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    690   { "mediaplayerSoundLevel2Down",
    691     IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    692   { "mediaplayerSoundLevel1",
    693     IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON, ui::SCALE_FACTOR_100P },
    694   { "mediaplayerSoundLevel1Hover",
    695     IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    696   { "mediaplayerSoundLevel1Down",
    697     IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    698   { "mediaplayerSoundLevel0",
    699     IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON, ui::SCALE_FACTOR_100P },
    700   { "mediaplayerSoundLevel0Hover",
    701     IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    702   { "mediaplayerSoundLevel0Down",
    703     IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    704   { "mediaplayerSoundDisabled",
    705     IDR_MEDIAPLAYER_SOUND_DISABLED, ui::SCALE_FACTOR_100P },
    706   { "mediaplayerSliderThumb",
    707     IDR_MEDIAPLAYER_SLIDER_THUMB, ui::SCALE_FACTOR_100P },
    708   { "mediaplayerSliderThumbHover",
    709     IDR_MEDIAPLAYER_SLIDER_THUMB_HOVER, ui::SCALE_FACTOR_100P },
    710   { "mediaplayerSliderThumbDown",
    711     IDR_MEDIAPLAYER_SLIDER_THUMB_DOWN, ui::SCALE_FACTOR_100P },
    712   { "mediaplayerVolumeSliderThumb",
    713     IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB, ui::SCALE_FACTOR_100P },
    714   { "mediaplayerVolumeSliderThumbHover",
    715     IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_HOVER, ui::SCALE_FACTOR_100P },
    716   { "mediaplayerVolumeSliderThumbDown",
    717     IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DOWN, ui::SCALE_FACTOR_100P },
    718   { "mediaplayerVolumeSliderThumbDisabled",
    719     IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DISABLED, ui::SCALE_FACTOR_100P },
    720   { "mediaplayerClosedCaption",
    721     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON, ui::SCALE_FACTOR_100P },
    722   { "mediaplayerClosedCaptionHover",
    723     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    724   { "mediaplayerClosedCaptionDown",
    725     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    726   { "mediaplayerClosedCaptionDisabled",
    727     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
    728   { "mediaplayerFullscreen",
    729     IDR_MEDIAPLAYER_FULLSCREEN_BUTTON, ui::SCALE_FACTOR_100P },
    730   { "mediaplayerFullscreenHover",
    731     IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    732   { "mediaplayerFullscreenDown",
    733     IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    734   { "mediaplayerFullscreenDisabled",
    735     IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
    736   { "mediaplayerOverlayPlay",
    737     IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON, ui::SCALE_FACTOR_100P },
    738 #if defined(OS_MACOSX)
    739   { "overhangPattern", IDR_OVERHANG_PATTERN, ui::SCALE_FACTOR_100P },
    740   { "overhangShadow", IDR_OVERHANG_SHADOW, ui::SCALE_FACTOR_100P },
    741 #endif
    742   { "panIcon", IDR_PAN_SCROLL_ICON, ui::SCALE_FACTOR_100P },
    743   { "searchCancel", IDR_SEARCH_CANCEL, ui::SCALE_FACTOR_100P },
    744   { "searchCancelPressed", IDR_SEARCH_CANCEL_PRESSED, ui::SCALE_FACTOR_100P },
    745   { "searchMagnifier", IDR_SEARCH_MAGNIFIER, ui::SCALE_FACTOR_100P },
    746   { "searchMagnifierResults",
    747     IDR_SEARCH_MAGNIFIER_RESULTS, ui::SCALE_FACTOR_100P },
    748   { "textAreaResizeCorner", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_100P },
    749   { "textAreaResizeCorner@2x", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_200P },
    750   { "generatePassword", IDR_PASSWORD_GENERATION_ICON, ui::SCALE_FACTOR_100P },
    751   { "generatePasswordHover",
    752     IDR_PASSWORD_GENERATION_ICON_HOVER, ui::SCALE_FACTOR_100P },
    753 };
    754 
    755 }  // namespace
    756 
    757 WebData BlinkPlatformImpl::loadResource(const char* name) {
    758   // Some clients will call into this method with an empty |name| when they have
    759   // optional resources.  For example, the PopupMenuChromium code can have icons
    760   // for some Autofill items but not for others.
    761   if (!strlen(name))
    762     return WebData();
    763 
    764   // Check the name prefix to see if it's an audio resource.
    765   if (StartsWithASCII(name, "IRC_Composite", true) ||
    766       StartsWithASCII(name, "Composite", true))
    767     return loadAudioSpatializationResource(name);
    768 
    769   // TODO(flackr): We should use a better than linear search here, a trie would
    770   // be ideal.
    771   for (size_t i = 0; i < arraysize(kDataResources); ++i) {
    772     if (!strcmp(name, kDataResources[i].name)) {
    773       base::StringPiece resource = GetContentClient()->GetDataResource(
    774           kDataResources[i].id, kDataResources[i].scale_factor);
    775       return WebData(resource.data(), resource.size());
    776     }
    777   }
    778 
    779   NOTREACHED() << "Unknown image resource " << name;
    780   return WebData();
    781 }
    782 
    783 WebString BlinkPlatformImpl::queryLocalizedString(
    784     WebLocalizedString::Name name) {
    785   int message_id = ToMessageID(name);
    786   if (message_id < 0)
    787     return WebString();
    788   return GetContentClient()->GetLocalizedString(message_id);
    789 }
    790 
    791 WebString BlinkPlatformImpl::queryLocalizedString(
    792     WebLocalizedString::Name name, int numeric_value) {
    793   return queryLocalizedString(name, base::IntToString16(numeric_value));
    794 }
    795 
    796 WebString BlinkPlatformImpl::queryLocalizedString(
    797     WebLocalizedString::Name name, const WebString& value) {
    798   int message_id = ToMessageID(name);
    799   if (message_id < 0)
    800     return WebString();
    801   return ReplaceStringPlaceholders(GetContentClient()->GetLocalizedString(
    802       message_id), value, NULL);
    803 }
    804 
    805 WebString BlinkPlatformImpl::queryLocalizedString(
    806     WebLocalizedString::Name name,
    807     const WebString& value1,
    808     const WebString& value2) {
    809   int message_id = ToMessageID(name);
    810   if (message_id < 0)
    811     return WebString();
    812   std::vector<base::string16> values;
    813   values.reserve(2);
    814   values.push_back(value1);
    815   values.push_back(value2);
    816   return ReplaceStringPlaceholders(
    817       GetContentClient()->GetLocalizedString(message_id), values, NULL);
    818 }
    819 
    820 double BlinkPlatformImpl::currentTime() {
    821   return base::Time::Now().ToDoubleT();
    822 }
    823 
    824 double BlinkPlatformImpl::monotonicallyIncreasingTime() {
    825   return base::TimeTicks::Now().ToInternalValue() /
    826       static_cast<double>(base::Time::kMicrosecondsPerSecond);
    827 }
    828 
    829 void BlinkPlatformImpl::cryptographicallyRandomValues(
    830     unsigned char* buffer, size_t length) {
    831   base::RandBytes(buffer, length);
    832 }
    833 
    834 void BlinkPlatformImpl::setSharedTimerFiredFunction(void (*func)()) {
    835   shared_timer_func_ = func;
    836 }
    837 
    838 void BlinkPlatformImpl::setSharedTimerFireInterval(
    839     double interval_seconds) {
    840   shared_timer_fire_time_ = interval_seconds + monotonicallyIncreasingTime();
    841   if (shared_timer_suspended_) {
    842     shared_timer_fire_time_was_set_while_suspended_ = true;
    843     return;
    844   }
    845 
    846   // By converting between double and int64 representation, we run the risk
    847   // of losing precision due to rounding errors. Performing computations in
    848   // microseconds reduces this risk somewhat. But there still is the potential
    849   // of us computing a fire time for the timer that is shorter than what we
    850   // need.
    851   // As the event loop will check event deadlines prior to actually firing
    852   // them, there is a risk of needlessly rescheduling events and of
    853   // needlessly looping if sleep times are too short even by small amounts.
    854   // This results in measurable performance degradation unless we use ceil() to
    855   // always round up the sleep times.
    856   int64 interval = static_cast<int64>(
    857       ceil(interval_seconds * base::Time::kMillisecondsPerSecond)
    858       * base::Time::kMicrosecondsPerMillisecond);
    859 
    860   if (interval < 0)
    861     interval = 0;
    862 
    863   shared_timer_.Stop();
    864   shared_timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds(interval),
    865                       this, &BlinkPlatformImpl::DoTimeout);
    866   OnStartSharedTimer(base::TimeDelta::FromMicroseconds(interval));
    867 }
    868 
    869 void BlinkPlatformImpl::stopSharedTimer() {
    870   shared_timer_.Stop();
    871 }
    872 
    873 void BlinkPlatformImpl::callOnMainThread(
    874     void (*func)(void*), void* context) {
    875   main_loop_->PostTask(FROM_HERE, base::Bind(func, context));
    876 }
    877 
    878 blink::WebGestureCurve* BlinkPlatformImpl::createFlingAnimationCurve(
    879     blink::WebGestureDevice device_source,
    880     const blink::WebFloatPoint& velocity,
    881     const blink::WebSize& cumulative_scroll) {
    882 #if defined(OS_ANDROID)
    883   return FlingAnimatorImpl::CreateAndroidGestureCurve(
    884       velocity,
    885       cumulative_scroll);
    886 #endif
    887 
    888   if (device_source == blink::WebGestureDeviceTouchscreen)
    889     return fling_curve_configuration_->CreateForTouchScreen(velocity,
    890                                                             cumulative_scroll);
    891 
    892   return fling_curve_configuration_->CreateForTouchPad(velocity,
    893                                                        cumulative_scroll);
    894 }
    895 
    896 void BlinkPlatformImpl::didStartWorkerRunLoop(
    897     const blink::WebWorkerRunLoop& runLoop) {
    898   WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance();
    899   worker_task_runner->OnWorkerRunLoopStarted(runLoop);
    900 }
    901 
    902 void BlinkPlatformImpl::didStopWorkerRunLoop(
    903     const blink::WebWorkerRunLoop& runLoop) {
    904   WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance();
    905   worker_task_runner->OnWorkerRunLoopStopped(runLoop);
    906 }
    907 
    908 blink::WebCrypto* BlinkPlatformImpl::crypto() {
    909   WebCryptoImpl::EnsureInit();
    910   return &web_crypto_;
    911 }
    912 
    913 
    914 WebThemeEngine* BlinkPlatformImpl::themeEngine() {
    915   return &native_theme_engine_;
    916 }
    917 
    918 WebFallbackThemeEngine* BlinkPlatformImpl::fallbackThemeEngine() {
    919   return &fallback_theme_engine_;
    920 }
    921 
    922 blink::Platform::FileHandle BlinkPlatformImpl::databaseOpenFile(
    923     const blink::WebString& vfs_file_name, int desired_flags) {
    924 #if defined(OS_WIN)
    925   return INVALID_HANDLE_VALUE;
    926 #elif defined(OS_POSIX)
    927   return -1;
    928 #endif
    929 }
    930 
    931 int BlinkPlatformImpl::databaseDeleteFile(
    932     const blink::WebString& vfs_file_name, bool sync_dir) {
    933   return -1;
    934 }
    935 
    936 long BlinkPlatformImpl::databaseGetFileAttributes(
    937     const blink::WebString& vfs_file_name) {
    938   return 0;
    939 }
    940 
    941 long long BlinkPlatformImpl::databaseGetFileSize(
    942     const blink::WebString& vfs_file_name) {
    943   return 0;
    944 }
    945 
    946 long long BlinkPlatformImpl::databaseGetSpaceAvailableForOrigin(
    947     const blink::WebString& origin_identifier) {
    948   return 0;
    949 }
    950 
    951 blink::WebString BlinkPlatformImpl::signedPublicKeyAndChallengeString(
    952     unsigned key_size_index,
    953     const blink::WebString& challenge,
    954     const blink::WebURL& url) {
    955   return blink::WebString("");
    956 }
    957 
    958 static scoped_ptr<base::ProcessMetrics> CurrentProcessMetrics() {
    959   using base::ProcessMetrics;
    960 #if defined(OS_MACOSX)
    961   return scoped_ptr<ProcessMetrics>(
    962       // The default port provider is sufficient to get data for the current
    963       // process.
    964       ProcessMetrics::CreateProcessMetrics(base::GetCurrentProcessHandle(),
    965                                            NULL));
    966 #else
    967   return scoped_ptr<ProcessMetrics>(
    968       ProcessMetrics::CreateProcessMetrics(base::GetCurrentProcessHandle()));
    969 #endif
    970 }
    971 
    972 static size_t getMemoryUsageMB(bool bypass_cache) {
    973   size_t current_mem_usage = 0;
    974   MemoryUsageCache* mem_usage_cache_singleton = MemoryUsageCache::GetInstance();
    975   if (!bypass_cache &&
    976       mem_usage_cache_singleton->IsCachedValueValid(&current_mem_usage))
    977     return current_mem_usage;
    978 
    979   current_mem_usage = GetMemoryUsageKB() >> 10;
    980   mem_usage_cache_singleton->SetMemoryValue(current_mem_usage);
    981   return current_mem_usage;
    982 }
    983 
    984 size_t BlinkPlatformImpl::memoryUsageMB() {
    985   return getMemoryUsageMB(false);
    986 }
    987 
    988 size_t BlinkPlatformImpl::actualMemoryUsageMB() {
    989   return getMemoryUsageMB(true);
    990 }
    991 
    992 size_t BlinkPlatformImpl::physicalMemoryMB() {
    993   return static_cast<size_t>(base::SysInfo::AmountOfPhysicalMemoryMB());
    994 }
    995 
    996 size_t BlinkPlatformImpl::virtualMemoryLimitMB() {
    997   return static_cast<size_t>(base::SysInfo::AmountOfVirtualMemoryMB());
    998 }
    999 
   1000 size_t BlinkPlatformImpl::numberOfProcessors() {
   1001   return static_cast<size_t>(base::SysInfo::NumberOfProcessors());
   1002 }
   1003 
   1004 void BlinkPlatformImpl::startHeapProfiling(
   1005   const blink::WebString& prefix) {
   1006   // FIXME(morrita): Make this built on windows.
   1007 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
   1008   HeapProfilerStart(prefix.utf8().data());
   1009 #endif
   1010 }
   1011 
   1012 void BlinkPlatformImpl::stopHeapProfiling() {
   1013 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
   1014   HeapProfilerStop();
   1015 #endif
   1016 }
   1017 
   1018 void BlinkPlatformImpl::dumpHeapProfiling(
   1019   const blink::WebString& reason) {
   1020 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
   1021   HeapProfilerDump(reason.utf8().data());
   1022 #endif
   1023 }
   1024 
   1025 WebString BlinkPlatformImpl::getHeapProfile() {
   1026 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
   1027   char* data = GetHeapProfile();
   1028   WebString result = WebString::fromUTF8(std::string(data));
   1029   free(data);
   1030   return result;
   1031 #else
   1032   return WebString();
   1033 #endif
   1034 }
   1035 
   1036 bool BlinkPlatformImpl::processMemorySizesInBytes(
   1037     size_t* private_bytes,
   1038     size_t* shared_bytes) {
   1039   return CurrentProcessMetrics()->GetMemoryBytes(private_bytes, shared_bytes);
   1040 }
   1041 
   1042 bool BlinkPlatformImpl::memoryAllocatorWasteInBytes(size_t* size) {
   1043   return base::allocator::GetAllocatorWasteSize(size);
   1044 }
   1045 
   1046 blink::WebDiscardableMemory*
   1047 BlinkPlatformImpl::allocateAndLockDiscardableMemory(size_t bytes) {
   1048   base::DiscardableMemoryType type =
   1049       base::DiscardableMemory::GetPreferredType();
   1050   if (type == base::DISCARDABLE_MEMORY_TYPE_EMULATED)
   1051     return NULL;
   1052   return content::WebDiscardableMemoryImpl::CreateLockedMemory(bytes).release();
   1053 }
   1054 
   1055 size_t BlinkPlatformImpl::maxDecodedImageBytes() {
   1056 #if defined(OS_ANDROID)
   1057   if (base::android::SysUtils::IsLowEndDevice()) {
   1058     // Limit image decoded size to 3M pixels on low end devices.
   1059     // 4 is maximum number of bytes per pixel.
   1060     return 3 * 1024 * 1024 * 4;
   1061   }
   1062   // For other devices, limit decoded image size based on the amount of physical
   1063   // memory.
   1064   // In some cases all physical memory is not accessible by Chromium, as it can
   1065   // be reserved for direct use by certain hardware. Thus, we set the limit so
   1066   // that 1.6GB of reported physical memory on a 2GB device is enough to set the
   1067   // limit at 16M pixels, which is a desirable value since 4K*4K is a relatively
   1068   // common texture size.
   1069   return base::SysInfo::AmountOfPhysicalMemory() / 25;
   1070 #else
   1071   return noDecodedImageByteLimit;
   1072 #endif
   1073 }
   1074 
   1075 void BlinkPlatformImpl::SetFlingCurveParameters(
   1076     const std::vector<float>& new_touchpad,
   1077     const std::vector<float>& new_touchscreen) {
   1078   fling_curve_configuration_->SetCurveParameters(new_touchpad, new_touchscreen);
   1079 }
   1080 
   1081 void BlinkPlatformImpl::SuspendSharedTimer() {
   1082   ++shared_timer_suspended_;
   1083 }
   1084 
   1085 void BlinkPlatformImpl::ResumeSharedTimer() {
   1086   DCHECK_GT(shared_timer_suspended_, 0);
   1087 
   1088   // The shared timer may have fired or been adjusted while we were suspended.
   1089   if (--shared_timer_suspended_ == 0 &&
   1090       (!shared_timer_.IsRunning() ||
   1091        shared_timer_fire_time_was_set_while_suspended_)) {
   1092     shared_timer_fire_time_was_set_while_suspended_ = false;
   1093     setSharedTimerFireInterval(
   1094         shared_timer_fire_time_ - monotonicallyIncreasingTime());
   1095   }
   1096 }
   1097 
   1098 // static
   1099 void BlinkPlatformImpl::DestroyCurrentThread(void* thread) {
   1100   WebThreadImplForMessageLoop* impl =
   1101       static_cast<WebThreadImplForMessageLoop*>(thread);
   1102   delete impl;
   1103 }
   1104 
   1105 }  // namespace content
   1106