summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
Diffstat (limited to 'webkit')
-rw-r--r--webkit/child/ftp_directory_listing_response_delegate.h3
-rw-r--r--webkit/child/webkit_child.gyp8
-rw-r--r--webkit/child/webkitplatformsupport_impl.cc918
-rw-r--r--webkit/child/webkitplatformsupport_impl.h156
-rw-r--r--webkit/child/websocketstreamhandle_bridge.h37
-rw-r--r--webkit/child/websocketstreamhandle_delegate.h44
-rw-r--r--webkit/child/websocketstreamhandle_impl.cc197
-rw-r--r--webkit/child/websocketstreamhandle_impl.h40
-rw-r--r--webkit/child/weburlloader_impl.cc871
-rw-r--r--webkit/child/weburlloader_impl.h51
10 files changed, 2323 insertions, 2 deletions
diff --git a/webkit/child/ftp_directory_listing_response_delegate.h b/webkit/child/ftp_directory_listing_response_delegate.h
index af18f38..254ca80 100644
--- a/webkit/child/ftp_directory_listing_response_delegate.h
+++ b/webkit/child/ftp_directory_listing_response_delegate.h
@@ -12,7 +12,6 @@
#include "base/basictypes.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "webkit/child/webkit_child_export.h"
namespace blink {
class WebURLLoader;
@@ -23,7 +22,7 @@ class GURL;
namespace webkit_glue {
-class WEBKIT_CHILD_EXPORT FtpDirectoryListingResponseDelegate {
+class FtpDirectoryListingResponseDelegate {
public:
FtpDirectoryListingResponseDelegate(blink::WebURLLoaderClient* client,
blink::WebURLLoader* loader,
diff --git a/webkit/child/webkit_child.gyp b/webkit/child/webkit_child.gyp
index cf341e52..6183b7b 100644
--- a/webkit/child/webkit_child.gyp
+++ b/webkit/child/webkit_child.gyp
@@ -67,6 +67,14 @@
'webkit_child_export.h',
'webkit_child_helpers.cc',
'webkit_child_helpers.h',
+ 'webkitplatformsupport_impl.cc',
+ 'webkitplatformsupport_impl.h',
+ 'websocketstreamhandle_bridge.h',
+ 'websocketstreamhandle_delegate.h',
+ 'websocketstreamhandle_impl.cc',
+ 'websocketstreamhandle_impl.h',
+ 'weburlloader_impl.cc',
+ 'weburlloader_impl.h',
'weburlrequest_extradata_impl.cc',
'weburlrequest_extradata_impl.h',
'weburlresponse_extradata_impl.cc',
diff --git a/webkit/child/webkitplatformsupport_impl.cc b/webkit/child/webkitplatformsupport_impl.cc
new file mode 100644
index 0000000..1c55e13
--- /dev/null
+++ b/webkit/child/webkitplatformsupport_impl.cc
@@ -0,0 +1,918 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/child/webkitplatformsupport_impl.h"
+
+#include <math.h>
+
+#include <vector>
+
+#include "base/allocator/allocator_extension.h"
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
+#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
+#include "base/metrics/stats_counters.h"
+#include "base/platform_file.h"
+#include "base/process/process_metrics.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
+#include "base/sys_info.h"
+#include "base/time/time.h"
+#include "grit/blink_resources.h"
+#include "grit/webkit_resources.h"
+#include "grit/webkit_strings.h"
+#include "net/base/data_url.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_errors.h"
+#include "third_party/WebKit/public/platform/WebData.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "ui/base/layout.h"
+#include "webkit/child/webkit_child_helpers.h"
+#include "webkit/child/websocketstreamhandle_impl.h"
+#include "webkit/child/weburlloader_impl.h"
+#include "webkit/common/user_agent/user_agent.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/sys_utils.h"
+#endif
+
+#if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
+#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
+#endif
+
+using blink::WebData;
+using blink::WebLocalizedString;
+using blink::WebString;
+using blink::WebSocketStreamHandle;
+using blink::WebURL;
+using blink::WebURLError;
+using blink::WebURLLoader;
+
+namespace {
+
+// A simple class to cache the memory usage for a given amount of time.
+class MemoryUsageCache {
+ public:
+ // Retrieves the Singleton.
+ static MemoryUsageCache* GetInstance() {
+ return Singleton<MemoryUsageCache>::get();
+ }
+
+ MemoryUsageCache() : memory_value_(0) { Init(); }
+ ~MemoryUsageCache() {}
+
+ void Init() {
+ const unsigned int kCacheSeconds = 1;
+ cache_valid_time_ = base::TimeDelta::FromSeconds(kCacheSeconds);
+ }
+
+ // Returns true if the cached value is fresh.
+ // Returns false if the cached value is stale, or if |cached_value| is NULL.
+ bool IsCachedValueValid(size_t* cached_value) {
+ base::AutoLock scoped_lock(lock_);
+ if (!cached_value)
+ return false;
+ if (base::Time::Now() - last_updated_time_ > cache_valid_time_)
+ return false;
+ *cached_value = memory_value_;
+ return true;
+ };
+
+ // Setter for |memory_value_|, refreshes |last_updated_time_|.
+ void SetMemoryValue(const size_t value) {
+ base::AutoLock scoped_lock(lock_);
+ memory_value_ = value;
+ last_updated_time_ = base::Time::Now();
+ }
+
+ private:
+ // The cached memory value.
+ size_t memory_value_;
+
+ // How long the cached value should remain valid.
+ base::TimeDelta cache_valid_time_;
+
+ // The last time the cached value was updated.
+ base::Time last_updated_time_;
+
+ base::Lock lock_;
+};
+
+} // anonymous namespace
+
+namespace webkit_glue {
+
+static int ToMessageID(WebLocalizedString::Name name) {
+ switch (name) {
+ case WebLocalizedString::AXAMPMFieldText:
+ return IDS_AX_AM_PM_FIELD_TEXT;
+ case WebLocalizedString::AXButtonActionVerb:
+ return IDS_AX_BUTTON_ACTION_VERB;
+ case WebLocalizedString::AXCheckedCheckBoxActionVerb:
+ return IDS_AX_CHECKED_CHECK_BOX_ACTION_VERB;
+ case WebLocalizedString::AXDateTimeFieldEmptyValueText:
+ return IDS_AX_DATE_TIME_FIELD_EMPTY_VALUE_TEXT;
+ case WebLocalizedString::AXDayOfMonthFieldText:
+ return IDS_AX_DAY_OF_MONTH_FIELD_TEXT;
+ case WebLocalizedString::AXHeadingText:
+ return IDS_AX_ROLE_HEADING;
+ case WebLocalizedString::AXHourFieldText:
+ return IDS_AX_HOUR_FIELD_TEXT;
+ case WebLocalizedString::AXImageMapText:
+ return IDS_AX_ROLE_IMAGE_MAP;
+ case WebLocalizedString::AXLinkActionVerb:
+ return IDS_AX_LINK_ACTION_VERB;
+ case WebLocalizedString::AXLinkText:
+ return IDS_AX_ROLE_LINK;
+ case WebLocalizedString::AXListMarkerText:
+ return IDS_AX_ROLE_LIST_MARKER;
+ case WebLocalizedString::AXMediaDefault:
+ return IDS_AX_MEDIA_DEFAULT;
+ case WebLocalizedString::AXMediaAudioElement:
+ return IDS_AX_MEDIA_AUDIO_ELEMENT;
+ case WebLocalizedString::AXMediaVideoElement:
+ return IDS_AX_MEDIA_VIDEO_ELEMENT;
+ case WebLocalizedString::AXMediaMuteButton:
+ return IDS_AX_MEDIA_MUTE_BUTTON;
+ case WebLocalizedString::AXMediaUnMuteButton:
+ return IDS_AX_MEDIA_UNMUTE_BUTTON;
+ case WebLocalizedString::AXMediaPlayButton:
+ return IDS_AX_MEDIA_PLAY_BUTTON;
+ case WebLocalizedString::AXMediaPauseButton:
+ return IDS_AX_MEDIA_PAUSE_BUTTON;
+ case WebLocalizedString::AXMediaSlider:
+ return IDS_AX_MEDIA_SLIDER;
+ case WebLocalizedString::AXMediaSliderThumb:
+ return IDS_AX_MEDIA_SLIDER_THUMB;
+ case WebLocalizedString::AXMediaCurrentTimeDisplay:
+ return IDS_AX_MEDIA_CURRENT_TIME_DISPLAY;
+ case WebLocalizedString::AXMediaTimeRemainingDisplay:
+ return IDS_AX_MEDIA_TIME_REMAINING_DISPLAY;
+ case WebLocalizedString::AXMediaStatusDisplay:
+ return IDS_AX_MEDIA_STATUS_DISPLAY;
+ case WebLocalizedString::AXMediaEnterFullscreenButton:
+ return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON;
+ case WebLocalizedString::AXMediaExitFullscreenButton:
+ return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON;
+ case WebLocalizedString::AXMediaShowClosedCaptionsButton:
+ return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON;
+ case WebLocalizedString::AXMediaHideClosedCaptionsButton:
+ return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON;
+ case WebLocalizedString::AXMediaAudioElementHelp:
+ return IDS_AX_MEDIA_AUDIO_ELEMENT_HELP;
+ case WebLocalizedString::AXMediaVideoElementHelp:
+ return IDS_AX_MEDIA_VIDEO_ELEMENT_HELP;
+ case WebLocalizedString::AXMediaMuteButtonHelp:
+ return IDS_AX_MEDIA_MUTE_BUTTON_HELP;
+ case WebLocalizedString::AXMediaUnMuteButtonHelp:
+ return IDS_AX_MEDIA_UNMUTE_BUTTON_HELP;
+ case WebLocalizedString::AXMediaPlayButtonHelp:
+ return IDS_AX_MEDIA_PLAY_BUTTON_HELP;
+ case WebLocalizedString::AXMediaPauseButtonHelp:
+ return IDS_AX_MEDIA_PAUSE_BUTTON_HELP;
+ case WebLocalizedString::AXMediaSliderHelp:
+ return IDS_AX_MEDIA_SLIDER_HELP;
+ case WebLocalizedString::AXMediaSliderThumbHelp:
+ return IDS_AX_MEDIA_SLIDER_THUMB_HELP;
+ case WebLocalizedString::AXMediaCurrentTimeDisplayHelp:
+ return IDS_AX_MEDIA_CURRENT_TIME_DISPLAY_HELP;
+ case WebLocalizedString::AXMediaTimeRemainingDisplayHelp:
+ return IDS_AX_MEDIA_TIME_REMAINING_DISPLAY_HELP;
+ case WebLocalizedString::AXMediaStatusDisplayHelp:
+ return IDS_AX_MEDIA_STATUS_DISPLAY_HELP;
+ case WebLocalizedString::AXMediaEnterFullscreenButtonHelp:
+ return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON_HELP;
+ case WebLocalizedString::AXMediaExitFullscreenButtonHelp:
+ return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON_HELP;
+ case WebLocalizedString::AXMediaShowClosedCaptionsButtonHelp:
+ return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON_HELP;
+ case WebLocalizedString::AXMediaHideClosedCaptionsButtonHelp:
+ return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON_HELP;
+ case WebLocalizedString::AXMillisecondFieldText:
+ return IDS_AX_MILLISECOND_FIELD_TEXT;
+ case WebLocalizedString::AXMinuteFieldText:
+ return IDS_AX_MINUTE_FIELD_TEXT;
+ case WebLocalizedString::AXMonthFieldText:
+ return IDS_AX_MONTH_FIELD_TEXT;
+ case WebLocalizedString::AXRadioButtonActionVerb:
+ return IDS_AX_RADIO_BUTTON_ACTION_VERB;
+ case WebLocalizedString::AXSecondFieldText:
+ return IDS_AX_SECOND_FIELD_TEXT;
+ case WebLocalizedString::AXTextFieldActionVerb:
+ return IDS_AX_TEXT_FIELD_ACTION_VERB;
+ case WebLocalizedString::AXUncheckedCheckBoxActionVerb:
+ return IDS_AX_UNCHECKED_CHECK_BOX_ACTION_VERB;
+ case WebLocalizedString::AXWebAreaText:
+ return IDS_AX_ROLE_WEB_AREA;
+ case WebLocalizedString::AXWeekOfYearFieldText:
+ return IDS_AX_WEEK_OF_YEAR_FIELD_TEXT;
+ case WebLocalizedString::AXYearFieldText:
+ return IDS_AX_YEAR_FIELD_TEXT;
+ case WebLocalizedString::CalendarClear:
+ return IDS_FORM_CALENDAR_CLEAR;
+ case WebLocalizedString::CalendarToday:
+ return IDS_FORM_CALENDAR_TODAY;
+ case WebLocalizedString::DateFormatDayInMonthLabel:
+ return IDS_FORM_DATE_FORMAT_DAY_IN_MONTH;
+ case WebLocalizedString::DateFormatMonthLabel:
+ return IDS_FORM_DATE_FORMAT_MONTH;
+ case WebLocalizedString::DateFormatYearLabel:
+ return IDS_FORM_DATE_FORMAT_YEAR;
+ case WebLocalizedString::DetailsLabel:
+ return IDS_DETAILS_WITHOUT_SUMMARY_LABEL;
+ case WebLocalizedString::FileButtonChooseFileLabel:
+ return IDS_FORM_FILE_BUTTON_LABEL;
+ case WebLocalizedString::FileButtonChooseMultipleFilesLabel:
+ return IDS_FORM_MULTIPLE_FILES_BUTTON_LABEL;
+ case WebLocalizedString::FileButtonNoFileSelectedLabel:
+ return IDS_FORM_FILE_NO_FILE_LABEL;
+ case WebLocalizedString::InputElementAltText:
+ return IDS_FORM_INPUT_ALT;
+ case WebLocalizedString::KeygenMenuHighGradeKeySize:
+ return IDS_KEYGEN_HIGH_GRADE_KEY;
+ case WebLocalizedString::KeygenMenuMediumGradeKeySize:
+ return IDS_KEYGEN_MED_GRADE_KEY;
+ case WebLocalizedString::MissingPluginText:
+ return IDS_PLUGIN_INITIALIZATION_ERROR;
+ case WebLocalizedString::MultipleFileUploadText:
+ return IDS_FORM_FILE_MULTIPLE_UPLOAD;
+ case WebLocalizedString::OtherColorLabel:
+ return IDS_FORM_OTHER_COLOR_LABEL;
+ case WebLocalizedString::OtherDateLabel:
+ return IDS_FORM_OTHER_DATE_LABEL;
+ case WebLocalizedString::OtherMonthLabel:
+ return IDS_FORM_OTHER_MONTH_LABEL;
+ case WebLocalizedString::OtherTimeLabel:
+ return IDS_FORM_OTHER_TIME_LABEL;
+ case WebLocalizedString::OtherWeekLabel:
+ return IDS_FORM_OTHER_WEEK_LABEL;
+ case WebLocalizedString::PlaceholderForDayOfMonthField:
+ return IDS_FORM_PLACEHOLDER_FOR_DAY_OF_MONTH_FIELD;
+ case WebLocalizedString::PlaceholderForMonthField:
+ return IDS_FORM_PLACEHOLDER_FOR_MONTH_FIELD;
+ case WebLocalizedString::PlaceholderForYearField:
+ return IDS_FORM_PLACEHOLDER_FOR_YEAR_FIELD;
+ case WebLocalizedString::ResetButtonDefaultLabel:
+ return IDS_FORM_RESET_LABEL;
+ case WebLocalizedString::SearchableIndexIntroduction:
+ return IDS_SEARCHABLE_INDEX_INTRO;
+ case WebLocalizedString::SearchMenuClearRecentSearchesText:
+ return IDS_RECENT_SEARCHES_CLEAR;
+ case WebLocalizedString::SearchMenuNoRecentSearchesText:
+ return IDS_RECENT_SEARCHES_NONE;
+ case WebLocalizedString::SearchMenuRecentSearchesText:
+ return IDS_RECENT_SEARCHES;
+ case WebLocalizedString::SubmitButtonDefaultLabel:
+ return IDS_FORM_SUBMIT_LABEL;
+ case WebLocalizedString::ThisMonthButtonLabel:
+ return IDS_FORM_THIS_MONTH_LABEL;
+ case WebLocalizedString::ThisWeekButtonLabel:
+ return IDS_FORM_THIS_WEEK_LABEL;
+ case WebLocalizedString::ValidationBadInputForDateTime:
+ return IDS_FORM_VALIDATION_BAD_INPUT_DATETIME;
+ case WebLocalizedString::ValidationBadInputForNumber:
+ return IDS_FORM_VALIDATION_BAD_INPUT_NUMBER;
+ case WebLocalizedString::ValidationPatternMismatch:
+ return IDS_FORM_VALIDATION_PATTERN_MISMATCH;
+ case WebLocalizedString::ValidationRangeOverflow:
+ return IDS_FORM_VALIDATION_RANGE_OVERFLOW;
+ case WebLocalizedString::ValidationRangeOverflowDateTime:
+ return IDS_FORM_VALIDATION_RANGE_OVERFLOW_DATETIME;
+ case WebLocalizedString::ValidationRangeUnderflow:
+ return IDS_FORM_VALIDATION_RANGE_UNDERFLOW;
+ case WebLocalizedString::ValidationRangeUnderflowDateTime:
+ return IDS_FORM_VALIDATION_RANGE_UNDERFLOW_DATETIME;
+ case WebLocalizedString::ValidationStepMismatch:
+ return IDS_FORM_VALIDATION_STEP_MISMATCH;
+ case WebLocalizedString::ValidationStepMismatchCloseToLimit:
+ return IDS_FORM_VALIDATION_STEP_MISMATCH_CLOSE_TO_LIMIT;
+ case WebLocalizedString::ValidationTooLong:
+ return IDS_FORM_VALIDATION_TOO_LONG;
+ case WebLocalizedString::ValidationTypeMismatch:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH;
+ case WebLocalizedString::ValidationTypeMismatchForEmail:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL;
+ case WebLocalizedString::ValidationTypeMismatchForEmailEmpty:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY;
+ case WebLocalizedString::ValidationTypeMismatchForEmailEmptyDomain:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_DOMAIN;
+ case WebLocalizedString::ValidationTypeMismatchForEmailEmptyLocal:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_LOCAL;
+ case WebLocalizedString::ValidationTypeMismatchForEmailInvalidDomain:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOMAIN;
+ case WebLocalizedString::ValidationTypeMismatchForEmailInvalidDots:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOTS;
+ case WebLocalizedString::ValidationTypeMismatchForEmailInvalidLocal:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_LOCAL;
+ case WebLocalizedString::ValidationTypeMismatchForEmailNoAtSign:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_NO_AT_SIGN;
+ case WebLocalizedString::ValidationTypeMismatchForMultipleEmail:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_MULTIPLE_EMAIL;
+ case WebLocalizedString::ValidationTypeMismatchForURL:
+ return IDS_FORM_VALIDATION_TYPE_MISMATCH_URL;
+ case WebLocalizedString::ValidationValueMissing:
+ return IDS_FORM_VALIDATION_VALUE_MISSING;
+ case WebLocalizedString::ValidationValueMissingForCheckbox:
+ return IDS_FORM_VALIDATION_VALUE_MISSING_CHECKBOX;
+ case WebLocalizedString::ValidationValueMissingForFile:
+ return IDS_FORM_VALIDATION_VALUE_MISSING_FILE;
+ case WebLocalizedString::ValidationValueMissingForMultipleFile:
+ return IDS_FORM_VALIDATION_VALUE_MISSING_MULTIPLE_FILE;
+ case WebLocalizedString::ValidationValueMissingForRadio:
+ return IDS_FORM_VALIDATION_VALUE_MISSING_RADIO;
+ case WebLocalizedString::ValidationValueMissingForSelect:
+ return IDS_FORM_VALIDATION_VALUE_MISSING_SELECT;
+ case WebLocalizedString::WeekFormatTemplate:
+ return IDS_FORM_INPUT_WEEK_TEMPLATE;
+ case WebLocalizedString::WeekNumberLabel:
+ return IDS_FORM_WEEK_NUMBER_LABEL;
+ // This "default:" line exists to avoid compile warnings about enum
+ // coverage when we add a new symbol to WebLocalizedString.h in WebKit.
+ // After a planned WebKit patch is landed, we need to add a case statement
+ // for the added symbol here.
+ default:
+ break;
+ }
+ return -1;
+}
+
+WebKitPlatformSupportImpl::WebKitPlatformSupportImpl()
+ : main_loop_(base::MessageLoop::current()),
+ shared_timer_func_(NULL),
+ shared_timer_fire_time_(0.0),
+ shared_timer_fire_time_was_set_while_suspended_(false),
+ shared_timer_suspended_(0) {}
+
+WebKitPlatformSupportImpl::~WebKitPlatformSupportImpl() {
+}
+
+WebURLLoader* WebKitPlatformSupportImpl::createURLLoader() {
+ return new WebURLLoaderImpl(this);
+}
+
+WebSocketStreamHandle* WebKitPlatformSupportImpl::createSocketStreamHandle() {
+ return new WebSocketStreamHandleImpl(this);
+}
+
+WebString WebKitPlatformSupportImpl::userAgent(const WebURL& url) {
+ return WebString::fromUTF8(webkit_glue::GetUserAgent(url));
+}
+
+WebData WebKitPlatformSupportImpl::parseDataURL(
+ const WebURL& url,
+ WebString& mimetype_out,
+ WebString& charset_out) {
+ std::string mime_type, char_set, data;
+ if (net::DataURL::Parse(url, &mime_type, &char_set, &data)
+ && net::IsSupportedMimeType(mime_type)) {
+ mimetype_out = WebString::fromUTF8(mime_type);
+ charset_out = WebString::fromUTF8(char_set);
+ return data;
+ }
+ return WebData();
+}
+
+WebURLError WebKitPlatformSupportImpl::cancelledError(
+ const WebURL& unreachableURL) const {
+ return WebURLLoaderImpl::CreateError(unreachableURL, false, net::ERR_ABORTED);
+}
+
+void WebKitPlatformSupportImpl::decrementStatsCounter(const char* name) {
+ base::StatsCounter(name).Decrement();
+}
+
+void WebKitPlatformSupportImpl::incrementStatsCounter(const char* name) {
+ base::StatsCounter(name).Increment();
+}
+
+void WebKitPlatformSupportImpl::histogramCustomCounts(
+ const char* name, int sample, int min, int max, int bucket_count) {
+ // Copied from histogram macro, but without the static variable caching
+ // the histogram because name is dynamic.
+ base::HistogramBase* counter =
+ base::Histogram::FactoryGet(name, min, max, bucket_count,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ DCHECK_EQ(name, counter->histogram_name());
+ counter->Add(sample);
+}
+
+void WebKitPlatformSupportImpl::histogramEnumeration(
+ const char* name, int sample, int boundary_value) {
+ // Copied from histogram macro, but without the static variable caching
+ // the histogram because name is dynamic.
+ base::HistogramBase* counter =
+ base::LinearHistogram::FactoryGet(name, 1, boundary_value,
+ boundary_value + 1, base::HistogramBase::kUmaTargetedHistogramFlag);
+ DCHECK_EQ(name, counter->histogram_name());
+ counter->Add(sample);
+}
+
+void WebKitPlatformSupportImpl::histogramSparse(const char* name, int sample) {
+ // For sparse histograms, we can use the macro, as it does not incorporate a
+ // static.
+ UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample);
+}
+
+const unsigned char* WebKitPlatformSupportImpl::getTraceCategoryEnabledFlag(
+ const char* category_group) {
+ return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
+}
+
+long* WebKitPlatformSupportImpl::getTraceSamplingState(
+ const unsigned thread_bucket) {
+ switch (thread_bucket) {
+ case 0:
+ return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(0));
+ case 1:
+ return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(1));
+ case 2:
+ return reinterpret_cast<long*>(&TRACE_EVENT_API_THREAD_BUCKET(2));
+ default:
+ NOTREACHED() << "Unknown thread bucket type.";
+ }
+ return NULL;
+}
+
+COMPILE_ASSERT(
+ sizeof(blink::Platform::TraceEventHandle) ==
+ sizeof(base::debug::TraceEventHandle),
+ TraceEventHandle_types_must_be_same_size);
+
+blink::Platform::TraceEventHandle WebKitPlatformSupportImpl::addTraceEvent(
+ char phase,
+ const unsigned char* category_group_enabled,
+ const char* name,
+ unsigned long long id,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
+ unsigned char flags) {
+ base::debug::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, category_group_enabled, name, id,
+ num_args, arg_names, arg_types, arg_values, NULL, flags);
+ blink::Platform::TraceEventHandle result;
+ memcpy(&result, &handle, sizeof(result));
+ return result;
+}
+
+void WebKitPlatformSupportImpl::updateTraceEventDuration(
+ const unsigned char* category_group_enabled,
+ const char* name,
+ TraceEventHandle handle) {
+ base::debug::TraceEventHandle traceEventHandle;
+ memcpy(&traceEventHandle, &handle, sizeof(handle));
+ TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
+ category_group_enabled, name, traceEventHandle);
+}
+
+namespace {
+
+WebData loadAudioSpatializationResource(WebKitPlatformSupportImpl* platform,
+ const char* name) {
+#ifdef IDR_AUDIO_SPATIALIZATION_COMPOSITE
+ if (!strcmp(name, "Composite")) {
+ base::StringPiece resource =
+ platform->GetDataResource(IDR_AUDIO_SPATIALIZATION_COMPOSITE,
+ ui::SCALE_FACTOR_NONE);
+ return WebData(resource.data(), resource.size());
+ }
+#endif
+
+#ifdef IDR_AUDIO_SPATIALIZATION_T000_P000
+ const size_t kExpectedSpatializationNameLength = 31;
+ if (strlen(name) != kExpectedSpatializationNameLength) {
+ return WebData();
+ }
+
+ // Extract the azimuth and elevation from the resource name.
+ int azimuth = 0;
+ int elevation = 0;
+ int values_parsed =
+ sscanf(name, "IRC_Composite_C_R0195_T%3d_P%3d", &azimuth, &elevation);
+ if (values_parsed != 2) {
+ return WebData();
+ }
+
+ // The resource index values go through the elevations first, then azimuths.
+ const int kAngleSpacing = 15;
+
+ // 0 <= elevation <= 90 (or 315 <= elevation <= 345)
+ // in increments of 15 degrees.
+ int elevation_index =
+ elevation <= 90 ? elevation / kAngleSpacing :
+ 7 + (elevation - 315) / kAngleSpacing;
+ bool is_elevation_index_good = 0 <= elevation_index && elevation_index < 10;
+
+ // 0 <= azimuth < 360 in increments of 15 degrees.
+ int azimuth_index = azimuth / kAngleSpacing;
+ bool is_azimuth_index_good = 0 <= azimuth_index && azimuth_index < 24;
+
+ const int kNumberOfElevations = 10;
+ const int kNumberOfAudioResources = 240;
+ int resource_index = kNumberOfElevations * azimuth_index + elevation_index;
+ bool is_resource_index_good = 0 <= resource_index &&
+ resource_index < kNumberOfAudioResources;
+
+ if (is_azimuth_index_good && is_elevation_index_good &&
+ is_resource_index_good) {
+ const int kFirstAudioResourceIndex = IDR_AUDIO_SPATIALIZATION_T000_P000;
+ base::StringPiece resource =
+ platform->GetDataResource(kFirstAudioResourceIndex + resource_index,
+ ui::SCALE_FACTOR_NONE);
+ return WebData(resource.data(), resource.size());
+ }
+#endif // IDR_AUDIO_SPATIALIZATION_T000_P000
+
+ NOTREACHED();
+ return WebData();
+}
+
+struct DataResource {
+ const char* name;
+ int id;
+ ui::ScaleFactor scale_factor;
+};
+
+const DataResource kDataResources[] = {
+ { "missingImage", IDR_BROKENIMAGE, ui::SCALE_FACTOR_100P },
+ { "missingImage@2x", IDR_BROKENIMAGE, ui::SCALE_FACTOR_200P },
+ { "mediaplayerPause", IDR_MEDIAPLAYER_PAUSE_BUTTON, ui::SCALE_FACTOR_100P },
+ { "mediaplayerPauseHover",
+ IDR_MEDIAPLAYER_PAUSE_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerPauseDown",
+ IDR_MEDIAPLAYER_PAUSE_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerPlay", IDR_MEDIAPLAYER_PLAY_BUTTON, ui::SCALE_FACTOR_100P },
+ { "mediaplayerPlayHover",
+ IDR_MEDIAPLAYER_PLAY_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerPlayDown",
+ IDR_MEDIAPLAYER_PLAY_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerPlayDisabled",
+ IDR_MEDIAPLAYER_PLAY_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel3",
+ IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel3Hover",
+ IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel3Down",
+ IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel2",
+ IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel2Hover",
+ IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel2Down",
+ IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel1",
+ IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel1Hover",
+ IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel1Down",
+ IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel0",
+ IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel0Hover",
+ IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundLevel0Down",
+ IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSoundDisabled",
+ IDR_MEDIAPLAYER_SOUND_DISABLED, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSliderThumb",
+ IDR_MEDIAPLAYER_SLIDER_THUMB, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSliderThumbHover",
+ IDR_MEDIAPLAYER_SLIDER_THUMB_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerSliderThumbDown",
+ IDR_MEDIAPLAYER_SLIDER_THUMB_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerVolumeSliderThumb",
+ IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB, ui::SCALE_FACTOR_100P },
+ { "mediaplayerVolumeSliderThumbHover",
+ IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerVolumeSliderThumbDown",
+ IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerVolumeSliderThumbDisabled",
+ IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DISABLED, ui::SCALE_FACTOR_100P },
+ { "mediaplayerClosedCaption",
+ IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON, ui::SCALE_FACTOR_100P },
+ { "mediaplayerClosedCaptionHover",
+ IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerClosedCaptionDown",
+ IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerClosedCaptionDisabled",
+ IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
+ { "mediaplayerFullscreen",
+ IDR_MEDIAPLAYER_FULLSCREEN_BUTTON, ui::SCALE_FACTOR_100P },
+ { "mediaplayerFullscreenHover",
+ IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
+ { "mediaplayerFullscreenDown",
+ IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerFullscreenDisabled",
+ IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
+#if defined(OS_ANDROID)
+ { "mediaplayerOverlayPlay",
+ IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON, ui::SCALE_FACTOR_100P },
+#endif
+#if defined(OS_MACOSX)
+ { "overhangPattern", IDR_OVERHANG_PATTERN, ui::SCALE_FACTOR_100P },
+ { "overhangShadow", IDR_OVERHANG_SHADOW, ui::SCALE_FACTOR_100P },
+#endif
+ { "panIcon", IDR_PAN_SCROLL_ICON, ui::SCALE_FACTOR_100P },
+ { "searchCancel", IDR_SEARCH_CANCEL, ui::SCALE_FACTOR_100P },
+ { "searchCancelPressed", IDR_SEARCH_CANCEL_PRESSED, ui::SCALE_FACTOR_100P },
+ { "searchMagnifier", IDR_SEARCH_MAGNIFIER, ui::SCALE_FACTOR_100P },
+ { "searchMagnifierResults",
+ IDR_SEARCH_MAGNIFIER_RESULTS, ui::SCALE_FACTOR_100P },
+ { "textAreaResizeCorner", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_100P },
+ { "textAreaResizeCorner@2x", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_200P },
+ { "inputSpeech", IDR_INPUT_SPEECH, ui::SCALE_FACTOR_100P },
+ { "inputSpeechRecording", IDR_INPUT_SPEECH_RECORDING, ui::SCALE_FACTOR_100P },
+ { "inputSpeechWaiting", IDR_INPUT_SPEECH_WAITING, ui::SCALE_FACTOR_100P },
+ { "americanExpressCC", IDR_AUTOFILL_CC_AMEX, ui::SCALE_FACTOR_100P },
+ { "dinersCC", IDR_AUTOFILL_CC_DINERS, ui::SCALE_FACTOR_100P },
+ { "discoverCC", IDR_AUTOFILL_CC_DISCOVER, ui::SCALE_FACTOR_100P },
+ { "genericCC", IDR_AUTOFILL_CC_GENERIC, ui::SCALE_FACTOR_100P },
+ { "jcbCC", IDR_AUTOFILL_CC_JCB, ui::SCALE_FACTOR_100P },
+ { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD, ui::SCALE_FACTOR_100P },
+ { "visaCC", IDR_AUTOFILL_CC_VISA, ui::SCALE_FACTOR_100P },
+ { "generatePassword", IDR_PASSWORD_GENERATION_ICON, ui::SCALE_FACTOR_100P },
+ { "generatePasswordHover",
+ IDR_PASSWORD_GENERATION_ICON_HOVER, ui::SCALE_FACTOR_100P },
+ { "syntheticTouchCursor",
+ IDR_SYNTHETIC_TOUCH_CURSOR, ui::SCALE_FACTOR_100P },
+};
+
+} // namespace
+
+WebData WebKitPlatformSupportImpl::loadResource(const char* name) {
+ // Some clients will call into this method with an empty |name| when they have
+ // optional resources. For example, the PopupMenuChromium code can have icons
+ // for some Autofill items but not for others.
+ if (!strlen(name))
+ return WebData();
+
+ // Check the name prefix to see if it's an audio resource.
+ if (StartsWithASCII(name, "IRC_Composite", true) ||
+ StartsWithASCII(name, "Composite", true))
+ return loadAudioSpatializationResource(this, name);
+
+ // TODO(flackr): We should use a better than linear search here, a trie would
+ // be ideal.
+ for (size_t i = 0; i < arraysize(kDataResources); ++i) {
+ if (!strcmp(name, kDataResources[i].name)) {
+ base::StringPiece resource =
+ GetDataResource(kDataResources[i].id,
+ kDataResources[i].scale_factor);
+ return WebData(resource.data(), resource.size());
+ }
+ }
+
+ NOTREACHED() << "Unknown image resource " << name;
+ return WebData();
+}
+
+WebString WebKitPlatformSupportImpl::queryLocalizedString(
+ WebLocalizedString::Name name) {
+ int message_id = ToMessageID(name);
+ if (message_id < 0)
+ return WebString();
+ return GetLocalizedString(message_id);
+}
+
+WebString WebKitPlatformSupportImpl::queryLocalizedString(
+ WebLocalizedString::Name name, int numeric_value) {
+ return queryLocalizedString(name, base::IntToString16(numeric_value));
+}
+
+WebString WebKitPlatformSupportImpl::queryLocalizedString(
+ WebLocalizedString::Name name, const WebString& value) {
+ int message_id = ToMessageID(name);
+ if (message_id < 0)
+ return WebString();
+ return ReplaceStringPlaceholders(GetLocalizedString(message_id), value, NULL);
+}
+
+WebString WebKitPlatformSupportImpl::queryLocalizedString(
+ WebLocalizedString::Name name,
+ const WebString& value1,
+ const WebString& value2) {
+ int message_id = ToMessageID(name);
+ if (message_id < 0)
+ return WebString();
+ std::vector<base::string16> values;
+ values.reserve(2);
+ values.push_back(value1);
+ values.push_back(value2);
+ return ReplaceStringPlaceholders(
+ GetLocalizedString(message_id), values, NULL);
+}
+
+double WebKitPlatformSupportImpl::currentTime() {
+ return base::Time::Now().ToDoubleT();
+}
+
+double WebKitPlatformSupportImpl::monotonicallyIncreasingTime() {
+ return base::TimeTicks::Now().ToInternalValue() /
+ static_cast<double>(base::Time::kMicrosecondsPerSecond);
+}
+
+void WebKitPlatformSupportImpl::cryptographicallyRandomValues(
+ unsigned char* buffer, size_t length) {
+ base::RandBytes(buffer, length);
+}
+
+void WebKitPlatformSupportImpl::setSharedTimerFiredFunction(void (*func)()) {
+ shared_timer_func_ = func;
+}
+
+void WebKitPlatformSupportImpl::setSharedTimerFireInterval(
+ double interval_seconds) {
+ shared_timer_fire_time_ = interval_seconds + monotonicallyIncreasingTime();
+ if (shared_timer_suspended_) {
+ shared_timer_fire_time_was_set_while_suspended_ = true;
+ return;
+ }
+
+ // By converting between double and int64 representation, we run the risk
+ // of losing precision due to rounding errors. Performing computations in
+ // microseconds reduces this risk somewhat. But there still is the potential
+ // of us computing a fire time for the timer that is shorter than what we
+ // need.
+ // As the event loop will check event deadlines prior to actually firing
+ // them, there is a risk of needlessly rescheduling events and of
+ // needlessly looping if sleep times are too short even by small amounts.
+ // This results in measurable performance degradation unless we use ceil() to
+ // always round up the sleep times.
+ int64 interval = static_cast<int64>(
+ ceil(interval_seconds * base::Time::kMillisecondsPerSecond)
+ * base::Time::kMicrosecondsPerMillisecond);
+
+ if (interval < 0)
+ interval = 0;
+
+ shared_timer_.Stop();
+ shared_timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds(interval),
+ this, &WebKitPlatformSupportImpl::DoTimeout);
+ OnStartSharedTimer(base::TimeDelta::FromMicroseconds(interval));
+}
+
+void WebKitPlatformSupportImpl::stopSharedTimer() {
+ shared_timer_.Stop();
+}
+
+void WebKitPlatformSupportImpl::callOnMainThread(
+ void (*func)(void*), void* context) {
+ main_loop_->PostTask(FROM_HERE, base::Bind(func, context));
+}
+
+base::PlatformFile WebKitPlatformSupportImpl::databaseOpenFile(
+ const blink::WebString& vfs_file_name, int desired_flags) {
+ return base::kInvalidPlatformFileValue;
+}
+
+int WebKitPlatformSupportImpl::databaseDeleteFile(
+ const blink::WebString& vfs_file_name, bool sync_dir) {
+ return -1;
+}
+
+long WebKitPlatformSupportImpl::databaseGetFileAttributes(
+ const blink::WebString& vfs_file_name) {
+ return 0;
+}
+
+long long WebKitPlatformSupportImpl::databaseGetFileSize(
+ const blink::WebString& vfs_file_name) {
+ return 0;
+}
+
+long long WebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin(
+ const blink::WebString& origin_identifier) {
+ return 0;
+}
+
+blink::WebString WebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
+ unsigned key_size_index,
+ const blink::WebString& challenge,
+ const blink::WebURL& url) {
+ return blink::WebString("");
+}
+
+static scoped_ptr<base::ProcessMetrics> CurrentProcessMetrics() {
+ using base::ProcessMetrics;
+#if defined(OS_MACOSX)
+ return scoped_ptr<ProcessMetrics>(
+ // The default port provider is sufficient to get data for the current
+ // process.
+ ProcessMetrics::CreateProcessMetrics(base::GetCurrentProcessHandle(),
+ NULL));
+#else
+ return scoped_ptr<ProcessMetrics>(
+ ProcessMetrics::CreateProcessMetrics(base::GetCurrentProcessHandle()));
+#endif
+}
+
+static size_t getMemoryUsageMB(bool bypass_cache) {
+ size_t current_mem_usage = 0;
+ MemoryUsageCache* mem_usage_cache_singleton = MemoryUsageCache::GetInstance();
+ if (!bypass_cache &&
+ mem_usage_cache_singleton->IsCachedValueValid(&current_mem_usage))
+ return current_mem_usage;
+
+ current_mem_usage = MemoryUsageKB() >> 10;
+ mem_usage_cache_singleton->SetMemoryValue(current_mem_usage);
+ return current_mem_usage;
+}
+
+size_t WebKitPlatformSupportImpl::memoryUsageMB() {
+ return getMemoryUsageMB(false);
+}
+
+size_t WebKitPlatformSupportImpl::actualMemoryUsageMB() {
+ return getMemoryUsageMB(true);
+}
+
+size_t WebKitPlatformSupportImpl::physicalMemoryMB() {
+ return static_cast<size_t>(base::SysInfo::AmountOfPhysicalMemoryMB());
+}
+
+size_t WebKitPlatformSupportImpl::numberOfProcessors() {
+ return static_cast<size_t>(base::SysInfo::NumberOfProcessors());
+}
+
+void WebKitPlatformSupportImpl::startHeapProfiling(
+ const blink::WebString& prefix) {
+ // FIXME(morrita): Make this built on windows.
+#if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
+ HeapProfilerStart(prefix.utf8().data());
+#endif
+}
+
+void WebKitPlatformSupportImpl::stopHeapProfiling() {
+#if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
+ HeapProfilerStop();
+#endif
+}
+
+void WebKitPlatformSupportImpl::dumpHeapProfiling(
+ const blink::WebString& reason) {
+#if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
+ HeapProfilerDump(reason.utf8().data());
+#endif
+}
+
+WebString WebKitPlatformSupportImpl::getHeapProfile() {
+#if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
+ char* data = GetHeapProfile();
+ WebString result = WebString::fromUTF8(std::string(data));
+ free(data);
+ return result;
+#else
+ return WebString();
+#endif
+}
+
+bool WebKitPlatformSupportImpl::processMemorySizesInBytes(
+ size_t* private_bytes,
+ size_t* shared_bytes) {
+ return CurrentProcessMetrics()->GetMemoryBytes(private_bytes, shared_bytes);
+}
+
+bool WebKitPlatformSupportImpl::memoryAllocatorWasteInBytes(size_t* size) {
+ return base::allocator::GetAllocatorWasteSize(size);
+}
+
+size_t WebKitPlatformSupportImpl::maxDecodedImageBytes() {
+#if defined(OS_ANDROID)
+ if (base::android::SysUtils::IsLowEndDevice()) {
+ // Limit image decoded size to 3M pixels on low end devices.
+ // 4 is maximum number of bytes per pixel.
+ return 3 * 1024 * 1024 * 4;
+ }
+ // For other devices, limit decoded image size based on the amount of physical
+ // memory. For a device with 2GB physical memory the limit is 16M pixels.
+ return base::SysInfo::AmountOfPhysicalMemory() / 32;
+#else
+ return noDecodedImageByteLimit;
+#endif
+}
+
+void WebKitPlatformSupportImpl::SuspendSharedTimer() {
+ ++shared_timer_suspended_;
+}
+
+void WebKitPlatformSupportImpl::ResumeSharedTimer() {
+ // The shared timer may have fired or been adjusted while we were suspended.
+ if (--shared_timer_suspended_ == 0 &&
+ (!shared_timer_.IsRunning() ||
+ shared_timer_fire_time_was_set_while_suspended_)) {
+ shared_timer_fire_time_was_set_while_suspended_ = false;
+ setSharedTimerFireInterval(
+ shared_timer_fire_time_ - monotonicallyIncreasingTime());
+ }
+}
+
+} // namespace webkit_glue
diff --git a/webkit/child/webkitplatformsupport_impl.h b/webkit/child/webkitplatformsupport_impl.h
new file mode 100644
index 0000000..6af5b78
--- /dev/null
+++ b/webkit/child/webkitplatformsupport_impl.h
@@ -0,0 +1,156 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_CHILD_WEBKITPLATFORMSUPPORT_IMPL_H_
+#define WEBKIT_CHILD_WEBKITPLATFORMSUPPORT_IMPL_H_
+
+#include "base/compiler_specific.h"
+#include "base/debug/trace_event.h"
+#include "base/platform_file.h"
+#include "base/timer/timer.h"
+#include "third_party/WebKit/public/platform/Platform.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
+#include "ui/base/layout.h"
+#include "webkit/child/resource_loader_bridge.h"
+#include "webkit/child/webkit_child_export.h"
+
+namespace base {
+class MessageLoop;
+}
+
+namespace blink {
+class WebSocketStreamHandle;
+}
+
+namespace webkit_glue {
+
+class WebSocketStreamHandleDelegate;
+class WebSocketStreamHandleBridge;
+
+class WEBKIT_CHILD_EXPORT WebKitPlatformSupportImpl :
+ NON_EXPORTED_BASE(public blink::Platform) {
+ public:
+ WebKitPlatformSupportImpl();
+ virtual ~WebKitPlatformSupportImpl();
+
+ // Platform methods (partial implementation):
+ virtual base::PlatformFile databaseOpenFile(
+ const blink::WebString& vfs_file_name, int desired_flags);
+ virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
+ bool sync_dir);
+ virtual long databaseGetFileAttributes(
+ const blink::WebString& vfs_file_name);
+ virtual long long databaseGetFileSize(const blink::WebString& vfs_file_name);
+ virtual long long databaseGetSpaceAvailableForOrigin(
+ const blink::WebString& origin_identifier);
+ virtual blink::WebString signedPublicKeyAndChallengeString(
+ unsigned key_size_index, const blink::WebString& challenge,
+ const blink::WebURL& url);
+ virtual size_t memoryUsageMB();
+ virtual size_t actualMemoryUsageMB();
+ virtual size_t physicalMemoryMB();
+ virtual size_t numberOfProcessors();
+
+ virtual void startHeapProfiling(const blink::WebString& prefix);
+ virtual void stopHeapProfiling() OVERRIDE;
+ virtual void dumpHeapProfiling(const blink::WebString& reason);
+ virtual blink::WebString getHeapProfile() OVERRIDE;
+
+ virtual bool processMemorySizesInBytes(size_t* private_bytes,
+ size_t* shared_bytes);
+ virtual bool memoryAllocatorWasteInBytes(size_t* size);
+ virtual size_t maxDecodedImageBytes() OVERRIDE;
+ virtual blink::WebURLLoader* createURLLoader();
+ virtual blink::WebSocketStreamHandle* createSocketStreamHandle();
+ virtual blink::WebString userAgent(const blink::WebURL& url);
+ virtual blink::WebData parseDataURL(
+ const blink::WebURL& url, blink::WebString& mimetype,
+ blink::WebString& charset);
+ virtual blink::WebURLError cancelledError(const blink::WebURL& url) const;
+ virtual void decrementStatsCounter(const char* name);
+ virtual void incrementStatsCounter(const char* name);
+ virtual void histogramCustomCounts(
+ const char* name, int sample, int min, int max, int bucket_count);
+ virtual void histogramEnumeration(
+ const char* name, int sample, int boundary_value);
+ virtual void histogramSparse(const char* name, int sample);
+ virtual const unsigned char* getTraceCategoryEnabledFlag(
+ const char* category_name);
+ virtual long* getTraceSamplingState(const unsigned thread_bucket);
+ virtual TraceEventHandle addTraceEvent(
+ char phase,
+ const unsigned char* category_group_enabled,
+ const char* name,
+ unsigned long long id,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
+ unsigned char flags);
+ virtual void updateTraceEventDuration(
+ const unsigned char* category_group_enabled,
+ const char* name,
+ TraceEventHandle);
+ virtual blink::WebData loadResource(const char* name);
+ virtual blink::WebString queryLocalizedString(
+ blink::WebLocalizedString::Name name);
+ virtual blink::WebString queryLocalizedString(
+ blink::WebLocalizedString::Name name, int numeric_value);
+ virtual blink::WebString queryLocalizedString(
+ blink::WebLocalizedString::Name name, const blink::WebString& value);
+ virtual blink::WebString queryLocalizedString(
+ blink::WebLocalizedString::Name name,
+ const blink::WebString& value1, const blink::WebString& value2);
+ virtual void suddenTerminationChanged(bool enabled) { }
+ virtual double currentTime();
+ virtual double monotonicallyIncreasingTime();
+ virtual void cryptographicallyRandomValues(
+ unsigned char* buffer, size_t length);
+ virtual void setSharedTimerFiredFunction(void (*func)());
+ virtual void setSharedTimerFireInterval(double interval_seconds);
+ virtual void stopSharedTimer();
+ virtual void callOnMainThread(void (*func)(void*), void* context);
+
+
+ // Embedder functions. The following are not implemented by the glue layer and
+ // need to be specialized by the embedder.
+
+ // Gets a localized string given a message id. Returns an empty string if the
+ // message id is not found.
+ virtual base::string16 GetLocalizedString(int message_id) = 0;
+
+ // Returns the raw data for a resource. This resource must have been
+ // specified as BINDATA in the relevant .rc file.
+ virtual base::StringPiece GetDataResource(int resource_id,
+ ui::ScaleFactor scale_factor) = 0;
+
+ // Creates a ResourceLoaderBridge.
+ virtual ResourceLoaderBridge* CreateResourceLoader(
+ const ResourceLoaderBridge::RequestInfo& request_info) = 0;
+ // Creates a WebSocketStreamHandleBridge.
+ virtual WebSocketStreamHandleBridge* CreateWebSocketStreamBridge(
+ blink::WebSocketStreamHandle* handle,
+ WebSocketStreamHandleDelegate* delegate) = 0;
+
+ void SuspendSharedTimer();
+ void ResumeSharedTimer();
+ virtual void OnStartSharedTimer(base::TimeDelta delay) {}
+
+ private:
+ void DoTimeout() {
+ if (shared_timer_func_ && !shared_timer_suspended_)
+ shared_timer_func_();
+ }
+
+ base::MessageLoop* main_loop_;
+ base::OneShotTimer<WebKitPlatformSupportImpl> shared_timer_;
+ void (*shared_timer_func_)();
+ double shared_timer_fire_time_;
+ bool shared_timer_fire_time_was_set_while_suspended_;
+ int shared_timer_suspended_; // counter
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_CHILD_WEBKITPLATFORMSUPPORT_IMPL_H_
diff --git a/webkit/child/websocketstreamhandle_bridge.h b/webkit/child/websocketstreamhandle_bridge.h
new file mode 100644
index 0000000..f66afd2
--- /dev/null
+++ b/webkit/child/websocketstreamhandle_bridge.h
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_BRIDGE_H_
+#define WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_BRIDGE_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+
+class GURL;
+
+namespace webkit_glue {
+
+class WebSocketStreamHandleBridge
+ : public base::RefCountedThreadSafe<WebSocketStreamHandleBridge> {
+ public:
+ virtual void Connect(const GURL& url) = 0;
+
+ virtual bool Send(const std::vector<char>& data) = 0;
+
+ virtual void Close() = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<WebSocketStreamHandleBridge>;
+ WebSocketStreamHandleBridge() {}
+ virtual ~WebSocketStreamHandleBridge() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebSocketStreamHandleBridge);
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_BRIDGE_H_
diff --git a/webkit/child/websocketstreamhandle_delegate.h b/webkit/child/websocketstreamhandle_delegate.h
new file mode 100644
index 0000000..16d15a0
--- /dev/null
+++ b/webkit/child/websocketstreamhandle_delegate.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_DELEGATE_H_
+#define WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_DELEGATE_H_
+
+#include "base/strings/string16.h"
+
+class GURL;
+
+namespace blink {
+class WebSocketStreamHandle;
+}
+
+namespace webkit_glue {
+
+class WebSocketStreamHandleDelegate {
+ public:
+ WebSocketStreamHandleDelegate() {}
+
+ virtual void WillOpenStream(blink::WebSocketStreamHandle* handle,
+ const GURL& url) {}
+ virtual void WillSendData(blink::WebSocketStreamHandle* handle,
+ const char* data, int len) {}
+
+ virtual void DidOpenStream(blink::WebSocketStreamHandle* handle,
+ int max_amount_send_allowed) {}
+ virtual void DidSendData(blink::WebSocketStreamHandle* handle,
+ int amount_sent) {}
+ virtual void DidReceiveData(blink::WebSocketStreamHandle* handle,
+ const char* data, int len) {}
+ virtual void DidClose(blink::WebSocketStreamHandle*) {}
+ virtual void DidFail(blink::WebSocketStreamHandle* handle,
+ int error_code,
+ const base::string16& error_msg) {}
+
+ protected:
+ virtual ~WebSocketStreamHandleDelegate() {}
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_DELEGATE_H_
diff --git a/webkit/child/websocketstreamhandle_impl.cc b/webkit/child/websocketstreamhandle_impl.cc
new file mode 100644
index 0000000..761749f
--- /dev/null
+++ b/webkit/child/websocketstreamhandle_impl.cc
@@ -0,0 +1,197 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// An implementation of WebSocketStreamHandle.
+
+#include "webkit/child/websocketstreamhandle_impl.h"
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
+#include "third_party/WebKit/public/platform/WebData.h"
+#include "third_party/WebKit/public/platform/WebSocketStreamError.h"
+#include "third_party/WebKit/public/platform/WebSocketStreamHandleClient.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "webkit/child/webkitplatformsupport_impl.h"
+#include "webkit/child/websocketstreamhandle_bridge.h"
+#include "webkit/child/websocketstreamhandle_delegate.h"
+
+using blink::WebData;
+using blink::WebSocketStreamError;
+using blink::WebSocketStreamHandle;
+using blink::WebSocketStreamHandleClient;
+using blink::WebURL;
+
+namespace webkit_glue {
+
+// WebSocketStreamHandleImpl::Context -----------------------------------------
+
+class WebSocketStreamHandleImpl::Context
+ : public base::RefCounted<Context>,
+ public WebSocketStreamHandleDelegate {
+ public:
+ explicit Context(WebSocketStreamHandleImpl* handle);
+
+ WebSocketStreamHandleClient* client() const { return client_; }
+ void set_client(WebSocketStreamHandleClient* client) {
+ client_ = client;
+ }
+
+ void Connect(const WebURL& url, WebKitPlatformSupportImpl* platform);
+ bool Send(const WebData& data);
+ void Close();
+
+ // Must be called before |handle_| or |client_| is deleted.
+ // Once detached, it never calls |client_| back.
+ void Detach();
+
+ // WebSocketStreamHandleDelegate methods:
+ virtual void DidOpenStream(WebSocketStreamHandle*, int) OVERRIDE;
+ virtual void DidSendData(WebSocketStreamHandle*, int) OVERRIDE;
+ virtual void DidReceiveData(WebSocketStreamHandle*,
+ const char*,
+ int) OVERRIDE;
+ virtual void DidClose(WebSocketStreamHandle*) OVERRIDE;
+ virtual void DidFail(WebSocketStreamHandle*,
+ int,
+ const base::string16&) OVERRIDE;
+
+ private:
+ friend class base::RefCounted<Context>;
+ virtual ~Context() {
+ DCHECK(!handle_);
+ DCHECK(!client_);
+ DCHECK(!bridge_.get());
+ }
+
+ WebSocketStreamHandleImpl* handle_;
+ WebSocketStreamHandleClient* client_;
+ // |bridge_| is alive from Connect to DidClose, so Context must be alive
+ // in the time period.
+ scoped_refptr<WebSocketStreamHandleBridge> bridge_;
+
+ DISALLOW_COPY_AND_ASSIGN(Context);
+};
+
+WebSocketStreamHandleImpl::Context::Context(WebSocketStreamHandleImpl* handle)
+ : handle_(handle),
+ client_(NULL) {
+}
+
+void WebSocketStreamHandleImpl::Context::Connect(
+ const WebURL& url,
+ WebKitPlatformSupportImpl* platform) {
+ VLOG(1) << "Connect url=" << url;
+ DCHECK(!bridge_.get());
+ bridge_ = platform->CreateWebSocketStreamBridge(handle_, this);
+ AddRef(); // Will be released by DidClose().
+ bridge_->Connect(url);
+}
+
+bool WebSocketStreamHandleImpl::Context::Send(const WebData& data) {
+ VLOG(1) << "Send data.size=" << data.size();
+ DCHECK(bridge_.get());
+ return bridge_->Send(
+ std::vector<char>(data.data(), data.data() + data.size()));
+}
+
+void WebSocketStreamHandleImpl::Context::Close() {
+ VLOG(1) << "Close";
+ if (bridge_.get())
+ bridge_->Close();
+}
+
+void WebSocketStreamHandleImpl::Context::Detach() {
+ handle_ = NULL;
+ client_ = NULL;
+ // If Connect was called, |bridge_| is not NULL, so that this Context closes
+ // the |bridge_| here. Then |bridge_| will call back DidClose, and will
+ // be released by itself.
+ // Otherwise, |bridge_| is NULL.
+ if (bridge_.get())
+ bridge_->Close();
+}
+
+void WebSocketStreamHandleImpl::Context::DidOpenStream(
+ WebSocketStreamHandle* web_handle, int max_amount_send_allowed) {
+ VLOG(1) << "DidOpen";
+ if (client_)
+ client_->didOpenStream(handle_, max_amount_send_allowed);
+}
+
+void WebSocketStreamHandleImpl::Context::DidSendData(
+ WebSocketStreamHandle* web_handle, int amount_sent) {
+ if (client_)
+ client_->didSendData(handle_, amount_sent);
+}
+
+void WebSocketStreamHandleImpl::Context::DidReceiveData(
+ WebSocketStreamHandle* web_handle, const char* data, int size) {
+ if (client_)
+ client_->didReceiveData(handle_, WebData(data, size));
+}
+
+void WebSocketStreamHandleImpl::Context::DidClose(
+ WebSocketStreamHandle* web_handle) {
+ VLOG(1) << "DidClose";
+ bridge_ = NULL;
+ WebSocketStreamHandleImpl* handle = handle_;
+ handle_ = NULL;
+ if (client_) {
+ WebSocketStreamHandleClient* client = client_;
+ client_ = NULL;
+ client->didClose(handle);
+ }
+ Release();
+}
+
+void WebSocketStreamHandleImpl::Context::DidFail(
+ WebSocketStreamHandle* web_handle,
+ int error_code,
+ const base::string16& error_msg) {
+ VLOG(1) << "DidFail";
+ if (client_) {
+ client_->didFail(
+ handle_,
+ WebSocketStreamError(error_code, error_msg));
+ }
+}
+
+// WebSocketStreamHandleImpl ------------------------------------------------
+
+WebSocketStreamHandleImpl::WebSocketStreamHandleImpl(
+ WebKitPlatformSupportImpl* platform)
+ : context_(new Context(this)),
+ platform_(platform) {
+}
+
+WebSocketStreamHandleImpl::~WebSocketStreamHandleImpl() {
+ // We won't receive any events from |context_|.
+ // |context_| is ref counted, and will be released when it received
+ // DidClose.
+ context_->Detach();
+}
+
+void WebSocketStreamHandleImpl::connect(
+ const WebURL& url, WebSocketStreamHandleClient* client) {
+ VLOG(1) << "connect url=" << url;
+ DCHECK(!context_->client());
+ context_->set_client(client);
+
+ context_->Connect(url, platform_);
+}
+
+bool WebSocketStreamHandleImpl::send(const WebData& data) {
+ return context_->Send(data);
+}
+
+void WebSocketStreamHandleImpl::close() {
+ context_->Close();
+}
+
+} // namespace webkit_glue
diff --git a/webkit/child/websocketstreamhandle_impl.h b/webkit/child/websocketstreamhandle_impl.h
new file mode 100644
index 0000000..c2f7f31
--- /dev/null
+++ b/webkit/child/websocketstreamhandle_impl.h
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_IMPL_H_
+#define WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/supports_user_data.h"
+#include "third_party/WebKit/public/platform/WebSocketStreamHandle.h"
+
+namespace webkit_glue {
+
+class WebKitPlatformSupportImpl;
+
+class WebSocketStreamHandleImpl
+ : public base::SupportsUserData,
+ public blink::WebSocketStreamHandle {
+ public:
+ explicit WebSocketStreamHandleImpl(WebKitPlatformSupportImpl* platform);
+ virtual ~WebSocketStreamHandleImpl();
+
+ // WebSocketStreamHandle methods:
+ virtual void connect(
+ const blink::WebURL& url,
+ blink::WebSocketStreamHandleClient* client);
+ virtual bool send(const blink::WebData& data);
+ virtual void close();
+
+ private:
+ class Context;
+ scoped_refptr<Context> context_;
+ WebKitPlatformSupportImpl* platform_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketStreamHandleImpl);
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_CHILD_WEBSOCKETSTREAMHANDLE_IMPL_H_
diff --git a/webkit/child/weburlloader_impl.cc b/webkit/child/weburlloader_impl.cc
new file mode 100644
index 0000000..7e5a8ad
--- /dev/null
+++ b/webkit/child/weburlloader_impl.cc
@@ -0,0 +1,871 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// An implementation of WebURLLoader in terms of ResourceLoaderBridge.
+
+#include "webkit/child/weburlloader_impl.h"
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_util.h"
+#include "base/time/time.h"
+#include "net/base/data_url.h"
+#include "net/base/load_flags.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request.h"
+#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/public/platform/WebHTTPLoadInfo.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
+#include "third_party/WebKit/public/platform/WebURLLoadTiming.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
+#include "webkit/child/ftp_directory_listing_response_delegate.h"
+#include "webkit/child/multipart_response_delegate.h"
+#include "webkit/child/resource_loader_bridge.h"
+#include "webkit/child/webkitplatformsupport_impl.h"
+#include "webkit/child/weburlrequest_extradata_impl.h"
+#include "webkit/child/weburlresponse_extradata_impl.h"
+#include "webkit/common/resource_request_body.h"
+
+using base::Time;
+using base::TimeTicks;
+using blink::WebData;
+using blink::WebHTTPBody;
+using blink::WebHTTPHeaderVisitor;
+using blink::WebHTTPLoadInfo;
+using blink::WebReferrerPolicy;
+using blink::WebSecurityPolicy;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebURLError;
+using blink::WebURLLoadTiming;
+using blink::WebURLLoader;
+using blink::WebURLLoaderClient;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
+
+namespace webkit_glue {
+
+// Utilities ------------------------------------------------------------------
+
+namespace {
+
+const char kThrottledErrorDescription[] =
+ "Request throttled. Visit http://dev.chromium.org/throttling for more "
+ "information.";
+
+class HeaderFlattener : public WebHTTPHeaderVisitor {
+ public:
+ explicit HeaderFlattener(int load_flags)
+ : load_flags_(load_flags),
+ has_accept_header_(false) {
+ }
+
+ virtual void visitHeader(const WebString& name, const WebString& value) {
+ // Headers are latin1.
+ const std::string& name_latin1 = name.latin1();
+ const std::string& value_latin1 = value.latin1();
+
+ // Skip over referrer headers found in the header map because we already
+ // pulled it out as a separate parameter.
+ if (LowerCaseEqualsASCII(name_latin1, "referer"))
+ return;
+
+ // Skip over "Cache-Control: max-age=0" header if the corresponding
+ // load flag is already specified. FrameLoader sets both the flag and
+ // the extra header -- the extra header is redundant since our network
+ // implementation will add the necessary headers based on load flags.
+ // See http://code.google.com/p/chromium/issues/detail?id=3434.
+ if ((load_flags_ & net::LOAD_VALIDATE_CACHE) &&
+ LowerCaseEqualsASCII(name_latin1, "cache-control") &&
+ LowerCaseEqualsASCII(value_latin1, "max-age=0"))
+ return;
+
+ if (LowerCaseEqualsASCII(name_latin1, "accept"))
+ has_accept_header_ = true;
+
+ if (!buffer_.empty())
+ buffer_.append("\r\n");
+ buffer_.append(name_latin1 + ": " + value_latin1);
+ }
+
+ const std::string& GetBuffer() {
+ // In some cases, WebKit doesn't add an Accept header, but not having the
+ // header confuses some web servers. See bug 808613.
+ if (!has_accept_header_) {
+ if (!buffer_.empty())
+ buffer_.append("\r\n");
+ buffer_.append("Accept: */*");
+ has_accept_header_ = true;
+ }
+ return buffer_;
+ }
+
+ private:
+ int load_flags_;
+ std::string buffer_;
+ bool has_accept_header_;
+};
+
+// Extracts the information from a data: url.
+bool GetInfoFromDataURL(const GURL& url,
+ ResourceResponseInfo* info,
+ std::string* data,
+ int* error_code) {
+ std::string mime_type;
+ std::string charset;
+ if (net::DataURL::Parse(url, &mime_type, &charset, data)) {
+ *error_code = net::OK;
+ // Assure same time for all time fields of data: URLs.
+ Time now = Time::Now();
+ info->load_timing.request_start = TimeTicks::Now();
+ info->load_timing.request_start_time = now;
+ info->request_time = now;
+ info->response_time = now;
+ info->headers = NULL;
+ info->mime_type.swap(mime_type);
+ info->charset.swap(charset);
+ info->security_info.clear();
+ info->content_length = data->length();
+ info->encoded_data_length = 0;
+
+ return true;
+ }
+
+ *error_code = net::ERR_INVALID_URL;
+ return false;
+}
+
+typedef ResourceDevToolsInfo::HeadersVector HeadersVector;
+
+// Converts timing data from |load_timing| to the format used by WebKit.
+void PopulateURLLoadTiming(const net::LoadTimingInfo& load_timing,
+ WebURLLoadTiming* url_timing) {
+ DCHECK(!load_timing.request_start.is_null());
+
+ const TimeTicks kNullTicks;
+ url_timing->initialize();
+ url_timing->setRequestTime(
+ (load_timing.request_start - kNullTicks).InSecondsF());
+ url_timing->setProxyStart(
+ (load_timing.proxy_resolve_start - kNullTicks).InSecondsF());
+ url_timing->setProxyEnd(
+ (load_timing.proxy_resolve_end - kNullTicks).InSecondsF());
+ url_timing->setDNSStart(
+ (load_timing.connect_timing.dns_start - kNullTicks).InSecondsF());
+ url_timing->setDNSEnd(
+ (load_timing.connect_timing.dns_end - kNullTicks).InSecondsF());
+ url_timing->setConnectStart(
+ (load_timing.connect_timing.connect_start - kNullTicks).InSecondsF());
+ url_timing->setConnectEnd(
+ (load_timing.connect_timing.connect_end - kNullTicks).InSecondsF());
+ url_timing->setSSLStart(
+ (load_timing.connect_timing.ssl_start - kNullTicks).InSecondsF());
+ url_timing->setSSLEnd(
+ (load_timing.connect_timing.ssl_end - kNullTicks).InSecondsF());
+ url_timing->setSendStart(
+ (load_timing.send_start - kNullTicks).InSecondsF());
+ url_timing->setSendEnd(
+ (load_timing.send_end - kNullTicks).InSecondsF());
+ url_timing->setReceiveHeadersEnd(
+ (load_timing.receive_headers_end - kNullTicks).InSecondsF());
+}
+
+net::RequestPriority ConvertWebKitPriorityToNetPriority(
+ const WebURLRequest::Priority& priority) {
+ switch (priority) {
+ case WebURLRequest::PriorityVeryHigh:
+ return net::HIGHEST;
+
+ case WebURLRequest::PriorityHigh:
+ return net::MEDIUM;
+
+ case WebURLRequest::PriorityMedium:
+ return net::LOW;
+
+ case WebURLRequest::PriorityLow:
+ return net::LOWEST;
+
+ case WebURLRequest::PriorityVeryLow:
+ return net::IDLE;
+
+ case WebURLRequest::PriorityUnresolved:
+ default:
+ NOTREACHED();
+ return net::LOW;
+ }
+}
+
+} // namespace
+
+// WebURLLoaderImpl::Context --------------------------------------------------
+
+// This inner class exists since the WebURLLoader may be deleted while inside a
+// call to WebURLLoaderClient. The bridge requires its Peer to stay alive
+// until it receives OnCompletedRequest.
+class WebURLLoaderImpl::Context : public base::RefCounted<Context>,
+ public ResourceLoaderBridge::Peer {
+ public:
+ explicit Context(WebURLLoaderImpl* loader);
+
+ WebURLLoaderClient* client() const { return client_; }
+ void set_client(WebURLLoaderClient* client) { client_ = client; }
+
+ void Cancel();
+ void SetDefersLoading(bool value);
+ void DidChangePriority(WebURLRequest::Priority new_priority);
+ void Start(
+ const WebURLRequest& request,
+ ResourceLoaderBridge::SyncLoadResponse* sync_load_response,
+ WebKitPlatformSupportImpl* platform);
+
+ // ResourceLoaderBridge::Peer methods:
+ virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
+ virtual bool OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceResponseInfo& info,
+ bool* has_new_first_party_for_cookies,
+ GURL* new_first_party_for_cookies) OVERRIDE;
+ virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE;
+ virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE;
+ virtual void OnReceivedData(const char* data,
+ int data_length,
+ int encoded_data_length) OVERRIDE;
+ virtual void OnReceivedCachedMetadata(const char* data, int len) OVERRIDE;
+ virtual void OnCompletedRequest(
+ int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64 total_transfer_size) OVERRIDE;
+
+ private:
+ friend class base::RefCounted<Context>;
+ virtual ~Context() {}
+
+ // We can optimize the handling of data URLs in most cases.
+ bool CanHandleDataURL(const GURL& url) const;
+ void HandleDataURL();
+
+ WebURLLoaderImpl* loader_;
+ WebURLRequest request_;
+ WebURLLoaderClient* client_;
+ WebReferrerPolicy referrer_policy_;
+ scoped_ptr<ResourceLoaderBridge> bridge_;
+ scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
+ scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
+ scoped_ptr<ResourceLoaderBridge> completed_bridge_;
+};
+
+WebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader)
+ : loader_(loader),
+ client_(NULL),
+ referrer_policy_(blink::WebReferrerPolicyDefault) {
+}
+
+void WebURLLoaderImpl::Context::Cancel() {
+ // The bridge will still send OnCompletedRequest, which will Release() us, so
+ // we don't do that here.
+ if (bridge_)
+ bridge_->Cancel();
+
+ // Ensure that we do not notify the multipart delegate anymore as it has
+ // its own pointer to the client.
+ if (multipart_delegate_)
+ multipart_delegate_->Cancel();
+
+ // Do not make any further calls to the client.
+ client_ = NULL;
+ loader_ = NULL;
+}
+
+void WebURLLoaderImpl::Context::SetDefersLoading(bool value) {
+ if (bridge_)
+ bridge_->SetDefersLoading(value);
+}
+
+void WebURLLoaderImpl::Context::DidChangePriority(
+ WebURLRequest::Priority new_priority) {
+ if (bridge_)
+ bridge_->DidChangePriority(
+ ConvertWebKitPriorityToNetPriority(new_priority));
+}
+
+void WebURLLoaderImpl::Context::Start(
+ const WebURLRequest& request,
+ ResourceLoaderBridge::SyncLoadResponse* sync_load_response,
+ WebKitPlatformSupportImpl* platform) {
+ DCHECK(!bridge_.get());
+
+ request_ = request; // Save the request.
+
+ GURL url = request.url();
+ if (url.SchemeIs("data") && CanHandleDataURL(url)) {
+ if (sync_load_response) {
+ // This is a sync load. Do the work now.
+ sync_load_response->url = url;
+ std::string data;
+ GetInfoFromDataURL(sync_load_response->url, sync_load_response,
+ &sync_load_response->data,
+ &sync_load_response->error_code);
+ } else {
+ AddRef(); // Balanced in OnCompletedRequest
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&Context::HandleDataURL, this));
+ }
+ return;
+ }
+
+ GURL referrer_url(
+ request.httpHeaderField(WebString::fromUTF8("Referer")).latin1());
+ const std::string& method = request.httpMethod().latin1();
+
+ int load_flags = net::LOAD_NORMAL;
+ switch (request.cachePolicy()) {
+ case WebURLRequest::ReloadIgnoringCacheData:
+ // Required by LayoutTests/http/tests/misc/refresh-headers.php
+ load_flags |= net::LOAD_VALIDATE_CACHE;
+ break;
+ case WebURLRequest::ReturnCacheDataElseLoad:
+ load_flags |= net::LOAD_PREFERRING_CACHE;
+ break;
+ case WebURLRequest::ReturnCacheDataDontLoad:
+ load_flags |= net::LOAD_ONLY_FROM_CACHE;
+ break;
+ case WebURLRequest::UseProtocolCachePolicy:
+ break;
+ }
+
+ if (request.reportUploadProgress())
+ load_flags |= net::LOAD_ENABLE_UPLOAD_PROGRESS;
+ if (request.reportLoadTiming())
+ load_flags |= net::LOAD_ENABLE_LOAD_TIMING;
+ if (request.reportRawHeaders())
+ load_flags |= net::LOAD_REPORT_RAW_HEADERS;
+
+ if (!request.allowCookies() || !request.allowStoredCredentials()) {
+ load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
+ load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
+ }
+
+ if (!request.allowStoredCredentials())
+ load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;
+
+ if (request.targetType() == WebURLRequest::TargetIsXHR &&
+ (url.has_username() || url.has_password())) {
+ load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN;
+ }
+
+ HeaderFlattener flattener(load_flags);
+ request.visitHTTPHeaderFields(&flattener);
+
+ // TODO(brettw) this should take parameter encoding into account when
+ // creating the GURLs.
+
+ ResourceLoaderBridge::RequestInfo request_info;
+ request_info.method = method;
+ request_info.url = url;
+ request_info.first_party_for_cookies = request.firstPartyForCookies();
+ request_info.referrer = referrer_url;
+ request_info.headers = flattener.GetBuffer();
+ request_info.load_flags = load_flags;
+ // requestor_pid only needs to be non-zero if the request originates outside
+ // the render process, so we can use requestorProcessID even for requests
+ // from in-process plugins.
+ request_info.requestor_pid = request.requestorProcessID();
+ request_info.request_type =
+ ResourceType::FromTargetType(request.targetType());
+ request_info.priority =
+ ConvertWebKitPriorityToNetPriority(request.priority());
+ request_info.appcache_host_id = request.appCacheHostID();
+ request_info.routing_id = request.requestorID();
+ request_info.download_to_file = request.downloadToFile();
+ request_info.has_user_gesture = request.hasUserGesture();
+ request_info.extra_data = request.extraData();
+ referrer_policy_ = request.referrerPolicy();
+ request_info.referrer_policy = request.referrerPolicy();
+ bridge_.reset(platform->CreateResourceLoader(request_info));
+
+ if (!request.httpBody().isNull()) {
+ // GET and HEAD requests shouldn't have http bodies.
+ DCHECK(method != "GET" && method != "HEAD");
+ const WebHTTPBody& httpBody = request.httpBody();
+ size_t i = 0;
+ WebHTTPBody::Element element;
+ scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
+ while (httpBody.elementAt(i++, element)) {
+ switch (element.type) {
+ case WebHTTPBody::Element::TypeData:
+ if (!element.data.isEmpty()) {
+ // WebKit sometimes gives up empty data to append. These aren't
+ // necessary so we just optimize those out here.
+ request_body->AppendBytes(
+ element.data.data(), static_cast<int>(element.data.size()));
+ }
+ break;
+ case WebHTTPBody::Element::TypeFile:
+ if (element.fileLength == -1) {
+ request_body->AppendFileRange(
+ base::FilePath::FromUTF16Unsafe(element.filePath),
+ 0, kuint64max, base::Time());
+ } else {
+ request_body->AppendFileRange(
+ base::FilePath::FromUTF16Unsafe(element.filePath),
+ static_cast<uint64>(element.fileStart),
+ static_cast<uint64>(element.fileLength),
+ base::Time::FromDoubleT(element.modificationTime));
+ }
+ break;
+ case WebHTTPBody::Element::TypeFileSystemURL: {
+ GURL file_system_url = element.fileSystemURL;
+ DCHECK(file_system_url.SchemeIsFileSystem());
+ request_body->AppendFileSystemFileRange(
+ file_system_url,
+ static_cast<uint64>(element.fileStart),
+ static_cast<uint64>(element.fileLength),
+ base::Time::FromDoubleT(element.modificationTime));
+ break;
+ }
+ case WebHTTPBody::Element::TypeBlob:
+ request_body->AppendBlob(element.blobUUID.utf8());
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+ request_body->set_identifier(request.httpBody().identifier());
+ bridge_->SetRequestBody(request_body.get());
+ }
+
+ if (sync_load_response) {
+ bridge_->SyncLoad(sync_load_response);
+ return;
+ }
+
+ if (bridge_->Start(this)) {
+ AddRef(); // Balanced in OnCompletedRequest
+ } else {
+ bridge_.reset();
+ }
+}
+
+void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) {
+ if (client_)
+ client_->didSendData(loader_, position, size);
+}
+
+bool WebURLLoaderImpl::Context::OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceResponseInfo& info,
+ bool* has_new_first_party_for_cookies,
+ GURL* new_first_party_for_cookies) {
+ if (!client_)
+ return false;
+
+ WebURLResponse response;
+ response.initialize();
+ PopulateURLResponse(request_.url(), info, &response);
+
+ // TODO(darin): We lack sufficient information to construct the actual
+ // request that resulted from the redirect.
+ WebURLRequest new_request(new_url);
+ new_request.setFirstPartyForCookies(request_.firstPartyForCookies());
+ new_request.setDownloadToFile(request_.downloadToFile());
+
+ WebString referrer_string = WebString::fromUTF8("Referer");
+ WebString referrer = WebSecurityPolicy::generateReferrerHeader(
+ referrer_policy_,
+ new_url,
+ request_.httpHeaderField(referrer_string));
+ if (!referrer.isEmpty())
+ new_request.setHTTPReferrer(referrer, referrer_policy_);
+
+ std::string method = request_.httpMethod().utf8();
+ std::string new_method = net::URLRequest::ComputeMethodForRedirect(
+ method, response.httpStatusCode());
+ new_request.setHTTPMethod(WebString::fromUTF8(new_method));
+ if (new_method == method)
+ new_request.setHTTPBody(request_.httpBody());
+
+ client_->willSendRequest(loader_, new_request, response);
+ request_ = new_request;
+ *has_new_first_party_for_cookies = true;
+ *new_first_party_for_cookies = request_.firstPartyForCookies();
+
+ // Only follow the redirect if WebKit left the URL unmodified.
+ if (new_url == GURL(new_request.url()))
+ return true;
+
+ // We assume that WebKit only changes the URL to suppress a redirect, and we
+ // assume that it does so by setting it to be invalid.
+ DCHECK(!new_request.url().isValid());
+ return false;
+}
+
+void WebURLLoaderImpl::Context::OnReceivedResponse(
+ const ResourceResponseInfo& info) {
+ if (!client_)
+ return;
+
+ WebURLResponse response;
+ response.initialize();
+ PopulateURLResponse(request_.url(), info, &response);
+
+ bool show_raw_listing = (GURL(request_.url()).query() == "raw");
+
+ if (info.mime_type == "text/vnd.chromium.ftp-dir") {
+ if (show_raw_listing) {
+ // Set the MIME type to plain text to prevent any active content.
+ response.setMIMEType("text/plain");
+ } else {
+ // We're going to produce a parsed listing in HTML.
+ response.setMIMEType("text/html");
+ }
+ }
+
+ scoped_refptr<Context> protect(this);
+ client_->didReceiveResponse(loader_, response);
+
+ // We may have been cancelled after didReceiveResponse, which would leave us
+ // without a client and therefore without much need to do further handling.
+ if (!client_)
+ return;
+
+ DCHECK(!ftp_listing_delegate_.get());
+ DCHECK(!multipart_delegate_.get());
+ if (info.headers.get() && info.mime_type == "multipart/x-mixed-replace") {
+ std::string content_type;
+ info.headers->EnumerateHeader(NULL, "content-type", &content_type);
+
+ std::string mime_type;
+ std::string charset;
+ bool had_charset = false;
+ std::string boundary;
+ net::HttpUtil::ParseContentType(content_type, &mime_type, &charset,
+ &had_charset, &boundary);
+ base::TrimString(boundary, " \"", &boundary);
+
+ // If there's no boundary, just handle the request normally. In the gecko
+ // code, nsMultiMixedConv::OnStartRequest throws an exception.
+ if (!boundary.empty()) {
+ multipart_delegate_.reset(
+ new MultipartResponseDelegate(client_, loader_, response, boundary));
+ }
+ } else if (info.mime_type == "text/vnd.chromium.ftp-dir" &&
+ !show_raw_listing) {
+ ftp_listing_delegate_.reset(
+ new FtpDirectoryListingResponseDelegate(client_, loader_, response));
+ }
+}
+
+void WebURLLoaderImpl::Context::OnDownloadedData(int len,
+ int encoded_data_length) {
+ if (client_)
+ client_->didDownloadData(loader_, len, encoded_data_length);
+}
+
+void WebURLLoaderImpl::Context::OnReceivedData(const char* data,
+ int data_length,
+ int encoded_data_length) {
+ if (!client_)
+ return;
+
+ if (ftp_listing_delegate_) {
+ // The FTP listing delegate will make the appropriate calls to
+ // client_->didReceiveData and client_->didReceiveResponse.
+ ftp_listing_delegate_->OnReceivedData(data, data_length);
+ } else if (multipart_delegate_) {
+ // The multipart delegate will make the appropriate calls to
+ // client_->didReceiveData and client_->didReceiveResponse.
+ multipart_delegate_->OnReceivedData(data, data_length, encoded_data_length);
+ } else {
+ client_->didReceiveData(loader_, data, data_length, encoded_data_length);
+ }
+}
+
+void WebURLLoaderImpl::Context::OnReceivedCachedMetadata(
+ const char* data, int len) {
+ if (client_)
+ client_->didReceiveCachedMetadata(loader_, data, len);
+}
+
+void WebURLLoaderImpl::Context::OnCompletedRequest(
+ int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64 total_transfer_size) {
+ if (ftp_listing_delegate_) {
+ ftp_listing_delegate_->OnCompletedRequest();
+ ftp_listing_delegate_.reset(NULL);
+ } else if (multipart_delegate_) {
+ multipart_delegate_->OnCompletedRequest();
+ multipart_delegate_.reset(NULL);
+ }
+
+ // Prevent any further IPC to the browser now that we're complete, but
+ // don't delete it to keep any downloaded temp files alive.
+ DCHECK(!completed_bridge_.get());
+ completed_bridge_.swap(bridge_);
+
+ if (client_) {
+ if (error_code != net::OK) {
+ client_->didFail(loader_, CreateError(request_.url(),
+ stale_copy_in_cache,
+ error_code));
+ } else {
+ client_->didFinishLoading(
+ loader_, (completion_time - TimeTicks()).InSecondsF(),
+ total_transfer_size);
+ }
+ }
+
+ // We are done with the bridge now, and so we need to release the reference
+ // to ourselves that we took on behalf of the bridge. This may cause our
+ // destruction.
+ Release();
+}
+
+bool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const {
+ DCHECK(url.SchemeIs("data"));
+
+ // Optimize for the case where we can handle a data URL locally. We must
+ // skip this for data URLs targetted at frames since those could trigger a
+ // download.
+ //
+ // NOTE: We special case MIME types we can render both for performance
+ // reasons as well as to support unit tests, which do not have an underlying
+ // ResourceLoaderBridge implementation.
+
+#if defined(OS_ANDROID)
+ // For compatibility reasons on Android we need to expose top-level data://
+ // to the browser.
+ if (request_.targetType() == WebURLRequest::TargetIsMainFrame)
+ return false;
+#endif
+
+ if (request_.targetType() != WebURLRequest::TargetIsMainFrame &&
+ request_.targetType() != WebURLRequest::TargetIsSubframe)
+ return true;
+
+ std::string mime_type, unused_charset;
+ if (net::DataURL::Parse(url, &mime_type, &unused_charset, NULL) &&
+ net::IsSupportedMimeType(mime_type))
+ return true;
+
+ return false;
+}
+
+void WebURLLoaderImpl::Context::HandleDataURL() {
+ ResourceResponseInfo info;
+ int error_code;
+ std::string data;
+
+ if (GetInfoFromDataURL(request_.url(), &info, &data, &error_code)) {
+ OnReceivedResponse(info);
+ if (!data.empty())
+ OnReceivedData(data.data(), data.size(), 0);
+ }
+
+ OnCompletedRequest(error_code, false, false, info.security_info,
+ base::TimeTicks::Now(), 0);
+}
+
+// WebURLLoaderImpl -----------------------------------------------------------
+
+WebURLLoaderImpl::WebURLLoaderImpl(WebKitPlatformSupportImpl* platform)
+ : context_(new Context(this)),
+ platform_(platform) {
+}
+
+WebURLLoaderImpl::~WebURLLoaderImpl() {
+ cancel();
+}
+
+WebURLError WebURLLoaderImpl::CreateError(const WebURL& unreachable_url,
+ bool stale_copy_in_cache,
+ int reason) {
+ WebURLError error;
+ error.domain = WebString::fromUTF8(net::kErrorDomain);
+ error.reason = reason;
+ error.unreachableURL = unreachable_url;
+ error.staleCopyInCache = stale_copy_in_cache;
+ if (reason == net::ERR_ABORTED) {
+ error.isCancellation = true;
+ } else if (reason == net::ERR_TEMPORARILY_THROTTLED) {
+ error.localizedDescription = WebString::fromUTF8(
+ kThrottledErrorDescription);
+ } else {
+ error.localizedDescription = WebString::fromUTF8(
+ net::ErrorToString(reason));
+ }
+ return error;
+}
+
+void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
+ const ResourceResponseInfo& info,
+ WebURLResponse* response) {
+ response->setURL(url);
+ response->setResponseTime(info.response_time.ToDoubleT());
+ response->setMIMEType(WebString::fromUTF8(info.mime_type));
+ response->setTextEncodingName(WebString::fromUTF8(info.charset));
+ response->setExpectedContentLength(info.content_length);
+ response->setSecurityInfo(info.security_info);
+ response->setAppCacheID(info.appcache_id);
+ response->setAppCacheManifestURL(info.appcache_manifest_url);
+ response->setWasCached(!info.load_timing.request_start_time.is_null() &&
+ info.response_time < info.load_timing.request_start_time);
+ response->setRemoteIPAddress(
+ WebString::fromUTF8(info.socket_address.host()));
+ response->setRemotePort(info.socket_address.port());
+ response->setConnectionID(info.load_timing.socket_log_id);
+ response->setConnectionReused(info.load_timing.socket_reused);
+ response->setDownloadFilePath(info.download_file_path.AsUTF16Unsafe());
+ WebURLResponseExtraDataImpl* extra_data =
+ new WebURLResponseExtraDataImpl(info.npn_negotiated_protocol);
+ response->setExtraData(extra_data);
+ extra_data->set_was_fetched_via_spdy(info.was_fetched_via_spdy);
+ extra_data->set_was_npn_negotiated(info.was_npn_negotiated);
+ extra_data->set_was_alternate_protocol_available(
+ info.was_alternate_protocol_available);
+ extra_data->set_connection_info(info.connection_info);
+ extra_data->set_was_fetched_via_proxy(info.was_fetched_via_proxy);
+
+ // If there's no received headers end time, don't set load timing. This is
+ // the case for non-HTTP requests, requests that don't go over the wire, and
+ // certain error cases.
+ if (!info.load_timing.receive_headers_end.is_null()) {
+ WebURLLoadTiming timing;
+ PopulateURLLoadTiming(info.load_timing, &timing);
+ response->setLoadTiming(timing);
+ }
+
+ if (info.devtools_info.get()) {
+ WebHTTPLoadInfo load_info;
+
+ load_info.setHTTPStatusCode(info.devtools_info->http_status_code);
+ load_info.setHTTPStatusText(WebString::fromLatin1(
+ info.devtools_info->http_status_text));
+ load_info.setEncodedDataLength(info.encoded_data_length);
+
+ load_info.setRequestHeadersText(WebString::fromLatin1(
+ info.devtools_info->request_headers_text));
+ load_info.setResponseHeadersText(WebString::fromLatin1(
+ info.devtools_info->response_headers_text));
+ const HeadersVector& request_headers = info.devtools_info->request_headers;
+ for (HeadersVector::const_iterator it = request_headers.begin();
+ it != request_headers.end(); ++it) {
+ load_info.addRequestHeader(WebString::fromLatin1(it->first),
+ WebString::fromLatin1(it->second));
+ }
+ const HeadersVector& response_headers =
+ info.devtools_info->response_headers;
+ for (HeadersVector::const_iterator it = response_headers.begin();
+ it != response_headers.end(); ++it) {
+ load_info.addResponseHeader(WebString::fromLatin1(it->first),
+ WebString::fromLatin1(it->second));
+ }
+ response->setHTTPLoadInfo(load_info);
+ }
+
+ const net::HttpResponseHeaders* headers = info.headers.get();
+ if (!headers)
+ return;
+
+ WebURLResponse::HTTPVersion version = WebURLResponse::Unknown;
+ if (headers->GetHttpVersion() == net::HttpVersion(0, 9))
+ version = WebURLResponse::HTTP_0_9;
+ else if (headers->GetHttpVersion() == net::HttpVersion(1, 0))
+ version = WebURLResponse::HTTP_1_0;
+ else if (headers->GetHttpVersion() == net::HttpVersion(1, 1))
+ version = WebURLResponse::HTTP_1_1;
+ response->setHTTPVersion(version);
+ response->setHTTPStatusCode(headers->response_code());
+ response->setHTTPStatusText(WebString::fromLatin1(headers->GetStatusText()));
+
+ // TODO(darin): We should leverage HttpResponseHeaders for this, and this
+ // should be using the same code as ResourceDispatcherHost.
+ // TODO(jungshik): Figure out the actual value of the referrer charset and
+ // pass it to GetSuggestedFilename.
+ std::string value;
+ headers->EnumerateHeader(NULL, "content-disposition", &value);
+ response->setSuggestedFileName(
+ net::GetSuggestedFilename(url,
+ value,
+ std::string(), // referrer_charset
+ std::string(), // suggested_name
+ std::string(), // mime_type
+ std::string())); // default_name
+
+ Time time_val;
+ if (headers->GetLastModifiedValue(&time_val))
+ response->setLastModifiedDate(time_val.ToDoubleT());
+
+ // Build up the header map.
+ void* iter = NULL;
+ std::string name;
+ while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
+ response->addHTTPHeaderField(WebString::fromLatin1(name),
+ WebString::fromLatin1(value));
+ }
+}
+
+void WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request,
+ WebURLResponse& response,
+ WebURLError& error,
+ WebData& data) {
+ ResourceLoaderBridge::SyncLoadResponse sync_load_response;
+ context_->Start(request, &sync_load_response, platform_);
+
+ const GURL& final_url = sync_load_response.url;
+
+ // TODO(tc): For file loads, we may want to include a more descriptive
+ // status code or status text.
+ int error_code = sync_load_response.error_code;
+ if (error_code != net::OK) {
+ response.setURL(final_url);
+ error.domain = WebString::fromUTF8(net::kErrorDomain);
+ error.reason = error_code;
+ error.unreachableURL = final_url;
+ return;
+ }
+
+ PopulateURLResponse(final_url, sync_load_response, &response);
+
+ data.assign(sync_load_response.data.data(),
+ sync_load_response.data.size());
+}
+
+void WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request,
+ WebURLLoaderClient* client) {
+ DCHECK(!context_->client());
+
+ context_->set_client(client);
+ context_->Start(request, NULL, platform_);
+}
+
+void WebURLLoaderImpl::cancel() {
+ context_->Cancel();
+}
+
+void WebURLLoaderImpl::setDefersLoading(bool value) {
+ context_->SetDefersLoading(value);
+}
+
+void WebURLLoaderImpl::didChangePriority(WebURLRequest::Priority new_priority) {
+ context_->DidChangePriority(new_priority);
+}
+
+} // namespace webkit_glue
diff --git a/webkit/child/weburlloader_impl.h b/webkit/child/weburlloader_impl.h
new file mode 100644
index 0000000..3c69923
--- /dev/null
+++ b/webkit/child/weburlloader_impl.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_CHILD_WEBURLLOADER_IMPL_H_
+#define WEBKIT_CHILD_WEBURLLOADER_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "third_party/WebKit/public/platform/WebURLLoader.h"
+#include "webkit/child/webkit_child_export.h"
+
+namespace webkit_glue {
+
+class WebKitPlatformSupportImpl;
+struct ResourceResponseInfo;
+
+class WebURLLoaderImpl : public blink::WebURLLoader {
+ public:
+ explicit WebURLLoaderImpl(WebKitPlatformSupportImpl* platform);
+ virtual ~WebURLLoaderImpl();
+
+ static blink::WebURLError CreateError(const blink::WebURL& unreachable_url,
+ bool stale_copy_in_cache,
+ int reason);
+ WEBKIT_CHILD_EXPORT static void PopulateURLResponse(
+ const GURL& url,
+ const ResourceResponseInfo& info,
+ blink::WebURLResponse* response);
+
+ // WebURLLoader methods:
+ virtual void loadSynchronously(
+ const blink::WebURLRequest& request,
+ blink::WebURLResponse& response,
+ blink::WebURLError& error,
+ blink::WebData& data);
+ virtual void loadAsynchronously(
+ const blink::WebURLRequest& request,
+ blink::WebURLLoaderClient* client);
+ virtual void cancel();
+ virtual void setDefersLoading(bool value);
+ virtual void didChangePriority(blink::WebURLRequest::Priority new_priority);
+
+ private:
+ class Context;
+ scoped_refptr<Context> context_;
+ WebKitPlatformSupportImpl* platform_;
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_CHILD_WEBURLLOADER_IMPL_H_