summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-09-28 18:37:14 +0200
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-09-29 07:47:06 +0000
commit0e8ff63a407fe323e215bb1a2c423c09a4747c8a (patch)
treee27e357e125d2d705bd504e1e3c8a3da1ed20f1d
parentc3d0bb5bb15d008606b18b865841e19cd9bb5847 (diff)
downloadqtwebengine-chromium-upstream-45.tar.gz
BASELINE: Update chromium to 45.0.2454.101upstream-45
Also adds web_cache component Change-Id: I51238ceea8ee99854cc4989ae70a4fc2fc6bedcb Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
-rw-r--r--chromium/DEPS13
-rw-r--r--chromium/ash/ash.gyp1
-rw-r--r--chromium/base/win/scoped_handle.cc15
-rw-r--r--chromium/build/util/LASTCHANGE2
-rw-r--r--chromium/build/util/LASTCHANGE.blink2
-rwxr-xr-xchromium/build/util/lastchange.py14
-rw-r--r--chromium/build/whitespace_file.txt2
-rw-r--r--chromium/cc/layers/picture_layer_impl.cc4
-rw-r--r--chromium/chrome/VERSION2
-rw-r--r--chromium/chrome/app/theme/default_100_percent/cros/logo_google_color_90.pngbin2141 -> 1388 bytes
-rw-r--r--chromium/chrome/app/theme/default_200_percent/cros/logo_google_color_90.pngbin4149 -> 2845 bytes
-rw-r--r--chromium/chrome/browser/resources/pdf/pdf.js19
-rw-r--r--chromium/chrome/chrome_browser.gypi2
-rw-r--r--chromium/chrome/chrome_installer.gypi1
-rw-r--r--chromium/chrome/common/localized_error.cc3
-rw-r--r--chromium/chrome/renderer/resources/plugins/plugin_placeholders.css16
-rw-r--r--chromium/chrome/renderer/resources/plugins/plugin_poster.html37
-rw-r--r--chromium/components/web_cache/OWNERS6
-rw-r--r--chromium/components/web_cache/browser/BUILD.gn20
-rw-r--r--chromium/components/web_cache/browser/DEPS5
-rw-r--r--chromium/components/web_cache/browser/web_cache_manager.cc443
-rw-r--r--chromium/components/web_cache/browser/web_cache_manager.h244
-rw-r--r--chromium/components/web_cache/browser/web_cache_manager_unittest.cc466
-rw-r--r--chromium/components/web_cache/common/BUILD.gn16
-rw-r--r--chromium/components/web_cache/common/DEPS3
-rw-r--r--chromium/components/web_cache/common/OWNERS11
-rw-r--r--chromium/components/web_cache/common/web_cache_message_generator.cc33
-rw-r--r--chromium/components/web_cache/common/web_cache_message_generator.h7
-rw-r--r--chromium/components/web_cache/common/web_cache_messages.h23
-rw-r--r--chromium/components/web_cache/renderer/BUILD.gn17
-rw-r--r--chromium/components/web_cache/renderer/DEPS4
-rw-r--r--chromium/components/web_cache/renderer/web_cache_render_process_observer.cc84
-rw-r--r--chromium/components/web_cache/renderer/web_cache_render_process_observer.h51
-rw-r--r--chromium/content/browser/android/background_sync_launcher_android.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc3
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc4
-rw-r--r--chromium/content/child/service_worker/web_service_worker_impl.cc6
-rw-r--r--chromium/content/common/gpu/media/h264_decoder.cc34
-rw-r--r--chromium/content/content.gyp1
-rw-r--r--chromium/content/public/android/BUILD.gn1
-rw-r--r--chromium/google_apis/gaia/oauth2_token_service_delegate.cc3
-rw-r--r--chromium/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp28
-rw-r--r--chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp35
-rw-r--r--chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h29
-rw-r--r--chromium/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp17
-rw-r--r--chromium/third_party/WebKit/Source/bindings/templates/interface.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp5
-rw-r--r--chromium/third_party/WebKit/Source/core/dom/Document.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/core/dom/Text.cpp19
-rw-r--r--chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp9
-rw-r--r--chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.h1
-rw-r--r--chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp9
-rw-r--r--chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp6
-rw-r--r--chromium/third_party/WebKit/Source/core/layout/LayoutObject.cpp12
-rw-r--r--chromium/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/elements/Spectrum.js1
-rw-r--r--chromium/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js6
-rw-r--r--chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp21
-rw-r--r--chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h4
-rw-r--r--chromium/third_party/WebKit/Source/web/WebSecurityPolicy.cpp5
-rw-r--r--chromium/third_party/WebKit/public/web/WebSecurityPolicy.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc9
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc20
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager.cc96
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager.h14
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc5
-rw-r--r--chromium/ui/resources/default_100_percent/common/ntp_google_logo.pngbin10737 -> 4337 bytes
-rw-r--r--chromium/ui/resources/default_200_percent/common/ntp_google_logo.pngbin12545 -> 9147 bytes
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h1
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.cc9
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.h4
-rw-r--r--chromium/ui/views/win/hwnd_message_handler_delegate.h3
-rw-r--r--chromium/url/url_canon_path.cc118
-rw-r--r--chromium/url/url_canon_unittest.cc15
-rw-r--r--chromium/v8/build/features.gypi4
-rw-r--r--chromium/v8/codereview.settings2
-rw-r--r--chromium/v8/include/v8-version.h2
-rw-r--r--chromium/v8/src/arm/assembler-arm.cc3
-rw-r--r--chromium/v8/src/arm64/assembler-arm64.cc3
-rw-r--r--chromium/v8/src/ast.cc1
-rw-r--r--chromium/v8/src/base/cpu.h3
-rw-r--r--chromium/v8/src/flag-definitions.h2
-rw-r--r--chromium/v8/src/heap/gc-tracer.cc8
-rw-r--r--chromium/v8/src/heap/gc-tracer.h7
-rw-r--r--chromium/v8/src/heap/heap.cc122
-rw-r--r--chromium/v8/src/heap/heap.h17
-rw-r--r--chromium/v8/src/heap/incremental-marking.cc24
-rw-r--r--chromium/v8/src/heap/incremental-marking.h23
-rw-r--r--chromium/v8/src/messages.h1
-rw-r--r--chromium/v8/src/object-observe.js4
-rw-r--r--chromium/v8/src/runtime/runtime-object.cc8
-rw-r--r--chromium/v8/src/runtime/runtime.h3
-rw-r--r--chromium/v8/src/scanner-character-streams.cc38
-rw-r--r--chromium/v8/src/scanner-character-streams.h4
98 files changed, 2191 insertions, 252 deletions
diff --git a/chromium/DEPS b/chromium/DEPS
index 9296acad29f..ae1795bd274 100644
--- a/chromium/DEPS
+++ b/chromium/DEPS
@@ -4,7 +4,7 @@ vars = {
'boringssl_revision':
'de24aadc5bc01130b6a9d25582203bb5308fabe1',
'buildspec_platforms':
- 'android,',
+ 'all',
'buildtools_revision':
'ecc8e253abac3b6186a97573871a084f4c0ca3ae',
'chromium_git':
@@ -34,9 +34,7 @@ vars = {
'swarming_revision':
'b39a448d8522392389b28f6997126a6ab04bfe87',
'v8_revision':
- '7f211533faba9dd85708b1394186c7fe99b88392',
- 'webkit_revision':
- 'abaaf1d0b6b6483140b5dca34e80fc259833ddf7'
+ '7f211533faba9dd85708b1394186c7fe99b88392'
}
allowed_hosts = [
@@ -65,8 +63,6 @@ deps = {
(Var("chromium_git")) + '/external/googlemock.git@29763965ab52f24565299976b936d1265cb6a271',
'src/testing/gtest':
(Var("chromium_git")) + '/external/googletest.git@23574bf2333f834ff665f894c97bef8a5b33a0a9',
- 'src/third_party/WebKit':
- (Var("chromium_git")) + '/chromium/blink.git@4a6bcd0338160a0d9a8750dc71e1c8332b1fd6f3',
'src/third_party/angle':
(Var("chromium_git")) + '/angle/angle.git@6f0fd8c5457f9dcffc9fa9fab3852417311be0a9',
'src/third_party/bidichecker':
@@ -120,7 +116,7 @@ deps = {
'src/third_party/opus/src':
(Var("chromium_git")) + '/chromium/deps/opus.git@cae696156f1e60006e39821e79a1811ae1933c69',
'src/third_party/pdfium':
- 'https://pdfium.googlesource.com/pdfium.git@f81f724838983add18125f41292e98ef94e1bb39',
+ 'https://pdfium.googlesource.com/pdfium.git@860a3eb0f3c18853f95df5a70dc50a95a29aafb1',
'src/third_party/py_trace_event/src':
(Var("chromium_git")) + '/external/py_trace_event.git@dd463ea9e2c430de2b9e53dea57a77b4c3ac9b30',
'src/third_party/pyftpdlib/src':
@@ -164,7 +160,7 @@ deps = {
'src/tools/swarming_client':
(Var("chromium_git")) + '/external/swarming.client.git@b39a448d8522392389b28f6997126a6ab04bfe87',
'src/v8':
- (Var("chromium_git")) + '/v8/v8.git@d2356f267b8ee81447223bf7b22d1829eac3e608'
+ (Var("chromium_git")) + '/v8/v8.git@96dddb455daff3d8626bc4e5d7b2898fbab55991'
}
deps_os = {
@@ -388,6 +384,7 @@ hooks = [
'action': [
'python',
'src/build/util/lastchange.py',
+ '--git-hash-only',
'-s',
'src/third_party/WebKit',
'-o',
diff --git a/chromium/ash/ash.gyp b/chromium/ash/ash.gyp
index 13d84cefe1e..c4fd69453e8 100644
--- a/chromium/ash/ash.gyp
+++ b/chromium/ash/ash.gyp
@@ -827,6 +827,7 @@
'metrics/user_metrics_recorder_unittest.cc',
'popup_message_unittest.cc',
'root_window_controller_unittest.cc',
+ 'rotator/screen_rotation_animation_unittest.cc',
'screen_util_unittest.cc',
'shelf/scoped_observer_with_duplicated_sources_unittest.cc',
'shelf/shelf_button_pressed_metric_tracker_unittest.cc',
diff --git a/chromium/base/win/scoped_handle.cc b/chromium/base/win/scoped_handle.cc
index ce944e43b9f..2ebef320bb8 100644
--- a/chromium/base/win/scoped_handle.cc
+++ b/chromium/base/win/scoped_handle.cc
@@ -152,12 +152,6 @@ void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
if (!enabled_)
return;
- // Idea here is to make our handles non-closable until we close it ourselves.
- // Handles provided could be totally fabricated especially through our
- // unittest, we are ignoring that for now by not checking return value.
- ::SetHandleInformation(handle, HANDLE_FLAG_PROTECT_FROM_CLOSE,
- HANDLE_FLAG_PROTECT_FROM_CLOSE);
-
// Grab the thread id before the lock.
DWORD thread_id = GetCurrentThreadId();
@@ -178,15 +172,6 @@ void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
if (!enabled_)
return;
- // We expect handle to be protected till this point.
- DWORD flags = 0;
- if (::GetHandleInformation(handle, &flags)) {
- CHECK_NE(0U, (flags & HANDLE_FLAG_PROTECT_FROM_CLOSE));
-
- // Unprotect handle so that it could be closed.
- ::SetHandleInformation(handle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
- }
-
AutoNativeLock lock(*lock_);
HandleMap::iterator i = map_.find(handle);
if (i == map_.end())
diff --git a/chromium/build/util/LASTCHANGE b/chromium/build/util/LASTCHANGE
index e8df4b9dcb5..146de03183c 100644
--- a/chromium/build/util/LASTCHANGE
+++ b/chromium/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=1f6e893ac083faeb6f7779a9aa740c4bd7db248c
+LASTCHANGE=25cac1820a03dc7a2feb10c40813c9e3dc418fb0
diff --git a/chromium/build/util/LASTCHANGE.blink b/chromium/build/util/LASTCHANGE.blink
index 16b0ebb3702..5b2c6ec0bbf 100644
--- a/chromium/build/util/LASTCHANGE.blink
+++ b/chromium/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=cb0d6dcc6b193a8927ceea52f508124b067589db
+LASTCHANGE=8cee86b1597ea97322ea5d54881fc04be701d11c
diff --git a/chromium/build/util/lastchange.py b/chromium/build/util/lastchange.py
index 3f3ee4af471..ce1926afc4d 100755
--- a/chromium/build/util/lastchange.py
+++ b/chromium/build/util/lastchange.py
@@ -90,7 +90,7 @@ def RunGitCommand(directory, command):
return None
-def FetchGitRevision(directory):
+def FetchGitRevision(directory, hash_only):
"""
Fetch the Git hash for a given directory.
@@ -116,7 +116,7 @@ def FetchGitRevision(directory):
if line.startswith('Cr-Commit-Position:'):
pos = line.rsplit()[-1].strip()
break
- if not pos:
+ if hash_only or not pos:
return VersionInfo('git', hsh)
return VersionInfo('git', '%s-%s' % (hsh, pos))
@@ -166,7 +166,7 @@ def FetchGitSVNRevision(directory, svn_url_regex, go_deeper):
def FetchVersionInfo(default_lastchange, directory=None,
directory_regex_prior_to_src_url='chrome|blink|svn',
- go_deeper=False):
+ go_deeper=False, hash_only=False):
"""
Returns the last change (in the form of a branch, revision tuple),
from some appropriate revision control system.
@@ -176,7 +176,7 @@ def FetchVersionInfo(default_lastchange, directory=None,
version_info = (FetchSVNRevision(directory, svn_url_regex) or
FetchGitSVNRevision(directory, svn_url_regex, go_deeper) or
- FetchGitRevision(directory))
+ FetchGitRevision(directory, hash_only))
if not version_info:
if default_lastchange and os.path.exists(default_lastchange):
revision = open(default_lastchange, 'r').read().strip()
@@ -263,6 +263,9 @@ def main(argv=None):
parser.add_option("--git-svn-go-deeper", action='store_true',
help="In a Git-SVN repo, dig down to the last committed " +
"SVN change (historic behaviour).")
+ parser.add_option("--git-hash-only", action="store_true",
+ help="In a Git repo with commit positions, only report " +
+ "the hash.")
opts, args = parser.parse_args(argv[1:])
out_file = opts.output
@@ -283,7 +286,8 @@ def main(argv=None):
version_info = FetchVersionInfo(opts.default_lastchange,
directory=src_dir,
- go_deeper=opts.git_svn_go_deeper)
+ go_deeper=opts.git_svn_go_deeper,
+ hash_only=opts.git_hash_only)
if version_info.revision == None:
version_info.revision = '0'
diff --git a/chromium/build/whitespace_file.txt b/chromium/build/whitespace_file.txt
index ea82f4e4ca7..3a03ab0d798 100644
--- a/chromium/build/whitespace_file.txt
+++ b/chromium/build/whitespace_file.txt
@@ -154,3 +154,5 @@ In the BUILD we trust.
^_^
In the masters we don't.
+
+chrome-tpm
diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc
index c7076bdc1e1..90fdeb1efb4 100644
--- a/chromium/cc/layers/picture_layer_impl.cc
+++ b/chromium/cc/layers/picture_layer_impl.cc
@@ -183,7 +183,9 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
gfx::Rect visible_geometry_rect =
scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
- if (visible_geometry_rect.IsEmpty())
+ // TODO(enne): HasRecordings is a workaround for crash in crbug.com/526402.
+ // Need proper fix for when recording does not cover visible rect.
+ if (visible_geometry_rect.IsEmpty() || !raster_source_->HasRecordings())
return;
gfx::Rect quad_content_rect = shared_quad_state->visible_quad_layer_rect;
diff --git a/chromium/chrome/VERSION b/chromium/chrome/VERSION
index 152e81f0aaf..64c1fb9445c 100644
--- a/chromium/chrome/VERSION
+++ b/chromium/chrome/VERSION
@@ -1,4 +1,4 @@
MAJOR=45
MINOR=0
BUILD=2454
-PATCH=79
+PATCH=101
diff --git a/chromium/chrome/app/theme/default_100_percent/cros/logo_google_color_90.png b/chromium/chrome/app/theme/default_100_percent/cros/logo_google_color_90.png
index 9ac7df1da31..e836fc30994 100644
--- a/chromium/chrome/app/theme/default_100_percent/cros/logo_google_color_90.png
+++ b/chromium/chrome/app/theme/default_100_percent/cros/logo_google_color_90.png
Binary files differ
diff --git a/chromium/chrome/app/theme/default_200_percent/cros/logo_google_color_90.png b/chromium/chrome/app/theme/default_200_percent/cros/logo_google_color_90.png
index ccd9a53c4e9..ea1ee1ad7c1 100644
--- a/chromium/chrome/app/theme/default_200_percent/cros/logo_google_color_90.png
+++ b/chromium/chrome/app/theme/default_200_percent/cros/logo_google_color_90.png
Binary files differ
diff --git a/chromium/chrome/browser/resources/pdf/pdf.js b/chromium/chrome/browser/resources/pdf/pdf.js
index 43e085e434b..c4975746d57 100644
--- a/chromium/chrome/browser/resources/pdf/pdf.js
+++ b/chromium/chrome/browser/resources/pdf/pdf.js
@@ -84,6 +84,7 @@ function PDFViewer(browserApi) {
this.browserApi_ = browserApi;
this.loadState_ = LoadState.LOADING;
this.parentWindow_ = null;
+ this.parentOrigin_ = null;
this.delayedScriptingMessages_ = [];
@@ -674,6 +675,7 @@ PDFViewer.prototype = {
handleScriptingMessage: function(message) {
if (this.parentWindow_ != message.source) {
this.parentWindow_ = message.source;
+ this.parentOrigin_ = message.origin;
// Ensure that we notify the embedder if the document is loaded.
if (this.loadState_ != LoadState.LOADING)
this.sendDocumentLoadedMessage_();
@@ -760,11 +762,22 @@ PDFViewer.prototype = {
* @param {Object} message the message to send.
*/
sendScriptingMessage_: function(message) {
- if (this.parentWindow_)
- this.parentWindow_.postMessage(message, '*');
+ if (this.parentWindow_ && this.parentOrigin_) {
+ var targetOrigin;
+ // Only send data back to the embedder if it is from the same origin,
+ // unless we're sending it to ourselves (which could happen in the case
+ // of tests). We also allow documentLoaded messages through as this won't
+ // leak important information.
+ if (this.parentOrigin_ == window.location.origin)
+ targetOrigin = this.parentOrigin_;
+ else if (message.type == 'documentLoaded')
+ targetOrigin = '*';
+ else
+ targetOrigin = this.browserApi_.getStreamInfo().originalUrl;
+ this.parentWindow_.postMessage(message, targetOrigin);
+ }
},
-
/**
* @type {Viewport} the viewport of the PDF viewer.
*/
diff --git a/chromium/chrome/chrome_browser.gypi b/chromium/chrome/chrome_browser.gypi
index 6300411b413..58639ea625f 100644
--- a/chromium/chrome/chrome_browser.gypi
+++ b/chromium/chrome/chrome_browser.gypi
@@ -72,8 +72,6 @@
'browser/android/compositor/layer/tab_handle_layer.h',
'browser/android/compositor/layer/tab_layer.cc',
'browser/android/compositor/layer/tab_layer.h',
- 'browser/android/compositor/layer/throbber_layer.cc',
- 'browser/android/compositor/layer/throbber_layer.h',
'browser/android/compositor/layer/thumbnail_layer.cc',
'browser/android/compositor/layer/thumbnail_layer.h',
'browser/android/compositor/layer/toolbar_layer.cc',
diff --git a/chromium/chrome/chrome_installer.gypi b/chromium/chrome/chrome_installer.gypi
index efc5f889fd2..eeb633514bc 100644
--- a/chromium/chrome/chrome_installer.gypi
+++ b/chromium/chrome/chrome_installer.gypi
@@ -211,6 +211,7 @@
'target_name': 'setup',
'type': 'executable',
'dependencies': [
+ 'chrome_version_header',
'installer_util',
'installer_util_strings',
'../base/base.gyp:base',
diff --git a/chromium/chrome/common/localized_error.cc b/chromium/chrome/common/localized_error.cc
index 3089c7c829e..7033f6499fe 100644
--- a/chromium/chrome/common/localized_error.cc
+++ b/chromium/chrome/common/localized_error.cc
@@ -44,8 +44,7 @@ namespace {
static const char kRedirectLoopLearnMoreUrl[] =
"https://support.google.com/chrome/answer/95626";
static const char kWeakDHKeyLearnMoreUrl[] =
- "https://www.chromium.org/administrators/"
- "err_ssl_weak_server_ephemeral_dh_key";
+ "https://support.google.com/chrome?p=dh_error";
static const char kCachedCopyButtonFieldTrial[] =
"EnableGoogleCachedCopyTextExperiment";
static const char kCachedCopyButtonExpTypeControl[] = "control";
diff --git a/chromium/chrome/renderer/resources/plugins/plugin_placeholders.css b/chromium/chrome/renderer/resources/plugins/plugin_placeholders.css
index 119119f6803..345ef673f95 100644
--- a/chromium/chrome/renderer/resources/plugins/plugin_placeholders.css
+++ b/chromium/chrome/renderer/resources/plugins/plugin_placeholders.css
@@ -31,26 +31,16 @@ p {
}
#outer {
+ align-items: center;
border: 1px black solid;
box-sizing: border-box;
+ display: flex;
height: 100%;
+ justify-content: center;
position: absolute;
width: 100%;
}
-#inner {
- height: 100%;
-<if expr="not is_android">
- margin-top: -70px;
-</if>
-<if expr="is_android">
- margin-top: -14px;
-</if>
- position: relative;
- top: 50%;
- width: 100%;
-}
-
#close {
background-image: -webkit-image-set(
url(../../../../ui/resources/default_100_percent/close_2.png) 1x,
diff --git a/chromium/chrome/renderer/resources/plugins/plugin_poster.html b/chromium/chrome/renderer/resources/plugins/plugin_poster.html
index d5945d1314a..4a4b90c8bd3 100644
--- a/chromium/chrome/renderer/resources/plugins/plugin_poster.html
+++ b/chromium/chrome/renderer/resources/plugins/plugin_poster.html
@@ -21,7 +21,6 @@
#outer {
border: none;
cursor: pointer;
- position: relative;
}
#shielding {
@@ -34,11 +33,12 @@
z-index: 2;
}
-#plugin_icon {
+#plugin-icon {
+ display: block;
opacity: 0.8;
}
-#plugin_icon:hover {
+#plugin-icon:hover {
opacity: 0.95;
}
@@ -49,14 +49,14 @@
z-index: 1;
}
-#inner_container {
- height: 100%;
- position: relative;
- width: 100%;
-}
-
-#inner {
- margin-top: -25px;
+#inner-container {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ left: 0px;
+ position: absolute;
+ top: 0px;
+ z-index: 2;
}
</style>
<base i18n-values="href:baseurl">
@@ -65,12 +65,13 @@
<body>
<div i18n-values="title:name" id="outer">
<img id="poster" i18n-values="srcset:poster">
- <div id="shielding">
- <div id="inner_container"
- i18n-values=".style.width:visibleWidth;.style.height:visibleHeight">
- <div id="inner">
- <img id="plugin_icon" src="plugin_power_saver_play.png" />
- </div>
+ <div id="shielding"></div>
+ <div id="inner-container"
+ i18n-values=".style.width:visibleWidth;.style.height:visibleHeight">
+ <div id="inner">
+ <img id="plugin-icon" src="plugin_power_saver_play.png"
+ i18n-values=".style.maxWidth:visibleWidth;
+ .style.maxHeight:visibleHeight" />
</div>
</div>
</div>
@@ -84,7 +85,7 @@
};
window.setPosterMargin = function(marginLeft, marginTop) {
- var container = document.getElementById('inner_container');
+ var container = document.getElementById('inner-container');
container.style.marginLeft = marginLeft;
container.style.marginTop = marginTop;
};
diff --git a/chromium/components/web_cache/OWNERS b/chromium/components/web_cache/OWNERS
new file mode 100644
index 00000000000..5948538407c
--- /dev/null
+++ b/chromium/components/web_cache/OWNERS
@@ -0,0 +1,6 @@
+# Reviewers:
+jochen@chromium.org
+jhawkins@chromium.org
+sky@chromium.org
+thakis@chromium.org
+thestig@chromium.org
diff --git a/chromium/components/web_cache/browser/BUILD.gn b/chromium/components/web_cache/browser/BUILD.gn
new file mode 100644
index 00000000000..b9ba85bd634
--- /dev/null
+++ b/chromium/components/web_cache/browser/BUILD.gn
@@ -0,0 +1,20 @@
+# 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.
+
+static_library("browser") {
+ output_name = "web_cache_browser"
+ sources = [
+ "web_cache_manager.cc",
+ "web_cache_manager.h",
+ ]
+
+ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+
+ deps = [
+ "//base",
+ "//components/web_cache/common",
+ "//content/public/browser",
+ "//third_party/WebKit/public:blink",
+ ]
+}
diff --git a/chromium/components/web_cache/browser/DEPS b/chromium/components/web_cache/browser/DEPS
new file mode 100644
index 00000000000..f6417ed8f4e
--- /dev/null
+++ b/chromium/components/web_cache/browser/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "+content/public/browser",
+ "+content/public",
+ '+third_party/WebKit/public/web',
+]
diff --git a/chromium/components/web_cache/browser/web_cache_manager.cc b/chromium/components/web_cache/browser/web_cache_manager.cc
new file mode 100644
index 00000000000..dfed012ebfb
--- /dev/null
+++ b/chromium/components/web_cache/browser/web_cache_manager.cc
@@ -0,0 +1,443 @@
+// Copyright (c) 2012 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 "components/web_cache/browser/web_cache_manager.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/location.h"
+#include "base/memory/singleton.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "base/single_thread_task_runner.h"
+#include "base/sys_info.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "components/web_cache/common/web_cache_messages.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_process_host.h"
+
+using base::Time;
+using base::TimeDelta;
+using blink::WebCache;
+
+namespace web_cache {
+
+static const int kReviseAllocationDelayMS = 200;
+
+// The default size limit of the in-memory cache is 8 MB
+static const int kDefaultMemoryCacheSize = 8 * 1024 * 1024;
+
+namespace {
+
+int GetDefaultCacheSize() {
+ // Start off with a modest default
+ int default_cache_size = kDefaultMemoryCacheSize;
+
+ // Check how much physical memory the OS has
+ int mem_size_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
+ if (mem_size_mb >= 1000) // If we have a GB of memory, set a larger default.
+ default_cache_size *= 4;
+ else if (mem_size_mb >= 512) // With 512 MB, set a slightly larger default.
+ default_cache_size *= 2;
+
+ UMA_HISTOGRAM_MEMORY_MB("Cache.MaxCacheSizeMB",
+ default_cache_size / 1024 / 1024);
+
+ return default_cache_size;
+}
+
+} // anonymous namespace
+
+// static
+WebCacheManager* WebCacheManager::GetInstance() {
+ return Singleton<WebCacheManager>::get();
+}
+
+WebCacheManager::WebCacheManager()
+ : global_size_limit_(GetDefaultGlobalSizeLimit()),
+ weak_factory_(this) {
+ registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
+ content::NotificationService::AllBrowserContextsAndSources());
+}
+
+WebCacheManager::~WebCacheManager() {
+}
+
+void WebCacheManager::Add(int renderer_id) {
+ DCHECK(inactive_renderers_.count(renderer_id) == 0);
+
+ // It is tempting to make the following DCHECK here, but it fails when a new
+ // tab is created as we observe activity from that tab because the
+ // RenderProcessHost is recreated and adds itself.
+ //
+ // DCHECK(active_renderers_.count(renderer_id) == 0);
+ //
+ // However, there doesn't seem to be much harm in receiving the calls in this
+ // order.
+
+ active_renderers_.insert(renderer_id);
+
+ RendererInfo* stats = &(stats_[renderer_id]);
+ memset(stats, 0, sizeof(*stats));
+ stats->access = Time::Now();
+
+ // Revise our allocation strategy to account for this new renderer.
+ ReviseAllocationStrategyLater();
+}
+
+void WebCacheManager::Remove(int renderer_id) {
+ // Erase all knowledge of this renderer
+ active_renderers_.erase(renderer_id);
+ inactive_renderers_.erase(renderer_id);
+ stats_.erase(renderer_id);
+
+ // Reallocate the resources used by this renderer
+ ReviseAllocationStrategyLater();
+}
+
+void WebCacheManager::ObserveActivity(int renderer_id) {
+ StatsMap::iterator item = stats_.find(renderer_id);
+ if (item == stats_.end())
+ return; // We might see stats for a renderer that has been destroyed.
+
+ // Record activity.
+ active_renderers_.insert(renderer_id);
+ item->second.access = Time::Now();
+
+ std::set<int>::iterator elmt = inactive_renderers_.find(renderer_id);
+ if (elmt != inactive_renderers_.end()) {
+ inactive_renderers_.erase(elmt);
+
+ // A renderer that was inactive, just became active. We should make sure
+ // it is given a fair cache allocation, but we defer this for a bit in
+ // order to make this function call cheap.
+ ReviseAllocationStrategyLater();
+ }
+}
+
+void WebCacheManager::ObserveStats(int renderer_id,
+ const WebCache::UsageStats& stats) {
+ StatsMap::iterator entry = stats_.find(renderer_id);
+ if (entry == stats_.end())
+ return; // We might see stats for a renderer that has been destroyed.
+
+ // Record the updated stats.
+ entry->second.capacity = stats.capacity;
+ entry->second.deadSize = stats.deadSize;
+ entry->second.liveSize = stats.liveSize;
+ entry->second.maxDeadCapacity = stats.maxDeadCapacity;
+ entry->second.minDeadCapacity = stats.minDeadCapacity;
+}
+
+void WebCacheManager::SetGlobalSizeLimit(size_t bytes) {
+ global_size_limit_ = bytes;
+ ReviseAllocationStrategyLater();
+}
+
+void WebCacheManager::ClearCache() {
+ // Tell each renderer process to clear the cache.
+ ClearRendererCache(active_renderers_, INSTANTLY);
+ ClearRendererCache(inactive_renderers_, INSTANTLY);
+}
+
+void WebCacheManager::ClearCacheOnNavigation() {
+ // Tell each renderer process to clear the cache when a tab is reloaded or
+ // the user navigates to a new website.
+ ClearRendererCache(active_renderers_, ON_NAVIGATION);
+ ClearRendererCache(inactive_renderers_, ON_NAVIGATION);
+}
+
+void WebCacheManager::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
+ content::RenderProcessHost* process =
+ content::Source<content::RenderProcessHost>(source).ptr();
+ Add(process->GetID());
+ break;
+ }
+ case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
+ content::RenderProcessHost* process =
+ content::Source<content::RenderProcessHost>(source).ptr();
+ Remove(process->GetID());
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+// static
+size_t WebCacheManager::GetDefaultGlobalSizeLimit() {
+ return GetDefaultCacheSize();
+}
+
+void WebCacheManager::GatherStats(const std::set<int>& renderers,
+ WebCache::UsageStats* stats) {
+ DCHECK(stats);
+
+ memset(stats, 0, sizeof(WebCache::UsageStats));
+
+ std::set<int>::const_iterator iter = renderers.begin();
+ while (iter != renderers.end()) {
+ StatsMap::iterator elmt = stats_.find(*iter);
+ if (elmt != stats_.end()) {
+ stats->minDeadCapacity += elmt->second.minDeadCapacity;
+ stats->maxDeadCapacity += elmt->second.maxDeadCapacity;
+ stats->capacity += elmt->second.capacity;
+ stats->liveSize += elmt->second.liveSize;
+ stats->deadSize += elmt->second.deadSize;
+ }
+ ++iter;
+ }
+}
+
+// static
+size_t WebCacheManager::GetSize(AllocationTactic tactic,
+ const WebCache::UsageStats& stats) {
+ switch (tactic) {
+ case DIVIDE_EVENLY:
+ // We aren't going to reserve any space for existing objects.
+ return 0;
+ case KEEP_CURRENT_WITH_HEADROOM:
+ // We need enough space for our current objects, plus some headroom.
+ return 3 * GetSize(KEEP_CURRENT, stats) / 2;
+ case KEEP_CURRENT:
+ // We need enough space to keep our current objects.
+ return stats.liveSize + stats.deadSize;
+ case KEEP_LIVE_WITH_HEADROOM:
+ // We need enough space to keep out live resources, plus some headroom.
+ return 3 * GetSize(KEEP_LIVE, stats) / 2;
+ case KEEP_LIVE:
+ // We need enough space to keep our live resources.
+ return stats.liveSize;
+ default:
+ NOTREACHED() << "Unknown cache allocation tactic";
+ return 0;
+ }
+}
+
+bool WebCacheManager::AttemptTactic(
+ AllocationTactic active_tactic,
+ const WebCache::UsageStats& active_stats,
+ AllocationTactic inactive_tactic,
+ const WebCache::UsageStats& inactive_stats,
+ AllocationStrategy* strategy) {
+ DCHECK(strategy);
+
+ size_t active_size = GetSize(active_tactic, active_stats);
+ size_t inactive_size = GetSize(inactive_tactic, inactive_stats);
+
+ // Give up if we don't have enough space to use this tactic.
+ if (global_size_limit_ < active_size + inactive_size)
+ return false;
+
+ // Compute the unreserved space available.
+ size_t total_extra = global_size_limit_ - (active_size + inactive_size);
+
+ // The plan for the extra space is to divide it evenly amoung the active
+ // renderers.
+ size_t shares = active_renderers_.size();
+
+ // The inactive renderers get one share of the extra memory to be divided
+ // among themselves.
+ size_t inactive_extra = 0;
+ if (!inactive_renderers_.empty()) {
+ ++shares;
+ inactive_extra = total_extra / shares;
+ }
+
+ // The remaining memory is allocated to the active renderers.
+ size_t active_extra = total_extra - inactive_extra;
+
+ // Actually compute the allocations for each renderer.
+ AddToStrategy(active_renderers_, active_tactic, active_extra, strategy);
+ AddToStrategy(inactive_renderers_, inactive_tactic, inactive_extra, strategy);
+
+ // We succeeded in computing an allocation strategy.
+ return true;
+}
+
+void WebCacheManager::AddToStrategy(const std::set<int>& renderers,
+ AllocationTactic tactic,
+ size_t extra_bytes_to_allocate,
+ AllocationStrategy* strategy) {
+ DCHECK(strategy);
+
+ // Nothing to do if there are no renderers. It is common for there to be no
+ // inactive renderers if there is a single active tab.
+ if (renderers.empty())
+ return;
+
+ // Divide the extra memory evenly among the renderers.
+ size_t extra_each = extra_bytes_to_allocate / renderers.size();
+
+ std::set<int>::const_iterator iter = renderers.begin();
+ while (iter != renderers.end()) {
+ size_t cache_size = extra_each;
+
+ // Add in the space required to implement |tactic|.
+ StatsMap::iterator elmt = stats_.find(*iter);
+ if (elmt != stats_.end())
+ cache_size += GetSize(tactic, elmt->second);
+
+ // Record the allocation in our strategy.
+ strategy->push_back(Allocation(*iter, cache_size));
+ ++iter;
+ }
+}
+
+void WebCacheManager::EnactStrategy(const AllocationStrategy& strategy) {
+ // Inform each render process of its cache allocation.
+ AllocationStrategy::const_iterator allocation = strategy.begin();
+ while (allocation != strategy.end()) {
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(allocation->first);
+ if (host) {
+ // This is the capacity this renderer has been allocated.
+ size_t capacity = allocation->second;
+
+ // We don't reserve any space for dead objects in the cache. Instead, we
+ // prefer to keep live objects around. There is probably some performance
+ // tuning to be done here.
+ size_t min_dead_capacity = 0;
+
+ // We allow the dead objects to consume up to half of the cache capacity.
+ size_t max_dead_capacity = capacity / 2;
+ if (base::SysInfo::IsLowEndDevice()) {
+ max_dead_capacity = std::min(static_cast<size_t>(512 * 1024),
+ max_dead_capacity);
+ }
+ host->Send(new WebCacheMsg_SetCacheCapacities(min_dead_capacity,
+ max_dead_capacity,
+ capacity));
+ }
+ ++allocation;
+ }
+}
+
+void WebCacheManager::ClearCacheForProcess(int render_process_id) {
+ std::set<int> renderers;
+ renderers.insert(render_process_id);
+ ClearRendererCache(renderers, INSTANTLY);
+}
+
+void WebCacheManager::ClearRendererCache(
+ const std::set<int>& renderers,
+ WebCacheManager::ClearCacheOccasion occasion) {
+ std::set<int>::const_iterator iter = renderers.begin();
+ for (; iter != renderers.end(); ++iter) {
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(*iter);
+ if (host)
+ host->Send(new WebCacheMsg_ClearCache(occasion == ON_NAVIGATION));
+ }
+}
+
+void WebCacheManager::ReviseAllocationStrategy() {
+ DCHECK(stats_.size() <=
+ active_renderers_.size() + inactive_renderers_.size());
+
+ // Check if renderers have gone inactive.
+ FindInactiveRenderers();
+
+ // Gather statistics
+ WebCache::UsageStats active;
+ WebCache::UsageStats inactive;
+ GatherStats(active_renderers_, &active);
+ GatherStats(inactive_renderers_, &inactive);
+
+ UMA_HISTOGRAM_COUNTS_100("Cache.ActiveTabs", active_renderers_.size());
+ UMA_HISTOGRAM_COUNTS_100("Cache.InactiveTabs", inactive_renderers_.size());
+ UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveCapacityMB",
+ active.capacity / 1024 / 1024);
+ UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveDeadSizeMB",
+ active.deadSize / 1024 / 1024);
+ UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveLiveSizeMB",
+ active.liveSize / 1024 / 1024);
+ UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveCapacityMB",
+ inactive.capacity / 1024 / 1024);
+ UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveDeadSizeMB",
+ inactive.deadSize / 1024 / 1024);
+ UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveLiveSizeMB",
+ inactive.liveSize / 1024 / 1024);
+
+ // Compute an allocation strategy.
+ //
+ // We attempt various tactics in order of preference. Our first preference
+ // is not to evict any objects. If we don't have enough resources, we'll
+ // first try to evict dead data only. If that fails, we'll just divide the
+ // resources we have evenly.
+ //
+ // We always try to give the active renderers some head room in their
+ // allocations so they can take memory away from an inactive renderer with
+ // a large cache allocation.
+ //
+ // Notice the early exit will prevent attempting less desirable tactics once
+ // we've found a workable strategy.
+ AllocationStrategy strategy;
+ if ( // Ideally, we'd like to give the active renderers some headroom and
+ // keep all our current objects.
+ AttemptTactic(KEEP_CURRENT_WITH_HEADROOM, active,
+ KEEP_CURRENT, inactive, &strategy) ||
+ // If we can't have that, then we first try to evict the dead objects in
+ // the caches of inactive renderers.
+ AttemptTactic(KEEP_CURRENT_WITH_HEADROOM, active,
+ KEEP_LIVE, inactive, &strategy) ||
+ // Next, we try to keep the live objects in the active renders (with some
+ // room for new objects) and give whatever is left to the inactive
+ // renderers.
+ AttemptTactic(KEEP_LIVE_WITH_HEADROOM, active,
+ DIVIDE_EVENLY, inactive, &strategy) ||
+ // If we've gotten this far, then we are very tight on memory. Let's try
+ // to at least keep around the live objects for the active renderers.
+ AttemptTactic(KEEP_LIVE, active, DIVIDE_EVENLY, inactive, &strategy) ||
+ // We're basically out of memory. The best we can do is just divide up
+ // what we have and soldier on.
+ AttemptTactic(DIVIDE_EVENLY, active, DIVIDE_EVENLY, inactive,
+ &strategy)) {
+ // Having found a workable strategy, we enact it.
+ EnactStrategy(strategy);
+ } else {
+ // DIVIDE_EVENLY / DIVIDE_EVENLY should always succeed.
+ NOTREACHED() << "Unable to find a cache allocation";
+ }
+}
+
+void WebCacheManager::ReviseAllocationStrategyLater() {
+ // Ask to be called back in a few milliseconds to actually recompute our
+ // allocation.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&WebCacheManager::ReviseAllocationStrategy,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kReviseAllocationDelayMS));
+}
+
+void WebCacheManager::FindInactiveRenderers() {
+ std::set<int>::const_iterator iter = active_renderers_.begin();
+ while (iter != active_renderers_.end()) {
+ StatsMap::iterator elmt = stats_.find(*iter);
+ DCHECK(elmt != stats_.end());
+ TimeDelta idle = Time::Now() - elmt->second.access;
+ if (idle >= TimeDelta::FromMinutes(kRendererInactiveThresholdMinutes)) {
+ // Moved to inactive status. This invalidates our iterator.
+ inactive_renderers_.insert(*iter);
+ active_renderers_.erase(*iter);
+ iter = active_renderers_.begin();
+ continue;
+ }
+ ++iter;
+ }
+}
+
+} // namespace web_cache
diff --git a/chromium/components/web_cache/browser/web_cache_manager.h b/chromium/components/web_cache/browser/web_cache_manager.h
new file mode 100644
index 00000000000..0d2d3ffb644
--- /dev/null
+++ b/chromium/components/web_cache/browser/web_cache_manager.h
@@ -0,0 +1,244 @@
+// Copyright (c) 2011 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.
+
+// This is the browser side of the cache manager, it tracks the activity of the
+// render processes and allocates available memory cache resources.
+
+#ifndef COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_
+#define COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_
+
+#include <list>
+#include <map>
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "third_party/WebKit/public/web/WebCache.h"
+
+template<typename Type>
+struct DefaultSingletonTraits;
+class PrefRegistrySimple;
+
+namespace web_cache {
+
+class WebCacheManager : public content::NotificationObserver {
+ friend class WebCacheManagerTest;
+ FRIEND_TEST_ALL_PREFIXES(
+ WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_1);
+ FRIEND_TEST_ALL_PREFIXES(
+ WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_2);
+ FRIEND_TEST_ALL_PREFIXES(
+ WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_3);
+ FRIEND_TEST_ALL_PREFIXES(
+ WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_4);
+ FRIEND_TEST_ALL_PREFIXES(
+ WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_5);
+ FRIEND_TEST_ALL_PREFIXES(
+ WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_6);
+
+ public:
+ // Gets the singleton WebCacheManager object. The first time this method
+ // is called, a WebCacheManager object is constructed and returned.
+ // Subsequent calls will return the same object.
+ static WebCacheManager* GetInstance();
+
+ // When a render process is created, it registers itself with the cache
+ // manager host, causing the renderer to be allocated cache resources.
+ void Add(int renderer_id);
+
+ // When a render process ends, it removes itself from the cache manager host,
+ // freeing the manager to assign its cache resources to other renderers.
+ void Remove(int renderer_id);
+
+ // The cache manager assigns more cache resources to active renderer. When a
+ // renderer is active, it should inform the cache manager to receive more
+ // cache resources.
+ //
+ // When a renderer moves from being inactive to being active, the cache
+ // manager may decide to adjust its resource allocation, but it will delay
+ // the recalculation, allowing ObserveActivity to return quickly.
+ void ObserveActivity(int renderer_id);
+
+ // Periodically, renderers should inform the cache manager of their current
+ // statistics. The more up-to-date the cache manager's statistics, the
+ // better it can allocate cache resources.
+ void ObserveStats(
+ int renderer_id, const blink::WebCache::UsageStats& stats);
+
+ // The global limit on the number of bytes in all the in-memory caches.
+ size_t global_size_limit() const { return global_size_limit_; }
+
+ // Sets the global size limit, forcing a recalculation of cache allocations.
+ void SetGlobalSizeLimit(size_t bytes);
+
+ // Clears all in-memory caches.
+ void ClearCache();
+
+ // Instantly clears renderer cache for a process.
+ void ClearCacheForProcess(int process_id);
+
+ // Clears all in-memory caches when a tab is reloaded or the user navigates
+ // to a different website.
+ void ClearCacheOnNavigation();
+
+ // content::NotificationObserver implementation:
+ void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) override;
+
+ // Gets the default global size limit. This interrogates system metrics to
+ // tune the default size to the current system.
+ static size_t GetDefaultGlobalSizeLimit();
+
+ protected:
+ // The amount of idle time before we consider a tab to be "inactive"
+ static const int kRendererInactiveThresholdMinutes = 5;
+
+ // Keep track of some renderer information.
+ struct RendererInfo : blink::WebCache::UsageStats {
+ // The access time for this renderer.
+ base::Time access;
+ };
+
+ typedef std::map<int, RendererInfo> StatsMap;
+
+ // An allocation is the number of bytes a specific renderer should use for
+ // its cache.
+ typedef std::pair<int,size_t> Allocation;
+
+ // An allocation strategy is a list of allocations specifying the resources
+ // each renderer is permitted to consume for its cache.
+ typedef std::list<Allocation> AllocationStrategy;
+
+ // This class is a singleton. Do not instantiate directly.
+ WebCacheManager();
+ friend struct DefaultSingletonTraits<WebCacheManager>;
+
+ ~WebCacheManager() override;
+
+ // Recomputes the allocation of cache resources among the renderers. Also
+ // informs the renderers of their new allocation.
+ void ReviseAllocationStrategy();
+
+ // Schedules a call to ReviseAllocationStrategy after a short delay.
+ void ReviseAllocationStrategyLater();
+
+ // The various tactics used as part of an allocation strategy. To decide
+ // how many resources a given renderer should be allocated, we consider its
+ // usage statistics. Each tactic specifies the function that maps usage
+ // statistics to resource allocations.
+ //
+ // Determining a resource allocation strategy amounts to picking a tactic
+ // for each renderer and checking that the total memory required fits within
+ // our |global_size_limit_|.
+ enum AllocationTactic {
+ // Ignore cache statistics and divide resources equally among the given
+ // set of caches.
+ DIVIDE_EVENLY,
+
+ // Allow each renderer to keep its current set of cached resources, with
+ // some extra allocation to store new objects.
+ KEEP_CURRENT_WITH_HEADROOM,
+
+ // Allow each renderer to keep its current set of cached resources.
+ KEEP_CURRENT,
+
+ // Allow each renderer to keep cache resources it believes are currently
+ // being used, with some extra allocation to store new objects.
+ KEEP_LIVE_WITH_HEADROOM,
+
+ // Allow each renderer to keep cache resources it believes are currently
+ // being used, but instruct the renderer to discard all other data.
+ KEEP_LIVE,
+ };
+
+ // Helper functions for devising an allocation strategy
+
+ // Add up all the stats from the given set of renderers and place the result
+ // in |stats|.
+ void GatherStats(const std::set<int>& renderers,
+ blink::WebCache::UsageStats* stats);
+
+ // Get the amount of memory that would be required to implement |tactic|
+ // using the specified allocation tactic. This function defines the
+ // semantics for each of the tactics.
+ static size_t GetSize(AllocationTactic tactic,
+ const blink::WebCache::UsageStats& stats);
+
+ // Attempt to use the specified tactics to compute an allocation strategy
+ // and place the result in |strategy|. |active_stats| and |inactive_stats|
+ // are the aggregate statistics for |active_renderers_| and
+ // |inactive_renderers_|, respectively.
+ //
+ // Returns |true| on success and |false| on failure. Does not modify
+ // |strategy| on failure.
+ bool AttemptTactic(AllocationTactic active_tactic,
+ const blink::WebCache::UsageStats& active_stats,
+ AllocationTactic inactive_tactic,
+ const blink::WebCache::UsageStats& inactive_stats,
+ AllocationStrategy* strategy);
+
+ // For each renderer in |renderers|, computes its allocation according to
+ // |tactic| and add the result to |strategy|. Any |extra_bytes_to_allocate|
+ // is divided evenly among the renderers.
+ void AddToStrategy(const std::set<int>& renderers,
+ AllocationTactic tactic,
+ size_t extra_bytes_to_allocate,
+ AllocationStrategy* strategy);
+
+ // Enact an allocation strategy by informing the renderers of their
+ // allocations according to |strategy|.
+ void EnactStrategy(const AllocationStrategy& strategy);
+
+ enum ClearCacheOccasion {
+ // Instructs to clear the cache instantly.
+ INSTANTLY,
+ // Instructs to clear the cache when a navigation takes place (this
+ // includes reloading a tab).
+ ON_NAVIGATION
+ };
+
+ // Inform all |renderers| to clear their cache.
+ void ClearRendererCache(const std::set<int>& renderers,
+ ClearCacheOccasion occation);
+
+ // Check to see if any active renderers have fallen inactive.
+ void FindInactiveRenderers();
+
+ // The global size limit for all in-memory caches.
+ size_t global_size_limit_;
+
+ // Maps every renderer_id our most recent copy of its statistics.
+ StatsMap stats_;
+
+ // Every renderer we think is still around is in one of these two sets.
+ //
+ // Active renderers are those renderers that have been active more recently
+ // than they have been inactive.
+ std::set<int> active_renderers_;
+ // Inactive renderers are those renderers that have been inactive more
+ // recently than they have been active.
+ std::set<int> inactive_renderers_;
+
+ content::NotificationRegistrar registrar_;
+
+ base::WeakPtrFactory<WebCacheManager> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebCacheManager);
+};
+
+} // namespace web_cache
+
+#endif // COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_
diff --git a/chromium/components/web_cache/browser/web_cache_manager_unittest.cc b/chromium/components/web_cache/browser/web_cache_manager_unittest.cc
new file mode 100644
index 00000000000..bc8bcbd5076
--- /dev/null
+++ b/chromium/components/web_cache/browser/web_cache_manager_unittest.cc
@@ -0,0 +1,466 @@
+// Copyright (c) 2011 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 <string>
+
+#include "base/message_loop/message_loop.h"
+#include "components/web_cache/browser/web_cache_manager.h"
+#include "content/public/test/test_browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::Time;
+using base::TimeDelta;
+using content::BrowserThread;
+using blink::WebCache;
+
+namespace web_cache {
+
+class WebCacheManagerTest : public testing::Test {
+ protected:
+ typedef WebCacheManager::StatsMap StatsMap;
+ typedef WebCacheManager::Allocation Allocation;
+ typedef WebCacheManager::AllocationStrategy AllocationStrategy;
+
+ static const int kRendererID;
+ static const int kRendererID2;
+ static const WebCache::UsageStats kStats;
+ static const WebCache::UsageStats kStats2;
+
+ WebCacheManagerTest()
+ : ui_thread_(BrowserThread::UI, &message_loop_) {
+ }
+
+ // Thunks to access protected members of WebCacheManager
+ static std::map<int, WebCacheManager::RendererInfo>& stats(
+ WebCacheManager* h) {
+ return h->stats_;
+ }
+
+ static void SimulateInactivity(WebCacheManager* h, int renderer_id) {
+ stats(h)[renderer_id].access = Time::Now() - TimeDelta::FromMinutes(
+ WebCacheManager::kRendererInactiveThresholdMinutes);
+ h->FindInactiveRenderers();
+ }
+
+ static std::set<int>& active_renderers(WebCacheManager* h) {
+ return h->active_renderers_;
+ }
+ static std::set<int>& inactive_renderers(WebCacheManager* h) {
+ return h->inactive_renderers_;
+ }
+ static void GatherStats(WebCacheManager* h,
+ std::set<int> renderers,
+ WebCache::UsageStats* stats) {
+ h->GatherStats(renderers, stats);
+ }
+ static size_t GetSize(int tactic,
+ const WebCache::UsageStats& stats) {
+ return WebCacheManager::GetSize(
+ static_cast<WebCacheManager::AllocationTactic>(tactic), stats);
+ }
+ static bool AttemptTactic(WebCacheManager* h,
+ int active_tactic,
+ const WebCache::UsageStats& active_stats,
+ int inactive_tactic,
+ const WebCache::UsageStats& inactive_stats,
+ std::list< std::pair<int,size_t> >* strategy) {
+ return h->AttemptTactic(
+ static_cast<WebCacheManager::AllocationTactic>(active_tactic),
+ active_stats,
+ static_cast<WebCacheManager::AllocationTactic>(inactive_tactic),
+ inactive_stats,
+ strategy);
+ }
+ static void AddToStrategy(WebCacheManager* h,
+ std::set<int> renderers,
+ int tactic,
+ size_t extra_bytes_to_allocate,
+ std::list< std::pair<int,size_t> >* strategy) {
+ h->AddToStrategy(renderers,
+ static_cast<WebCacheManager::AllocationTactic>(tactic),
+ extra_bytes_to_allocate,
+ strategy);
+ }
+
+ enum {
+ DIVIDE_EVENLY = WebCacheManager::DIVIDE_EVENLY,
+ KEEP_CURRENT_WITH_HEADROOM = WebCacheManager::KEEP_CURRENT_WITH_HEADROOM,
+ KEEP_CURRENT = WebCacheManager::KEEP_CURRENT,
+ KEEP_LIVE_WITH_HEADROOM = WebCacheManager::KEEP_LIVE_WITH_HEADROOM,
+ KEEP_LIVE = WebCacheManager::KEEP_LIVE,
+ };
+
+ WebCacheManager* manager() { return &manager_; }
+
+ private:
+ WebCacheManager manager_;
+ base::MessageLoop message_loop_;
+ content::TestBrowserThread ui_thread_;
+};
+
+// static
+const int WebCacheManagerTest::kRendererID = 146;
+
+// static
+const int WebCacheManagerTest::kRendererID2 = 245;
+
+// static
+const WebCache::UsageStats WebCacheManagerTest::kStats = {
+ 0,
+ 1024 * 1024,
+ 1024 * 1024,
+ 256 * 1024,
+ 512,
+ };
+
+// static
+const WebCache::UsageStats WebCacheManagerTest::kStats2 = {
+ 0,
+ 2 * 1024 * 1024,
+ 2 * 1024 * 1024,
+ 2 * 256 * 1024,
+ 2 * 512,
+ };
+
+static bool operator==(const WebCache::UsageStats& lhs,
+ const WebCache::UsageStats& rhs) {
+ return !::memcmp(&lhs, &rhs, sizeof(WebCache::UsageStats));
+}
+
+TEST_F(WebCacheManagerTest, AddRemoveRendererTest) {
+ EXPECT_EQ(0U, active_renderers(manager()).size());
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ manager()->Add(kRendererID);
+ EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
+ EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
+
+ manager()->Remove(kRendererID);
+ EXPECT_EQ(0U, active_renderers(manager()).size());
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+}
+
+TEST_F(WebCacheManagerTest, ActiveInactiveTest) {
+ manager()->Add(kRendererID);
+
+ manager()->ObserveActivity(kRendererID);
+ EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
+ EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
+
+ SimulateInactivity(manager(), kRendererID);
+ EXPECT_EQ(0U, active_renderers(manager()).count(kRendererID));
+ EXPECT_EQ(1U, inactive_renderers(manager()).count(kRendererID));
+
+ manager()->ObserveActivity(kRendererID);
+ EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
+ EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
+
+ manager()->Remove(kRendererID);
+}
+
+TEST_F(WebCacheManagerTest, ObserveStatsTest) {
+ manager()->Add(kRendererID);
+
+ EXPECT_EQ(1U, stats(manager()).size());
+
+ manager()->ObserveStats(kRendererID, kStats);
+
+ EXPECT_EQ(1U, stats(manager()).size());
+ EXPECT_TRUE(kStats == stats(manager())[kRendererID]);
+
+ manager()->Remove(kRendererID);
+}
+
+TEST_F(WebCacheManagerTest, SetGlobalSizeLimitTest) {
+ size_t limit = manager()->GetDefaultGlobalSizeLimit();
+ manager()->SetGlobalSizeLimit(limit);
+ EXPECT_EQ(limit, manager()->global_size_limit());
+
+ manager()->SetGlobalSizeLimit(0);
+ EXPECT_EQ(0U, manager()->global_size_limit());
+}
+
+TEST_F(WebCacheManagerTest, GatherStatsTest) {
+ manager()->Add(kRendererID);
+ manager()->Add(kRendererID2);
+
+ manager()->ObserveStats(kRendererID, kStats);
+ manager()->ObserveStats(kRendererID2, kStats2);
+
+ std::set<int> renderer_set;
+ renderer_set.insert(kRendererID);
+
+ WebCache::UsageStats stats;
+ GatherStats(manager(), renderer_set, &stats);
+
+ EXPECT_TRUE(kStats == stats);
+
+ renderer_set.insert(kRendererID2);
+ GatherStats(manager(), renderer_set, &stats);
+
+ WebCache::UsageStats expected_stats = kStats;
+ expected_stats.minDeadCapacity += kStats2.minDeadCapacity;
+ expected_stats.maxDeadCapacity += kStats2.maxDeadCapacity;
+ expected_stats.capacity += kStats2.capacity;
+ expected_stats.liveSize += kStats2.liveSize;
+ expected_stats.deadSize += kStats2.deadSize;
+
+ EXPECT_TRUE(expected_stats == stats);
+
+ manager()->Remove(kRendererID);
+ manager()->Remove(kRendererID2);
+}
+
+TEST_F(WebCacheManagerTest, GetSizeTest) {
+ EXPECT_EQ(0U, GetSize(DIVIDE_EVENLY, kStats));
+ EXPECT_LT(256 * 1024u + 512, GetSize(KEEP_CURRENT_WITH_HEADROOM, kStats));
+ EXPECT_EQ(256 * 1024u + 512, GetSize(KEEP_CURRENT, kStats));
+ EXPECT_LT(256 * 1024u, GetSize(KEEP_LIVE_WITH_HEADROOM, kStats));
+ EXPECT_EQ(256 * 1024u, GetSize(KEEP_LIVE, kStats));
+}
+
+TEST_F(WebCacheManagerTest, AttemptTacticTest) {
+ manager()->Add(kRendererID);
+ manager()->Add(kRendererID2);
+
+ manager()->ObserveActivity(kRendererID);
+ SimulateInactivity(manager(), kRendererID2);
+
+ manager()->ObserveStats(kRendererID, kStats);
+ manager()->ObserveStats(kRendererID2, kStats2);
+
+ manager()->SetGlobalSizeLimit(kStats.liveSize + kStats.deadSize +
+ kStats2.liveSize + kStats2.deadSize/2);
+
+ AllocationStrategy strategy;
+
+ EXPECT_FALSE(AttemptTactic(manager(),
+ KEEP_CURRENT,
+ kStats,
+ KEEP_CURRENT,
+ kStats2,
+ &strategy));
+ EXPECT_TRUE(strategy.empty());
+
+ EXPECT_TRUE(AttemptTactic(manager(),
+ KEEP_CURRENT,
+ kStats,
+ KEEP_LIVE,
+ kStats2,
+ &strategy));
+ EXPECT_EQ(2U, strategy.size());
+
+ AllocationStrategy::iterator iter = strategy.begin();
+ while (iter != strategy.end()) {
+ if (iter->first == kRendererID)
+ EXPECT_LE(kStats.liveSize + kStats.deadSize, iter->second);
+ else if (iter->first == kRendererID2)
+ EXPECT_LE(kStats2.liveSize, iter->second);
+ else
+ ADD_FAILURE(); // Unexpected entry in strategy.
+ ++iter;
+ }
+
+ manager()->Remove(kRendererID);
+ manager()->Remove(kRendererID2);
+}
+
+TEST_F(WebCacheManagerTest, AddToStrategyTest) {
+ manager()->Add(kRendererID);
+ manager()->Add(kRendererID2);
+
+ std::set<int> renderer_set;
+ renderer_set.insert(kRendererID);
+ renderer_set.insert(kRendererID2);
+
+ manager()->ObserveStats(kRendererID, kStats);
+ manager()->ObserveStats(kRendererID2, kStats2);
+
+ const size_t kExtraBytesToAllocate = 10 * 1024;
+
+ AllocationStrategy strategy;
+ AddToStrategy(manager(),
+ renderer_set,
+ KEEP_CURRENT,
+ kExtraBytesToAllocate,
+ &strategy);
+
+ EXPECT_EQ(2U, strategy.size());
+
+ size_t total_bytes = 0;
+ AllocationStrategy::iterator iter = strategy.begin();
+ while (iter != strategy.end()) {
+ total_bytes += iter->second;
+
+ if (iter->first == kRendererID)
+ EXPECT_LE(kStats.liveSize + kStats.deadSize, iter->second);
+ else if (iter->first == kRendererID2)
+ EXPECT_LE(kStats2.liveSize + kStats2.deadSize, iter->second);
+ else
+ ADD_FAILURE(); // Unexpected entry in strategy.
+ ++iter;
+ }
+
+ size_t expected_total_bytes = kExtraBytesToAllocate +
+ kStats.liveSize + kStats.deadSize +
+ kStats2.liveSize + kStats2.deadSize;
+
+ EXPECT_GE(expected_total_bytes, total_bytes);
+
+ manager()->Remove(kRendererID);
+ manager()->Remove(kRendererID2);
+}
+
+// Regression test for http://crbug.com/12362.
+// There are three operations in the following order will cause the crash:
+// Remove(kRendererID) -> ObserveActivity(kRendererID) -> Remove(kRendererID2)
+// To prevent similar failures in the future, 6 tests are added in total to
+// cover all the possible orderings of these three operations.
+TEST_F(WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_1) {
+ EXPECT_EQ(0U, active_renderers(manager()).size());
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ // Add, Remove, and ObserveActivity trigger deferred
+ // calls to ReviseAllocationStrategy and that we call it directly after each
+ // operation to sidestep the need to wait for an unobservable background
+ // operation.
+ manager()->Add(kRendererID);
+ manager()->ReviseAllocationStrategy();
+ manager()->Add(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ // The following order will cause a crash in http://crbug.com/12362.
+ manager()->Remove(kRendererID);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->ObserveActivity(kRendererID);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+}
+
+TEST_F(WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_2) {
+ EXPECT_EQ(0U, active_renderers(manager()).size());
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ // Add, Remove, and ObserveActivity trigger deferred
+ // calls to ReviseAllocationStrategy and that we call it directly after each
+ // operation to sidestep the need to wait for an unobservable background
+ // operation.
+ manager()->Add(kRendererID);
+ manager()->ReviseAllocationStrategy();
+ manager()->Add(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->ObserveActivity(kRendererID);
+ manager()->ReviseAllocationStrategy();
+
+}
+
+TEST_F(WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_3) {
+ EXPECT_EQ(0U, active_renderers(manager()).size());
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ // Add, Remove, and ObserveActivity trigger deferred
+ // calls to ReviseAllocationStrategy and that we call it directly after each
+ // operation to sidestep the need to wait for an unobservable background
+ // operation.
+ manager()->Add(kRendererID);
+ manager()->ReviseAllocationStrategy();
+ manager()->Add(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->ObserveActivity(kRendererID);
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ manager()->Remove(kRendererID);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+}
+
+TEST_F(WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_4) {
+ EXPECT_EQ(0U, active_renderers(manager()).size());
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ // Add, Remove, and ObserveActivity trigger deferred
+ // calls to ReviseAllocationStrategy and that we call it directly after each
+ // operation to sidestep the need to wait for an unobservable background
+ // operation.
+ manager()->Add(kRendererID);
+ manager()->ReviseAllocationStrategy();
+ manager()->Add(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->ObserveActivity(kRendererID);
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ manager()->Remove(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID);
+ manager()->ReviseAllocationStrategy();
+}
+
+TEST_F(WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_5) {
+ EXPECT_EQ(0U, active_renderers(manager()).size());
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ // Add, Remove, and ObserveActivity trigger deferred
+ // calls to ReviseAllocationStrategy and that we call it directly after each
+ // operation to sidestep the need to wait for an unobservable background
+ // operation.
+ manager()->Add(kRendererID);
+ manager()->ReviseAllocationStrategy();
+ manager()->Add(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->ObserveActivity(kRendererID);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID);
+ manager()->ReviseAllocationStrategy();
+}
+
+TEST_F(WebCacheManagerTest,
+ CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_6) {
+ EXPECT_EQ(0U, active_renderers(manager()).size());
+ EXPECT_EQ(0U, inactive_renderers(manager()).size());
+
+ // Add, Remove, and ObserveActivity trigger deferred
+ // calls to ReviseAllocationStrategy and that we call it directly after each
+ // operation to sidestep the need to wait for an unobservable background
+ // operation.
+ manager()->Add(kRendererID);
+ manager()->ReviseAllocationStrategy();
+ manager()->Add(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID2);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->Remove(kRendererID);
+ manager()->ReviseAllocationStrategy();
+
+ manager()->ObserveActivity(kRendererID);
+ manager()->ReviseAllocationStrategy();
+}
+
+} // namespace web_cache
diff --git a/chromium/components/web_cache/common/BUILD.gn b/chromium/components/web_cache/common/BUILD.gn
new file mode 100644
index 00000000000..5c7b2ef196c
--- /dev/null
+++ b/chromium/components/web_cache/common/BUILD.gn
@@ -0,0 +1,16 @@
+# 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.
+
+static_library("common") {
+ output_name = "web_cache_common"
+ sources = [
+ "web_cache_message_generator.cc",
+ "web_cache_message_generator.h",
+ "web_cache_messages.h",
+ ]
+
+ deps = [
+ "//ipc",
+ ]
+}
diff --git a/chromium/components/web_cache/common/DEPS b/chromium/components/web_cache/common/DEPS
new file mode 100644
index 00000000000..1c40d981eb6
--- /dev/null
+++ b/chromium/components/web_cache/common/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+ipc",
+]
diff --git a/chromium/components/web_cache/common/OWNERS b/chromium/components/web_cache/common/OWNERS
new file mode 100644
index 00000000000..5ecb4069fa5
--- /dev/null
+++ b/chromium/components/web_cache/common/OWNERS
@@ -0,0 +1,11 @@
+# Changes to IPC messages require a security review to avoid introducing
+# new sandbox escapes.
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=dcheng@chromium.org
+per-file *_messages*.h=inferno@chromium.org
+per-file *_messages*.h=jln@chromium.org
+per-file *_messages*.h=jschuh@chromium.org
+per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=nasko@chromium.org
+per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/components/web_cache/common/web_cache_message_generator.cc b/chromium/components/web_cache/common/web_cache_message_generator.cc
new file mode 100644
index 00000000000..b4b2d265674
--- /dev/null
+++ b/chromium/components/web_cache/common/web_cache_message_generator.cc
@@ -0,0 +1,33 @@
+// 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.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "components/web_cache/common/web_cache_message_generator.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "components/web_cache/common/web_cache_message_generator.h"
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "components/web_cache/common/web_cache_message_generator.h"
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+namespace IPC {
+#include "components/web_cache/common/web_cache_message_generator.h"
+} // namespace IPC
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+namespace IPC {
+#include "components/web_cache/common/web_cache_message_generator.h"
+} // namespace IPC
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+namespace IPC {
+#include "components/web_cache/common/web_cache_message_generator.h"
+} // namespace IPC
diff --git a/chromium/components/web_cache/common/web_cache_message_generator.h b/chromium/components/web_cache/common/web_cache_message_generator.h
new file mode 100644
index 00000000000..d88eb86447e
--- /dev/null
+++ b/chromium/components/web_cache/common/web_cache_message_generator.h
@@ -0,0 +1,7 @@
+// 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.
+
+// Multiply-included file, no traditional include guard.
+
+#include "components/web_cache/common/web_cache_messages.h"
diff --git a/chromium/components/web_cache/common/web_cache_messages.h b/chromium/components/web_cache/common/web_cache_messages.h
new file mode 100644
index 00000000000..a521399101c
--- /dev/null
+++ b/chromium/components/web_cache/common/web_cache_messages.h
@@ -0,0 +1,23 @@
+// Copyright (c) 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.
+
+// Multiply-included file, no traditional include guard.
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+
+#define IPC_MESSAGE_START WebCacheMsgStart
+
+//-----------------------------------------------------------------------------
+// RenderView messages
+// These are messages sent from the browser to the renderer process.
+
+// Tells the renderer to set its maximum cache size to the supplied value.
+IPC_MESSAGE_CONTROL3(WebCacheMsg_SetCacheCapacities,
+ size_t /* min_dead_capacity */,
+ size_t /* max_dead_capacity */,
+ size_t /* capacity */)
+
+// Tells the renderer to clear the cache.
+IPC_MESSAGE_CONTROL1(WebCacheMsg_ClearCache,
+ bool /* on_navigation */)
diff --git a/chromium/components/web_cache/renderer/BUILD.gn b/chromium/components/web_cache/renderer/BUILD.gn
new file mode 100644
index 00000000000..cdd703a8145
--- /dev/null
+++ b/chromium/components/web_cache/renderer/BUILD.gn
@@ -0,0 +1,17 @@
+# 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.
+
+static_library("renderer") {
+ output_name = "web_cache_renderer"
+ sources = [
+ "web_cache_render_process_observer.cc",
+ "web_cache_render_process_observer.h",
+ ]
+
+ deps = [
+ "//components/web_cache/common",
+ "//content/public/renderer",
+ "//third_party/WebKit/public:blink",
+ ]
+}
diff --git a/chromium/components/web_cache/renderer/DEPS b/chromium/components/web_cache/renderer/DEPS
new file mode 100644
index 00000000000..100b3d3a109
--- /dev/null
+++ b/chromium/components/web_cache/renderer/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+content/public/renderer",
+ "+third_party/WebKit/public/web",
+]
diff --git a/chromium/components/web_cache/renderer/web_cache_render_process_observer.cc b/chromium/components/web_cache/renderer/web_cache_render_process_observer.cc
new file mode 100644
index 00000000000..a273817a2c0
--- /dev/null
+++ b/chromium/components/web_cache/renderer/web_cache_render_process_observer.cc
@@ -0,0 +1,84 @@
+// 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 "components/web_cache/renderer/web_cache_render_process_observer.h"
+
+#include <limits>
+
+#include "components/web_cache/common/web_cache_messages.h"
+#include "third_party/WebKit/public/web/WebCache.h"
+
+using blink::WebCache;
+
+namespace web_cache {
+
+namespace {
+const size_t kUnitializedCacheCapacity = UINT_MAX;
+}
+
+WebCacheRenderProcessObserver::WebCacheRenderProcessObserver()
+ : clear_cache_pending_(false),
+ webkit_initialized_(false),
+ pending_cache_min_dead_capacity_(0),
+ pending_cache_max_dead_capacity_(0),
+ pending_cache_capacity_(kUnitializedCacheCapacity) {
+}
+
+WebCacheRenderProcessObserver::~WebCacheRenderProcessObserver() {
+}
+
+void WebCacheRenderProcessObserver::ExecutePendingClearCache() {
+ if (clear_cache_pending_ && webkit_initialized_) {
+ clear_cache_pending_ = false;
+ WebCache::clear();
+ }
+}
+
+bool WebCacheRenderProcessObserver::OnControlMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(WebCacheRenderProcessObserver, message)
+ IPC_MESSAGE_HANDLER(WebCacheMsg_SetCacheCapacities, OnSetCacheCapacities)
+ IPC_MESSAGE_HANDLER(WebCacheMsg_ClearCache, OnClearCache)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void WebCacheRenderProcessObserver::WebKitInitialized() {
+ webkit_initialized_ = true;
+ if (pending_cache_capacity_ != kUnitializedCacheCapacity) {
+ WebCache::setCapacities(pending_cache_min_dead_capacity_,
+ pending_cache_max_dead_capacity_,
+ pending_cache_capacity_);
+ }
+}
+
+void WebCacheRenderProcessObserver::OnRenderProcessShutdown() {
+ webkit_initialized_ = false;
+}
+
+void WebCacheRenderProcessObserver::OnSetCacheCapacities(
+ size_t min_dead_capacity,
+ size_t max_dead_capacity,
+ size_t capacity) {
+ if (!webkit_initialized_) {
+ pending_cache_min_dead_capacity_ = min_dead_capacity;
+ pending_cache_max_dead_capacity_ = max_dead_capacity;
+ pending_cache_capacity_ = capacity;
+ return;
+ }
+
+ WebCache::setCapacities(
+ min_dead_capacity, max_dead_capacity, capacity);
+}
+
+void WebCacheRenderProcessObserver::OnClearCache(bool on_navigation) {
+ if (on_navigation || !webkit_initialized_)
+ clear_cache_pending_ = true;
+ else
+ WebCache::clear();
+}
+
+} // namespace web_cache
diff --git a/chromium/components/web_cache/renderer/web_cache_render_process_observer.h b/chromium/components/web_cache/renderer/web_cache_render_process_observer.h
new file mode 100644
index 00000000000..06ffc53319c
--- /dev/null
+++ b/chromium/components/web_cache/renderer/web_cache_render_process_observer.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 COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
+#define COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "content/public/renderer/render_process_observer.h"
+
+namespace web_cache {
+
+// This class filters the incoming cache related control messages.
+class WebCacheRenderProcessObserver : public content::RenderProcessObserver {
+ public:
+ WebCacheRenderProcessObserver();
+ ~WebCacheRenderProcessObserver() override;
+
+ // Needs to be called by RenderViews in case of navigations to execute
+ // any 'clear cache' commands that were delayed until the next navigation.
+ void ExecutePendingClearCache();
+
+ private:
+ // RenderProcessObserver implementation.
+ bool OnControlMessageReceived(const IPC::Message& message) override;
+ void WebKitInitialized() override;
+ void OnRenderProcessShutdown() override;
+
+ // Message handlers.
+ void OnSetCacheCapacities(size_t min_dead_capacity,
+ size_t max_dead_capacity,
+ size_t capacity);
+ // If |on_navigation| is true, the clearing is delayed until the next
+ // navigation event.
+ void OnClearCache(bool on_navigation);
+
+ // If true, the web cache shall be cleared before the next navigation event.
+ bool clear_cache_pending_;
+ bool webkit_initialized_;
+ size_t pending_cache_min_dead_capacity_;
+ size_t pending_cache_max_dead_capacity_;
+ size_t pending_cache_capacity_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebCacheRenderProcessObserver);
+};
+
+} // namespace web_cache
+
+#endif // COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
+
diff --git a/chromium/content/browser/android/background_sync_launcher_android.cc b/chromium/content/browser/android/background_sync_launcher_android.cc
index 78110c14f64..693817baa8a 100644
--- a/chromium/content/browser/android/background_sync_launcher_android.cc
+++ b/chromium/content/browser/android/background_sync_launcher_android.cc
@@ -46,7 +46,8 @@ void BackgroundSyncLauncherAndroid::LaunchBrowserWhenNextOnlineImpl(
if (was_launching != now_launching) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_BackgroundSyncLauncher_setLaunchWhenNextOnline(
- env, java_launcher_.obj(), now_launching);
+ env, java_launcher_.obj(), base::android::GetApplicationContext(),
+ now_launching);
}
}
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.cc b/chromium/content/browser/service_worker/service_worker_context_core.cc
index 17ff54548f6..bb17f8e3be1 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -494,6 +494,9 @@ void ServiceWorkerContextCore::TransferProviderHostIn(
scoped_ptr<ServiceWorkerProviderHost> transferee) {
ProviderMap* map = GetProviderMapForProcess(new_process_id);
ServiceWorkerProviderHost* temp = map->Lookup(new_provider_id);
+ if (!temp)
+ return;
+
DCHECK(temp->document_url().is_empty());
transferee->CompleteCrossSiteTransfer(new_process_id,
temp->frame_id(),
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index c5514f65877..9e48aa7b37e 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -1524,7 +1524,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Create the cross-site URL to navigate to.
GURL cross_site_url =
- embedded_test_server()->GetURL("foo.com", "/frame_tree/1-1.html");
+ embedded_test_server()->GetURL("foo.com", "/frame_tree/title2.html");
// Load cross-site page into the second iframe without waiting for the
// navigation to complete. Once LoadURLWithParams returns, we would expect
@@ -1584,7 +1584,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
// Load another cross-site page into the same iframe.
- cross_site_url = embedded_test_server()->GetURL("bar.com", "/title2.html");
+ cross_site_url = embedded_test_server()->GetURL("bar.com", "/title3.html");
{
// Perform the same checks as the first cross-site navigation, since
// there have been issues in subsequent cross-site navigations. Also ensure
diff --git a/chromium/content/child/service_worker/web_service_worker_impl.cc b/chromium/content/child/service_worker/web_service_worker_impl.cc
index 0939aaa7b6d..60d2a292565 100644
--- a/chromium/content/child/service_worker/web_service_worker_impl.cc
+++ b/chromium/content/child/service_worker/web_service_worker_impl.cc
@@ -44,7 +44,11 @@ WebServiceWorkerImpl::~WebServiceWorkerImpl() {
void WebServiceWorkerImpl::OnStateChanged(
blink::WebServiceWorkerState new_state) {
state_ = new_state;
- proxy_->dispatchStateChangeEvent();
+
+ // TODO(nhiroki): This is a quick fix for http://crbug.com/507110
+ DCHECK(proxy_);
+ if (proxy_)
+ proxy_->dispatchStateChangeEvent();
}
void WebServiceWorkerImpl::setProxy(blink::WebServiceWorkerProxy* proxy) {
diff --git a/chromium/content/common/gpu/media/h264_decoder.cc b/chromium/content/common/gpu/media/h264_decoder.cc
index 9953ff21a59..6f9c9180482 100644
--- a/chromium/content/common/gpu/media/h264_decoder.cc
+++ b/chromium/content/common/gpu/media/h264_decoder.cc
@@ -362,9 +362,6 @@ void H264Decoder::ConstructReferencePicListsP(
dpb_.GetLongTermRefPicsAppending(&ref_pic_list_p0_);
std::sort(ref_pic_list_p0_.begin() + num_short_refs, ref_pic_list_p0_.end(),
LongTermPicNumAscCompare());
-
- // Cut off if we have more than requested in slice header.
- ref_pic_list_p0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
}
struct POCAscCompare {
@@ -436,12 +433,6 @@ void H264Decoder::ConstructReferencePicListsB(
std::equal(ref_pic_list_b0_.begin(), ref_pic_list_b0_.end(),
ref_pic_list_b1_.begin()))
std::swap(ref_pic_list_b1_[0], ref_pic_list_b1_[1]);
-
- // Per 8.2.4.2 it's possible for num_ref_idx_lX_active_minus1 to indicate
- // there should be more ref pics on list than we constructed.
- // Those superfluous ones should be treated as non-reference.
- ref_pic_list_b0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
- ref_pic_list_b1_.resize(slice_hdr->num_ref_idx_l1_active_minus1 + 1);
}
// See 8.2.4
@@ -489,25 +480,36 @@ static void ShiftRightAndInsert(H264Picture::Vector* v,
bool H264Decoder::ModifyReferencePicList(media::H264SliceHeader* slice_hdr,
int list,
H264Picture::Vector* ref_pic_listx) {
+ bool ref_pic_list_modification_flag_lX;
int num_ref_idx_lX_active_minus1;
media::H264ModificationOfPicNum* list_mod;
// This can process either ref_pic_list0 or ref_pic_list1, depending on
// the list argument. Set up pointers to proper list to be processed here.
if (list == 0) {
- if (!slice_hdr->ref_pic_list_modification_flag_l0)
- return true;
-
+ ref_pic_list_modification_flag_lX =
+ slice_hdr->ref_pic_list_modification_flag_l0;
+ num_ref_idx_lX_active_minus1 =
+ slice_hdr->num_ref_idx_l0_active_minus1;
list_mod = slice_hdr->ref_list_l0_modifications;
} else {
- if (!slice_hdr->ref_pic_list_modification_flag_l1)
- return true;
-
+ ref_pic_list_modification_flag_lX =
+ slice_hdr->ref_pic_list_modification_flag_l1;
+ num_ref_idx_lX_active_minus1 =
+ slice_hdr->num_ref_idx_l1_active_minus1;
list_mod = slice_hdr->ref_list_l1_modifications;
}
- num_ref_idx_lX_active_minus1 = ref_pic_listx->size() - 1;
+ // Resize the list to the size requested in the slice header.
+ // Note that per 8.2.4.2 it's possible for num_ref_idx_lX_active_minus1 to
+ // indicate there should be more ref pics on list than we constructed.
+ // Those superfluous ones should be treated as non-reference and will be
+ // initialized to nullptr, which must be handled by clients.
DCHECK_GE(num_ref_idx_lX_active_minus1, 0);
+ ref_pic_listx->resize(num_ref_idx_lX_active_minus1 + 1);
+
+ if (!ref_pic_list_modification_flag_lX)
+ return true;
// Spec 8.2.4.3:
// Reorder pictures on the list in a way specified in the stream.
diff --git a/chromium/content/content.gyp b/chromium/content/content.gyp
index 9ce90ef469b..efcbf740586 100644
--- a/chromium/content/content.gyp
+++ b/chromium/content/content.gyp
@@ -430,6 +430,7 @@
'dependencies': [
'../base/base.gyp:base',
'../device/battery/battery.gyp:device_battery_java',
+ '../device/bluetooth/bluetooth.gyp:device_bluetooth_java',
'../device/vibration/vibration.gyp:device_vibration_java',
'../media/media.gyp:media_java',
'../mojo/mojo_base.gyp:mojo_application_bindings',
diff --git a/chromium/content/public/android/BUILD.gn b/chromium/content/public/android/BUILD.gn
index 663ccf69e82..98727004a89 100644
--- a/chromium/content/public/android/BUILD.gn
+++ b/chromium/content/public/android/BUILD.gn
@@ -34,6 +34,7 @@ android_library("content_java") {
"//base:base_java",
"//device/battery/android:battery_monitor_android",
"//device/battery:mojo_bindings_java",
+ "//device/bluetooth:java",
"//media/base/android:media_java",
"//media/midi:midi_java",
"//mojo/android:system_java",
diff --git a/chromium/google_apis/gaia/oauth2_token_service_delegate.cc b/chromium/google_apis/gaia/oauth2_token_service_delegate.cc
index 2f976145ea1..aed5db8bc23 100644
--- a/chromium/google_apis/gaia/oauth2_token_service_delegate.cc
+++ b/chromium/google_apis/gaia/oauth2_token_service_delegate.cc
@@ -48,8 +48,7 @@ void OAuth2TokenServiceDelegate::RemoveObserver(
// static
bool OAuth2TokenServiceDelegate::IsError(const GoogleServiceAuthError& error) {
- // TODO(rogerta): should we distinguish between transient and persistent?
- return error.state() != GoogleServiceAuthError::NONE;
+ return error.IsPersistentError();
}
void OAuth2TokenServiceDelegate::StartBatchChanges() {
diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp b/chromium/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
index ecd8bde98fb..ba3aeead268 100644
--- a/chromium/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
+++ b/chromium/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
@@ -139,6 +139,10 @@ void ScriptController::clearForClose()
void ScriptController::updateSecurityOrigin(SecurityOrigin* origin)
{
m_windowProxyManager->mainWorldProxy()->updateSecurityOrigin(origin);
+ Vector<std::pair<ScriptState*, SecurityOrigin*>> isolatedContexts;
+ m_windowProxyManager->collectIsolatedContexts(isolatedContexts);
+ for (auto isolatedContext : isolatedContexts)
+ m_windowProxyManager->windowProxy(isolatedContext.first->world())->updateSecurityOrigin(isolatedContext.second);
}
v8::MaybeLocal<v8::Value> ScriptController::callFunction(v8::Local<v8::Function> function, v8::Local<v8::Value> receiver, int argc, v8::Local<v8::Value> info[])
diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp b/chromium/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
index 72b7724bd88..52bbd0230fd 100644
--- a/chromium/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
+++ b/chromium/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
@@ -169,6 +169,7 @@ public:
, m_queueLeadPosition(0)
, m_queueTailPosition(0)
, m_bookmarkPosition(0)
+ , m_lengthOfBOM(0)
{
}
@@ -201,7 +202,7 @@ public:
{
ASSERT(!isMainThread());
m_bookmarkPosition = m_queueLeadPosition;
- return m_bookmarkPosition != 0; // Don't mess with BOM.
+ return true;
}
// Called by V8 on background thread.
@@ -211,7 +212,9 @@ public:
{
MutexLocker locker(m_mutex);
m_queueLeadPosition = m_bookmarkPosition;
- m_queueTailPosition = m_bookmarkPosition;
+ // See comments at m_lengthOfBOM declaration below for why
+ // we need this here.
+ m_queueTailPosition = m_bookmarkPosition + m_lengthOfBOM;
m_dataQueue.clear();
}
@@ -308,6 +311,11 @@ private:
}
}
+ if (lengthOfBOM > 0) {
+ ASSERT(!m_lengthOfBOM); // There should be only one BOM.
+ m_lengthOfBOM = lengthOfBOM;
+ }
+
// Copy the data chunks into a new buffer, since we're going to give the
// data to a background thread.
if (dataLength > lengthOfBOM) {
@@ -346,6 +354,22 @@ private:
unsigned m_queueLeadPosition; // Only used by v8 thread.
unsigned m_queueTailPosition; // Used by both threads; guarded by m_mutex.
unsigned m_bookmarkPosition; // Only used by v8 thread.
+
+ // BOM (Unicode Byte Order Mark) handling:
+ // This class is responsible for stripping out the BOM, since Chrome
+ // delivers the input stream potentially with BOM, but V8 doesn't want
+ // to see the BOM. This is mostly easy to do, except for a funky edge
+ // condition with bookmarking:
+ // - m_queueLeadPosition counts the bytes that V8 has received
+ // (i.e., without BOM)
+ // - m_queueTailPosition counts the bytes that Chrome has sent
+ // (i.e., with BOM)
+ // So when resetting the bookmark, we have to adjust the lead position
+ // to account for the BOM (which happens implicitly in the regular
+ // streaming case).
+ // We store this separately, to avoid having to guard all
+ // m_queueLeadPosition references with a mutex.
+ unsigned m_lengthOfBOM; // Used by both threads; guarded by m_mutex.
};
size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024;
diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp b/chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
index d1d463530fc..c83dd50607c 100644
--- a/chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
+++ b/chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
@@ -34,6 +34,7 @@
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8HTMLCollection.h"
#include "bindings/core/v8/V8HTMLDocument.h"
+#include "bindings/core/v8/V8Location.h"
#include "bindings/core/v8/V8ObjectConstructor.h"
#include "bindings/core/v8/V8PerContextData.h"
#include "bindings/core/v8/V8PerIsolateData.h"
@@ -72,7 +73,12 @@ static v8::Local<v8::Object> wrapInShadowTemplate(v8::Local<v8::Object> wrapper,
v8::Local<v8::Object> V8DOMWrapper::createWrapper(v8::Isolate* isolate, v8::Local<v8::Object> creationContext, const WrapperTypeInfo* type, ScriptWrappable* scriptWrappable)
{
- V8WrapperInstantiationScope scope(creationContext, isolate);
+ ASSERT(!type->equals(&V8Window::wrapperTypeInfo));
+ // According to https://html.spec.whatwg.org/multipage/browsers.html#security-location,
+ // cross-origin script access to a few properties of Location is allowed.
+ // Location already implements the necessary security checks.
+ bool withSecurityCheck = !type->equals(&V8Location::wrapperTypeInfo);
+ V8WrapperInstantiationScope scope(creationContext, isolate, withSecurityCheck);
V8PerContextData* perContextData = V8PerContextData::from(scope.context());
v8::Local<v8::Object> wrapper;
@@ -124,4 +130,31 @@ bool V8DOMWrapper::hasInternalFieldsSet(v8::Local<v8::Value> value)
&& untrustedWrapperTypeInfo->ginEmbedder == gin::kEmbedderBlink;
}
+void V8WrapperInstantiationScope::securityCheck(v8::Isolate* isolate, v8::Local<v8::Context> contextForWrapper)
+{
+ if (m_context.IsEmpty())
+ return;
+ // If the context is different, we need to make sure that the current
+ // context has access to the creation context.
+ Frame* frame = toFrameIfNotDetached(contextForWrapper);
+ if (!frame)
+ return;
+ const DOMWrapperWorld& currentWorld = DOMWrapperWorld::world(m_context);
+ RELEASE_ASSERT(currentWorld.worldId() == DOMWrapperWorld::world(contextForWrapper).worldId());
+ if (currentWorld.isMainWorld()) {
+ RELEASE_ASSERT(BindingSecurity::shouldAllowAccessToFrame(isolate, frame, DoNotReportSecurityError));
+ }
+}
+
+void V8WrapperInstantiationScope::convertException()
+{
+ v8::Isolate* isolate = m_context->GetIsolate();
+ // TODO(jochen): Currently, Location is the only object for which we can reach this code path. Should be generalized.
+ ExceptionState exceptionState(ExceptionState::ConstructionContext, "Location", isolate->GetCurrentContext()->Global(), isolate);
+ LocalDOMWindow* callingWindow = callingDOMWindow(isolate);
+ DOMWindow* targetWindow = toFrameIfNotDetached(m_context)->domWindow();
+ exceptionState.throwSecurityError(targetWindow->sanitizedCrossDomainAccessErrorMessage(callingWindow), targetWindow->crossDomainAccessErrorMessage(callingWindow));
+ exceptionState.throwIfNeeded();
+}
+
} // namespace blink
diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h b/chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h
index dbe68a1b083..e436cc39064 100644
--- a/chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h
+++ b/chromium/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.h
@@ -31,8 +31,10 @@
#ifndef V8DOMWrapper_h
#define V8DOMWrapper_h
+#include "bindings/core/v8/BindingSecurity.h"
#include "bindings/core/v8/DOMDataStore.h"
#include "bindings/core/v8/ScriptWrappable.h"
+#include "bindings/core/v8/V8Binding.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RawPtr.h"
#include "wtf/text/AtomicString.h"
@@ -106,19 +108,27 @@ inline v8::Local<v8::Object> V8DOMWrapper::associateObjectWithWrapper(v8::Isolat
class V8WrapperInstantiationScope {
public:
- V8WrapperInstantiationScope(v8::Local<v8::Object> creationContext, v8::Isolate* isolate)
+ V8WrapperInstantiationScope(v8::Local<v8::Object> creationContext, v8::Isolate* isolate, bool withSecurityCheck = true)
: m_didEnterContext(false)
, m_context(isolate->GetCurrentContext())
+ , m_tryCatch(isolate)
+ , m_convertExceptions(false)
{
// creationContext should not be empty. Because if we have an
// empty creationContext, we will end up creating
// a new object in the context currently entered. This is wrong.
RELEASE_ASSERT(!creationContext.IsEmpty());
v8::Local<v8::Context> contextForWrapper = creationContext->CreationContext();
+
// For performance, we enter the context only if the currently running context
// is different from the context that we are about to enter.
if (contextForWrapper == m_context)
return;
+ if (withSecurityCheck) {
+ securityCheck(isolate, contextForWrapper);
+ } else {
+ m_convertExceptions = true;
+ }
m_context = v8::Local<v8::Context>::New(isolate, contextForWrapper);
m_didEnterContext = true;
m_context->Enter();
@@ -126,16 +136,31 @@ public:
~V8WrapperInstantiationScope()
{
- if (!m_didEnterContext)
+ if (!m_didEnterContext) {
+ m_tryCatch.ReThrow();
return;
+ }
m_context->Exit();
+ // Rethrow any cross-context exceptions as security error.
+ if (m_tryCatch.HasCaught()) {
+ if (m_convertExceptions) {
+ m_tryCatch.Reset();
+ convertException();
+ }
+ m_tryCatch.ReThrow();
+ }
}
v8::Local<v8::Context> context() const { return m_context; }
private:
+ void securityCheck(v8::Isolate*, v8::Local<v8::Context> contextForWrapper);
+ void convertException();
+
bool m_didEnterContext;
v8::Local<v8::Context> m_context;
+ v8::TryCatch m_tryCatch;
+ bool m_convertExceptions;
};
} // namespace blink
diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp b/chromium/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
index 7b322634614..532e36cbfab 100644
--- a/chromium/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
+++ b/chromium/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
@@ -428,8 +428,22 @@ void WindowProxy::setSecurityToken(SecurityOrigin* origin)
return;
}
- if (m_world->isPrivateScriptIsolatedWorld())
+ if (m_world->isPrivateScriptIsolatedWorld()) {
token = "private-script://" + token;
+ } else if (m_world->isIsolatedWorld()) {
+ SecurityOrigin* frameSecurityOrigin = m_frame->securityContext()->securityOrigin();
+ String frameSecurityToken = frameSecurityOrigin->toString();
+ // We need to check the return value of domainWasSetInDOM() on the
+ // frame's SecurityOrigin because, if that's the case, only
+ // SecurityOrigin::m_domain would have been modified.
+ // m_domain is not used by SecurityOrigin::toString(), so we would end
+ // up generating the same token that was already set.
+ if (frameSecurityOrigin->domainWasSetInDOM() || frameSecurityToken.isEmpty() || frameSecurityToken == "null") {
+ context->UseDefaultSecurityToken();
+ return;
+ }
+ token = frameSecurityToken + token;
+ }
CString utf8Token = token.utf8();
// NOTE: V8 does identity comparison in fast path, must use a symbol
@@ -522,7 +536,6 @@ void WindowProxy::namedItemRemoved(HTMLDocument* document, const AtomicString& n
void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin)
{
- ASSERT(m_world->isMainWorld());
if (!isContextInitialized())
return;
setSecurityToken(origin);
diff --git a/chromium/third_party/WebKit/Source/bindings/templates/interface.cpp b/chromium/third_party/WebKit/Source/bindings/templates/interface.cpp
index 439672c30b1..c67a5c4d7a5 100644
--- a/chromium/third_party/WebKit/Source/bindings/templates/interface.cpp
+++ b/chromium/third_party/WebKit/Source/bindings/templates/interface.cpp
@@ -560,8 +560,8 @@ void {{v8_class}}::visitDOMWrapper(v8::Isolate* isolate, ScriptWrappable* script
{
{{cpp_class}}* impl = scriptWrappable->toImpl<{{cpp_class}}>();
{% if set_wrapper_reference_to %}
- v8::Local<v8::Object> creationContext = v8::Local<v8::Object>::New(isolate, wrapper);
- V8WrapperInstantiationScope scope(creationContext, isolate);
+ v8::Local<v8::Object> context = v8::Local<v8::Object>::New(isolate, wrapper);
+ v8::Context::Scope scope(context->CreationContext());
{{set_wrapper_reference_to.cpp_type}} {{set_wrapper_reference_to.name}} = impl->{{set_wrapper_reference_to.name}}();
if ({{set_wrapper_reference_to.name}}) {
if (DOMDataStore::containsWrapper({{set_wrapper_reference_to.name}}, isolate))
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
index bc59b437401..1764fbef7b2 100644
--- a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -100,6 +100,11 @@ static PassRefPtrWillBeRawPtr<StringKeyframeEffectModel> createKeyframeEffectMod
timingFunction = CSSTimingData::initialTimingFunction();
}
keyframe->setEasing(timingFunction.release());
+ } else if (property == CSSPropertyFilter) {
+ // TODO(alancutter): We will not support animating filter until -webkit-filter is an alias for it.
+ // This is to prevent animations on both -webkit-filter and filter from being run on the main thread when
+ // they would otherwise run on the compositor.
+ continue;
} else if (CSSAnimations::isAnimatableProperty(property)) {
keyframe->setPropertyValue(property, properties.propertyAt(j).value());
}
diff --git a/chromium/third_party/WebKit/Source/core/dom/Document.cpp b/chromium/third_party/WebKit/Source/core/dom/Document.cpp
index d1a46222e65..b21280d217a 100644
--- a/chromium/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/chromium/third_party/WebKit/Source/core/dom/Document.cpp
@@ -4073,6 +4073,9 @@ String Document::lastModified() const
const KURL& Document::firstPartyForCookies() const
{
+ if (SchemeRegistry::shouldTreatURLSchemeAsFirstPartyWhenTopLevel(topDocument().url().protocol()))
+ return topDocument().url();
+
// We're intentionally using the URL of each document rather than the document's SecurityOrigin.
// Sandboxing a document into a unique origin shouldn't effect first-/third-party status for
// cookies and site data.
@@ -5377,10 +5380,10 @@ void Document::updateHoverActiveState(const HitTestRequest& request, Element* in
if (oldActiveElement && !request.active()) {
// The oldActiveElement layoutObject is null, dropped on :active by setting display: none,
// for instance. We still need to clear the ActiveChain as the mouse is released.
- for (Node* node = oldActiveElement; node; node = ComposedTreeTraversal::parent(*node)) {
+ for (RefPtrWillBeRawPtr<Node> node = oldActiveElement; node; node = ComposedTreeTraversal::parent(*node)) {
ASSERT(!node->isTextNode());
node->setActive(false);
- m_userActionElements.setInActiveChain(node, false);
+ m_userActionElements.setInActiveChain(node.get(), false);
}
setActiveHoverElement(nullptr);
} else {
diff --git a/chromium/third_party/WebKit/Source/core/dom/Text.cpp b/chromium/third_party/WebKit/Source/core/dom/Text.cpp
index 71ce46fafe3..4f46e8abb87 100644
--- a/chromium/third_party/WebKit/Source/core/dom/Text.cpp
+++ b/chromium/third_party/WebKit/Source/core/dom/Text.cpp
@@ -237,31 +237,12 @@ PassRefPtrWillBeRawPtr<Node> Text::cloneNode(bool /*deep*/)
return cloneWithData(data());
}
-static inline bool hasGeneratedAnonymousTableCells(const LayoutObject& parent)
-{
- // We're checking whether the table part has generated anonymous table
- // part wrappers to hold its contents, so inspecting its first child will suffice.
- LayoutObject* child = parent.slowFirstChild();
- if (!child || !child->isAnonymous())
- return false;
- if (child->isTableCell())
- return true;
- if (child->isTableSection() || child->isTableRow())
- return hasGeneratedAnonymousTableCells(*child);
- return false;
-}
-
static inline bool canHaveWhitespaceChildren(const LayoutObject& parent)
{
// <button> should allow whitespace even though LayoutFlexibleBox doesn't.
if (parent.isLayoutButton())
return true;
- // Allow whitespace when the text is inside a table, section or row element that
- // has generated anonymous table cells to hold its contents.
- if (hasGeneratedAnonymousTableCells(parent))
- return true;
-
if (parent.isTable() || parent.isTableRow() || parent.isTableSection()
|| parent.isLayoutTableCol() || parent.isFrameSet()
|| parent.isFlexibleBox() || parent.isLayoutGrid()
diff --git a/chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp b/chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
index 5954fd198e8..421b23333f8 100644
--- a/chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
+++ b/chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
@@ -122,11 +122,6 @@ void ResourceLoader::start()
ASSERT(!m_request.isNull());
ASSERT(m_deferredRequest.isNull());
- if (responseNeedsAccessControlCheck() && m_fetcher->isControlledByServiceWorker()) {
- m_fallbackRequestForServiceWorker = adoptPtr(new ResourceRequest(m_request));
- m_fallbackRequestForServiceWorker->setSkipServiceWorker(true);
- }
-
m_fetcher->willStartLoadingResource(m_resource, m_request);
if (m_options.synchronousPolicy == RequestSynchronously) {
@@ -331,13 +326,13 @@ void ResourceLoader::didReceiveResponse(WebURLLoader*, const WebURLResponse& res
if (responseNeedsAccessControlCheck()) {
if (response.wasFetchedViaServiceWorker()) {
if (response.wasFallbackRequiredByServiceWorker()) {
- ASSERT(m_fallbackRequestForServiceWorker);
m_loader->cancel();
m_loader.clear();
m_connectionState = ConnectionStateStarted;
- m_request = *m_fallbackRequestForServiceWorker;
m_loader = adoptPtr(Platform::current()->createURLLoader());
ASSERT(m_loader);
+ ASSERT(!m_request.skipServiceWorker());
+ m_request.setSkipServiceWorker(true);
WrappedResourceRequest wrappedRequest(m_request);
m_loader->loadAsynchronously(wrappedRequest, this);
return;
diff --git a/chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.h b/chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.h
index 68ca49a0414..1cb4d81569a 100644
--- a/chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.h
+++ b/chromium/third_party/WebKit/Source/core/fetch/ResourceLoader.h
@@ -111,7 +111,6 @@ private:
bool m_defersLoading;
bool m_loadingMultipartContent;
- OwnPtr<ResourceRequest> m_fallbackRequestForServiceWorker;
ResourceRequest m_deferredRequest;
ResourceLoaderOptions m_options;
diff --git a/chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index 45477c7040b..5ba8e8d21ce 100644
--- a/chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -661,8 +661,17 @@ ApplicationCache* LocalDOMWindow::applicationCache() const
Navigator* LocalDOMWindow::navigator() const
{
+ if (!isCurrentlyDisplayedInFrame() && (!m_navigator || m_navigator->frame())) {
+ // We return a navigator with null frame instead of returning null
+ // pointer as other functions do, in order to allow users to access
+ // functions such as navigator.product.
+ m_navigator = Navigator::create(nullptr);
+ }
if (!m_navigator)
m_navigator = Navigator::create(frame());
+ // As described above, when not dispayed in the frame, the returning
+ // navigator should not be associated with the frame.
+ ASSERT(isCurrentlyDisplayedInFrame() || !m_navigator->frame());
return m_navigator.get();
}
diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
index 0370672ff31..60883065ed3 100644
--- a/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
+++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
@@ -432,6 +432,8 @@ void BaseMultipleFieldsDateAndTimeInputType::requiredAttributeChanged()
void BaseMultipleFieldsDateAndTimeInputType::handleKeydownEvent(KeyboardEvent* event)
{
+ if (!element().focused())
+ return;
if (m_pickerIndicatorIsVisible
&& ((event->keyIdentifier() == "Down" && event->getModifierState("Alt")) || (LayoutTheme::theme().shouldOpenPickerWithF4Key() && event->keyIdentifier() == "F4"))) {
if (PickerIndicatorElement* element = pickerIndicatorElement())
diff --git a/chromium/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/chromium/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 4ab73282d46..05e43ad632e 100644
--- a/chromium/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/chromium/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -459,7 +459,7 @@ void LayoutBlockFlow::determineLogicalLeftPositionForChild(LayoutBox& child)
LayoutUnit newPosition = startPosition + childMarginStart;
LayoutUnit positionToAvoidFloats;
- if (child.avoidsFloats() && containsFloats() && !flowThreadContainingBlock())
+ if (child.avoidsFloats() && containsFloats())
positionToAvoidFloats = startOffsetForLine(logicalTopForChild(child), false, logicalHeightForChild(child));
// If the child has an offset from the content edge to avoid floats then use that, otherwise let any negative
@@ -808,7 +808,9 @@ LayoutUnit LayoutBlockFlow::adjustForUnsplittableChild(LayoutBox& child, LayoutU
if (!pageLogicalHeight)
return logicalOffset;
LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
- if (remainingLogicalHeight < childLogicalHeight)
+ // Break if there's not enough space left for us, but only as long as we're not already at the
+ // top of a page. No point in leaving a page completely blank.
+ if (remainingLogicalHeight < childLogicalHeight && remainingLogicalHeight < pageLogicalHeight)
return logicalOffset + remainingLogicalHeight;
return logicalOffset;
}
diff --git a/chromium/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/chromium/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 74c449fdef3..7c5a4f66404 100644
--- a/chromium/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -864,6 +864,16 @@ LayoutBlock* LayoutObject::containingBlockForAbsolutePosition() const
if (o->canContainFixedPositionObjects())
break;
+ // For relpositioned inlines, we return the nearest non-anonymous enclosing block. We don't try
+ // to return the inline itself. This allows us to avoid having a positioned objects
+ // list in all LayoutInlines and lets us return a strongly-typed LayoutBlock* result
+ // from this method. The container() method can actually be used to obtain the
+ // inline directly.
+ if (o->style()->hasInFlowPosition() && o->isInline() && !o->isReplaced()) {
+ o = o->containingBlock();
+ break;
+ }
+
o = o->parent();
}
@@ -3253,7 +3263,7 @@ void LayoutObject::invalidateDisplayItemClientForNonCompositingDescendantsOf(con
explicit Functor(const LayoutBoxModelObject& paintInvalidationContainer) : m_paintInvalidationContainer(paintInvalidationContainer) { }
void operator()(LayoutObject& object) const override
{
- m_paintInvalidationContainer.invalidateDisplayItemClientOnBacking(object);
+ object.invalidateDisplayItemClients(m_paintInvalidationContainer);
}
private:
const LayoutBoxModelObject& m_paintInvalidationContainer;
diff --git a/chromium/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp b/chromium/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp
index a01f145b6f0..91ada25c62f 100644
--- a/chromium/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp
+++ b/chromium/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp
@@ -723,6 +723,7 @@ PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerP
{
initializeLibXMLIfNecessary();
xmlParserCtxtPtr parser = xmlCreatePushParserCtxt(handlers, 0, 0, 0, 0);
+ xmlCtxtUseOptions(parser, XML_PARSE_HUGE);
parser->_private = userData;
parser->replaceEntities = true;
return adoptRef(new XMLParserContext(parser));
@@ -745,7 +746,8 @@ PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerP
// Set parser options.
// XML_PARSE_NODICT: default dictionary option.
// XML_PARSE_NOENT: force entities substitutions.
- xmlCtxtUseOptions(parser, XML_PARSE_NODICT | XML_PARSE_NOENT);
+ // XML_PARSE_HUGE: don't impose arbitrary limits on document size.
+ xmlCtxtUseOptions(parser, XML_PARSE_NODICT | XML_PARSE_NOENT | XML_PARSE_HUGE);
// Internal initialization
parser->sax2 = 1;
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/elements/Spectrum.js b/chromium/third_party/WebKit/Source/devtools/front_end/elements/Spectrum.js
index 7b5b1de58cf..ec7b8a21f50 100644
--- a/chromium/third_party/WebKit/Source/devtools/front_end/elements/Spectrum.js
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/elements/Spectrum.js
@@ -91,6 +91,7 @@ WebInspector.Spectrum = function()
this._hexValue = this._hexContainer.createChild("input", "spectrum-text-value");
this._hexValue.maxLength = 7;
this._hexValue.addEventListener("keydown", this._inputChanged.bind(this), false);
+ this._hexValue.addEventListener("input", this._inputChanged.bind(this), false);
this._hexValue.addEventListener("mousewheel", this._inputChanged.bind(this), false);
var label = this._hexContainer.createChild("div", "spectrum-text-label");
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/chromium/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index c11bd01e5e2..36d5a594b76 100644
--- a/chromium/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/chromium/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -1389,7 +1389,7 @@ WebInspector.TimelineUIUtils.generateDetailsContentForFrame = function(frameMode
var filmStripPreview = createElementWithClass("img", "timeline-filmstrip-preview");
filmStripFrame.imageDataPromise().then(onGotImageData.bind(null, filmStripPreview));
contentHelper.appendElementRow(WebInspector.UIString("Screenshot"), filmStripPreview);
- filmStripPreview.addEventListener("click", filmStripClicked.bind(null, filmStripFrame), false);
+ filmStripPreview.addEventListener("click", frameClicked.bind(null, filmStripFrame), false);
}
contentHelper.appendTextRow(WebInspector.UIString("Duration"), durationText);
contentHelper.appendTextRow(WebInspector.UIString("FPS"), Math.floor(1000 / durationInMillis));
@@ -1413,9 +1413,9 @@ WebInspector.TimelineUIUtils.generateDetailsContentForFrame = function(frameMode
/**
* @param {!WebInspector.FilmStripModel.Frame} filmStripFrame
*/
- function filmStripClicked(filmStripFrame)
+ function frameClicked(filmStripFrame)
{
- WebInspector.Dialog.show(null, new WebInspector.FilmStripView.DialogDelegate(filmStripFrame, 0));
+ new WebInspector.FilmStripView.DialogDelegate(filmStripFrame, 0);
}
return contentHelper.element;
diff --git a/chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp b/chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
index 822ae67a5fe..59f663c0779 100644
--- a/chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
+++ b/chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
@@ -176,6 +176,13 @@ static URLSchemesSet& serviceWorkerSchemes()
return serviceWorkerSchemes;
}
+static URLSchemesSet& firstPartyWhenTopLevelSchemes()
+{
+ assertLockHeld();
+ DEFINE_STATIC_LOCAL_NOASSERT(URLSchemesSet, firstPartyWhenTopLevelSchemes, ());
+ return firstPartyWhenTopLevelSchemes;
+}
+
static URLSchemesMap<SchemeRegistry::PolicyAreas>& ContentSecurityPolicyBypassingSchemes()
{
assertLockHeld();
@@ -353,6 +360,20 @@ bool SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(const String&
return serviceWorkerSchemes().contains(scheme);
}
+void SchemeRegistry::registerURLSchemeAsFirstPartyWhenTopLevel(const String& scheme)
+{
+ MutexLocker locker(mutex());
+ firstPartyWhenTopLevelSchemes().add(scheme);
+}
+
+bool SchemeRegistry::shouldTreatURLSchemeAsFirstPartyWhenTopLevel(const String& scheme)
+{
+ if (scheme.isEmpty())
+ return false;
+ MutexLocker locker(mutex());
+ return firstPartyWhenTopLevelSchemes().contains(scheme);
+}
+
void SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme, PolicyAreas policyAreas)
{
MutexLocker locker(mutex());
diff --git a/chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h b/chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
index e85d2bbec88..a9823d257ec 100644
--- a/chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
+++ b/chromium/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
@@ -91,6 +91,10 @@ public:
static void registerURLSchemeAsAllowingServiceWorkers(const String& scheme);
static bool shouldTreatURLSchemeAsAllowingServiceWorkers(const String& scheme);
+ // Schemes which override the first-/third-party checks on a Document.
+ static void registerURLSchemeAsFirstPartyWhenTopLevel(const String& scheme);
+ static bool shouldTreatURLSchemeAsFirstPartyWhenTopLevel(const String& scheme);
+
// Allow resources from some schemes to load on a page, regardless of its
// Content Security Policy.
// This enum should be kept in sync with public/web/WebSecurityPolicy.h.
diff --git a/chromium/third_party/WebKit/Source/web/WebSecurityPolicy.cpp b/chromium/third_party/WebKit/Source/web/WebSecurityPolicy.cpp
index 41e77211828..f309ea6b96a 100644
--- a/chromium/third_party/WebKit/Source/web/WebSecurityPolicy.cpp
+++ b/chromium/third_party/WebKit/Source/web/WebSecurityPolicy.cpp
@@ -91,6 +91,11 @@ void WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy(const
SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme, static_cast<SchemeRegistry::PolicyAreas>(policyAreas));
}
+void WebSecurityPolicy::registerURLSchemeAsFirstPartyWhenTopLevel(const WebString& scheme)
+{
+ SchemeRegistry::registerURLSchemeAsFirstPartyWhenTopLevel(scheme);
+}
+
void WebSecurityPolicy::registerURLSchemeAsEmptyDocument(const WebString& scheme)
{
SchemeRegistry::registerURLSchemeAsEmptyDocument(scheme);
diff --git a/chromium/third_party/WebKit/public/web/WebSecurityPolicy.h b/chromium/third_party/WebKit/public/web/WebSecurityPolicy.h
index 33b4c9984b8..e32093fd580 100644
--- a/chromium/third_party/WebKit/public/web/WebSecurityPolicy.h
+++ b/chromium/third_party/WebKit/public/web/WebSecurityPolicy.h
@@ -79,6 +79,9 @@ public:
// Registers a URL scheme whose resources can be loaded regardless of a page's Content Security Policy.
BLINK_EXPORT static void registerURLSchemeAsBypassingContentSecurityPolicy(const WebString&);
+ // Registers a URL scheme which will always be considered the first-party when loaded in a top-level context.
+ BLINK_EXPORT static void registerURLSchemeAsFirstPartyWhenTopLevel(const WebString&);
+
// Registers a URL scheme for which some kinds of resources bypass Content Security Policy.
// This enum should be kept in sync with Source/platform/weborigin/SchemeRegistry.h.
// Enforced in AssertMatchingEnums.cpp.
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc b/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc
index e3c39252569..6c0e1ca0964 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc
@@ -5,6 +5,7 @@
#include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h"
#include "base/time/time.h"
+#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
#include "ui/ozone/platform/drm/gpu/drm_window.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
@@ -21,9 +22,11 @@ void DrmVSyncProvider::GetVSyncParameters(const UpdateVSyncCallback& callback) {
if (!controller)
return;
+ // If we're in mirror mode the 2 CRTCs should have similar modes with the same
+ // refresh rates.
+ CrtcController* crtc = controller->crtc_controllers()[0];
// The value is invalid, so we can't update the parameters.
- if (controller->GetTimeOfLastFlip() == 0 ||
- controller->get_mode().vrefresh == 0)
+ if (controller->GetTimeOfLastFlip() == 0 || crtc->mode().vrefresh == 0)
return;
// Stores the time of the last refresh.
@@ -31,7 +34,7 @@ void DrmVSyncProvider::GetVSyncParameters(const UpdateVSyncCallback& callback) {
base::TimeTicks::FromInternalValue(controller->GetTimeOfLastFlip());
// Stores the refresh rate.
base::TimeDelta interval =
- base::TimeDelta::FromSeconds(1) / controller->get_mode().vrefresh;
+ base::TimeDelta::FromSeconds(1) / crtc->mode().vrefresh;
callback.Run(timebase, interval);
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index 5ee481931ff..efadce735e7 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -27,7 +27,6 @@ HardwareDisplayController::HardwareDisplayController(
scoped_ptr<CrtcController> controller,
const gfx::Point& origin)
: origin_(origin),
- mode_(controller->mode()),
is_disabled_(controller->is_disabled()) {
AddCrtc(controller.Pass());
}
@@ -46,7 +45,20 @@ bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
status &= crtc_controllers_[i]->Modeset(primary, mode);
is_disabled_ = false;
- mode_ = mode;
+
+ return status;
+}
+
+bool HardwareDisplayController::Enable(const OverlayPlane& primary) {
+ TRACE_EVENT0("drm", "HDC::Enable");
+ DCHECK(primary.buffer.get());
+ bool status = true;
+ for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
+ status &=
+ crtc_controllers_[i]->Modeset(primary, crtc_controllers_[i]->mode());
+ }
+
+ is_disabled_ = false;
return status;
}
@@ -192,7 +204,9 @@ bool HardwareDisplayController::IsDisabled() const {
}
gfx::Size HardwareDisplayController::GetModeSize() const {
- return gfx::Size(mode_.hdisplay, mode_.vdisplay);
+ // If there are multiple CRTCs they should all have the same size.
+ return gfx::Size(crtc_controllers_[0]->mode().hdisplay,
+ crtc_controllers_[0]->mode().vdisplay);
}
uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
index 3772c35302f..830a357ce59 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -98,6 +98,9 @@ class OZONE_EXPORT HardwareDisplayController {
// framebuffer for |primary| with |mode|.
bool Modeset(const OverlayPlane& primary, drmModeModeInfo mode);
+ // Performs a CRTC configuration re-using the modes from the CRTCs.
+ bool Enable(const OverlayPlane& primary);
+
// Disables the CRTC.
void Disable();
@@ -147,8 +150,6 @@ class OZONE_EXPORT HardwareDisplayController {
gfx::Point origin() const { return origin_; }
void set_origin(const gfx::Point& origin) { origin_ = origin; }
- const drmModeModeInfo& get_mode() const { return mode_; };
-
uint64_t GetTimeOfLastFlip() const;
const std::vector<CrtcController*>& crtc_controllers() const {
@@ -168,9 +169,6 @@ class OZONE_EXPORT HardwareDisplayController {
// Location of the controller on the screen.
gfx::Point origin_;
- // The mode used by the last modesetting operation.
- drmModeModeInfo mode_;
-
bool is_disabled_;
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
index 4b4d3f13d75..97bdfe33dbc 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -65,6 +65,18 @@ void FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
modeset_buffer.canvas()->drawImage(image.get(), 0, 0, &paint);
}
+CrtcController* GetCrtcController(HardwareDisplayController* controller,
+ const scoped_refptr<DrmDevice>& drm,
+ uint32_t crtc) {
+ for (CrtcController* crtc_controller : controller->crtc_controllers()) {
+ if (crtc_controller->crtc() == crtc)
+ return crtc_controller;
+ }
+
+ NOTREACHED();
+ return nullptr;
+}
+
} // namespace
ScreenManager::ScreenManager(ScanoutBufferGenerator* buffer_generator)
@@ -133,9 +145,10 @@ bool ScreenManager::ActualConfigureDisplayController(
<< ") doesn't exist.";
HardwareDisplayController* controller = *it;
+ CrtcController* crtc_controller = GetCrtcController(controller, drm, crtc);
// If nothing changed just enable the controller. Note, we perform an exact
// comparison on the mode since the refresh rate may have changed.
- if (SameMode(mode, controller->get_mode()) &&
+ if (SameMode(mode, crtc_controller->mode()) &&
origin == controller->origin()) {
if (controller->IsDisabled()) {
HardwareDisplayControllers::iterator mirror =
@@ -143,12 +156,11 @@ bool ScreenManager::ActualConfigureDisplayController(
// If there is an active controller at the same location then start mirror
// mode.
if (mirror != controllers_.end())
- return HandleMirrorMode(it, mirror, drm, crtc, connector);
+ return HandleMirrorMode(it, mirror, drm, crtc, connector, mode);
}
// Just re-enable the controller to re-use the current state.
- return EnableController(controller, controller->origin(),
- controller->get_mode());
+ return EnableController(controller);
}
// Either the mode or the location of the display changed, so exit mirror
@@ -166,9 +178,9 @@ bool ScreenManager::ActualConfigureDisplayController(
FindActiveDisplayControllerByLocation(modeset_bounds);
// Handle mirror mode.
if (mirror != controllers_.end() && it != mirror)
- return HandleMirrorMode(it, mirror, drm, crtc, connector);
+ return HandleMirrorMode(it, mirror, drm, crtc, connector, mode);
- return EnableController(controller, origin, mode);
+ return ModesetController(controller, origin, mode);
}
bool ScreenManager::DisableDisplayController(
@@ -256,9 +268,20 @@ bool ScreenManager::HandleMirrorMode(
HardwareDisplayControllers::iterator mirror,
const scoped_refptr<DrmDevice>& drm,
uint32_t crtc,
- uint32_t connector) {
- (*mirror)->AddCrtc((*original)->RemoveCrtc(drm, crtc));
- if (EnableController(*mirror, (*mirror)->origin(), (*mirror)->get_mode())) {
+ uint32_t connector,
+ const drmModeModeInfo& mode) {
+ gfx::Point last_origin = (*original)->origin();
+ // There should only be one CRTC in this controller.
+ drmModeModeInfo last_mode = (*original)->crtc_controllers()[0]->mode();
+
+ // Modeset the CRTC with its mode in the original controller so that only this
+ // CRTC is affected by the mode. Otherwise it could apply a mode with the same
+ // resolution and refresh rate but with different timings to the other CRTC.
+ // TODO(dnicoara): This is hacky, instead the DrmDisplay and CrtcController
+ // should be merged and picking the mode should be done properly within
+ // HardwareDisplayController.
+ if (ModesetController(*original, (*mirror)->origin(), mode)) {
+ (*mirror)->AddCrtc((*original)->RemoveCrtc(drm, crtc));
controllers_.erase(original);
return true;
}
@@ -268,8 +291,7 @@ bool ScreenManager::HandleMirrorMode(
// When things go wrong revert back to the previous configuration since
// it is expected that the configuration would not have changed if
// things fail.
- (*original)->AddCrtc((*mirror)->RemoveCrtc(drm, crtc));
- EnableController(*original, (*original)->origin(), (*original)->get_mode());
+ ModesetController(*original, last_origin, last_mode);
return false;
}
@@ -299,36 +321,50 @@ void ScreenManager::UpdateControllerToWindowMapping() {
}
}
-bool ScreenManager::EnableController(HardwareDisplayController* controller,
- const gfx::Point& origin,
- const drmModeModeInfo& mode) {
- DCHECK(!controller->crtc_controllers().empty());
- gfx::Rect rect(origin, gfx::Size(mode.hdisplay, mode.vdisplay));
- controller->set_origin(origin);
-
- DrmWindow* window = FindWindowAt(rect);
+OverlayPlane ScreenManager::GetModesetBuffer(
+ HardwareDisplayController* controller,
+ const gfx::Rect& bounds) {
+ DrmWindow* window = FindWindowAt(bounds);
if (window) {
const OverlayPlane* primary = window->GetLastModesetBuffer();
- if (primary) {
- if (!controller->Modeset(*primary, mode)) {
- LOG(ERROR) << "Failed to modeset controller";
- return false;
- }
-
- return true;
- }
+ if (primary && primary->buffer->GetSize() == bounds.size())
+ return *primary;
}
scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice();
scoped_refptr<ScanoutBuffer> buffer =
- buffer_generator_->Create(drm, rect.size());
+ buffer_generator_->Create(drm, bounds.size());
if (!buffer) {
LOG(ERROR) << "Failed to create scanout buffer";
- return false;
+ return OverlayPlane(nullptr, 0, gfx::OVERLAY_TRANSFORM_INVALID, gfx::Rect(),
+ gfx::RectF());
}
FillModesetBuffer(drm, controller, buffer.get());
- if (!controller->Modeset(OverlayPlane(buffer), mode)) {
+ return OverlayPlane(buffer);
+}
+
+bool ScreenManager::EnableController(HardwareDisplayController* controller) {
+ DCHECK(!controller->crtc_controllers().empty());
+ gfx::Rect rect(controller->origin(), controller->GetModeSize());
+ OverlayPlane plane = GetModesetBuffer(controller, rect);
+ if (!plane.buffer || !controller->Enable(plane)) {
+ LOG(ERROR) << "Failed to enable controller";
+ return false;
+ }
+
+ return true;
+}
+
+bool ScreenManager::ModesetController(HardwareDisplayController* controller,
+ const gfx::Point& origin,
+ const drmModeModeInfo& mode) {
+ DCHECK(!controller->crtc_controllers().empty());
+ gfx::Rect rect(origin, gfx::Size(mode.hdisplay, mode.vdisplay));
+ controller->set_origin(origin);
+
+ OverlayPlane plane = GetModesetBuffer(controller, rect);
+ if (!plane.buffer || !controller->Modeset(plane, mode)) {
LOG(ERROR) << "Failed to modeset controller";
return false;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
index f9c5bc0cfde..6c067ba2b31 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
@@ -108,13 +108,19 @@ class OZONE_EXPORT ScreenManager {
HardwareDisplayControllers::iterator mirror,
const scoped_refptr<DrmDevice>& drm,
uint32_t crtc,
- uint32_t connector);
+ uint32_t connector,
+ const drmModeModeInfo& mode);
+
+ OverlayPlane GetModesetBuffer(HardwareDisplayController* controller,
+ const gfx::Rect& bounds);
+
+ bool EnableController(HardwareDisplayController* controller);
// Modeset the |controller| using |origin| and |mode|. If there is a window at
// the controller location, then we'll re-use the current buffer.
- bool EnableController(HardwareDisplayController* controller,
- const gfx::Point& origin,
- const drmModeModeInfo& mode);
+ bool ModesetController(HardwareDisplayController* controller,
+ const gfx::Point& origin,
+ const drmModeModeInfo& mode);
DrmWindow* FindWindowAt(const gfx::Rect& bounds) const;
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
index f8b59a66a97..662aba94bbf 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -148,8 +148,9 @@ TEST_F(ScreenManagerTest, CheckChangingMode) {
gfx::Rect new_bounds(0, 0, new_mode.hdisplay, new_mode.vdisplay);
EXPECT_TRUE(screen_manager_->GetDisplayController(new_bounds));
EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
- drmModeModeInfo mode =
- screen_manager_->GetDisplayController(new_bounds)->get_mode();
+ drmModeModeInfo mode = screen_manager_->GetDisplayController(new_bounds)
+ ->crtc_controllers()[0]
+ ->mode();
EXPECT_EQ(new_mode.vdisplay, mode.vdisplay);
EXPECT_EQ(new_mode.hdisplay, mode.hdisplay);
}
diff --git a/chromium/ui/resources/default_100_percent/common/ntp_google_logo.png b/chromium/ui/resources/default_100_percent/common/ntp_google_logo.png
index a6fa11fd227..fee9f7695aa 100644
--- a/chromium/ui/resources/default_100_percent/common/ntp_google_logo.png
+++ b/chromium/ui/resources/default_100_percent/common/ntp_google_logo.png
Binary files differ
diff --git a/chromium/ui/resources/default_200_percent/common/ntp_google_logo.png b/chromium/ui/resources/default_200_percent/common/ntp_google_logo.png
index f2f5b8c58d5..0b55f7b38a7 100644
--- a/chromium/ui/resources/default_200_percent/common/ntp_google_logo.png
+++ b/chromium/ui/resources/default_200_percent/common/ntp_google_logo.png
Binary files differ
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 93b3c5b81fb..9278c2968c9 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -906,6 +906,16 @@ void DesktopWindowTreeHostWin::HandleWindowSizeChanging() {
compositor()->DisableSwapUntilResize();
}
+void DesktopWindowTreeHostWin::HandleWindowSizeChanged() {
+ // A resize may not have occurred if the window size happened not to have
+ // changed (can occur on Windows 10 when snapping a window to the side of
+ // the screen). In that case do a resize to the current size to reenable
+ // swaps.
+ if (compositor())
+ compositor()->SetScaleAndSize(compositor()->device_scale_factor(),
+ compositor()->size());
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostWin, private:
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index c213ffe453e..047498f81b6 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -191,6 +191,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
void PostHandleMSG(UINT message, WPARAM w_param, LPARAM l_param) override;
bool HandleScrollEvent(const ui::ScrollEvent& event) override;
void HandleWindowSizeChanging() override;
+ void HandleWindowSizeChanged() override;
Widget* GetWidget();
const Widget* GetWidget() const;
diff --git a/chromium/ui/views/win/hwnd_message_handler.cc b/chromium/ui/views/win/hwnd_message_handler.cc
index d2233494fed..cf71db8234e 100644
--- a/chromium/ui/views/win/hwnd_message_handler.cc
+++ b/chromium/ui/views/win/hwnd_message_handler.cc
@@ -329,9 +329,9 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
touch_down_contexts_(0),
last_mouse_hwheel_time_(0),
dwm_transition_desired_(false),
+ sent_window_size_changing_(false),
autohide_factory_(this),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
HWNDMessageHandler::~HWNDMessageHandler() {
delegate_ = NULL;
@@ -2470,6 +2470,7 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
if ((old_size != new_size && !(window_pos->flags & SWP_NOSIZE)) ||
window_pos->flags & SWP_FRAMECHANGED) {
delegate_->HandleWindowSizeChanging();
+ sent_window_size_changing_ = true;
}
if (ScopedFullscreenVisibility::IsHiddenForFullscreen(hwnd())) {
@@ -2509,6 +2510,10 @@ void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) {
if (direct_manipulation_helper_)
direct_manipulation_helper_->Deactivate(hwnd());
}
+ if (sent_window_size_changing_) {
+ sent_window_size_changing_ = false;
+ delegate_->HandleWindowSizeChanged();
+ }
SetMsgHandled(FALSE);
}
diff --git a/chromium/ui/views/win/hwnd_message_handler.h b/chromium/ui/views/win/hwnd_message_handler.h
index e7fc8af7b51..6b8f719699b 100644
--- a/chromium/ui/views/win/hwnd_message_handler.h
+++ b/chromium/ui/views/win/hwnd_message_handler.h
@@ -584,6 +584,10 @@ class VIEWS_EXPORT HWNDMessageHandler :
// glass. Defaults to false.
bool dwm_transition_desired_;
+ // True if HandleWindowSizeChanging has been called in the delegate, but not
+ // HandleWindowSizeChanged.
+ bool sent_window_size_changing_;
+
// Manages observation of Windows Session Change messages.
scoped_ptr<WindowsSessionChangeObserver> windows_session_change_observer_;
diff --git a/chromium/ui/views/win/hwnd_message_handler_delegate.h b/chromium/ui/views/win/hwnd_message_handler_delegate.h
index e773b817701..8f8957ae245 100644
--- a/chromium/ui/views/win/hwnd_message_handler_delegate.h
+++ b/chromium/ui/views/win/hwnd_message_handler_delegate.h
@@ -224,6 +224,9 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate {
// Called when the window size is about to change.
virtual void HandleWindowSizeChanging() = 0;
+ // Called when the window size has finished changing.
+ virtual void HandleWindowSizeChanged() = 0;
+
protected:
virtual ~HWNDMessageHandlerDelegate() {}
};
diff --git a/chromium/url/url_canon_path.cc b/chromium/url/url_canon_path.cc
index ceff6896319..d155dfbf4dc 100644
--- a/chromium/url/url_canon_path.cc
+++ b/chromium/url/url_canon_path.cc
@@ -162,6 +162,76 @@ void BackUpToPreviousSlash(int path_begin_in_output,
output->set_length(i + 1);
}
+// Looks for problematic nested escape sequences and escapes the output as
+// needed to ensure they can't be misinterpreted.
+//
+// Our concern is that in input escape sequence that's invalid because it
+// contains nested escape sequences might look valid once those are unescaped.
+// For example, "%%300" is not a valid escape sequence, but after unescaping the
+// inner "%30" this becomes "%00" which is valid. Leaving this in the output
+// string can result in callers re-canonicalizing the string and unescaping this
+// sequence, thus resulting in something fundamentally different than the
+// original input here. This can cause a variety of problems.
+//
+// This function is called after we've just unescaped a sequence that's within
+// two output characters of a previous '%' that we know didn't begin a valid
+// escape sequence in the input string. We look for whether the output is going
+// to turn into a valid escape sequence, and if so, convert the initial '%' into
+// an escaped "%25" so the output can't be misinterpreted.
+//
+// |spec| is the input string we're canonicalizing.
+// |next_input_index| is the index of the next unprocessed character in |spec|.
+// |input_len| is the length of |spec|.
+// |last_invalid_percent_index| is the index in |output| of a previously-seen
+// '%' character. The caller knows this '%' character isn't followed by a valid
+// escape sequence in the input string.
+// |output| is the canonicalized output thus far. The caller guarantees this
+// ends with a '%' followed by one or two characters, and the '%' is the one
+// pointed to by |last_invalid_percent_index|. The last character in the string
+// was just unescaped.
+template<typename CHAR>
+void CheckForNestedEscapes(const CHAR* spec,
+ int next_input_index,
+ int input_len,
+ int last_invalid_percent_index,
+ CanonOutput* output) {
+ const int length = output->length();
+ const char last_unescaped_char = output->at(length - 1);
+
+ // If |output| currently looks like "%c", we need to try appending the next
+ // input character to see if this will result in a problematic escape
+ // sequence. Note that this won't trigger on the first nested escape of a
+ // two-escape sequence like "%%30%30" -- we'll allow the conversion to
+ // "%0%30" -- but the second nested escape will be caught by this function
+ // when it's called again in that case.
+ const bool append_next_char = last_invalid_percent_index == length - 2;
+ if (append_next_char) {
+ // If the input doesn't contain a 7-bit character next, this case won't be a
+ // problem.
+ if ((next_input_index == input_len) || (spec[next_input_index] >= 0x80))
+ return;
+ output->push_back(static_cast<char>(spec[next_input_index]));
+ }
+
+ // Now output ends like "%cc". Try to unescape this.
+ int begin = last_invalid_percent_index;
+ unsigned char temp;
+ if (DecodeEscaped(output->data(), &begin, output->length(), &temp)) {
+ // New escape sequence found. Overwrite the characters following the '%'
+ // with "25", and push_back() the one or two characters that were following
+ // the '%' when we were called.
+ if (!append_next_char)
+ output->push_back(output->at(last_invalid_percent_index + 1));
+ output->set(last_invalid_percent_index + 1, '2');
+ output->set(last_invalid_percent_index + 2, '5');
+ output->push_back(last_unescaped_char);
+ } else if (append_next_char) {
+ // Not a valid escape sequence, but we still need to undo appending the next
+ // source character so the caller can process it normally.
+ output->set_length(length);
+ }
+}
+
// Appends the given path to the output. It assumes that if the input path
// starts with a slash, it should be copied to the output. If no path has
// already been appended to the output (the case when not resolving
@@ -182,10 +252,15 @@ bool DoPartialPath(const CHAR* spec,
CanonOutput* output) {
int end = path.end();
+ // We use this variable to minimize the amount of work done when unescaping --
+ // we'll only call CheckForNestedEscapes() when this points at one of the last
+ // couple of characters in |output|.
+ int last_invalid_percent_index = INT_MIN;
+
bool success = true;
for (int i = path.begin; i < end; i++) {
UCHAR uch = static_cast<UCHAR>(spec[i]);
- if (sizeof(CHAR) > sizeof(char) && uch >= 0x80) {
+ if (sizeof(CHAR) > 1 && uch >= 0x80) {
// We only need to test wide input for having non-ASCII characters. For
// narrow input, we'll always just use the lookup table. We don't try to
// do anything tricky with decoding/validating UTF-8. This function will
@@ -245,33 +320,40 @@ bool DoPartialPath(const CHAR* spec,
unsigned char unescaped_value;
if (DecodeEscaped(spec, &i, end, &unescaped_value)) {
// Valid escape sequence, see if we keep, reject, or unescape it.
+ // Note that at this point DecodeEscape() will have advanced |i| to
+ // the last character of the escape sequence.
char unescaped_flags = kPathCharLookup[unescaped_value];
if (unescaped_flags & UNESCAPE) {
- // This escaped value shouldn't be escaped, copy it.
+ // This escaped value shouldn't be escaped. Try to copy it.
output->push_back(unescaped_value);
- } else if (unescaped_flags & INVALID_BIT) {
- // Invalid escaped character, copy it and remember the error.
- output->push_back('%');
- output->push_back(static_cast<char>(spec[i - 1]));
- output->push_back(static_cast<char>(spec[i]));
- success = false;
+ // If we just unescaped a value within 2 output characters of the
+ // '%' from a previously-detected invalid escape sequence, we
+ // might have an input string with problematic nested escape
+ // sequences; detect and fix them.
+ if (last_invalid_percent_index >= (output->length() - 3)) {
+ CheckForNestedEscapes(spec, i + 1, end,
+ last_invalid_percent_index, output);
+ }
} else {
- // Valid escaped character but we should keep it escaped. We
- // don't want to change the case of any hex letters in case
- // the server is sensitive to that, so we just copy the two
- // characters without checking (DecodeEscape will have advanced
- // to the last character of the pair).
+ // Either this is an invalid escaped character, or it's a valid
+ // escaped character we should keep escaped. In the first case we
+ // should just copy it exactly and remember the error. In the
+ // second we also copy exactly in case the server is sensitive to
+ // changing the case of any hex letters.
output->push_back('%');
output->push_back(static_cast<char>(spec[i - 1]));
output->push_back(static_cast<char>(spec[i]));
+ if (unescaped_flags & INVALID_BIT)
+ success = false;
}
} else {
- // Invalid escape sequence. IE7 rejects any URLs with such
- // sequences, while Firefox, IE6, and Safari all pass it through
- // unchanged. We are more permissive unlike IE7. I don't think this
- // can cause significant problems, if it does, we should change
- // to be more like IE7.
+ // Invalid escape sequence. IE7+ rejects any URLs with such
+ // sequences, while other browsers pass them through unchanged. We
+ // use the permissive behavior.
+ // TODO(brettw): Consider testing IE's strict behavior, which would
+ // allow removing the code to handle nested escapes above.
+ last_invalid_percent_index = output->length();
output->push_back('%');
}
diff --git a/chromium/url/url_canon_unittest.cc b/chromium/url/url_canon_unittest.cc
index 67cced24607..f2247d1dd9d 100644
--- a/chromium/url/url_canon_unittest.cc
+++ b/chromium/url/url_canon_unittest.cc
@@ -1059,6 +1059,21 @@ TEST(URLCanonTest, Path) {
{"/%7Ffp3%3Eju%3Dduvgw%3Dd", L"/%7Ffp3%3Eju%3Dduvgw%3Dd", "/%7Ffp3%3Eju%3Dduvgw%3Dd", Component(0, 24), true},
// @ should be passed through unchanged (escaped or unescaped).
{"/@asdf%40", L"/@asdf%40", "/@asdf%40", Component(0, 9), true},
+ // Nested escape sequences should result in escaping the leading '%' if
+ // unescaping would result in a new escape sequence.
+ {"/%A%42", L"/%A%42", "/%25AB", Component(0, 6), true},
+ {"/%%41B", L"/%%41B", "/%25AB", Component(0, 6), true},
+ {"/%%41%42", L"/%%41%42", "/%25AB", Component(0, 6), true},
+ // Make sure truncated "nested" escapes don't result in reading off the
+ // string end.
+ {"/%%41", L"/%%41", "/%A", Component(0, 3), true},
+ // Don't unescape the leading '%' if unescaping doesn't result in a valid
+ // new escape sequence.
+ {"/%%470", L"/%%470", "/%G0", Component(0, 4), true},
+ {"/%%2D%41", L"/%%2D%41", "/%-A", Component(0, 4), true},
+ // Don't erroneously downcast a UTF-16 charater in a way that makes it
+ // look like part of an escape sequence.
+ {NULL, L"/%%41\x0130", "/%A%C4%B0", Component(0, 9), true},
// ----- encoding tests -----
// Basic conversions
diff --git a/chromium/v8/build/features.gypi b/chromium/v8/build/features.gypi
index 0e26969f646..59d15134ddf 100644
--- a/chromium/v8/build/features.gypi
+++ b/chromium/v8/build/features.gypi
@@ -108,7 +108,7 @@
'DebugBaseCommon': {
'abstract': 1,
'variables': {
- 'v8_enable_handle_zapping%': 0,
+ 'v8_enable_handle_zapping%': 1,
},
'conditions': [
['v8_enable_handle_zapping==1', {
@@ -118,7 +118,7 @@
}, # Debug
'Release': {
'variables': {
- 'v8_enable_handle_zapping%': 1,
+ 'v8_enable_handle_zapping%': 0,
},
'conditions': [
['v8_enable_handle_zapping==1', {
diff --git a/chromium/v8/codereview.settings b/chromium/v8/codereview.settings
index 7c4dd8e2556..532e4b4d7b0 100644
--- a/chromium/v8/codereview.settings
+++ b/chromium/v8/codereview.settings
@@ -1,5 +1,5 @@
CODE_REVIEW_SERVER: https://codereview.chromium.org
-CC_LIST: v8-dev@googlegroups.com
+CC_LIST: v8-reviews@googlegroups.com
VIEW_VC: https://chromium.googlesource.com/v8/v8/+/
STATUS: http://v8-status.appspot.com/status
TRY_ON_UPLOAD: False
diff --git a/chromium/v8/include/v8-version.h b/chromium/v8/include/v8-version.h
index 66e8c6eaa58..98dca238c85 100644
--- a/chromium/v8/include/v8-version.h
+++ b/chromium/v8/include/v8-version.h
@@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 4
#define V8_MINOR_VERSION 5
#define V8_BUILD_NUMBER 103
-#define V8_PATCH_LEVEL 28
+#define V8_PATCH_LEVEL 35
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/chromium/v8/src/arm/assembler-arm.cc b/chromium/v8/src/arm/assembler-arm.cc
index 96bdf79face..481a3b5cedd 100644
--- a/chromium/v8/src/arm/assembler-arm.cc
+++ b/chromium/v8/src/arm/assembler-arm.cc
@@ -128,7 +128,8 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
if (FLAG_enable_32dregs && cpu.has_vfp3_d32()) supported_ |= 1u << VFP32DREGS;
if (cpu.implementer() == base::CPU::NVIDIA &&
- cpu.variant() == base::CPU::NVIDIA_DENVER) {
+ cpu.variant() == base::CPU::NVIDIA_DENVER &&
+ cpu.part() <= base::CPU::NVIDIA_DENVER_V10) {
supported_ |= 1u << COHERENT_CACHE;
}
#endif
diff --git a/chromium/v8/src/arm64/assembler-arm64.cc b/chromium/v8/src/arm64/assembler-arm64.cc
index 5445fe1a1b1..f27d3b97b0f 100644
--- a/chromium/v8/src/arm64/assembler-arm64.cc
+++ b/chromium/v8/src/arm64/assembler-arm64.cc
@@ -53,7 +53,8 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
// Probe for runtime features
base::CPU cpu;
if (cpu.implementer() == base::CPU::NVIDIA &&
- cpu.variant() == base::CPU::NVIDIA_DENVER) {
+ cpu.variant() == base::CPU::NVIDIA_DENVER &&
+ cpu.part() <= base::CPU::NVIDIA_DENVER_V10) {
supported_ |= 1u << COHERENT_CACHE;
}
}
diff --git a/chromium/v8/src/ast.cc b/chromium/v8/src/ast.cc
index e52504a86fb..ec74e4afaf7 100644
--- a/chromium/v8/src/ast.cc
+++ b/chromium/v8/src/ast.cc
@@ -441,6 +441,7 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
if (position == boilerplate_properties_ * 2) {
DCHECK(property->is_computed_name());
+ is_simple = false;
break;
}
DCHECK(!property->is_computed_name());
diff --git a/chromium/v8/src/base/cpu.h b/chromium/v8/src/base/cpu.h
index f6c5a8506a0..1dc0a91f650 100644
--- a/chromium/v8/src/base/cpu.h
+++ b/chromium/v8/src/base/cpu.h
@@ -59,6 +59,9 @@ class CPU final {
static const int ARM_CORTEX_A12 = 0xc0c;
static const int ARM_CORTEX_A15 = 0xc0f;
+ // Denver-specific part code
+ static const int NVIDIA_DENVER_V10 = 0x002;
+
// PPC-specific part codes
enum {
PPC_POWER5,
diff --git a/chromium/v8/src/flag-definitions.h b/chromium/v8/src/flag-definitions.h
index a89c8e4d4ba..79611270dd4 100644
--- a/chromium/v8/src/flag-definitions.h
+++ b/chromium/v8/src/flag-definitions.h
@@ -613,6 +613,8 @@ DEFINE_INT(trace_allocation_stack_interval, -1,
DEFINE_BOOL(trace_fragmentation, false, "report fragmentation for old space")
DEFINE_BOOL(trace_fragmentation_verbose, false,
"report fragmentation for old space (detailed)")
+DEFINE_BOOL(trace_mutator_utilization, false,
+ "print mutator utilization, allocation speed, gc speed")
DEFINE_BOOL(weak_embedded_maps_in_optimized_code, true,
"make maps embedded in optimized code weak")
DEFINE_BOOL(weak_embedded_objects_in_optimized_code, true,
diff --git a/chromium/v8/src/heap/gc-tracer.cc b/chromium/v8/src/heap/gc-tracer.cc
index 214bb8b24d6..6728f09bdad 100644
--- a/chromium/v8/src/heap/gc-tracer.cc
+++ b/chromium/v8/src/heap/gc-tracer.cc
@@ -682,11 +682,15 @@ size_t GCTracer::AllocationThroughputInBytesPerMillisecond(
}
+size_t GCTracer::CurrentAllocationThroughputInBytesPerMillisecond() const {
+ return AllocationThroughputInBytesPerMillisecond(kThroughputTimeFrameMs);
+}
+
+
size_t GCTracer::CurrentOldGenerationAllocationThroughputInBytesPerMillisecond()
const {
- static const double kThroughputTimeFrame = 5000;
return OldGenerationAllocationThroughputInBytesPerMillisecond(
- kThroughputTimeFrame);
+ kThroughputTimeFrameMs);
}
diff --git a/chromium/v8/src/heap/gc-tracer.h b/chromium/v8/src/heap/gc-tracer.h
index 468fc9c0be7..e26fc898f99 100644
--- a/chromium/v8/src/heap/gc-tracer.h
+++ b/chromium/v8/src/heap/gc-tracer.h
@@ -291,6 +291,8 @@ class GCTracer {
typedef RingBuffer<SurvivalEvent, kRingBufferMaxSize> SurvivalEventBuffer;
+ static const int kThroughputTimeFrameMs = 5000;
+
explicit GCTracer(Heap* heap);
// Start collecting data.
@@ -408,6 +410,11 @@ class GCTracer {
// Returns 0 if no allocation events have been recorded.
size_t AllocationThroughputInBytesPerMillisecond(double time_ms) const;
+ // Allocation throughput in heap in bytes/milliseconds in
+ // the last five seconds.
+ // Returns 0 if no allocation events have been recorded.
+ size_t CurrentAllocationThroughputInBytesPerMillisecond() const;
+
// Allocation throughput in old generation in bytes/milliseconds in
// the last five seconds.
// Returns 0 if no allocation events have been recorded.
diff --git a/chromium/v8/src/heap/heap.cc b/chromium/v8/src/heap/heap.cc
index fc36be8041f..3d953730013 100644
--- a/chromium/v8/src/heap/heap.cc
+++ b/chromium/v8/src/heap/heap.cc
@@ -775,7 +775,8 @@ void Heap::PreprocessStackTraces() {
void Heap::HandleGCRequest() {
if (incremental_marking()->request_type() ==
IncrementalMarking::COMPLETE_MARKING) {
- CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt");
+ CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt",
+ incremental_marking()->CallbackFlags());
return;
}
DCHECK(FLAG_overapproximate_weak_closure);
@@ -985,7 +986,7 @@ bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason,
if (!mark_compact_collector()->abort_incremental_marking() &&
incremental_marking()->IsStopped() &&
incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) {
- incremental_marking()->Start(kNoGCFlags);
+ incremental_marking()->Start(kNoGCFlags, kNoGCCallbackFlags, "GC epilogue");
}
return next_gc_likely_to_collect_more;
@@ -1012,9 +1013,18 @@ int Heap::NotifyContextDisposed(bool dependant_context) {
}
+void Heap::StartIncrementalMarking(int gc_flags,
+ const GCCallbackFlags gc_callback_flags,
+ const char* reason) {
+ DCHECK(incremental_marking()->IsStopped());
+ incremental_marking()->Start(gc_flags, gc_callback_flags, reason);
+}
+
+
void Heap::StartIdleIncrementalMarking() {
gc_idle_time_handler_.ResetNoProgressCounter();
- incremental_marking()->Start(kReduceMemoryFootprintMask);
+ StartIncrementalMarking(kReduceMemoryFootprintMask, kNoGCCallbackFlags,
+ "idle");
}
@@ -4762,27 +4772,63 @@ void Heap::MakeHeapIterable() {
}
-bool Heap::HasLowYoungGenerationAllocationRate() {
- const double high_mutator_utilization = 0.993;
+static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) {
+ const double kMinMutatorUtilization = 0.0;
+ const double kConservativeGcSpeedInBytesPerMillisecond = 200000;
+ if (mutator_speed == 0) return kMinMutatorUtilization;
+ if (gc_speed == 0) gc_speed = kConservativeGcSpeedInBytesPerMillisecond;
+ // Derivation:
+ // mutator_utilization = mutator_time / (mutator_time + gc_time)
+ // mutator_time = 1 / mutator_speed
+ // gc_time = 1 / gc_speed
+ // mutator_utilization = (1 / mutator_speed) /
+ // (1 / mutator_speed + 1 / gc_speed)
+ // mutator_utilization = gc_speed / (mutator_speed + gc_speed)
+ return gc_speed / (mutator_speed + gc_speed);
+}
+
+
+double Heap::YoungGenerationMutatorUtilization() {
double mutator_speed = static_cast<double>(
tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond());
double gc_speed = static_cast<double>(
tracer()->ScavengeSpeedInBytesPerMillisecond(kForSurvivedObjects));
- if (mutator_speed == 0 || gc_speed == 0) return false;
- double mutator_utilization = gc_speed / (mutator_speed + gc_speed);
- return mutator_utilization > high_mutator_utilization;
+ double result = ComputeMutatorUtilization(mutator_speed, gc_speed);
+ if (FLAG_trace_mutator_utilization) {
+ PrintIsolate(isolate(),
+ "Young generation mutator utilization = %.3f ("
+ "mutator_speed=%.f, gc_speed=%.f)\n",
+ result, mutator_speed, gc_speed);
+ }
+ return result;
}
-bool Heap::HasLowOldGenerationAllocationRate() {
- const double high_mutator_utilization = 0.993;
+double Heap::OldGenerationMutatorUtilization() {
double mutator_speed = static_cast<double>(
tracer()->OldGenerationAllocationThroughputInBytesPerMillisecond());
double gc_speed = static_cast<double>(
tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond());
- if (mutator_speed == 0 || gc_speed == 0) return false;
- double mutator_utilization = gc_speed / (mutator_speed + gc_speed);
- return mutator_utilization > high_mutator_utilization;
+ double result = ComputeMutatorUtilization(mutator_speed, gc_speed);
+ if (FLAG_trace_mutator_utilization) {
+ PrintIsolate(isolate(),
+ "Old generation mutator utilization = %.3f ("
+ "mutator_speed=%.f, gc_speed=%.f)\n",
+ result, mutator_speed, gc_speed);
+ }
+ return result;
+}
+
+
+bool Heap::HasLowYoungGenerationAllocationRate() {
+ const double high_mutator_utilization = 0.993;
+ return YoungGenerationMutatorUtilization() > high_mutator_utilization;
+}
+
+
+bool Heap::HasLowOldGenerationAllocationRate() {
+ const double high_mutator_utilization = 0.993;
+ return OldGenerationMutatorUtilization() > high_mutator_utilization;
}
@@ -4808,7 +4854,13 @@ bool Heap::HasHighFragmentation(intptr_t used, intptr_t committed) {
void Heap::ReduceNewSpaceSize() {
- if (!FLAG_predictable && HasLowAllocationRate()) {
+ // TODO(ulan): Unify this constant with the similar constant in
+ // GCIdleTimeHandler once the change is merged to 4.5.
+ static const size_t kLowAllocationThroughput = 1000;
+ size_t allocation_throughput =
+ tracer()->CurrentAllocationThroughputInBytesPerMillisecond();
+ if (FLAG_predictable || allocation_throughput == 0) return;
+ if (allocation_throughput < kLowAllocationThroughput) {
new_space_.Shrink();
UncommitFromSpace();
}
@@ -4867,6 +4919,32 @@ GCIdleTimeHandler::HeapState Heap::ComputeHeapState() {
}
+double Heap::AdvanceIncrementalMarking(
+ intptr_t step_size_in_bytes, double deadline_in_ms,
+ IncrementalMarking::StepActions step_actions) {
+ DCHECK(!incremental_marking()->IsStopped());
+
+ if (step_size_in_bytes == 0) {
+ step_size_in_bytes = GCIdleTimeHandler::EstimateMarkingStepSize(
+ static_cast<size_t>(GCIdleTimeHandler::kIncrementalMarkingStepTimeInMs),
+ static_cast<size_t>(
+ tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()));
+ }
+
+ double remaining_time_in_ms = 0.0;
+ do {
+ incremental_marking()->Step(
+ step_size_in_bytes, step_actions.completion_action,
+ step_actions.force_marking, step_actions.force_completion);
+ remaining_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs();
+ } while (remaining_time_in_ms >=
+ 2.0 * GCIdleTimeHandler::kIncrementalMarkingStepTimeInMs &&
+ !incremental_marking()->IsComplete() &&
+ !mark_compact_collector_.marking_deque()->IsEmpty());
+ return remaining_time_in_ms;
+}
+
+
bool Heap::PerformIdleTimeAction(GCIdleTimeAction action,
GCIdleTimeHandler::HeapState heap_state,
double deadline_in_ms) {
@@ -4876,19 +4954,9 @@ bool Heap::PerformIdleTimeAction(GCIdleTimeAction action,
result = true;
break;
case DO_INCREMENTAL_MARKING: {
- DCHECK(!incremental_marking()->IsStopped());
- double remaining_idle_time_in_ms = 0.0;
- do {
- incremental_marking()->Step(
- action.parameter, IncrementalMarking::NO_GC_VIA_STACK_GUARD,
- IncrementalMarking::FORCE_MARKING,
- IncrementalMarking::DO_NOT_FORCE_COMPLETION);
- remaining_idle_time_in_ms =
- deadline_in_ms - MonotonicallyIncreasingTimeInMs();
- } while (remaining_idle_time_in_ms >=
- 2.0 * GCIdleTimeHandler::kIncrementalMarkingStepTimeInMs &&
- !incremental_marking()->IsComplete() &&
- !mark_compact_collector_.marking_deque()->IsEmpty());
+ const double remaining_idle_time_in_ms =
+ AdvanceIncrementalMarking(action.parameter, deadline_in_ms,
+ IncrementalMarking::IdleStepActions());
if (remaining_idle_time_in_ms > 0.0) {
action.additional_work = TryFinalizeIdleIncrementalMarking(
remaining_idle_time_in_ms, heap_state.size_of_objects,
diff --git a/chromium/v8/src/heap/heap.h b/chromium/v8/src/heap/heap.h
index 6fb429ae7d6..4c9e3ad1448 100644
--- a/chromium/v8/src/heap/heap.h
+++ b/chromium/v8/src/heap/heap.h
@@ -837,6 +837,21 @@ class Heap {
// incremental steps.
void StartIdleIncrementalMarking();
+ // Starts incremental marking assuming incremental marking is currently
+ // stopped.
+ void StartIncrementalMarking(int gc_flags,
+ const GCCallbackFlags gc_callback_flags,
+ const char* reason = nullptr);
+
+ // Performs incremental marking steps of step_size_in_bytes as long as
+ // deadline_ins_ms is not reached. step_size_in_bytes can be 0 to compute
+ // an estimate increment. Returns the remaining time that cannot be used
+ // for incremental marking anymore because a single step would exceed the
+ // deadline.
+ double AdvanceIncrementalMarking(
+ intptr_t step_size_in_bytes, double deadline_in_ms,
+ IncrementalMarking::StepActions step_actions);
+
inline void increment_scan_on_scavenge_pages() {
scan_on_scavenge_pages_++;
if (FLAG_gc_verbose) {
@@ -2267,6 +2282,8 @@ class Heap {
bool HasLowYoungGenerationAllocationRate();
bool HasLowOldGenerationAllocationRate();
+ double YoungGenerationMutatorUtilization();
+ double OldGenerationMutatorUtilization();
void ReduceNewSpaceSize();
diff --git a/chromium/v8/src/heap/incremental-marking.cc b/chromium/v8/src/heap/incremental-marking.cc
index 22051eaab2d..58eb0aa4097 100644
--- a/chromium/v8/src/heap/incremental-marking.cc
+++ b/chromium/v8/src/heap/incremental-marking.cc
@@ -16,22 +16,34 @@ namespace v8 {
namespace internal {
+IncrementalMarking::StepActions IncrementalMarking::IdleStepActions() {
+ return StepActions(IncrementalMarking::NO_GC_VIA_STACK_GUARD,
+ IncrementalMarking::FORCE_MARKING,
+ IncrementalMarking::DO_NOT_FORCE_COMPLETION);
+}
+
+
IncrementalMarking::IncrementalMarking(Heap* heap)
: heap_(heap),
state_(STOPPED),
+ is_compacting_(false),
steps_count_(0),
old_generation_space_available_at_start_of_incremental_(0),
old_generation_space_used_at_start_of_incremental_(0),
+ bytes_rescanned_(0),
should_hurry_(false),
marking_speed_(0),
+ bytes_scanned_(0),
allocated_(0),
+ write_barriers_invoked_since_last_step_(0),
idle_marking_delay_counter_(0),
no_marking_scope_depth_(0),
unscanned_bytes_of_large_object_(0),
was_activated_(false),
weak_closure_was_overapproximated_(false),
weak_closure_approximation_rounds_(0),
- request_type_(COMPLETE_MARKING) {}
+ request_type_(COMPLETE_MARKING),
+ gc_callback_flags_(kNoGCCallbackFlags) {}
void IncrementalMarking::RecordWriteSlow(HeapObject* obj, Object** slot,
@@ -472,9 +484,12 @@ static void PatchIncrementalMarkingRecordWriteStubs(
}
-void IncrementalMarking::Start(int mark_compact_flags) {
+void IncrementalMarking::Start(int mark_compact_flags,
+ const GCCallbackFlags gc_callback_flags,
+ const char* reason) {
if (FLAG_trace_incremental_marking) {
- PrintF("[IncrementalMarking] Start\n");
+ PrintF("[IncrementalMarking] Start (%s)\n",
+ (reason == nullptr) ? "unknown reason" : reason);
}
DCHECK(FLAG_incremental_marking);
DCHECK(FLAG_incremental_marking_steps);
@@ -484,6 +499,7 @@ void IncrementalMarking::Start(int mark_compact_flags) {
ResetStepCounters();
+ gc_callback_flags_ = gc_callback_flags;
was_activated_ = true;
if (!heap_->mark_compact_collector()->sweeping_in_progress()) {
@@ -826,7 +842,7 @@ void IncrementalMarking::Epilogue() {
void IncrementalMarking::OldSpaceStep(intptr_t allocated) {
if (IsStopped() && ShouldActivateEvenWithoutIdleNotification()) {
- Start(Heap::kNoGCFlags);
+ Start(Heap::kNoGCFlags, kNoGCCallbackFlags, "old space step");
} else {
Step(allocated * kFastMarking / kInitialMarkingSpeed, GC_VIA_STACK_GUARD);
}
diff --git a/chromium/v8/src/heap/incremental-marking.h b/chromium/v8/src/heap/incremental-marking.h
index 8fe341154fa..706e3323270 100644
--- a/chromium/v8/src/heap/incremental-marking.h
+++ b/chromium/v8/src/heap/incremental-marking.h
@@ -26,6 +26,21 @@ class IncrementalMarking {
enum GCRequestType { COMPLETE_MARKING, OVERAPPROXIMATION };
+ struct StepActions {
+ StepActions(CompletionAction complete_action_,
+ ForceMarkingAction force_marking_,
+ ForceCompletionAction force_completion_)
+ : completion_action(complete_action_),
+ force_marking(force_marking_),
+ force_completion(force_completion_) {}
+
+ CompletionAction completion_action;
+ ForceMarkingAction force_marking;
+ ForceCompletionAction force_completion;
+ };
+
+ static StepActions IdleStepActions();
+
explicit IncrementalMarking(Heap* heap);
static void Initialize();
@@ -67,7 +82,9 @@ class IncrementalMarking {
bool WasActivated();
- void Start(int mark_compact_flags);
+ void Start(int mark_compact_flags,
+ const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags,
+ const char* reason = nullptr);
void Stop();
@@ -185,6 +202,8 @@ class IncrementalMarking {
Heap* heap() const { return heap_; }
+ GCCallbackFlags CallbackFlags() const { return gc_callback_flags_; }
+
private:
int64_t SpaceLeftInOldSpace();
@@ -243,6 +262,8 @@ class IncrementalMarking {
GCRequestType request_type_;
+ GCCallbackFlags gc_callback_flags_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking);
};
}
diff --git a/chromium/v8/src/messages.h b/chromium/v8/src/messages.h
index 4072300bf6a..5c3e867933c 100644
--- a/chromium/v8/src/messages.h
+++ b/chromium/v8/src/messages.h
@@ -173,6 +173,7 @@ class CallSite {
T(ObserveCallbackFrozen, \
"Object.observe cannot deliver to a frozen function object") \
T(ObserveGlobalProxy, "% cannot be called on the global proxy object") \
+ T(ObserveAccessChecked, "% cannot be called on access-checked objects") \
T(ObserveInvalidAccept, \
"Third argument to Object.observe must be an array of strings.") \
T(ObserveNonFunction, "Object.% cannot deliver to non-function") \
diff --git a/chromium/v8/src/object-observe.js b/chromium/v8/src/object-observe.js
index 56859a1c97b..9c49fd38fb6 100644
--- a/chromium/v8/src/object-observe.js
+++ b/chromium/v8/src/object-observe.js
@@ -389,6 +389,8 @@ function ObjectObserve(object, callback, acceptList) {
throw MakeTypeError(kObserveNonObject, "observe", "observe");
if (%IsJSGlobalProxy(object))
throw MakeTypeError(kObserveGlobalProxy, "observe");
+ if (%IsAccessCheckNeeded(object))
+ throw MakeTypeError(kObserveAccessChecked, "observe");
if (!IS_SPEC_FUNCTION(callback))
throw MakeTypeError(kObserveNonFunction, "observe");
if (ObjectIsFrozen(callback))
@@ -617,6 +619,8 @@ function ObjectGetNotifier(object) {
throw MakeTypeError(kObserveNonObject, "getNotifier", "getNotifier");
if (%IsJSGlobalProxy(object))
throw MakeTypeError(kObserveGlobalProxy, "getNotifier");
+ if (%IsAccessCheckNeeded(object))
+ throw MakeTypeError(kObserveAccessChecked, "getNotifier");
if (ObjectIsFrozen(object)) return null;
diff --git a/chromium/v8/src/runtime/runtime-object.cc b/chromium/v8/src/runtime/runtime-object.cc
index da1ec4977be..9536ec0cc40 100644
--- a/chromium/v8/src/runtime/runtime-object.cc
+++ b/chromium/v8/src/runtime/runtime-object.cc
@@ -1435,5 +1435,13 @@ RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
setter, attrs));
return isolate->heap()->undefined_value();
}
+
+
+RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) {
+ SealHandleScope shs(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_CHECKED(Object, object, 0);
+ return isolate->heap()->ToBoolean(object->IsAccessCheckNeeded());
+}
} // namespace internal
} // namespace v8
diff --git a/chromium/v8/src/runtime/runtime.h b/chromium/v8/src/runtime/runtime.h
index da1ae40ba06..c4f74e7de11 100644
--- a/chromium/v8/src/runtime/runtime.h
+++ b/chromium/v8/src/runtime/runtime.h
@@ -483,7 +483,8 @@ namespace internal {
F(IsStrong, 1, 1) \
F(ClassOf, 1, 1) \
F(DefineGetterPropertyUnchecked, 4, 1) \
- F(DefineSetterPropertyUnchecked, 4, 1)
+ F(DefineSetterPropertyUnchecked, 4, 1) \
+ F(IsAccessCheckNeeded, 1, 1)
#define FOR_EACH_INTRINSIC_OBSERVE(F) \
diff --git a/chromium/v8/src/scanner-character-streams.cc b/chromium/v8/src/scanner-character-streams.cc
index 442bc75d6cc..eaaa9bc1f72 100644
--- a/chromium/v8/src/scanner-character-streams.cc
+++ b/chromium/v8/src/scanner-character-streams.cc
@@ -346,6 +346,7 @@ size_t ExternalStreamingStream::FillBuffer(size_t position) {
current_data_length_ = source_stream_->GetMoreData(&current_data_);
current_data_offset_ = 0;
bool data_ends = current_data_length_ == 0;
+ bookmark_data_is_from_current_data_ = false;
// A caveat: a data chunk might end with bytes from an incomplete UTF-8
// character (the rest of the bytes will be in the next chunk).
@@ -405,6 +406,15 @@ bool ExternalStreamingStream::SetBookmark() {
// - buffer_[buffer_cursor_ .. buffer_end_] => bookmark_buffer_
// - current_data_[.._offset_ .. .._length_] => bookmark_data_
// - utf8_split_char_buffer_* => bookmark_utf8_split...
+ //
+ // To make sure we don't unnecessarily copy data, we also maintain
+ // whether bookmark_data_ contains a copy of the current current_data_
+ // block. This is done with:
+ // - bookmark_data_is_from_current_data_
+ // - bookmark_data_offset_: offset into bookmark_data_
+ //
+ // Note that bookmark_data_is_from_current_data_ must be maintained
+ // whenever current_data_ is updated.
bookmark_ = pos_;
@@ -414,10 +424,21 @@ bool ExternalStreamingStream::SetBookmark() {
CopyCharsUnsigned(bookmark_buffer_.start(), buffer_cursor_, buffer_length);
size_t data_length = current_data_length_ - current_data_offset_;
- bookmark_data_.Dispose();
- bookmark_data_ = Vector<uint8_t>::New(static_cast<int>(data_length));
- CopyBytes(bookmark_data_.start(), current_data_ + current_data_offset_,
- data_length);
+ size_t bookmark_data_length = static_cast<size_t>(bookmark_data_.length());
+ if (bookmark_data_is_from_current_data_ &&
+ data_length < bookmark_data_length) {
+ // Fast case: bookmark_data_ was previously copied from the current
+ // data block, and we have enough data for this bookmark.
+ bookmark_data_offset_ = bookmark_data_length - data_length;
+ } else {
+ // Slow case: We need to copy current_data_.
+ bookmark_data_.Dispose();
+ bookmark_data_ = Vector<uint8_t>::New(static_cast<int>(data_length));
+ CopyBytes(bookmark_data_.start(), current_data_ + current_data_offset_,
+ data_length);
+ bookmark_data_is_from_current_data_ = true;
+ bookmark_data_offset_ = 0;
+ }
bookmark_utf8_split_char_buffer_length_ = utf8_split_char_buffer_length_;
for (size_t i = 0; i < utf8_split_char_buffer_length_; i++) {
@@ -436,12 +457,14 @@ void ExternalStreamingStream::ResetToBookmark() {
// bookmark_data_* => current_data_*
// (current_data_ assumes ownership of its memory.)
- uint8_t* data = new uint8_t[bookmark_data_.length()];
current_data_offset_ = 0;
- current_data_length_ = bookmark_data_.length();
- CopyCharsUnsigned(data, bookmark_data_.begin(), bookmark_data_.length());
+ current_data_length_ = bookmark_data_.length() - bookmark_data_offset_;
+ uint8_t* data = new uint8_t[current_data_length_];
+ CopyCharsUnsigned(data, bookmark_data_.begin() + bookmark_data_offset_,
+ current_data_length_);
delete[] current_data_;
current_data_ = data;
+ bookmark_data_is_from_current_data_ = true;
// bookmark_buffer_ needs to be copied to buffer_.
CopyCharsUnsigned(buffer_, bookmark_buffer_.begin(),
@@ -462,6 +485,7 @@ void ExternalStreamingStream::FlushCurrent() {
current_data_ = NULL;
current_data_length_ = 0;
current_data_offset_ = 0;
+ bookmark_data_is_from_current_data_ = false;
}
diff --git a/chromium/v8/src/scanner-character-streams.h b/chromium/v8/src/scanner-character-streams.h
index 582165710db..f3ee20463af 100644
--- a/chromium/v8/src/scanner-character-streams.h
+++ b/chromium/v8/src/scanner-character-streams.h
@@ -94,6 +94,8 @@ class ExternalStreamingStream : public BufferedUtf16CharacterStream {
current_data_length_(0),
utf8_split_char_buffer_length_(0),
bookmark_(0),
+ bookmark_data_is_from_current_data_(false),
+ bookmark_data_offset_(0),
bookmark_utf8_split_char_buffer_length_(0) {}
virtual ~ExternalStreamingStream() {
@@ -134,6 +136,8 @@ class ExternalStreamingStream : public BufferedUtf16CharacterStream {
size_t bookmark_;
Vector<uint16_t> bookmark_buffer_;
Vector<uint8_t> bookmark_data_;
+ bool bookmark_data_is_from_current_data_;
+ size_t bookmark_data_offset_;
uint8_t bookmark_utf8_split_char_buffer_[4];
size_t bookmark_utf8_split_char_buffer_length_;
};