1// Copyright (c) 2011 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/glue/webkitclient_impl.h" 6 7#if defined(OS_LINUX) 8#include <malloc.h> 9#endif 10 11#include <math.h> 12 13#include <vector> 14 15#include "base/debug/trace_event.h" 16#include "base/memory/singleton.h" 17#include "base/message_loop.h" 18#include "base/metrics/histogram.h" 19#include "base/metrics/stats_counters.h" 20#include "base/platform_file.h" 21#include "base/process_util.h" 22#include "base/rand_util.h" 23#include "base/string_number_conversions.h" 24#include "base/string_util.h" 25#include "base/synchronization/lock.h" 26#include "base/time.h" 27#include "base/utf_string_conversions.h" 28#include "gpu/common/gpu_trace_event.h" 29#include "grit/webkit_chromium_resources.h" 30#include "grit/webkit_resources.h" 31#include "grit/webkit_strings.h" 32#include "third_party/WebKit/Source/WebKit/chromium/public/WebCookie.h" 33#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h" 34#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrameClient.h" 35#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginListBuilder.h" 36#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h" 37#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" 38#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" 39#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" 40#include "webkit/glue/media/audio_decoder.h" 41#include "webkit/plugins/npapi/plugin_instance.h" 42#include "webkit/plugins/npapi/webplugininfo.h" 43#include "webkit/glue/webkit_glue.h" 44#include "webkit/glue/websocketstreamhandle_impl.h" 45#include "webkit/glue/weburlloader_impl.h" 46 47#if defined(OS_LINUX) 48#include "v8/include/v8.h" 49#endif 50 51using WebKit::WebAudioBus; 52using WebKit::WebCookie; 53using WebKit::WebData; 54using WebKit::WebLocalizedString; 55using WebKit::WebPluginListBuilder; 56using WebKit::WebString; 57using WebKit::WebSocketStreamHandle; 58using WebKit::WebThemeEngine; 59using WebKit::WebURL; 60using WebKit::WebURLLoader; 61using WebKit::WebVector; 62 63namespace { 64 65// A simple class to cache the memory usage for a given amount of time. 66class MemoryUsageCache { 67 public: 68 // Retrieves the Singleton. 69 static MemoryUsageCache* GetInstance() { 70 return Singleton<MemoryUsageCache>::get(); 71 } 72 73 MemoryUsageCache() : memory_value_(0) { Init(); } 74 ~MemoryUsageCache() {} 75 76 void Init() { 77 const unsigned int kCacheSeconds = 1; 78 cache_valid_time_ = base::TimeDelta::FromSeconds(kCacheSeconds); 79 } 80 81 // Returns true if the cached value is fresh. 82 // Returns false if the cached value is stale, or if |cached_value| is NULL. 83 bool IsCachedValueValid(size_t* cached_value) { 84 base::AutoLock scoped_lock(lock_); 85 if (!cached_value) 86 return false; 87 if (base::Time::Now() - last_updated_time_ > cache_valid_time_) 88 return false; 89 *cached_value = memory_value_; 90 return true; 91 }; 92 93 // Setter for |memory_value_|, refreshes |last_updated_time_|. 94 void SetMemoryValue(const size_t value) { 95 base::AutoLock scoped_lock(lock_); 96 memory_value_ = value; 97 last_updated_time_ = base::Time::Now(); 98 } 99 100 private: 101 // The cached memory value. 102 size_t memory_value_; 103 104 // How long the cached value should remain valid. 105 base::TimeDelta cache_valid_time_; 106 107 // The last time the cached value was updated. 108 base::Time last_updated_time_; 109 110 base::Lock lock_; 111}; 112 113} // anonymous namespace 114 115namespace webkit_glue { 116 117static int ToMessageID(WebLocalizedString::Name name) { 118 switch (name) { 119 case WebLocalizedString::SubmitButtonDefaultLabel: 120 return IDS_FORM_SUBMIT_LABEL; 121 case WebLocalizedString::InputElementAltText: 122 return IDS_FORM_INPUT_ALT; 123 case WebLocalizedString::ResetButtonDefaultLabel: 124 return IDS_FORM_RESET_LABEL; 125 case WebLocalizedString::FileButtonChooseFileLabel: 126 return IDS_FORM_FILE_BUTTON_LABEL; 127 case WebLocalizedString::FileButtonNoFileSelectedLabel: 128 return IDS_FORM_FILE_NO_FILE_LABEL; 129 case WebLocalizedString::MultipleFileUploadText: 130 return IDS_FORM_FILE_MULTIPLE_UPLOAD; 131 case WebLocalizedString::SearchableIndexIntroduction: 132 return IDS_SEARCHABLE_INDEX_INTRO; 133 case WebLocalizedString::SearchMenuNoRecentSearchesText: 134 return IDS_RECENT_SEARCHES_NONE; 135 case WebLocalizedString::SearchMenuRecentSearchesText: 136 return IDS_RECENT_SEARCHES; 137 case WebLocalizedString::SearchMenuClearRecentSearchesText: 138 return IDS_RECENT_SEARCHES_CLEAR; 139 case WebLocalizedString::AXWebAreaText: 140 return IDS_AX_ROLE_WEB_AREA; 141 case WebLocalizedString::AXLinkText: 142 return IDS_AX_ROLE_LINK; 143 case WebLocalizedString::AXListMarkerText: 144 return IDS_AX_ROLE_LIST_MARKER; 145 case WebLocalizedString::AXImageMapText: 146 return IDS_AX_ROLE_IMAGE_MAP; 147 case WebLocalizedString::AXHeadingText: 148 return IDS_AX_ROLE_HEADING; 149 case WebLocalizedString::AXButtonActionVerb: 150 return IDS_AX_BUTTON_ACTION_VERB; 151 case WebLocalizedString::AXRadioButtonActionVerb: 152 return IDS_AX_RADIO_BUTTON_ACTION_VERB; 153 case WebLocalizedString::AXTextFieldActionVerb: 154 return IDS_AX_TEXT_FIELD_ACTION_VERB; 155 case WebLocalizedString::AXCheckedCheckBoxActionVerb: 156 return IDS_AX_CHECKED_CHECK_BOX_ACTION_VERB; 157 case WebLocalizedString::AXUncheckedCheckBoxActionVerb: 158 return IDS_AX_UNCHECKED_CHECK_BOX_ACTION_VERB; 159 case WebLocalizedString::AXLinkActionVerb: 160 return IDS_AX_LINK_ACTION_VERB; 161 case WebLocalizedString::KeygenMenuHighGradeKeySize: 162 return IDS_KEYGEN_HIGH_GRADE_KEY; 163 case WebLocalizedString::KeygenMenuMediumGradeKeySize: 164 return IDS_KEYGEN_MED_GRADE_KEY; 165 case WebLocalizedString::ValidationValueMissing: 166 return IDS_FORM_VALIDATION_VALUE_MISSING; 167 case WebLocalizedString::ValidationValueMissingForCheckbox: 168 return IDS_FORM_VALIDATION_VALUE_MISSING_CHECKBOX; 169 case WebLocalizedString::ValidationValueMissingForFile: 170 return IDS_FORM_VALIDATION_VALUE_MISSING_FILE; 171 case WebLocalizedString::ValidationValueMissingForMultipleFile: 172 return IDS_FORM_VALIDATION_VALUE_MISSING_MULTIPLE_FILE; 173 case WebLocalizedString::ValidationValueMissingForRadio: 174 return IDS_FORM_VALIDATION_VALUE_MISSING_RADIO; 175 case WebLocalizedString::ValidationValueMissingForSelect: 176 return IDS_FORM_VALIDATION_VALUE_MISSING_SELECT; 177 case WebLocalizedString::ValidationTypeMismatch: 178 return IDS_FORM_VALIDATION_TYPE_MISMATCH; 179 case WebLocalizedString::ValidationTypeMismatchForEmail: 180 return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL; 181 case WebLocalizedString::ValidationTypeMismatchForMultipleEmail: 182 return IDS_FORM_VALIDATION_TYPE_MISMATCH_MULTIPLE_EMAIL; 183 case WebLocalizedString::ValidationTypeMismatchForURL: 184 return IDS_FORM_VALIDATION_TYPE_MISMATCH_URL; 185 case WebLocalizedString::ValidationPatternMismatch: 186 return IDS_FORM_VALIDATION_PATTERN_MISMATCH; 187 case WebLocalizedString::ValidationTooLong: 188 return IDS_FORM_VALIDATION_TOO_LONG; 189 case WebLocalizedString::ValidationRangeUnderflow: 190 return IDS_FORM_VALIDATION_RANGE_UNDERFLOW; 191 case WebLocalizedString::ValidationRangeOverflow: 192 return IDS_FORM_VALIDATION_RANGE_OVERFLOW; 193 case WebLocalizedString::ValidationStepMismatch: 194 return IDS_FORM_VALIDATION_STEP_MISMATCH; 195 } 196 return -1; 197} 198 199WebKitClientImpl::WebKitClientImpl() 200 : main_loop_(MessageLoop::current()), 201 shared_timer_func_(NULL), 202 shared_timer_fire_time_(0.0), 203 shared_timer_suspended_(0) { 204} 205 206WebKitClientImpl::~WebKitClientImpl() { 207} 208 209WebThemeEngine* WebKitClientImpl::themeEngine() { 210#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) 211 return &theme_engine_; 212#else 213 return NULL; 214#endif 215} 216 217WebURLLoader* WebKitClientImpl::createURLLoader() { 218 return new WebURLLoaderImpl(); 219} 220 221WebSocketStreamHandle* WebKitClientImpl::createSocketStreamHandle() { 222 return new WebSocketStreamHandleImpl(); 223} 224 225WebString WebKitClientImpl::userAgent(const WebURL& url) { 226 return WebString::fromUTF8(webkit_glue::GetUserAgent(url)); 227} 228 229void WebKitClientImpl::getPluginList(bool refresh, 230 WebPluginListBuilder* builder) { 231 std::vector<webkit::npapi::WebPluginInfo> plugins; 232 GetPlugins(refresh, &plugins); 233 234 for (size_t i = 0; i < plugins.size(); ++i) { 235 const webkit::npapi::WebPluginInfo& plugin = plugins[i]; 236 237 builder->addPlugin( 238 plugin.name, plugin.desc, 239 FilePathStringToWebString(plugin.path.BaseName().value())); 240 241 for (size_t j = 0; j < plugin.mime_types.size(); ++j) { 242 const webkit::npapi::WebPluginMimeType& mime_type = plugin.mime_types[j]; 243 244 builder->addMediaTypeToLastPlugin( 245 WebString::fromUTF8(mime_type.mime_type), mime_type.description); 246 247 for (size_t k = 0; k < mime_type.file_extensions.size(); ++k) { 248 builder->addFileExtensionToLastMediaType( 249 UTF8ToUTF16(mime_type.file_extensions[k])); 250 } 251 } 252 } 253} 254 255void WebKitClientImpl::decrementStatsCounter(const char* name) { 256 base::StatsCounter(name).Decrement(); 257} 258 259void WebKitClientImpl::incrementStatsCounter(const char* name) { 260 base::StatsCounter(name).Increment(); 261} 262 263void WebKitClientImpl::histogramCustomCounts( 264 const char* name, int sample, int min, int max, int bucket_count) { 265 // Copied from histogram macro, but without the static variable caching 266 // the histogram because name is dynamic. 267 base::Histogram* counter = 268 base::Histogram::FactoryGet(name, min, max, bucket_count, 269 base::Histogram::kUmaTargetedHistogramFlag); 270 DCHECK_EQ(name, counter->histogram_name()); 271 counter->Add(sample); 272} 273 274void WebKitClientImpl::histogramEnumeration( 275 const char* name, int sample, int boundary_value) { 276 // Copied from histogram macro, but without the static variable caching 277 // the histogram because name is dynamic. 278 base::Histogram* counter = 279 base::LinearHistogram::FactoryGet(name, 1, boundary_value, 280 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); 281 DCHECK_EQ(name, counter->histogram_name()); 282 counter->Add(sample); 283} 284 285void WebKitClientImpl::traceEventBegin(const char* name, void* id, 286 const char* extra) { 287 TRACE_EVENT_BEGIN(name, id, extra); 288 GPU_TRACE_EVENT_BEGIN2("webkit", name, 289 "id", StringPrintf("%p", id).c_str(), 290 "extra", extra ? extra : ""); 291} 292 293void WebKitClientImpl::traceEventEnd(const char* name, void* id, 294 const char* extra) { 295 TRACE_EVENT_END(name, id, extra); 296 GPU_TRACE_EVENT_END0("webkit", name); 297} 298 299namespace { 300 301WebData loadAudioSpatializationResource(const char* name) { 302#ifdef IDR_AUDIO_SPATIALIZATION_T000_P000 303 const size_t kExpectedSpatializationNameLength = 31; 304 if (strlen(name) != kExpectedSpatializationNameLength) { 305 return WebData(); 306 } 307 308 // Extract the azimuth and elevation from the resource name. 309 int azimuth = 0; 310 int elevation = 0; 311 int values_parsed = 312 sscanf(name, "IRC_Composite_C_R0195_T%3d_P%3d", &azimuth, &elevation); 313 if (values_parsed != 2) { 314 return WebData(); 315 } 316 317 // The resource index values go through the elevations first, then azimuths. 318 const int kAngleSpacing = 15; 319 320 // 0 <= elevation <= 90 (or 315 <= elevation <= 345) 321 // in increments of 15 degrees. 322 int elevation_index = 323 elevation <= 90 ? elevation / kAngleSpacing : 324 7 + (elevation - 315) / kAngleSpacing; 325 bool is_elevation_index_good = 0 <= elevation_index && elevation_index < 10; 326 327 // 0 <= azimuth < 360 in increments of 15 degrees. 328 int azimuth_index = azimuth / kAngleSpacing; 329 bool is_azimuth_index_good = 0 <= azimuth_index && azimuth_index < 24; 330 331 const int kNumberOfElevations = 10; 332 const int kNumberOfAudioResources = 240; 333 int resource_index = kNumberOfElevations * azimuth_index + elevation_index; 334 bool is_resource_index_good = 0 <= resource_index && 335 resource_index < kNumberOfAudioResources; 336 337 if (is_azimuth_index_good && is_elevation_index_good && 338 is_resource_index_good) { 339 const int kFirstAudioResourceIndex = IDR_AUDIO_SPATIALIZATION_T000_P000; 340 base::StringPiece resource = 341 GetDataResource(kFirstAudioResourceIndex + resource_index); 342 return WebData(resource.data(), resource.size()); 343 } 344#endif // IDR_AUDIO_SPATIALIZATION_T000_P000 345 346 NOTREACHED(); 347 return WebData(); 348} 349 350} // namespace 351 352WebData WebKitClientImpl::loadResource(const char* name) { 353 struct { 354 const char* name; 355 int id; 356 } resources[] = { 357 { "missingImage", IDR_BROKENIMAGE }, 358 { "mediaPause", IDR_MEDIA_PAUSE_BUTTON }, 359 { "mediaPlay", IDR_MEDIA_PLAY_BUTTON }, 360 { "mediaPlayDisabled", IDR_MEDIA_PLAY_BUTTON_DISABLED }, 361 { "mediaSoundDisabled", IDR_MEDIA_SOUND_DISABLED }, 362 { "mediaSoundFull", IDR_MEDIA_SOUND_FULL_BUTTON }, 363 { "mediaSoundNone", IDR_MEDIA_SOUND_NONE_BUTTON }, 364 { "mediaSliderThumb", IDR_MEDIA_SLIDER_THUMB }, 365 { "mediaVolumeSliderThumb", IDR_MEDIA_VOLUME_SLIDER_THUMB }, 366 { "panIcon", IDR_PAN_SCROLL_ICON }, 367 { "searchCancel", IDR_SEARCH_CANCEL }, 368 { "searchCancelPressed", IDR_SEARCH_CANCEL_PRESSED }, 369 { "searchMagnifier", IDR_SEARCH_MAGNIFIER }, 370 { "searchMagnifierResults", IDR_SEARCH_MAGNIFIER_RESULTS }, 371 { "textAreaResizeCorner", IDR_TEXTAREA_RESIZER }, 372 { "tickmarkDash", IDR_TICKMARK_DASH }, 373 { "inputSpeech", IDR_INPUT_SPEECH }, 374 { "inputSpeechRecording", IDR_INPUT_SPEECH_RECORDING }, 375 { "inputSpeechWaiting", IDR_INPUT_SPEECH_WAITING }, 376 { "americanExpressCC", IDR_AUTOFILL_CC_AMEX }, 377 { "dinersCC", IDR_AUTOFILL_CC_DINERS }, 378 { "discoverCC", IDR_AUTOFILL_CC_DISCOVER }, 379 { "genericCC", IDR_AUTOFILL_CC_GENERIC }, 380 { "jcbCC", IDR_AUTOFILL_CC_JCB }, 381 { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD }, 382 { "soloCC", IDR_AUTOFILL_CC_SOLO }, 383 { "visaCC", IDR_AUTOFILL_CC_VISA }, 384 }; 385 386 // Check the name prefix to see if it's an audio resource. 387 if (StartsWithASCII(name, "IRC_Composite", true)) { 388 return loadAudioSpatializationResource(name); 389 } else { 390 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resources); ++i) { 391 if (!strcmp(name, resources[i].name)) { 392 base::StringPiece resource = GetDataResource(resources[i].id); 393 return WebData(resource.data(), resource.size()); 394 } 395 } 396 } 397 // TODO(jhawkins): Restore this NOTREACHED once WK stops sending in empty 398 // strings. http://crbug.com/50675. 399 //NOTREACHED() << "Unknown image resource " << name; 400 return WebData(); 401} 402 403bool WebKitClientImpl::loadAudioResource( 404 WebKit::WebAudioBus* destination_bus, const char* audio_file_data, 405 size_t data_size, double sample_rate) { 406 return DecodeAudioFileData(destination_bus, 407 audio_file_data, 408 data_size, 409 sample_rate); 410} 411 412WebString WebKitClientImpl::queryLocalizedString( 413 WebLocalizedString::Name name) { 414 int message_id = ToMessageID(name); 415 if (message_id < 0) 416 return WebString(); 417 return GetLocalizedString(message_id); 418} 419 420WebString WebKitClientImpl::queryLocalizedString( 421 WebLocalizedString::Name name, int numeric_value) { 422 return queryLocalizedString(name, base::IntToString16(numeric_value)); 423} 424 425WebString WebKitClientImpl::queryLocalizedString( 426 WebLocalizedString::Name name, const WebString& value) { 427 int message_id = ToMessageID(name); 428 if (message_id < 0) 429 return WebString(); 430 return ReplaceStringPlaceholders(GetLocalizedString(message_id), value, NULL); 431} 432 433WebString WebKitClientImpl::queryLocalizedString( 434 WebLocalizedString::Name name, 435 const WebString& value1, 436 const WebString& value2) { 437 int message_id = ToMessageID(name); 438 if (message_id < 0) 439 return WebString(); 440 std::vector<string16> values; 441 values.reserve(2); 442 values.push_back(value1); 443 values.push_back(value2); 444 return ReplaceStringPlaceholders( 445 GetLocalizedString(message_id), values, NULL); 446} 447 448double WebKitClientImpl::currentTime() { 449 return base::Time::Now().ToDoubleT(); 450} 451 452void WebKitClientImpl::cryptographicallyRandomValues( 453 unsigned char* buffer, size_t length) { 454 uint64 bytes = 0; 455 for (size_t i = 0; i < length; ++i) { 456 size_t offset = i % sizeof(bytes); 457 if (!offset) 458 bytes = base::RandUint64(); 459 buffer[i] = reinterpret_cast<unsigned char*>(&bytes)[offset]; 460 } 461} 462 463void WebKitClientImpl::setSharedTimerFiredFunction(void (*func)()) { 464 shared_timer_func_ = func; 465} 466 467void WebKitClientImpl::setSharedTimerFireTime(double fire_time) { 468 shared_timer_fire_time_ = fire_time; 469 if (shared_timer_suspended_) 470 return; 471 472 // By converting between double and int64 representation, we run the risk 473 // of losing precision due to rounding errors. Performing computations in 474 // microseconds reduces this risk somewhat. But there still is the potential 475 // of us computing a fire time for the timer that is shorter than what we 476 // need. 477 // As the event loop will check event deadlines prior to actually firing 478 // them, there is a risk of needlessly rescheduling events and of 479 // needlessly looping if sleep times are too short even by small amounts. 480 // This results in measurable performance degradation unless we use ceil() to 481 // always round up the sleep times. 482 int64 interval = static_cast<int64>( 483 ceil((fire_time - currentTime()) * base::Time::kMicrosecondsPerSecond)); 484 if (interval < 0) 485 interval = 0; 486 487 shared_timer_.Stop(); 488 shared_timer_.Start(base::TimeDelta::FromMicroseconds(interval), this, 489 &WebKitClientImpl::DoTimeout); 490} 491 492void WebKitClientImpl::stopSharedTimer() { 493 shared_timer_.Stop(); 494} 495 496void WebKitClientImpl::callOnMainThread(void (*func)(void*), void* context) { 497 main_loop_->PostTask(FROM_HERE, NewRunnableFunction(func, context)); 498} 499 500base::PlatformFile WebKitClientImpl::databaseOpenFile( 501 const WebKit::WebString& vfs_file_name, int desired_flags) { 502 return base::kInvalidPlatformFileValue; 503} 504 505int WebKitClientImpl::databaseDeleteFile( 506 const WebKit::WebString& vfs_file_name, bool sync_dir) { 507 return -1; 508} 509 510long WebKitClientImpl::databaseGetFileAttributes( 511 const WebKit::WebString& vfs_file_name) { 512 return 0; 513} 514 515long long WebKitClientImpl::databaseGetFileSize( 516 const WebKit::WebString& vfs_file_name) { 517 return 0; 518} 519 520WebKit::WebString WebKitClientImpl::signedPublicKeyAndChallengeString( 521 unsigned key_size_index, 522 const WebKit::WebString& challenge, 523 const WebKit::WebURL& url) { 524 NOTREACHED(); 525 return WebKit::WebString(); 526} 527 528#if defined(OS_LINUX) 529static size_t memoryUsageMBLinux() { 530 struct mallinfo minfo = mallinfo(); 531 uint64_t mem_usage = 532#if defined(USE_TCMALLOC) 533 minfo.uordblks 534#else 535 (minfo.hblkhd + minfo.arena) 536#endif 537 >> 20; 538 539 v8::HeapStatistics stat; 540 v8::V8::GetHeapStatistics(&stat); 541 return mem_usage + (static_cast<uint64_t>(stat.total_heap_size()) >> 20); 542} 543#endif 544 545#if defined(OS_MACOSX) 546static size_t memoryUsageMBMac() { 547 using base::ProcessMetrics; 548 static ProcessMetrics* process_metrics = 549 // The default port provider is sufficient to get data for the current 550 // process. 551 ProcessMetrics::CreateProcessMetrics(base::GetCurrentProcessHandle(), 552 NULL); 553 DCHECK(process_metrics); 554 return process_metrics->GetPagefileUsage() >> 20; 555} 556#endif 557 558#if !defined(OS_LINUX) && !defined(OS_MACOSX) 559static size_t memoryUsageMBGeneric() { 560 using base::ProcessMetrics; 561 static ProcessMetrics* process_metrics = 562 ProcessMetrics::CreateProcessMetrics(base::GetCurrentProcessHandle()); 563 DCHECK(process_metrics); 564 return process_metrics->GetPagefileUsage() >> 20; 565} 566#endif 567 568static size_t getMemoryUsageMB(bool bypass_cache) { 569 size_t current_mem_usage = 0; 570 MemoryUsageCache* mem_usage_cache_singleton = MemoryUsageCache::GetInstance(); 571 if (!bypass_cache && 572 mem_usage_cache_singleton->IsCachedValueValid(¤t_mem_usage)) 573 return current_mem_usage; 574 575 current_mem_usage = 576#if defined(OS_LINUX) 577 memoryUsageMBLinux(); 578#elif defined(OS_MACOSX) 579 memoryUsageMBMac(); 580#else 581 memoryUsageMBGeneric(); 582#endif 583 mem_usage_cache_singleton->SetMemoryValue(current_mem_usage); 584 return current_mem_usage; 585} 586 587size_t WebKitClientImpl::memoryUsageMB() { 588 return getMemoryUsageMB(false); 589} 590 591size_t WebKitClientImpl::actualMemoryUsageMB() { 592 return getMemoryUsageMB(true); 593} 594 595void WebKitClientImpl::SuspendSharedTimer() { 596 ++shared_timer_suspended_; 597} 598 599void WebKitClientImpl::ResumeSharedTimer() { 600 // The shared timer may have fired or been adjusted while we were suspended. 601 if (--shared_timer_suspended_ == 0 && !shared_timer_.IsRunning()) 602 setSharedTimerFireTime(shared_timer_fire_time_); 603} 604 605} // namespace webkit_glue 606