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