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 51 using WebKit::WebAudioBus; 52 using WebKit::WebCookie; 53 using WebKit::WebData; 54 using WebKit::WebLocalizedString; 55 using WebKit::WebPluginListBuilder; 56 using WebKit::WebString; 57 using WebKit::WebSocketStreamHandle; 58 using WebKit::WebThemeEngine; 59 using WebKit::WebURL; 60 using WebKit::WebURLLoader; 61 using WebKit::WebVector; 62 63 namespace { 64 65 // A simple class to cache the memory usage for a given amount of time. 66 class 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 115 namespace webkit_glue { 116 117 static 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 199 WebKitClientImpl::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 206 WebKitClientImpl::~WebKitClientImpl() { 207 } 208 209 WebThemeEngine* 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 217 WebURLLoader* WebKitClientImpl::createURLLoader() { 218 return new WebURLLoaderImpl(); 219 } 220 221 WebSocketStreamHandle* WebKitClientImpl::createSocketStreamHandle() { 222 return new WebSocketStreamHandleImpl(); 223 } 224 225 WebString WebKitClientImpl::userAgent(const WebURL& url) { 226 return WebString::fromUTF8(webkit_glue::GetUserAgent(url)); 227 } 228 229 void 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 255 void WebKitClientImpl::decrementStatsCounter(const char* name) { 256 base::StatsCounter(name).Decrement(); 257 } 258 259 void WebKitClientImpl::incrementStatsCounter(const char* name) { 260 base::StatsCounter(name).Increment(); 261 } 262 263 void 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 274 void 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 285 void 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 293 void 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 299 namespace { 300 301 WebData 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 352 WebData 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 403 bool 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 412 WebString 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 420 WebString WebKitClientImpl::queryLocalizedString( 421 WebLocalizedString::Name name, int numeric_value) { 422 return queryLocalizedString(name, base::IntToString16(numeric_value)); 423 } 424 425 WebString 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 433 WebString 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 448 double WebKitClientImpl::currentTime() { 449 return base::Time::Now().ToDoubleT(); 450 } 451 452 void 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 463 void WebKitClientImpl::setSharedTimerFiredFunction(void (*func)()) { 464 shared_timer_func_ = func; 465 } 466 467 void 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 492 void WebKitClientImpl::stopSharedTimer() { 493 shared_timer_.Stop(); 494 } 495 496 void WebKitClientImpl::callOnMainThread(void (*func)(void*), void* context) { 497 main_loop_->PostTask(FROM_HERE, NewRunnableFunction(func, context)); 498 } 499 500 base::PlatformFile WebKitClientImpl::databaseOpenFile( 501 const WebKit::WebString& vfs_file_name, int desired_flags) { 502 return base::kInvalidPlatformFileValue; 503 } 504 505 int WebKitClientImpl::databaseDeleteFile( 506 const WebKit::WebString& vfs_file_name, bool sync_dir) { 507 return -1; 508 } 509 510 long WebKitClientImpl::databaseGetFileAttributes( 511 const WebKit::WebString& vfs_file_name) { 512 return 0; 513 } 514 515 long long WebKitClientImpl::databaseGetFileSize( 516 const WebKit::WebString& vfs_file_name) { 517 return 0; 518 } 519 520 WebKit::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) 529 static 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) 546 static 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) 559 static 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 568 static 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 587 size_t WebKitClientImpl::memoryUsageMB() { 588 return getMemoryUsageMB(false); 589 } 590 591 size_t WebKitClientImpl::actualMemoryUsageMB() { 592 return getMemoryUsageMB(true); 593 } 594 595 void WebKitClientImpl::SuspendSharedTimer() { 596 ++shared_timer_suspended_; 597 } 598 599 void 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