Home | History | Annotate | Download | only in child
      1 // Copyright (c) 2012 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 "webkit/child/webkitplatformsupport_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/platform_file.h"
     21 #include "base/process/process_metrics.h"
     22 #include "base/rand_util.h"
     23 #include "base/strings/string_number_conversions.h"
     24 #include "base/strings/string_util.h"
     25 #include "base/strings/utf_string_conversions.h"
     26 #include "base/synchronization/lock.h"
     27 #include "base/time/time.h"
     28 #include "content/public/common/webplugininfo.h"
     29 #include "grit/blink_resources.h"
     30 #include "grit/webkit_resources.h"
     31 #include "grit/webkit_strings.h"
     32 #include "net/base/data_url.h"
     33 #include "net/base/mime_util.h"
     34 #include "net/base/net_errors.h"
     35 #include "third_party/WebKit/public/platform/WebCookie.h"
     36 #include "third_party/WebKit/public/platform/WebData.h"
     37 #include "third_party/WebKit/public/platform/WebDiscardableMemory.h"
     38 #include "third_party/WebKit/public/platform/WebGestureCurve.h"
     39 #include "third_party/WebKit/public/platform/WebPluginListBuilder.h"
     40 #include "third_party/WebKit/public/platform/WebString.h"
     41 #include "third_party/WebKit/public/platform/WebURL.h"
     42 #include "third_party/WebKit/public/platform/WebVector.h"
     43 #include "third_party/WebKit/public/web/WebFrameClient.h"
     44 #include "third_party/WebKit/public/web/WebInputEvent.h"
     45 #include "third_party/WebKit/public/web/WebScreenInfo.h"
     46 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
     47 #include "ui/base/layout.h"
     48 #include "webkit/child/webkit_child_helpers.h"
     49 #include "webkit/child/websocketstreamhandle_impl.h"
     50 #include "webkit/child/weburlloader_impl.h"
     51 #include "webkit/common/user_agent/user_agent.h"
     52 #include "webkit/glue/webkit_glue.h"
     53 
     54 using WebKit::WebAudioBus;
     55 using WebKit::WebCookie;
     56 using WebKit::WebData;
     57 using WebKit::WebLocalizedString;
     58 using WebKit::WebPluginListBuilder;
     59 using WebKit::WebString;
     60 using WebKit::WebSocketStreamHandle;
     61 using WebKit::WebURL;
     62 using WebKit::WebURLError;
     63 using WebKit::WebURLLoader;
     64 using WebKit::WebVector;
     65 
     66 namespace {
     67 
     68 // A simple class to cache the memory usage for a given amount of time.
     69 class MemoryUsageCache {
     70  public:
     71   // Retrieves the Singleton.
     72   static MemoryUsageCache* GetInstance() {
     73     return Singleton<MemoryUsageCache>::get();
     74   }
     75 
     76   MemoryUsageCache() : memory_value_(0) { Init(); }
     77   ~MemoryUsageCache() {}
     78 
     79   void Init() {
     80     const unsigned int kCacheSeconds = 1;
     81     cache_valid_time_ = base::TimeDelta::FromSeconds(kCacheSeconds);
     82   }
     83 
     84   // Returns true if the cached value is fresh.
     85   // Returns false if the cached value is stale, or if |cached_value| is NULL.
     86   bool IsCachedValueValid(size_t* cached_value) {
     87     base::AutoLock scoped_lock(lock_);
     88     if (!cached_value)
     89       return false;
     90     if (base::Time::Now() - last_updated_time_ > cache_valid_time_)
     91       return false;
     92     *cached_value = memory_value_;
     93     return true;
     94   };
     95 
     96   // Setter for |memory_value_|, refreshes |last_updated_time_|.
     97   void SetMemoryValue(const size_t value) {
     98     base::AutoLock scoped_lock(lock_);
     99     memory_value_ = value;
    100     last_updated_time_ = base::Time::Now();
    101   }
    102 
    103  private:
    104   // The cached memory value.
    105   size_t memory_value_;
    106 
    107   // How long the cached value should remain valid.
    108   base::TimeDelta cache_valid_time_;
    109 
    110   // The last time the cached value was updated.
    111   base::Time last_updated_time_;
    112 
    113   base::Lock lock_;
    114 };
    115 
    116 }  // anonymous namespace
    117 
    118 namespace webkit_glue {
    119 
    120 static int ToMessageID(WebLocalizedString::Name name) {
    121   switch (name) {
    122     case WebLocalizedString::AXAMPMFieldText:
    123       return IDS_AX_AM_PM_FIELD_TEXT;
    124     case WebLocalizedString::AXButtonActionVerb:
    125       return IDS_AX_BUTTON_ACTION_VERB;
    126     case WebLocalizedString::AXCheckedCheckBoxActionVerb:
    127       return IDS_AX_CHECKED_CHECK_BOX_ACTION_VERB;
    128     case WebLocalizedString::AXDateTimeFieldEmptyValueText:
    129       return IDS_AX_DATE_TIME_FIELD_EMPTY_VALUE_TEXT;
    130     case WebLocalizedString::AXDayOfMonthFieldText:
    131       return IDS_AX_DAY_OF_MONTH_FIELD_TEXT;
    132     case WebLocalizedString::AXHeadingText:
    133       return IDS_AX_ROLE_HEADING;
    134     case WebLocalizedString::AXHourFieldText:
    135       return IDS_AX_HOUR_FIELD_TEXT;
    136     case WebLocalizedString::AXImageMapText:
    137       return IDS_AX_ROLE_IMAGE_MAP;
    138     case WebLocalizedString::AXLinkActionVerb:
    139       return IDS_AX_LINK_ACTION_VERB;
    140     case WebLocalizedString::AXLinkText:
    141       return IDS_AX_ROLE_LINK;
    142     case WebLocalizedString::AXListMarkerText:
    143       return IDS_AX_ROLE_LIST_MARKER;
    144     case WebLocalizedString::AXMediaDefault:
    145       return IDS_AX_MEDIA_DEFAULT;
    146     case WebLocalizedString::AXMediaAudioElement:
    147       return IDS_AX_MEDIA_AUDIO_ELEMENT;
    148     case WebLocalizedString::AXMediaVideoElement:
    149       return IDS_AX_MEDIA_VIDEO_ELEMENT;
    150     case WebLocalizedString::AXMediaMuteButton:
    151       return IDS_AX_MEDIA_MUTE_BUTTON;
    152     case WebLocalizedString::AXMediaUnMuteButton:
    153       return IDS_AX_MEDIA_UNMUTE_BUTTON;
    154     case WebLocalizedString::AXMediaPlayButton:
    155       return IDS_AX_MEDIA_PLAY_BUTTON;
    156     case WebLocalizedString::AXMediaPauseButton:
    157       return IDS_AX_MEDIA_PAUSE_BUTTON;
    158     case WebLocalizedString::AXMediaSlider:
    159       return IDS_AX_MEDIA_SLIDER;
    160     case WebLocalizedString::AXMediaSliderThumb:
    161       return IDS_AX_MEDIA_SLIDER_THUMB;
    162     case WebLocalizedString::AXMediaRewindButton:
    163       return IDS_AX_MEDIA_REWIND_BUTTON;
    164     case WebLocalizedString::AXMediaReturnToRealTime:
    165       return IDS_AX_MEDIA_RETURN_TO_REALTIME_BUTTON;
    166     case WebLocalizedString::AXMediaCurrentTimeDisplay:
    167       return IDS_AX_MEDIA_CURRENT_TIME_DISPLAY;
    168     case WebLocalizedString::AXMediaTimeRemainingDisplay:
    169       return IDS_AX_MEDIA_TIME_REMAINING_DISPLAY;
    170     case WebLocalizedString::AXMediaStatusDisplay:
    171       return IDS_AX_MEDIA_STATUS_DISPLAY;
    172     case WebLocalizedString::AXMediaEnterFullscreenButton:
    173       return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON;
    174     case WebLocalizedString::AXMediaExitFullscreenButton:
    175       return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON;
    176   case WebLocalizedString::AXMediaSeekForwardButton:
    177     return IDS_AX_MEDIA_SEEK_FORWARD_BUTTON;
    178     case WebLocalizedString::AXMediaSeekBackButton:
    179       return IDS_AX_MEDIA_SEEK_BACK_BUTTON;
    180     case WebLocalizedString::AXMediaShowClosedCaptionsButton:
    181       return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON;
    182     case WebLocalizedString::AXMediaHideClosedCaptionsButton:
    183       return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON;
    184     case WebLocalizedString::AXMediaAudioElementHelp:
    185       return IDS_AX_MEDIA_AUDIO_ELEMENT_HELP;
    186     case WebLocalizedString::AXMediaVideoElementHelp:
    187       return IDS_AX_MEDIA_VIDEO_ELEMENT_HELP;
    188     case WebLocalizedString::AXMediaMuteButtonHelp:
    189       return IDS_AX_MEDIA_MUTE_BUTTON_HELP;
    190     case WebLocalizedString::AXMediaUnMuteButtonHelp:
    191       return IDS_AX_MEDIA_UNMUTE_BUTTON_HELP;
    192     case WebLocalizedString::AXMediaPlayButtonHelp:
    193       return IDS_AX_MEDIA_PLAY_BUTTON_HELP;
    194     case WebLocalizedString::AXMediaPauseButtonHelp:
    195       return IDS_AX_MEDIA_PAUSE_BUTTON_HELP;
    196     case WebLocalizedString::AXMediaSliderHelp:
    197       return IDS_AX_MEDIA_SLIDER_HELP;
    198     case WebLocalizedString::AXMediaSliderThumbHelp:
    199       return IDS_AX_MEDIA_SLIDER_THUMB_HELP;
    200     case WebLocalizedString::AXMediaRewindButtonHelp:
    201       return IDS_AX_MEDIA_REWIND_BUTTON_HELP;
    202     case WebLocalizedString::AXMediaReturnToRealTimeHelp:
    203       return IDS_AX_MEDIA_RETURN_TO_REALTIME_BUTTON_HELP;
    204     case WebLocalizedString::AXMediaCurrentTimeDisplayHelp:
    205       return IDS_AX_MEDIA_CURRENT_TIME_DISPLAY_HELP;
    206     case WebLocalizedString::AXMediaTimeRemainingDisplayHelp:
    207       return IDS_AX_MEDIA_TIME_REMAINING_DISPLAY_HELP;
    208     case WebLocalizedString::AXMediaStatusDisplayHelp:
    209       return IDS_AX_MEDIA_STATUS_DISPLAY_HELP;
    210     case WebLocalizedString::AXMediaEnterFullscreenButtonHelp:
    211       return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON_HELP;
    212     case WebLocalizedString::AXMediaExitFullscreenButtonHelp:
    213       return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON_HELP;
    214   case WebLocalizedString::AXMediaSeekForwardButtonHelp:
    215     return IDS_AX_MEDIA_SEEK_FORWARD_BUTTON_HELP;
    216     case WebLocalizedString::AXMediaSeekBackButtonHelp:
    217       return IDS_AX_MEDIA_SEEK_BACK_BUTTON_HELP;
    218     case WebLocalizedString::AXMediaShowClosedCaptionsButtonHelp:
    219       return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON_HELP;
    220     case WebLocalizedString::AXMediaHideClosedCaptionsButtonHelp:
    221       return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON_HELP;
    222     case WebLocalizedString::AXMillisecondFieldText:
    223       return IDS_AX_MILLISECOND_FIELD_TEXT;
    224     case WebLocalizedString::AXMinuteFieldText:
    225       return IDS_AX_MINUTE_FIELD_TEXT;
    226     case WebLocalizedString::AXMonthFieldText:
    227       return IDS_AX_MONTH_FIELD_TEXT;
    228     case WebLocalizedString::AXRadioButtonActionVerb:
    229       return IDS_AX_RADIO_BUTTON_ACTION_VERB;
    230     case WebLocalizedString::AXSecondFieldText:
    231       return IDS_AX_SECOND_FIELD_TEXT;
    232     case WebLocalizedString::AXTextFieldActionVerb:
    233       return IDS_AX_TEXT_FIELD_ACTION_VERB;
    234     case WebLocalizedString::AXUncheckedCheckBoxActionVerb:
    235       return IDS_AX_UNCHECKED_CHECK_BOX_ACTION_VERB;
    236     case WebLocalizedString::AXWebAreaText:
    237       return IDS_AX_ROLE_WEB_AREA;
    238     case WebLocalizedString::AXWeekOfYearFieldText:
    239       return IDS_AX_WEEK_OF_YEAR_FIELD_TEXT;
    240     case WebLocalizedString::AXYearFieldText:
    241       return IDS_AX_YEAR_FIELD_TEXT;
    242     case WebLocalizedString::CalendarClear:
    243       return IDS_FORM_CALENDAR_CLEAR;
    244     case WebLocalizedString::CalendarToday:
    245       return IDS_FORM_CALENDAR_TODAY;
    246     case WebLocalizedString::DateFormatDayInMonthLabel:
    247       return IDS_FORM_DATE_FORMAT_DAY_IN_MONTH;
    248     case WebLocalizedString::DateFormatMonthLabel:
    249       return IDS_FORM_DATE_FORMAT_MONTH;
    250     case WebLocalizedString::DateFormatYearLabel:
    251       return IDS_FORM_DATE_FORMAT_YEAR;
    252     case WebLocalizedString::DetailsLabel:
    253       return IDS_DETAILS_WITHOUT_SUMMARY_LABEL;
    254     case WebLocalizedString::FileButtonChooseFileLabel:
    255       return IDS_FORM_FILE_BUTTON_LABEL;
    256     case WebLocalizedString::FileButtonChooseMultipleFilesLabel:
    257       return IDS_FORM_MULTIPLE_FILES_BUTTON_LABEL;
    258     case WebLocalizedString::FileButtonNoFileSelectedLabel:
    259       return IDS_FORM_FILE_NO_FILE_LABEL;
    260     case WebLocalizedString::InputElementAltText:
    261       return IDS_FORM_INPUT_ALT;
    262     case WebLocalizedString::KeygenMenuHighGradeKeySize:
    263       return IDS_KEYGEN_HIGH_GRADE_KEY;
    264     case WebLocalizedString::KeygenMenuMediumGradeKeySize:
    265       return IDS_KEYGEN_MED_GRADE_KEY;
    266     case WebLocalizedString::MissingPluginText:
    267       return IDS_PLUGIN_INITIALIZATION_ERROR;
    268     case WebLocalizedString::MultipleFileUploadText:
    269       return IDS_FORM_FILE_MULTIPLE_UPLOAD;
    270     case WebLocalizedString::OtherColorLabel:
    271       return IDS_FORM_OTHER_COLOR_LABEL;
    272     case WebLocalizedString::OtherDateLabel:
    273         return IDS_FORM_OTHER_DATE_LABEL;
    274     case WebLocalizedString::OtherMonthLabel:
    275       return IDS_FORM_OTHER_MONTH_LABEL;
    276     case WebLocalizedString::OtherTimeLabel:
    277       return IDS_FORM_OTHER_TIME_LABEL;
    278     case WebLocalizedString::OtherWeekLabel:
    279       return IDS_FORM_OTHER_WEEK_LABEL;
    280     case WebLocalizedString::PlaceholderForDayOfMonthField:
    281       return IDS_FORM_PLACEHOLDER_FOR_DAY_OF_MONTH_FIELD;
    282     case WebLocalizedString::PlaceholderForMonthField:
    283       return IDS_FORM_PLACEHOLDER_FOR_MONTH_FIELD;
    284     case WebLocalizedString::PlaceholderForYearField:
    285       return IDS_FORM_PLACEHOLDER_FOR_YEAR_FIELD;
    286     case WebLocalizedString::ResetButtonDefaultLabel:
    287       return IDS_FORM_RESET_LABEL;
    288     case WebLocalizedString::SearchableIndexIntroduction:
    289       return IDS_SEARCHABLE_INDEX_INTRO;
    290     case WebLocalizedString::SearchMenuClearRecentSearchesText:
    291       return IDS_RECENT_SEARCHES_CLEAR;
    292     case WebLocalizedString::SearchMenuNoRecentSearchesText:
    293       return IDS_RECENT_SEARCHES_NONE;
    294     case WebLocalizedString::SearchMenuRecentSearchesText:
    295       return IDS_RECENT_SEARCHES;
    296     case WebLocalizedString::SubmitButtonDefaultLabel:
    297       return IDS_FORM_SUBMIT_LABEL;
    298     case WebLocalizedString::ThisMonthButtonLabel:
    299       return IDS_FORM_THIS_MONTH_LABEL;
    300     case WebLocalizedString::ThisWeekButtonLabel:
    301       return IDS_FORM_THIS_WEEK_LABEL;
    302     case WebLocalizedString::ValidationBadInputForDateTime:
    303       return IDS_FORM_VALIDATION_BAD_INPUT_DATETIME;
    304     case WebLocalizedString::ValidationBadInputForNumber:
    305       return IDS_FORM_VALIDATION_BAD_INPUT_NUMBER;
    306     case WebLocalizedString::ValidationPatternMismatch:
    307       return IDS_FORM_VALIDATION_PATTERN_MISMATCH;
    308     case WebLocalizedString::ValidationRangeOverflow:
    309       return IDS_FORM_VALIDATION_RANGE_OVERFLOW;
    310     case WebLocalizedString::ValidationRangeUnderflow:
    311       return IDS_FORM_VALIDATION_RANGE_UNDERFLOW;
    312     case WebLocalizedString::ValidationStepMismatch:
    313       return IDS_FORM_VALIDATION_STEP_MISMATCH;
    314     case WebLocalizedString::ValidationTooLong:
    315       return IDS_FORM_VALIDATION_TOO_LONG;
    316     case WebLocalizedString::ValidationTypeMismatch:
    317       return IDS_FORM_VALIDATION_TYPE_MISMATCH;
    318     case WebLocalizedString::ValidationTypeMismatchForEmail:
    319       return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL;
    320     case WebLocalizedString::ValidationTypeMismatchForMultipleEmail:
    321       return IDS_FORM_VALIDATION_TYPE_MISMATCH_MULTIPLE_EMAIL;
    322     case WebLocalizedString::ValidationTypeMismatchForURL:
    323       return IDS_FORM_VALIDATION_TYPE_MISMATCH_URL;
    324     case WebLocalizedString::ValidationValueMissing:
    325       return IDS_FORM_VALIDATION_VALUE_MISSING;
    326     case WebLocalizedString::ValidationValueMissingForCheckbox:
    327       return IDS_FORM_VALIDATION_VALUE_MISSING_CHECKBOX;
    328     case WebLocalizedString::ValidationValueMissingForFile:
    329       return IDS_FORM_VALIDATION_VALUE_MISSING_FILE;
    330     case WebLocalizedString::ValidationValueMissingForMultipleFile:
    331       return IDS_FORM_VALIDATION_VALUE_MISSING_MULTIPLE_FILE;
    332     case WebLocalizedString::ValidationValueMissingForRadio:
    333       return IDS_FORM_VALIDATION_VALUE_MISSING_RADIO;
    334     case WebLocalizedString::ValidationValueMissingForSelect:
    335       return IDS_FORM_VALIDATION_VALUE_MISSING_SELECT;
    336     case WebLocalizedString::WeekFormatTemplate:
    337       return IDS_FORM_INPUT_WEEK_TEMPLATE;
    338     case WebLocalizedString::WeekNumberLabel:
    339       return IDS_FORM_WEEK_NUMBER_LABEL;
    340     // This "default:" line exists to avoid compile warnings about enum
    341     // coverage when we add a new symbol to WebLocalizedString.h in WebKit.
    342     // After a planned WebKit patch is landed, we need to add a case statement
    343     // for the added symbol here.
    344     default:
    345       break;
    346   }
    347   return -1;
    348 }
    349 
    350 WebKitPlatformSupportImpl::WebKitPlatformSupportImpl()
    351     : main_loop_(base::MessageLoop::current()),
    352       shared_timer_func_(NULL),
    353       shared_timer_fire_time_(0.0),
    354       shared_timer_fire_time_was_set_while_suspended_(false),
    355       shared_timer_suspended_(0) {}
    356 
    357 WebKitPlatformSupportImpl::~WebKitPlatformSupportImpl() {
    358 }
    359 
    360 WebURLLoader* WebKitPlatformSupportImpl::createURLLoader() {
    361   return new WebURLLoaderImpl(this);
    362 }
    363 
    364 WebSocketStreamHandle* WebKitPlatformSupportImpl::createSocketStreamHandle() {
    365   return new WebSocketStreamHandleImpl(this);
    366 }
    367 
    368 WebString WebKitPlatformSupportImpl::userAgent(const WebURL& url) {
    369   return WebString::fromUTF8(webkit_glue::GetUserAgent(url));
    370 }
    371 
    372 WebData WebKitPlatformSupportImpl::parseDataURL(
    373     const WebURL& url,
    374     WebString& mimetype_out,
    375     WebString& charset_out) {
    376   std::string mime_type, char_set, data;
    377   if (net::DataURL::Parse(url, &mime_type, &char_set, &data)
    378       && net::IsSupportedMimeType(mime_type)) {
    379     mimetype_out = WebString::fromUTF8(mime_type);
    380     charset_out = WebString::fromUTF8(char_set);
    381     return data;
    382   }
    383   return WebData();
    384 }
    385 
    386 WebURLError WebKitPlatformSupportImpl::cancelledError(
    387     const WebURL& unreachableURL) const {
    388   return WebURLLoaderImpl::CreateError(unreachableURL, net::ERR_ABORTED);
    389 }
    390 
    391 void WebKitPlatformSupportImpl::decrementStatsCounter(const char* name) {
    392   base::StatsCounter(name).Decrement();
    393 }
    394 
    395 void WebKitPlatformSupportImpl::incrementStatsCounter(const char* name) {
    396   base::StatsCounter(name).Increment();
    397 }
    398 
    399 void WebKitPlatformSupportImpl::histogramCustomCounts(
    400     const char* name, int sample, int min, int max, int bucket_count) {
    401   // Copied from histogram macro, but without the static variable caching
    402   // the histogram because name is dynamic.
    403   base::HistogramBase* counter =
    404       base::Histogram::FactoryGet(name, min, max, bucket_count,
    405           base::HistogramBase::kUmaTargetedHistogramFlag);
    406   DCHECK_EQ(name, counter->histogram_name());
    407   counter->Add(sample);
    408 }
    409 
    410 void WebKitPlatformSupportImpl::histogramEnumeration(
    411     const char* name, int sample, int boundary_value) {
    412   // Copied from histogram macro, but without the static variable caching
    413   // the histogram because name is dynamic.
    414   base::HistogramBase* counter =
    415       base::LinearHistogram::FactoryGet(name, 1, boundary_value,
    416           boundary_value + 1, base::HistogramBase::kUmaTargetedHistogramFlag);
    417   DCHECK_EQ(name, counter->histogram_name());
    418   counter->Add(sample);
    419 }
    420 
    421 void WebKitPlatformSupportImpl::histogramSparse(const char* name, int sample) {
    422   // For sparse histograms, we can use the macro, as it does not incorporate a
    423   // static.
    424   UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample);
    425 }
    426 
    427 const unsigned char* WebKitPlatformSupportImpl::getTraceCategoryEnabledFlag(
    428     const char* category_group) {
    429   return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
    430 }
    431 
    432 long* WebKitPlatformSupportImpl::getTraceSamplingState(
    433     const unsigned thread_bucket) {
    434   switch (thread_bucket) {
    435     case 0:
    436       return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(0));
    437     case 1:
    438       return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(1));
    439     case 2:
    440       return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(2));
    441     default:
    442       NOTREACHED() << "Unknown thread bucket type.";
    443   }
    444   return NULL;
    445 }
    446 
    447 void WebKitPlatformSupportImpl::addTraceEvent(
    448     char phase,
    449     const unsigned char* category_group_enabled,
    450     const char* name,
    451     unsigned long long id,
    452     int num_args,
    453     const char** arg_names,
    454     const unsigned char* arg_types,
    455     const unsigned long long* arg_values,
    456     unsigned char flags) {
    457   TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name, id,
    458                                   num_args, arg_names, arg_types,
    459                                   arg_values, NULL, flags);
    460 }
    461 
    462 
    463 namespace {
    464 
    465 WebData loadAudioSpatializationResource(WebKitPlatformSupportImpl* platform,
    466                                         const char* name) {
    467 #ifdef IDR_AUDIO_SPATIALIZATION_COMPOSITE
    468   if (!strcmp(name, "Composite")) {
    469     base::StringPiece resource =
    470         platform->GetDataResource(IDR_AUDIO_SPATIALIZATION_COMPOSITE,
    471                                   ui::SCALE_FACTOR_NONE);
    472     return WebData(resource.data(), resource.size());
    473   }
    474 #endif
    475 
    476 #ifdef IDR_AUDIO_SPATIALIZATION_T000_P000
    477   const size_t kExpectedSpatializationNameLength = 31;
    478   if (strlen(name) != kExpectedSpatializationNameLength) {
    479     return WebData();
    480   }
    481 
    482   // Extract the azimuth and elevation from the resource name.
    483   int azimuth = 0;
    484   int elevation = 0;
    485   int values_parsed =
    486       sscanf(name, "IRC_Composite_C_R0195_T%3d_P%3d", &azimuth, &elevation);
    487   if (values_parsed != 2) {
    488     return WebData();
    489   }
    490 
    491   // The resource index values go through the elevations first, then azimuths.
    492   const int kAngleSpacing = 15;
    493 
    494   // 0 <= elevation <= 90 (or 315 <= elevation <= 345)
    495   // in increments of 15 degrees.
    496   int elevation_index =
    497       elevation <= 90 ? elevation / kAngleSpacing :
    498       7 + (elevation - 315) / kAngleSpacing;
    499   bool is_elevation_index_good = 0 <= elevation_index && elevation_index < 10;
    500 
    501   // 0 <= azimuth < 360 in increments of 15 degrees.
    502   int azimuth_index = azimuth / kAngleSpacing;
    503   bool is_azimuth_index_good = 0 <= azimuth_index && azimuth_index < 24;
    504 
    505   const int kNumberOfElevations = 10;
    506   const int kNumberOfAudioResources = 240;
    507   int resource_index = kNumberOfElevations * azimuth_index + elevation_index;
    508   bool is_resource_index_good = 0 <= resource_index &&
    509       resource_index < kNumberOfAudioResources;
    510 
    511   if (is_azimuth_index_good && is_elevation_index_good &&
    512       is_resource_index_good) {
    513     const int kFirstAudioResourceIndex = IDR_AUDIO_SPATIALIZATION_T000_P000;
    514     base::StringPiece resource =
    515         platform->GetDataResource(kFirstAudioResourceIndex + resource_index,
    516                                   ui::SCALE_FACTOR_NONE);
    517     return WebData(resource.data(), resource.size());
    518   }
    519 #endif  // IDR_AUDIO_SPATIALIZATION_T000_P000
    520 
    521   NOTREACHED();
    522   return WebData();
    523 }
    524 
    525 struct DataResource {
    526   const char* name;
    527   int id;
    528   ui::ScaleFactor scale_factor;
    529 };
    530 
    531 const DataResource kDataResources[] = {
    532   { "missingImage", IDR_BROKENIMAGE, ui::SCALE_FACTOR_100P },
    533   { "missingImage@2x", IDR_BROKENIMAGE, ui::SCALE_FACTOR_200P },
    534   { "mediaplayerPause", IDR_MEDIAPLAYER_PAUSE_BUTTON, ui::SCALE_FACTOR_100P },
    535   { "mediaplayerPauseHover",
    536     IDR_MEDIAPLAYER_PAUSE_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    537   { "mediaplayerPauseDown",
    538     IDR_MEDIAPLAYER_PAUSE_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    539   { "mediaplayerPlay", IDR_MEDIAPLAYER_PLAY_BUTTON, ui::SCALE_FACTOR_100P },
    540   { "mediaplayerPlayHover",
    541     IDR_MEDIAPLAYER_PLAY_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    542   { "mediaplayerPlayDown",
    543     IDR_MEDIAPLAYER_PLAY_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    544   { "mediaplayerPlayDisabled",
    545     IDR_MEDIAPLAYER_PLAY_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
    546   { "mediaplayerSoundLevel3",
    547     IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON, ui::SCALE_FACTOR_100P },
    548   { "mediaplayerSoundLevel3Hover",
    549     IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    550   { "mediaplayerSoundLevel3Down",
    551     IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    552   { "mediaplayerSoundLevel2",
    553     IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON, ui::SCALE_FACTOR_100P },
    554   { "mediaplayerSoundLevel2Hover",
    555     IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    556   { "mediaplayerSoundLevel2Down",
    557     IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    558   { "mediaplayerSoundLevel1",
    559     IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON, ui::SCALE_FACTOR_100P },
    560   { "mediaplayerSoundLevel1Hover",
    561     IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    562   { "mediaplayerSoundLevel1Down",
    563     IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    564   { "mediaplayerSoundLevel0",
    565     IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON, ui::SCALE_FACTOR_100P },
    566   { "mediaplayerSoundLevel0Hover",
    567     IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    568   { "mediaplayerSoundLevel0Down",
    569     IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    570   { "mediaplayerSoundDisabled",
    571     IDR_MEDIAPLAYER_SOUND_DISABLED, ui::SCALE_FACTOR_100P },
    572   { "mediaplayerSliderThumb",
    573     IDR_MEDIAPLAYER_SLIDER_THUMB, ui::SCALE_FACTOR_100P },
    574   { "mediaplayerSliderThumbHover",
    575     IDR_MEDIAPLAYER_SLIDER_THUMB_HOVER, ui::SCALE_FACTOR_100P },
    576   { "mediaplayerSliderThumbDown",
    577     IDR_MEDIAPLAYER_SLIDER_THUMB_DOWN, ui::SCALE_FACTOR_100P },
    578   { "mediaplayerVolumeSliderThumb",
    579     IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB, ui::SCALE_FACTOR_100P },
    580   { "mediaplayerVolumeSliderThumbHover",
    581     IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_HOVER, ui::SCALE_FACTOR_100P },
    582   { "mediaplayerVolumeSliderThumbDown",
    583     IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DOWN, ui::SCALE_FACTOR_100P },
    584   { "mediaplayerVolumeSliderThumbDisabled",
    585     IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DISABLED, ui::SCALE_FACTOR_100P },
    586   { "mediaplayerClosedCaption",
    587     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON, ui::SCALE_FACTOR_100P },
    588   { "mediaplayerClosedCaptionHover",
    589     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    590   { "mediaplayerClosedCaptionDown",
    591     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    592   { "mediaplayerClosedCaptionDisabled",
    593     IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
    594   { "mediaplayerFullscreen",
    595     IDR_MEDIAPLAYER_FULLSCREEN_BUTTON, ui::SCALE_FACTOR_100P },
    596   { "mediaplayerFullscreenHover",
    597     IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
    598   { "mediaplayerFullscreenDown",
    599     IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
    600   { "mediaplayerFullscreenDisabled",
    601     IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
    602 #if defined(OS_ANDROID)
    603   { "mediaplayerOverlayPlay",
    604     IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON, ui::SCALE_FACTOR_100P },
    605 #endif
    606 #if defined(OS_MACOSX)
    607   { "overhangPattern", IDR_OVERHANG_PATTERN, ui::SCALE_FACTOR_100P },
    608 #endif
    609   { "panIcon", IDR_PAN_SCROLL_ICON, ui::SCALE_FACTOR_100P },
    610   { "searchCancel", IDR_SEARCH_CANCEL, ui::SCALE_FACTOR_100P },
    611   { "searchCancelPressed", IDR_SEARCH_CANCEL_PRESSED, ui::SCALE_FACTOR_100P },
    612   { "searchMagnifier", IDR_SEARCH_MAGNIFIER, ui::SCALE_FACTOR_100P },
    613   { "searchMagnifierResults",
    614     IDR_SEARCH_MAGNIFIER_RESULTS, ui::SCALE_FACTOR_100P },
    615   { "textAreaResizeCorner", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_100P },
    616   { "textAreaResizeCorner@2x", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_200P },
    617   { "inputSpeech", IDR_INPUT_SPEECH, ui::SCALE_FACTOR_100P },
    618   { "inputSpeechRecording", IDR_INPUT_SPEECH_RECORDING, ui::SCALE_FACTOR_100P },
    619   { "inputSpeechWaiting", IDR_INPUT_SPEECH_WAITING, ui::SCALE_FACTOR_100P },
    620   { "americanExpressCC", IDR_AUTOFILL_CC_AMEX, ui::SCALE_FACTOR_100P },
    621   { "dinersCC", IDR_AUTOFILL_CC_DINERS, ui::SCALE_FACTOR_100P },
    622   { "discoverCC", IDR_AUTOFILL_CC_DISCOVER, ui::SCALE_FACTOR_100P },
    623   { "genericCC", IDR_AUTOFILL_CC_GENERIC, ui::SCALE_FACTOR_100P },
    624   { "jcbCC", IDR_AUTOFILL_CC_JCB, ui::SCALE_FACTOR_100P },
    625   { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD, ui::SCALE_FACTOR_100P },
    626   { "visaCC", IDR_AUTOFILL_CC_VISA, ui::SCALE_FACTOR_100P },
    627   { "generatePassword", IDR_PASSWORD_GENERATION_ICON, ui::SCALE_FACTOR_100P },
    628   { "generatePasswordHover",
    629     IDR_PASSWORD_GENERATION_ICON_HOVER, ui::SCALE_FACTOR_100P },
    630   { "syntheticTouchCursor",
    631     IDR_SYNTHETIC_TOUCH_CURSOR, ui::SCALE_FACTOR_100P },
    632 };
    633 
    634 }  // namespace
    635 
    636 WebData WebKitPlatformSupportImpl::loadResource(const char* name) {
    637   // Some clients will call into this method with an empty |name| when they have
    638   // optional resources.  For example, the PopupMenuChromium code can have icons
    639   // for some Autofill items but not for others.
    640   if (!strlen(name))
    641     return WebData();
    642 
    643   // Check the name prefix to see if it's an audio resource.
    644   if (StartsWithASCII(name, "IRC_Composite", true) ||
    645       StartsWithASCII(name, "Composite", true))
    646     return loadAudioSpatializationResource(this, name);
    647 
    648   // TODO(flackr): We should use a better than linear search here, a trie would
    649   // be ideal.
    650   for (size_t i = 0; i < arraysize(kDataResources); ++i) {
    651     if (!strcmp(name, kDataResources[i].name)) {
    652       base::StringPiece resource =
    653           GetDataResource(kDataResources[i].id,
    654                           kDataResources[i].scale_factor);
    655       return WebData(resource.data(), resource.size());
    656     }
    657   }
    658 
    659   NOTREACHED() << "Unknown image resource " << name;
    660   return WebData();
    661 }
    662 
    663 WebString WebKitPlatformSupportImpl::queryLocalizedString(
    664     WebLocalizedString::Name name) {
    665   int message_id = ToMessageID(name);
    666   if (message_id < 0)
    667     return WebString();
    668   return GetLocalizedString(message_id);
    669 }
    670 
    671 WebString WebKitPlatformSupportImpl::queryLocalizedString(
    672     WebLocalizedString::Name name, int numeric_value) {
    673   return queryLocalizedString(name, base::IntToString16(numeric_value));
    674 }
    675 
    676 WebString WebKitPlatformSupportImpl::queryLocalizedString(
    677     WebLocalizedString::Name name, const WebString& value) {
    678   int message_id = ToMessageID(name);
    679   if (message_id < 0)
    680     return WebString();
    681   return ReplaceStringPlaceholders(GetLocalizedString(message_id), value, NULL);
    682 }
    683 
    684 WebString WebKitPlatformSupportImpl::queryLocalizedString(
    685     WebLocalizedString::Name name,
    686     const WebString& value1,
    687     const WebString& value2) {
    688   int message_id = ToMessageID(name);
    689   if (message_id < 0)
    690     return WebString();
    691   std::vector<base::string16> values;
    692   values.reserve(2);
    693   values.push_back(value1);
    694   values.push_back(value2);
    695   return ReplaceStringPlaceholders(
    696       GetLocalizedString(message_id), values, NULL);
    697 }
    698 
    699 double WebKitPlatformSupportImpl::currentTime() {
    700   return base::Time::Now().ToDoubleT();
    701 }
    702 
    703 double WebKitPlatformSupportImpl::monotonicallyIncreasingTime() {
    704   return base::TimeTicks::Now().ToInternalValue() /
    705       static_cast<double>(base::Time::kMicrosecondsPerSecond);
    706 }
    707 
    708 void WebKitPlatformSupportImpl::cryptographicallyRandomValues(
    709     unsigned char* buffer, size_t length) {
    710   base::RandBytes(buffer, length);
    711 }
    712 
    713 void WebKitPlatformSupportImpl::setSharedTimerFiredFunction(void (*func)()) {
    714   shared_timer_func_ = func;
    715 }
    716 
    717 void WebKitPlatformSupportImpl::setSharedTimerFireInterval(
    718     double interval_seconds) {
    719   shared_timer_fire_time_ = interval_seconds + monotonicallyIncreasingTime();
    720   if (shared_timer_suspended_) {
    721     shared_timer_fire_time_was_set_while_suspended_ = true;
    722     return;
    723   }
    724 
    725   // By converting between double and int64 representation, we run the risk
    726   // of losing precision due to rounding errors. Performing computations in
    727   // microseconds reduces this risk somewhat. But there still is the potential
    728   // of us computing a fire time for the timer that is shorter than what we
    729   // need.
    730   // As the event loop will check event deadlines prior to actually firing
    731   // them, there is a risk of needlessly rescheduling events and of
    732   // needlessly looping if sleep times are too short even by small amounts.
    733   // This results in measurable performance degradation unless we use ceil() to
    734   // always round up the sleep times.
    735   int64 interval = static_cast<int64>(
    736       ceil(interval_seconds * base::Time::kMillisecondsPerSecond)
    737       * base::Time::kMicrosecondsPerMillisecond);
    738 
    739   if (interval < 0)
    740     interval = 0;
    741 
    742   shared_timer_.Stop();
    743   shared_timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds(interval),
    744                       this, &WebKitPlatformSupportImpl::DoTimeout);
    745   OnStartSharedTimer(base::TimeDelta::FromMicroseconds(interval));
    746 }
    747 
    748 void WebKitPlatformSupportImpl::stopSharedTimer() {
    749   shared_timer_.Stop();
    750 }
    751 
    752 void WebKitPlatformSupportImpl::callOnMainThread(
    753     void (*func)(void*), void* context) {
    754   main_loop_->PostTask(FROM_HERE, base::Bind(func, context));
    755 }
    756 
    757 base::PlatformFile WebKitPlatformSupportImpl::databaseOpenFile(
    758     const WebKit::WebString& vfs_file_name, int desired_flags) {
    759   return base::kInvalidPlatformFileValue;
    760 }
    761 
    762 int WebKitPlatformSupportImpl::databaseDeleteFile(
    763     const WebKit::WebString& vfs_file_name, bool sync_dir) {
    764   return -1;
    765 }
    766 
    767 long WebKitPlatformSupportImpl::databaseGetFileAttributes(
    768     const WebKit::WebString& vfs_file_name) {
    769   return 0;
    770 }
    771 
    772 long long WebKitPlatformSupportImpl::databaseGetFileSize(
    773     const WebKit::WebString& vfs_file_name) {
    774   return 0;
    775 }
    776 
    777 long long WebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin(
    778     const WebKit::WebString& origin_identifier) {
    779   return 0;
    780 }
    781 
    782 WebKit::WebString WebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
    783     unsigned key_size_index,
    784     const WebKit::WebString& challenge,
    785     const WebKit::WebURL& url) {
    786   return WebKit::WebString("");
    787 }
    788 
    789 static scoped_ptr<base::ProcessMetrics> CurrentProcessMetrics() {
    790   using base::ProcessMetrics;
    791 #if defined(OS_MACOSX)
    792   return scoped_ptr<ProcessMetrics>(
    793       // The default port provider is sufficient to get data for the current
    794       // process.
    795       ProcessMetrics::CreateProcessMetrics(base::GetCurrentProcessHandle(),
    796                                            NULL));
    797 #else
    798   return scoped_ptr<ProcessMetrics>(
    799       ProcessMetrics::CreateProcessMetrics(base::GetCurrentProcessHandle()));
    800 #endif
    801 }
    802 
    803 static size_t getMemoryUsageMB(bool bypass_cache) {
    804   size_t current_mem_usage = 0;
    805   MemoryUsageCache* mem_usage_cache_singleton = MemoryUsageCache::GetInstance();
    806   if (!bypass_cache &&
    807       mem_usage_cache_singleton->IsCachedValueValid(&current_mem_usage))
    808     return current_mem_usage;
    809 
    810   current_mem_usage = MemoryUsageKB() >> 10;
    811   mem_usage_cache_singleton->SetMemoryValue(current_mem_usage);
    812   return current_mem_usage;
    813 }
    814 
    815 size_t WebKitPlatformSupportImpl::memoryUsageMB() {
    816   return getMemoryUsageMB(false);
    817 }
    818 
    819 size_t WebKitPlatformSupportImpl::actualMemoryUsageMB() {
    820   return getMemoryUsageMB(true);
    821 }
    822 
    823 void WebKitPlatformSupportImpl::startHeapProfiling(
    824   const WebKit::WebString& prefix) {
    825   // FIXME(morrita): Make this built on windows.
    826 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
    827   HeapProfilerStart(prefix.utf8().data());
    828 #endif
    829 }
    830 
    831 void WebKitPlatformSupportImpl::stopHeapProfiling() {
    832 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
    833   HeapProfilerStop();
    834 #endif
    835 }
    836 
    837 void WebKitPlatformSupportImpl::dumpHeapProfiling(
    838   const WebKit::WebString& reason) {
    839 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
    840   HeapProfilerDump(reason.utf8().data());
    841 #endif
    842 }
    843 
    844 WebString WebKitPlatformSupportImpl::getHeapProfile() {
    845 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
    846   char* data = GetHeapProfile();
    847   WebString result = WebString::fromUTF8(std::string(data));
    848   free(data);
    849   return result;
    850 #else
    851   return WebString();
    852 #endif
    853 }
    854 
    855 bool WebKitPlatformSupportImpl::processMemorySizesInBytes(
    856     size_t* private_bytes,
    857     size_t* shared_bytes) {
    858   return CurrentProcessMetrics()->GetMemoryBytes(private_bytes, shared_bytes);
    859 }
    860 
    861 bool WebKitPlatformSupportImpl::memoryAllocatorWasteInBytes(size_t* size) {
    862   return base::allocator::GetAllocatorWasteSize(size);
    863 }
    864 
    865 void WebKitPlatformSupportImpl::SuspendSharedTimer() {
    866   ++shared_timer_suspended_;
    867 }
    868 
    869 void WebKitPlatformSupportImpl::ResumeSharedTimer() {
    870   // The shared timer may have fired or been adjusted while we were suspended.
    871   if (--shared_timer_suspended_ == 0 &&
    872       (!shared_timer_.IsRunning() ||
    873        shared_timer_fire_time_was_set_while_suspended_)) {
    874     shared_timer_fire_time_was_set_while_suspended_ = false;
    875     setSharedTimerFireInterval(
    876         shared_timer_fire_time_ - monotonicallyIncreasingTime());
    877   }
    878 }
    879 
    880 }  // namespace webkit_glue
    881