diff --git a/DEPS b/DEPS index def7415..02f1023 100644 --- a/DEPS +++ b/DEPS
@@ -43,7 +43,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '4e8d71c0d2d36db26197d48ae943c15807674653', + 'v8_revision': 'b8ad5b1f8f374f22e98bb528e67156e9239fa696', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -190,7 +190,7 @@ Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'f962bcb6a8aed397bb2d418527a4e4a23f5ab955', 'src/third_party/libjingle/source/talk': - Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '5a1f5b5548e30780dcb5211bcdf8ce4f4a937838', # commit position 10776 + Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '223d8ffb60e2f1e10af047a95480716997df860c', # commit position 10790 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/usrsctplib.git' + '@' + '36444a999739e9e408f8f587cb4c3ffeef2e50ac', # from svn revision 9215 @@ -214,7 +214,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'dbb9f9bf2684ac070e7f6b8807526498bfb4a115', # commit position 10778 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '57ea0a4064d963a7357070105070969417fdb3f9', # commit position 10796 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/base/trace_event/common/trace_event_common.h b/base/trace_event/common/trace_event_common.h index 16a9a37..cae3670 100644 --- a/base/trace_event/common/trace_event_common.h +++ b/base/trace_event/common/trace_event_common.h
@@ -484,6 +484,20 @@ static_cast<int>(value1_val), value2_name, \ static_cast<int>(value2_val)) +// Similar to TRACE_COUNTERx, but with a custom |timestamp| provided. +#define TRACE_COUNTER_WITH_TIMESTAMP1(category_group, name, timestamp, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ + TRACE_EVENT_PHASE_COUNTER, category_group, name, timestamp, \ + TRACE_EVENT_FLAG_NONE, "value", static_cast<int>(value)) + +#define TRACE_COUNTER_WITH_TIMESTAMP2(category_group, name, timestamp, \ + value1_name, value1_val, value2_name, \ + value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ + TRACE_EVENT_PHASE_COUNTER, category_group, name, timestamp, \ + TRACE_EVENT_FLAG_NONE, value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) + // Records the value of a counter called "name" immediately. Value // must be representable as a 32 bit integer. // - category and name strings must have application lifetime (statics or
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h index 95ea2159..14448e2 100644 --- a/base/trace_event/trace_event.h +++ b/base/trace_event/trace_event.h
@@ -302,6 +302,23 @@ // Implementation detail: internal macro to create static category and add // event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \ + timestamp, flags, ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ + if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ + trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \ + phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ + trace_event_internal::kNoId, trace_event_internal::kNoId, \ + TRACE_EVENT_API_CURRENT_THREAD_ID, \ + base::TimeTicks::FromInternalValue(timestamp), \ + flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, \ + trace_event_internal::kNoId, ##__VA_ARGS__); \ + } \ + } while (0) + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(phase, \ category_group, name, id, thread_id, timestamp, flags, ...) \ do { \
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc index 084c250..533a298 100644 --- a/base/trace_event/trace_event_unittest.cc +++ b/base/trace_event/trace_event_unittest.cc
@@ -459,6 +459,11 @@ "a", 30000, "b", 1415); + TRACE_COUNTER_WITH_TIMESTAMP1("all", "TRACE_COUNTER_WITH_TIMESTAMP1 call", + 42, 31415); + TRACE_COUNTER_WITH_TIMESTAMP2("all", "TRACE_COUNTER_WITH_TIMESTAMP2 call", + 42, "a", 30000, "b", 1415); + TRACE_COUNTER_ID1("all", "TRACE_COUNTER_ID1 call", 0x319009, 31415); TRACE_COUNTER_ID2("all", "TRACE_COUNTER_ID2 call", 0x319009, "a", 30000, "b", 1415); @@ -655,6 +660,39 @@ EXPECT_EQ(1415, value); } + EXPECT_FIND_("TRACE_COUNTER_WITH_TIMESTAMP1 call"); + { + std::string ph; + EXPECT_TRUE((item && item->GetString("ph", &ph))); + EXPECT_EQ("C", ph); + + int value; + EXPECT_TRUE((item && item->GetInteger("args.value", &value))); + EXPECT_EQ(31415, value); + + int ts; + EXPECT_TRUE((item && item->GetInteger("ts", &ts))); + EXPECT_EQ(42, ts); + } + + EXPECT_FIND_("TRACE_COUNTER_WITH_TIMESTAMP2 call"); + { + std::string ph; + EXPECT_TRUE((item && item->GetString("ph", &ph))); + EXPECT_EQ("C", ph); + + int value; + EXPECT_TRUE((item && item->GetInteger("args.a", &value))); + EXPECT_EQ(30000, value); + + EXPECT_TRUE((item && item->GetInteger("args.b", &value))); + EXPECT_EQ(1415, value); + + int ts; + EXPECT_TRUE((item && item->GetInteger("ts", &ts))); + EXPECT_EQ(42, ts); + } + EXPECT_FIND_("TRACE_COUNTER_ID1 call"); { std::string id;
diff --git a/build/buildflag.h b/build/buildflag.h new file mode 100644 index 0000000..283f5bc --- /dev/null +++ b/build/buildflag.h
@@ -0,0 +1,47 @@ +// Copyright 2015 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 BUILD_BUILDFLAG_H_ +#define BUILD_BUILDFLAG_H_ + +// These macros un-mangle the names of the build flags in a way that looks +// natural, and gives errors if the flag is not defined. Normally in the +// preprocessor it's easy to make mistakes that interpret "you haven't done +// the setup to know what the flag is" as "flag is off". Normally you would +// include the generated header rather than include this file directly. +// +// This is for use with generated headers. See build/build_header.gni. + +// This dance of two macros does a concatenation of two preprocessor args using +// ## doubly indirectly because using ## directly prevents macros in that +// parameter from being expanded. +#define BUILDFLAG_CAT_INDIRECT(a, b) a ## b +#define BUILDFLAG_CAT(a, b) BUILDFLAG_CAT_INDIRECT(a, b) + +// Accessor for build flags. +// +// To test for a value, if the build file specifies: +// +// ENABLE_FOO=true +// +// Then you would check at build-time in source code with: +// +// #include "foo_flags.h" // The header the build file specified. +// +// #if BUILDFLAG(ENABLE_FOO) +// ... +// #endif +// +// There will no #define called ENABLE_FOO so if you accidentally test for +// whether that is defined, it will always be negative. You can also use +// the value in expressions: +// +// const char kSpamServerName[] = BUILDFLAG(SPAM_SERVER_NAME); +// +// Because the flag is accessed as a preprocessor macro with (), an error +// will be thrown if the proper header defining the internal flag value has +// not been included. +#define BUILDFLAG(flag) (BUILDFLAG_CAT(BUILDFLAG_INTERNAL_, flag)()) + +#endif // BUILD_BUILDFLAG_H_
diff --git a/build/buildflag_header.gni b/build/buildflag_header.gni new file mode 100644 index 0000000..9054d07 --- /dev/null +++ b/build/buildflag_header.gni
@@ -0,0 +1,138 @@ +# Copyright 2015 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. + +# Generates a header with preprocessor defines specified by the build file. +# The GYP version of this (with instructions) is build/buildflag_header.gypi. +# +# The flags are converted to function-style defines with mangled names and +# code uses an accessor macro to access the values. This is to try to +# minimize bugs where code checks whether something is defined or not, and +# the proper header isn't included, meaning the answer will always be silently +# false or might vary across the code base. +# +# In the GN template, specify build flags in the template as a list +# of strings that encode key/value pairs like this: +# +# flags = [ "ENABLE_FOO=1", "ENABLE_BAR=$enable_bar" ] +# +# The GN values "true" and "false" will be mapped to 0 and 1 for boolean +# #if flags to be expressed naturally. This means you can't directly make a +# define that generates C++ value of true or false for use in code. If you +# REALLY need this, you can also use the string "(true)" and "(false)" to +# prevent the rewriting. + +# To check the value of the flag in C code: +# +# #include "path/to/here/header_file.h" +# +# #if BUILDFLAG(ENABLE_FOO) +# ... +# #endif +# +# const char kSpamServerUrl[] = BUILDFLAG(SPAM_SERVER_URL); +# +# There will no #define called ENABLE_FOO so if you accidentally test for that +# in an ifdef it will always be negative. +# +# +# Template parameters +# +# flags [required, list of strings] +# Flag values as described above. +# +# header [required, string] +# File name for generated header. By default, this will go in the +# generated file directory for this target, and you would include it +# with: +# #include "<path_to_this_BUILD_file>/<header>" +# +# header_dir [optional, string] +# Override the default location of the generated header. The string will +# be treated as a subdirectory of the root_gen_dir. For example: +# header_dir = "foo/bar" +# Then you can include the header as: +# #include "foo/bar/baz.h" +# +# deps, public_deps, testonly, visibility +# Normal meaning. +# +# +# Grit defines +# +# If one .grd file uses a flag, just add to the grit target: +# +# defines = [ +# "enable_doom_melon=$enable_doom_melon", +# ] +# +# If multiple .grd files use it, you'll want to put the defines in a .gni file +# so it can be shared. Generally this .gni file should include all grit defines +# for a given module (for some definition of "module"). Then do: +# +# defines = ui_grit_defines +# +# If you forget to do this, the flag will be implicitly false in the .grd file +# and those resources won't be compiled. You'll know because the resource +# #define won't be generated and any code that uses it won't compile. If you +# see a missing IDS_* string, this is probably the reason. +# +# +# Example +# +# buildflag_header("foo_features") { +# header = "foo_features.h" +# +# flags = [ +# # This uses the GN build flag enable_doom_melon as the definition. +# "ENABLE_DOOM_MELON=$enable_doom_melon", +# +# # This force-enables the flag. +# "ENABLE_SPACE_LASER=true", +# +# # This will expand to the quoted C string when used in source code. +# "SPAM_SERVER_URL=\"http://www.example.com/\"", +# ] +# } +template("buildflag_header") { + action(target_name) { + script = "//build/write_buildflag_header.py" + + if (defined(invoker.header_dir)) { + header_file = "${invoker.header_dir}/${invoker.header}" + } else { + # Compute the path from the root to this file. + header_file = rebase_path(".", "//") + "/${invoker.header}" + } + + outputs = [ + "$root_gen_dir/$header_file", + ] + + # Always write --flags to the file so it's not empty. Empty will confuse GN + # into thinking the response file isn't used. + response_file_contents = [ "--flags" ] + if (defined(invoker.flags)) { + response_file_contents += invoker.flags + } + + args = [ + "--output", + header_file, # Not rebased, Python script puts it inside gen-dir. + "--rulename", + get_label_info(":$target_name", "label_no_toolchain"), + "--gen-dir", + rebase_path(root_gen_dir, root_out_dir), + "--definitions", + "{{response_file_name}}", + ] + + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "testonly", + "visibility", + ]) + } +}
diff --git a/build/buildflag_header.gypi b/build/buildflag_header.gypi new file mode 100644 index 0000000..730ef429 --- /dev/null +++ b/build/buildflag_header.gypi
@@ -0,0 +1,118 @@ +# Copyright 2015 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. + +# Generates a header with preprocessor defines specified by the build file. +# +# The canonical documentation is in build/buildflag_header.gni. You should +# write the GN build, get it working, and then transform it into GYP. +# +# In every target that uses your generated header you must include a dependency +# on the GYP target that generates the header (this is implicit in GN). +# Otherwise, clean builds may not necessarily create the header before the +# source code is compiled. +# +# Assuming your GN code looks like this: +# +# buildflag_header("foo_features") { +# header = "foo_features.h" +# flags = [ +# "ENABLE_DOOM_MELON=$enable_doom_melon", +# "ENABLE_SPACE_LASER=true", +# "SPAM_SERVER_URL=\"http://www.example.com/\"", +# ] +# } +# +# Write a GYP target like this: +# +# { +# # GN version: //foo:foo_features +# 'target_name': 'foo_foo_features', +# 'includes': [ '../build/buildflag_header.gypi' ], +# 'variables': { +# 'buildflag_header_path': 'foo/foo_features.h', +# 'buildflag_header_flags': [ +# 'ENABLE_DOOM_MELON=<(enable_doom_melon)', +# 'ENABLE_SPACE_LASER=true', +# 'SPAM_SERVER_URL="http://www.example.com/"', +# ], +# }, +# } +# +# Variables +# +# target_name +# Base this on the GN label, replacing / and : with _ to make it globally +# unique. +# +# buildflag_header_path +# This must be the full path to the header from the source root. In GN +# you only say "features.h" and it uses the BUILD file's path implicitly. +# Use the path to BUILD.gn followed by your header name to produce the +# same output file. +# +# buildflag_flags (optional) +# List of the same format as GN's "flags". To expand variables, use +# "<(foo)" where GN would have used "$foo". +# +# includes +# List the relative path to build/buildflag_header.gypi from the .gyp +# file including this code, Note: If your code is in a .gypi file in a +# different directory, this must be relative to the .gyp including your +# file. +# +# +# Grit defines +# +# Follow the same advice as in the buildflag_header.gni, except on the grit +# action use the variable name 'grit_additional_defines' and explicitly add a +# '-D' in front: +# +# 'grit_grd_file': 'foo.grd', +# 'grit_additional_defines': [ +# '-D', 'enable_doom_melon=<(enable_doom_melon)', +# ], +# +# Put shared lists of defines in a .gypi. + +{ + 'type': 'none', + 'hard_dependency': 1, + + 'actions': [ + { + 'action_name': 'buildflag_header', + 'variables': { + # Default these values to empty if they're not defined. + 'variables': { + 'buildflag_flags%': [], + }, + + # Writes the flags to a response file with a name based on the name of + # this target. + 'response_file_name': '<|(<(_target_name)_buildflag_header.rsp --flags <@(buildflag_flags))', + + 'build_header_script': '<(DEPTH)/build/write_buildflag_header.py', + }, + + 'message': 'Generating build header.', + + 'inputs': [ + '<(build_header_script)', + '<(response_file_name)', + ], + + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/<(buildflag_header_path)', + ], + + 'action': [ + 'python', '<(build_header_script)', + '--output', '<(buildflag_header_path)', + '--rulename', '<(_target_name)', + '--gen-dir', '<(SHARED_INTERMEDIATE_DIR)', + '--definitions', '<(response_file_name)', + ], + } + ], +}
diff --git a/build/common.gypi b/build/common.gypi index 9c226a2f..c5d5c85d 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -547,9 +547,6 @@ # Enable Chrome browser extensions 'enable_extensions%': 1, - # Enable Google Now. - 'enable_google_now%': 1, - # Enable basic printing support and UI. 'enable_basic_printing%': 1, @@ -819,7 +816,6 @@ ['OS=="android"', { 'enable_extensions%': 0, - 'enable_google_now%': 0, 'cld2_table_size%': 0, 'enable_themes%': 0, 'remoting%': 0, @@ -867,7 +863,6 @@ 'configuration_policy%': 0, 'disable_ftp_support%': 1, 'enable_extensions%': 0, - 'enable_google_now%': 0, 'cld2_table_size%': 0, 'enable_basic_printing%': 0, 'enable_print_preview%': 0, @@ -1221,7 +1216,6 @@ 'enable_print_preview%': '<(enable_print_preview)', 'enable_spellcheck%': '<(enable_spellcheck)', 'use_browser_spellchecker%': '<(use_browser_spellchecker)', - 'enable_google_now%': '<(enable_google_now)', 'cld_version%': '<(cld_version)', 'cld2_table_size%': '<(cld2_table_size)', 'enable_captive_portal_detection%': '<(enable_captive_portal_detection)', @@ -2180,9 +2174,6 @@ ['enable_settings_app==1', { 'grit_defines': ['-D', 'enable_settings_app'], }], - ['enable_google_now==1', { - 'grit_defines': ['-D', 'enable_google_now'], - }], ['use_concatenated_impulse_responses==1', { 'grit_defines': ['-D', 'use_concatenated_impulse_responses'], }], @@ -2995,9 +2986,6 @@ ['enable_background==1', { 'defines': ['ENABLE_BACKGROUND=1'], }], - ['enable_google_now==1', { - 'defines': ['ENABLE_GOOGLE_NOW=1'], - }], ['enable_basic_printing==1 or enable_print_preview==1', { # Convenience define for ENABLE_BASIC_PRINTING || ENABLE_PRINT_PREVIEW. 'defines': ['ENABLE_PRINTING=1'],
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn index 9cc3756..5f85713 100644 --- a/build/config/BUILD.gn +++ b/build/config/BUILD.gn
@@ -218,9 +218,6 @@ if (enable_image_loader_extension) { defines += [ "IMAGE_LOADER_EXTENSION=1" ] } - if (enable_google_now) { - defines += [ "ENABLE_GOOGLE_NOW=1" ] - } if (enable_one_click_signin) { defines += [ "ENABLE_ONE_CLICK_SIGNIN" ] }
diff --git a/build/config/features.gni b/build/config/features.gni index 514a6673..1d5f305 100644 --- a/build/config/features.gni +++ b/build/config/features.gni
@@ -83,8 +83,6 @@ enable_autofill_dialog = !is_ios - enable_google_now = !is_ios && !is_android - enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos) enable_remoting = !is_ios && !is_chromecast && !is_headless
diff --git a/build/gypi_to_gn.py b/build/gypi_to_gn.py index a107f94f..6de1a63 100644 --- a/build/gypi_to_gn.py +++ b/build/gypi_to_gn.py
@@ -96,10 +96,12 @@ if 'target_conditions' in file_data: del file_data['target_conditions'] - # Strip targets in the toplevel, since some files define these and we can't - # slurp them in. + # Strip targets and includes in the toplevel, since some files define these + # and we can't slurp them in. if 'targets' in file_data: del file_data['targets'] + if 'includes' in file_data: + del file_data['includes'] return file_data
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index b8afe645..abd4f438 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -258,9 +258,6 @@ // http://crbug.com/388730 "race:g_next_user_script_id\n" -// http://crbug.com/389098 -"race:webrtc::voe::TransmitMixer::EnableStereoChannelSwapping\n" - // http://crbug.com/397022 "deadlock:" "base::trace_event::TraceEventTestFixture_ThreadOnceBlocking_Test::TestBody\n"
diff --git a/build/write_buildflag_header.py b/build/write_buildflag_header.py new file mode 100755 index 0000000..d46cfc8 --- /dev/null +++ b/build/write_buildflag_header.py
@@ -0,0 +1,95 @@ +#!/usr/bin/env python +# Copyright 2015 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 writes headers for build flags. See buildflag_header.gni for usage of +# this system as a whole. +# +# The parameters are passed in a response file so we don't have to worry +# about command line lengths. The name of the response file is passed on the +# command line. +# +# The format of the response file is: +# [--flags <list of one or more flag values>] + +import optparse +import os +import shlex +import sys + + +class Options: + def __init__(self, output, rulename, header_guard, flags): + self.output = output + self.rulename = rulename + self.header_guard = header_guard + self.flags = flags + + +def GetOptions(): + parser = optparse.OptionParser() + parser.add_option('--output', help="Output header name inside --gen-dir.") + parser.add_option('--rulename', + help="Helpful name of build rule for including in the " + + "comment at the top of the file.") + parser.add_option('--gen-dir', + help="Path to root of generated file directory tree.") + parser.add_option('--definitions', + help="Name of the response file containing the flags.") + cmdline_options, cmdline_flags = parser.parse_args() + + # Compute header guard by replacing some chars with _ and upper-casing. + header_guard = cmdline_options.output.upper() + header_guard = \ + header_guard.replace('/', '_').replace('\\', '_').replace('.', '_') + header_guard += '_' + + # The actual output file is inside the gen dir. + output = os.path.join(cmdline_options.gen_dir, cmdline_options.output) + + # Definition file in GYP is newline separated, in GN they are shell formatted. + # shlex can parse both of these. + with open(cmdline_options.definitions, 'r') as def_file: + defs = shlex.split(def_file.read()) + flags_index = defs.index('--flags') + + # Everything after --flags are flags. true/false are remapped to 1/0, + # everything else is passed through. + flags = [] + for flag in defs[flags_index + 1 :]: + equals_index = flag.index('=') + key = flag[:equals_index] + value = flag[equals_index + 1:] + + # Canonicalize and validate the value. + if value == 'true': + value = '1' + elif value == 'false': + value = '0' + flags.append((key, str(value))) + + return Options(output=output, + rulename=cmdline_options.rulename, + header_guard=header_guard, + flags=flags) + + +def WriteHeader(options): + with open(options.output, 'w') as output_file: + output_file.write("// Generated by build/write_buildflag_header.py\n") + if options.rulename: + output_file.write('// From "' + options.rulename + '"\n') + + output_file.write('\n#ifndef %s\n' % options.header_guard) + output_file.write('#define %s\n\n' % options.header_guard) + output_file.write('#include "build/buildflag.h"\n\n') + + for pair in options.flags: + output_file.write('#define BUILDFLAG_INTERNAL_%s() (%s)\n' % pair) + + output_file.write('\n#endif // %s\n' % options.header_guard) + + +options = GetOptions() +WriteHeader(options)
diff --git a/chrome/VERSION b/chrome/VERSION index ac838e90..939f6e6 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=49 MINOR=0 -BUILD=2575 +BUILD=2576 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkEditActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkEditActivity.java index 89933b5..7c098a0d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkEditActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkEditActivity.java
@@ -30,6 +30,7 @@ import org.chromium.chrome.browser.widget.TintedDrawable; import org.chromium.components.bookmarks.BookmarkId; import org.chromium.content_public.browser.WebContents; +import org.chromium.ui.base.DeviceFormFactor; /** * The activity that enables the user to modify the title, url and parent folder of a bookmark. @@ -311,9 +312,16 @@ } private void openBookmark() { - Intent intent = new Intent(); - intent.putExtra(EnhancedBookmarkActivity.INTENT_VISIT_BOOKMARK_ID, mBookmarkId.toString()); - setResult(RESULT_OK, intent); + // TODO(kkimlabs): Refactor this out to handle the intent in ChromeActivity. + if (DeviceFormFactor.isTablet(this)) { + EnhancedBookmarkUtils.openBookmark( + mEnhancedBookmarksModel, this, mBookmarkId, LaunchLocation.BOOKMARK_EDITOR); + } else { + Intent intent = new Intent(); + intent.putExtra( + EnhancedBookmarkActivity.INTENT_VISIT_BOOKMARK_ID, mBookmarkId.toString()); + setResult(RESULT_OK, intent); + } finish(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java index 12c84cba..e0678dc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
@@ -9,7 +9,6 @@ import android.content.Context; import android.preference.PreferenceManager; import android.support.v4.widget.DrawerLayout; -import android.text.TextUtils; import android.util.Log; import android.view.Gravity; import android.view.View; @@ -18,13 +17,11 @@ import org.chromium.base.ApplicationStatus; import org.chromium.base.ObserverList; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.bookmark.BookmarksBridge.BookmarkItem; import org.chromium.chrome.browser.bookmark.BookmarksBridge.BookmarkModelObserver; import org.chromium.chrome.browser.favicon.LargeIconBridge; -import org.chromium.chrome.browser.ntp.NewTabPageUma; import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim; import org.chromium.chrome.browser.profiles.Profile; @@ -434,20 +431,8 @@ @Override public void openBookmark(BookmarkId bookmark, int launchLocation) { clearSelection(); - if (mEnhancedBookmarksModel.getBookmarkById(bookmark) != null) { - String url = mEnhancedBookmarksModel.getLaunchUrlAndMarkAccessed(mActivity, bookmark); - // TODO(jianli): Notify the user about the failure. - if (TextUtils.isEmpty(url)) return; - - NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_BOOKMARK); - if (url.startsWith("file:")) { - RecordHistogram.recordEnumeratedHistogram("OfflinePages.LaunchLocation", - launchLocation, LaunchLocation.COUNT); - } else { - RecordHistogram.recordEnumeratedHistogram("Stars.LaunchLocation", launchLocation, - LaunchLocation.COUNT); - } - EnhancedBookmarkUtils.openBookmark(mActivity, url); + if (EnhancedBookmarkUtils.openBookmark( + mEnhancedBookmarksModel, mActivity, bookmark, launchLocation)) { EnhancedBookmarkUtils.finishActivityOnPhone(mActivity); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkUtils.java index 938d8380..62873dfa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkUtils.java
@@ -12,8 +12,10 @@ import android.os.AsyncTask; import android.os.Bundle; import android.provider.Browser; +import android.text.TextUtils; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeBrowserProviderClient; @@ -24,6 +26,7 @@ import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarksModel.AddBookmarkCallback; import org.chromium.chrome.browser.favicon.FaviconHelper; +import org.chromium.chrome.browser.ntp.NewTabPageUma; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.offlinepages.OfflinePageFreeUpSpaceCallback; import org.chromium.chrome.browser.offlinepages.OfflinePageFreeUpSpaceDialog; @@ -263,7 +266,7 @@ return false; } if (DeviceFormFactor.isTablet(activity)) { - openBookmark(activity, UrlConstants.BOOKMARKS_URL); + openUrl(activity, UrlConstants.BOOKMARKS_URL); } else { activity.startActivity(new Intent(activity, EnhancedBookmarkActivity.class)); } @@ -319,7 +322,37 @@ return BookmarkId.getBookmarkIdFromString(bundle.getString(BOOKMARK_SAVE_NAME)); } - public static void openBookmark(Activity activity, String url) { + /** + * Opens a bookmark depending on connection status and reports UMA. + * @param model Enhanced bookmarks model to manage the bookmark. + * @param activity Activity requesting to open the bookmark. + * @param bookmarkId ID of the bookmark to be opened. + * @param launchLocation Location from which the bookmark is being opened. + * @return Whether the bookmark was successfully opened. + */ + public static boolean openBookmark(EnhancedBookmarksModel model, Activity activity, + BookmarkId bookmarkId, int launchLocation) { + if (model.getBookmarkById(bookmarkId) == null) return false; + + String url = model.getLaunchUrlAndMarkAccessed(activity, bookmarkId); + + // TODO(jianli): Notify the user about the failure. + if (TextUtils.isEmpty(url)) return false; + + NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_BOOKMARK); + if (url.startsWith("file:")) { + RecordHistogram.recordEnumeratedHistogram( + "OfflinePages.LaunchLocation", launchLocation, LaunchLocation.COUNT); + } else { + RecordHistogram.recordEnumeratedHistogram( + "Stars.LaunchLocation", launchLocation, LaunchLocation.COUNT); + } + + openUrl(activity, url); + return true; + } + + private static void openUrl(Activity activity, String url) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.setClassName(activity.getApplicationContext().getPackageName(), ChromeLauncherActivity.class.getName());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 41ad51d..2c10a2fd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -110,6 +110,9 @@ private boolean mIsLoaded; + // Whether the NTP has loaded once and is in the foreground. + private boolean mIsVisible; + // Whether destroy() has been called. private boolean mIsDestroyed; @@ -407,6 +410,7 @@ RecordHistogram.recordTimesHistogram( "Tab.NewTabOnload", loadTimeMs, TimeUnit.MILLISECONDS); mIsLoaded = true; + mIsVisible = true; StartupMetrics.getInstance().recordOpenedNTP(); if (mIsDestroyed) return; @@ -451,6 +455,13 @@ public void onShown(Tab tab) { // Showing the NTP is only meaningful when the page has been loaded already. if (mIsLoaded) recordNTPShown(); + mIsVisible = true; + } + + @Override + public void onHidden(Tab tab) { + recordNTPInteractionTime(); + mIsVisible = false; } }; mTab.addObserver(mTabObserver); @@ -574,6 +585,11 @@ RecordUserAction.record("MobileNTPShown"); } + private void recordNTPInteractionTime() { + RecordHistogram.recordMediumTimesHistogram( + "NewTabPage.TimeSpent", System.nanoTime() - mLastShownTimeNs, TimeUnit.NANOSECONDS); + } + /** * @return Whether the NTP has finished loaded. */ @@ -595,6 +611,7 @@ public void destroy() { assert !mIsDestroyed; assert getView().getParent() == null : "Destroy called before removed from window"; + if (mIsVisible) recordNTPInteractionTime(); if (mFaviconHelper != null) { mFaviconHelper.destroy(); mFaviconHelper = null;
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 44416e7..d528833 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/crypto.gni") import("//build/config/features.gni") import("//build/config/ui.gni") +import("//chrome/common/features.gni") import("//media/media_options.gni") import("//third_party/protobuf/proto_library.gni") @@ -957,6 +958,7 @@ # (generate_browser_resources action) grit("resources") { source = "browser_resources.grd" + defines = chrome_grit_defines output_dir = "$root_gen_dir/chrome" outputs = [ "grit/browser_resources.h",
diff --git a/chrome/browser/apps/drive/drive_service_bridge.cc b/chrome/browser/apps/drive/drive_service_bridge.cc index f3facb04..916bcd5e 100644 --- a/chrome/browser/apps/drive/drive_service_bridge.cc +++ b/chrome/browser/apps/drive/drive_service_bridge.cc
@@ -83,6 +83,7 @@ drive_task_runner.get(), GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction), GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction), + GURL(google_apis::DriveApiUrlGenerator::kBaseThumbnailUrlForProduction), std::string() /* custom_user_agent */)); SigninManagerBase* signin_manager = SigninManagerFactory::GetForProfile(profile_);
diff --git a/chrome/browser/autofill/autofill_server_browsertest.cc b/chrome/browser/autofill/autofill_server_browsertest.cc index 18498d182..b5b28165 100644 --- a/chrome/browser/autofill/autofill_server_browsertest.cc +++ b/chrome/browser/autofill/autofill_server_browsertest.cc
@@ -149,14 +149,14 @@ " };" "</script>"; const char kQueryRequest[] = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"15916856893790176210\">" "<field signature=\"2594484045\" name=\"one\" type=\"text\"/>" "<field signature=\"2750915947\" name=\"two\" type=\"text\"/>" "<field signature=\"3494787134\" name=\"three\" type=\"text\"/>" "<field signature=\"1236501728\" name=\"four\" type=\"text\"/></form>" - "</autofillquery>"; + "</autofillquery>\n"; WindowedNetworkObserver query_network_observer(Compress(kQueryRequest)); ui_test_utils::NavigateToURL( browser(), GURL(std::string(kDataURIPrefix) + kFormHtml)); @@ -166,7 +166,7 @@ // triggered by user gestures are ignored. Expect an upload request upon form // submission, with form fields matching those from the query request. const char kUploadRequest[] = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<?xml version=\"1.0\"?>\n" "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" " formsignature=\"15916856893790176210\"" " autofillused=\"false\"" @@ -180,7 +180,7 @@ " autofilltype=\"2\"/>" "<field signature=\"1236501728\" name=\"four\" type=\"text\"" " autocomplete=\"off\" autofilltype=\"2\"/>" - "</autofillupload>"; + "</autofillupload>\n"; WindowedNetworkObserver upload_network_observer(Compress(kUploadRequest)); content::WebContents* web_contents = @@ -204,13 +204,13 @@ " <input type='submit'>" "</form>"; const char kQueryRequest[] = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"8900697631820480876\">" "<field signature=\"2594484045\" name=\"one\" type=\"text\"/>" "<field signature=\"2750915947\" name=\"two\" type=\"text\"/>" "<field signature=\"116843943\" name=\"three\" type=\"password\"/>" - "</form></autofillquery>"; + "</form></autofillquery>\n"; WindowedNetworkObserver query_network_observer(Compress(kQueryRequest)); ui_test_utils::NavigateToURL( browser(), GURL(std::string(kDataURIPrefix) + kFormHtml));
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index c69f48f9..9a1c03b8 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -388,11 +388,13 @@ wake_on_wifi_manager_.reset(new WakeOnWifiManager()); - arc_bridge_service_.reset(new arc::ArcBridgeService( - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::IO), - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::FILE))); + arc_bridge_service_ = + arc::ArcBridgeService::Create( + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::IO), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::FILE)) + .Pass(); arc_bridge_service_->DetectAvailability(); ChromeBrowserMainPartsLinux::PreMainMessageLoopRun();
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc index a9951e3..37c9f84 100644 --- a/chrome/browser/chromeos/drive/drive_integration_service.cc +++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -234,11 +234,11 @@ drive_service_.reset(test_drive_service); } else { drive_service_.reset(new DriveAPIService( - oauth_service, - g_browser_process->system_request_context(), + oauth_service, g_browser_process->system_request_context(), blocking_task_runner_.get(), GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction), GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction), + GURL(google_apis::DriveApiUrlGenerator::kBaseThumbnailUrlForProduction), GetDriveUserAgent())); } scheduler_.reset(new JobScheduler(
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc index caec650..7f2f1d70 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -96,7 +96,9 @@ DriveApiUrlGenerator url_generator( (GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction)), (GURL( - google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction))); + google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction)), + (GURL(google_apis::DriveApiUrlGenerator:: + kBaseThumbnailUrlForProduction))); properties->thumbnail_url.reset(new std::string( url_generator.GetThumbnailUrl(entry_proto.resource_id(), 500 /* width */, 500 /* height */, @@ -429,13 +431,27 @@ } ProvidedFileSystemInterface::MetadataFieldMask field_mask = - ProvidedFileSystemInterface::METADATA_FIELD_DEFAULT; - // TODO(mtomasz): Add other fields. All of them should be requested on - // demand. crbug.com/413161. + ProvidedFileSystemInterface::METADATA_FIELD_NONE; + if (names_.find(api::file_manager_private::ENTRY_PROPERTY_NAME_SIZE) != + names_.end()) { + field_mask |= ProvidedFileSystemInterface::METADATA_FIELD_SIZE; + } + if (names_.find( + api::file_manager_private::ENTRY_PROPERTY_NAME_MODIFICATIONTIME) != + names_.end()) { + field_mask |= + ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME; + } + if (names_.find( + api::file_manager_private::ENTRY_PROPERTY_NAME_CONTENTMIMETYPE) != + names_.end()) { + field_mask |= ProvidedFileSystemInterface::METADATA_FIELD_MIME_TYPE; + } if (names_.find( api::file_manager_private::ENTRY_PROPERTY_NAME_THUMBNAILURL) != - names_.end()) + names_.end()) { field_mask |= ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL; + } parser.file_system()->GetMetadata( parser.file_path(), field_mask, @@ -453,15 +469,31 @@ return; } - properties_->size.reset(new double(metadata->size)); - properties_->modification_time.reset( - new double(metadata->modification_time.ToJsTime())); + if (names_.find(api::file_manager_private::ENTRY_PROPERTY_NAME_SIZE) != + names_.end()) { + properties_->size.reset(new double(*metadata->size.get())); + } - if (!metadata->thumbnail.empty()) - properties_->thumbnail_url.reset(new std::string(metadata->thumbnail)); - if (!metadata->mime_type.empty()) { + if (names_.find( + api::file_manager_private::ENTRY_PROPERTY_NAME_MODIFICATIONTIME) != + names_.end()) { + properties_->modification_time.reset( + new double(metadata->modification_time->ToJsTime())); + } + + if (names_.find( + api::file_manager_private::ENTRY_PROPERTY_NAME_CONTENTMIMETYPE) != + names_.end() && + metadata->mime_type.get()) { properties_->content_mime_type.reset( - new std::string(metadata->mime_type)); + new std::string(*metadata->mime_type)); + } + + if (names_.find( + api::file_manager_private::ENTRY_PROPERTY_NAME_THUMBNAILURL) != + names_.end() && + metadata->thumbnail.get()) { + properties_->thumbnail_url.reset(new std::string(*metadata->thumbnail)); } CompleteGetEntryProperties(base::File::FILE_OK); @@ -1068,7 +1100,9 @@ DriveApiUrlGenerator url_generator( (GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction)), - (GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction))); + (GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction)), + (GURL( + google_apis::DriveApiUrlGenerator::kBaseThumbnailUrlForProduction))); download_url_ = url_generator.GenerateDownloadFileUrl(entry->resource_id()); ProfileOAuth2TokenService* oauth2_token_service =
diff --git a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc index ad0e0691..6990183 100644 --- a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc +++ b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc
@@ -561,9 +561,11 @@ class MultiProfileDriveFileSystemExtensionApiTest : public FileSystemExtensionApiTestBase { public: - MultiProfileDriveFileSystemExtensionApiTest() : second_profile(NULL) {} + MultiProfileDriveFileSystemExtensionApiTest() : second_profile_(NULL) {} void SetUpOnMainThread() override { + ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir()); + base::FilePath user_data_directory; PathService::Get(chrome::DIR_USER_DATA, &user_data_directory); user_manager::UserManager::Get()->UserLoggedIn( @@ -574,7 +576,7 @@ user_data_directory.Append( chromeos::ProfileHelper::GetUserProfileDir( kSecondProfileHash).BaseName()); - second_profile = + second_profile_ = g_browser_process->profile_manager()->GetProfile(profile_dir); FileSystemExtensionApiTestBase::SetUpOnMainThread(); @@ -593,7 +595,7 @@ void AddTestMountPoint() override { test_util::WaitUntilDriveMountPointIsAdded(browser()->profile()); - test_util::WaitUntilDriveMountPointIsAdded(second_profile); + test_util::WaitUntilDriveMountPointIsAdded(second_profile_); } protected: @@ -601,7 +603,8 @@ drive::DriveIntegrationService* CreateDriveIntegrationService( Profile* profile) { base::FilePath cache_dir; - base::CreateNewTempDirectory(base::FilePath::StringType(), &cache_dir); + base::CreateTemporaryDirInDir(tmp_dir_.path(), base::FilePath::StringType(), + &cache_dir); drive::FakeDriveService* const fake_drive_service = new drive::FakeDriveService; @@ -619,7 +622,7 @@ drive::util::GetDriveServiceByProfile(browser()->profile())); drive::FakeDriveService* const sub_service = static_cast<drive::FakeDriveService*>( - drive::util::GetDriveServiceByProfile(second_profile)); + drive::util::GetDriveServiceByProfile(second_profile_)); google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR; scoped_ptr<google_apis::FileResource> entry; @@ -645,11 +648,12 @@ return (error == google_apis::HTTP_CREATED); } + base::ScopedTempDir tmp_dir_; DriveIntegrationServiceFactory::FactoryCallback create_drive_integration_service_; scoped_ptr<DriveIntegrationServiceFactory::ScopedFactoryForTest> service_factory_for_test_; - Profile* second_profile; + Profile* second_profile_; std::map<std::string, std::string> resource_ids_; };
diff --git a/chrome/browser/chromeos/file_manager/filesystem_api_util.cc b/chrome/browser/chromeos/file_manager/filesystem_api_util.cc index b97071f3..231fbd16 100644 --- a/chrome/browser/chromeos/file_manager/filesystem_api_util.cc +++ b/chrome/browser/chromeos/file_manager/filesystem_api_util.cc
@@ -51,11 +51,11 @@ base::File::Error result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (result != base::File::FILE_OK || metadata->mime_type.empty()) { + if (result != base::File::FILE_OK || !metadata->mime_type.get()) { callback.Run(false, std::string()); return; } - callback.Run(true, metadata->mime_type); + callback.Run(true, *metadata->mime_type); } // Helper function to converts a callback that takes boolean value to that takes @@ -176,7 +176,7 @@ parser.file_system()->GetMetadata( parser.file_path(), chromeos::file_system_provider::ProvidedFileSystemInterface:: - METADATA_FIELD_DEFAULT, + METADATA_FIELD_MIME_TYPE, base::Bind(&GetMimeTypeAfterGetMetadataForProvidedFileSystem, callback)); return;
diff --git a/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.cc b/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.cc index fb3fce5..03fb9af 100644 --- a/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.cc +++ b/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.cc
@@ -60,11 +60,11 @@ DCHECK(entries_.find(entry_path) == entries_.end()); scoped_ptr<EntryMetadata> metadata(new EntryMetadata); - metadata->is_directory = is_directory; - metadata->name = name; - metadata->size = size; - metadata->modification_time = modification_time; - metadata->mime_type = mime_type; + metadata->is_directory.reset(new bool(is_directory)); + metadata->name.reset(new std::string(name)); + metadata->size.reset(new int64(size)); + metadata->modification_time.reset(new base::Time(modification_time)); + metadata->mime_type.reset(new std::string(mime_type)); entries_[entry_path] = make_linked_ptr(new FakeEntry(metadata.Pass(), contents)); @@ -98,12 +98,28 @@ } scoped_ptr<EntryMetadata> metadata(new EntryMetadata); - metadata->is_directory = entry_it->second->metadata->is_directory; - metadata->name = entry_it->second->metadata->name; - metadata->size = entry_it->second->metadata->size; - metadata->modification_time = entry_it->second->metadata->modification_time; - metadata->mime_type = entry_it->second->metadata->mime_type; - metadata->thumbnail = entry_it->second->metadata->thumbnail; + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_IS_DIRECTORY) { + metadata->is_directory.reset( + new bool(*entry_it->second->metadata->is_directory)); + } + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_NAME) + metadata->name.reset(new std::string(*entry_it->second->metadata->name)); + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_SIZE) + metadata->size.reset(new int64(*entry_it->second->metadata->size)); + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME) { + metadata->modification_time.reset( + new base::Time(*entry_it->second->metadata->modification_time)); + } + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_MIME_TYPE && + entry_it->second->metadata->mime_type.get()) { + metadata->mime_type.reset( + new std::string(*entry_it->second->metadata->mime_type)); + } + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL && + entry_it->second->metadata->thumbnail.get()) { + metadata->thumbnail.reset( + new std::string(*entry_it->second->metadata->thumbnail)); + } return PostAbortableTask( base::Bind(callback, base::Passed(&metadata), base::File::FILE_OK)); @@ -136,9 +152,9 @@ if (file_path == directory_path || directory_path.IsParent(file_path)) { const EntryMetadata* const metadata = it->second->metadata.get(); entry_list.push_back(storage::DirectoryEntry( - metadata->name, metadata->is_directory - ? storage::DirectoryEntry::DIRECTORY - : storage::DirectoryEntry::FILE)); + *metadata->name, *metadata->is_directory + ? storage::DirectoryEntry::DIRECTORY + : storage::DirectoryEntry::FILE)); } } @@ -209,7 +225,7 @@ int current_length = length; // Reading behind EOF is fine, it will just return 0 bytes. - if (current_offset >= entry_it->second->metadata->size || !current_length) { + if (current_offset >= *entry_it->second->metadata->size || !current_length) { return PostAbortableTask(base::Bind(callback, 0 /* chunk_length */, false /* has_more */, @@ -218,10 +234,10 @@ const FakeEntry* const entry = entry_it->second.get(); std::vector<int> task_ids; - while (current_offset < entry->metadata->size && current_length) { + while (current_offset < *entry->metadata->size && current_length) { buffer->data()[current_offset - offset] = entry->contents[current_offset]; const bool has_more = - (current_offset + 1 < entry->metadata->size) && (current_length - 1); + (current_offset + 1 < *entry->metadata->size) && (current_length - 1); const int task_id = tracker_.PostTask(base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE, base::Bind(callback, 1 /* chunk_length */, has_more, @@ -308,15 +324,15 @@ } FakeEntry* const entry = entry_it->second.get(); - if (offset > entry->metadata->size) { + if (offset > *entry->metadata->size) { return PostAbortableTask( base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION)); } // Allocate the string size in advance. - if (offset + length > entry->metadata->size) { - entry->metadata->size = offset + length; - entry->contents.resize(entry->metadata->size); + if (offset + length > *entry->metadata->size) { + *entry->metadata->size = offset + length; + entry->contents.resize(*entry->metadata->size); } entry->contents.replace(offset, length, buffer->data(), length);
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc index ce5a231..9af8931 100644 --- a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc +++ b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc
@@ -110,9 +110,9 @@ abort_callback_ = file_system_->GetMetadata( file_path_, - ProvidedFileSystemInterface::METADATA_FIELD_DEFAULT, - base::Bind(&OperationRunner::OnGetMetadataCompletedOnUIThread, - this, + ProvidedFileSystemInterface::METADATA_FIELD_SIZE | + ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME, + base::Bind(&OperationRunner::OnGetMetadataCompletedOnUIThread, this, callback)); } @@ -286,7 +286,7 @@ // may be changed without affecting the modification time. DCHECK(metadata.get()); if (!expected_modification_time_.is_null() && - metadata->modification_time != expected_modification_time_) { + *metadata->modification_time != expected_modification_time_) { state_ = FAILED; error_callback.Run(net::ERR_UPLOAD_FILE_CHANGED); return; @@ -466,13 +466,13 @@ // may be changed without affecting the modification time. DCHECK(metadata.get()); if (!expected_modification_time_.is_null() && - metadata->modification_time != expected_modification_time_) { + *metadata->modification_time != expected_modification_time_) { callback.Run(net::ERR_UPLOAD_FILE_CHANGED); return; } DCHECK_EQ(base::File::FILE_OK, result); - callback.Run(metadata->size); + callback.Run(*metadata->size); } } // namespace file_system_provider
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc index 2213239..d9db120d 100644 --- a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc +++ b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc
@@ -125,23 +125,22 @@ EventLogger logger; const int64 initial_offset = 0; - FileStreamReader reader( - NULL, file_url_, initial_offset, fake_file_->metadata->modification_time); + FileStreamReader reader(NULL, file_url_, initial_offset, + *fake_file_->metadata->modification_time); scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer( - base::CheckedNumeric<size_t>(fake_file_->metadata->size).ValueOrDie())); + base::CheckedNumeric<size_t>(*fake_file_->metadata->size).ValueOrDie())); const int result = - reader.Read(io_buffer.get(), - fake_file_->metadata->size, + reader.Read(io_buffer.get(), *fake_file_->metadata->size, base::Bind(&EventLogger::OnRead, logger.GetWeakPtr())); EXPECT_EQ(net::ERR_IO_PENDING, result); base::RunLoop().RunUntilIdle(); ASSERT_EQ(1u, logger.results().size()); EXPECT_LT(0, logger.results()[0]); - EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]); + EXPECT_EQ(*fake_file_->metadata->size, logger.results()[0]); - std::string buffer_as_string(io_buffer->data(), fake_file_->metadata->size); + std::string buffer_as_string(io_buffer->data(), *fake_file_->metadata->size); EXPECT_EQ(fake_file_->contents, buffer_as_string); } @@ -149,16 +148,13 @@ EventLogger logger; const int64 initial_offset = 0; - FileStreamReader reader(NULL, - wrong_file_url_, - initial_offset, - fake_file_->metadata->modification_time); + FileStreamReader reader(NULL, wrong_file_url_, initial_offset, + *fake_file_->metadata->modification_time); scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer( - base::CheckedNumeric<size_t>(fake_file_->metadata->size).ValueOrDie())); + base::CheckedNumeric<size_t>(*fake_file_->metadata->size).ValueOrDie())); const int result = - reader.Read(io_buffer.get(), - fake_file_->metadata->size, + reader.Read(io_buffer.get(), *fake_file_->metadata->size, base::Bind(&EventLogger::OnRead, logger.GetWeakPtr())); EXPECT_EQ(net::ERR_IO_PENDING, result); base::RunLoop().RunUntilIdle(); @@ -171,10 +167,10 @@ EventLogger logger; const int64 initial_offset = 0; - FileStreamReader reader( - NULL, file_url_, initial_offset, fake_file_->metadata->modification_time); + FileStreamReader reader(NULL, file_url_, initial_offset, + *fake_file_->metadata->modification_time); - for (int64 offset = 0; offset < fake_file_->metadata->size; ++offset) { + for (int64 offset = 0; offset < *fake_file_->metadata->size; ++offset) { scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(1)); const int result = reader.Read(io_buffer.get(), @@ -193,12 +189,12 @@ // Trim first 3 and last 3 characters. const int64 initial_offset = 3; - const int length = fake_file_->metadata->size - initial_offset - 3; - ASSERT_GT(fake_file_->metadata->size, initial_offset); + const int length = *fake_file_->metadata->size - initial_offset - 3; + ASSERT_GT(*fake_file_->metadata->size, initial_offset); ASSERT_LT(0, length); - FileStreamReader reader( - NULL, file_url_, initial_offset, fake_file_->metadata->modification_time); + FileStreamReader reader(NULL, file_url_, initial_offset, + *fake_file_->metadata->modification_time); scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length)); const int result = @@ -222,10 +218,10 @@ // Request reading 1KB more than available. const int64 initial_offset = 0; - const int length = fake_file_->metadata->size + 1024; + const int length = *fake_file_->metadata->size + 1024; - FileStreamReader reader( - NULL, file_url_, initial_offset, fake_file_->metadata->modification_time); + FileStreamReader reader(NULL, file_url_, initial_offset, + *fake_file_->metadata->modification_time); scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(length)); const int result = @@ -237,9 +233,9 @@ ASSERT_EQ(1u, logger.results().size()); EXPECT_LT(0, logger.results()[0]); - EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]); + EXPECT_EQ(*fake_file_->metadata->size, logger.results()[0]); - std::string buffer_as_string(io_buffer->data(), fake_file_->metadata->size); + std::string buffer_as_string(io_buffer->data(), *fake_file_->metadata->size); EXPECT_EQ(fake_file_->contents, buffer_as_string); } @@ -250,10 +246,9 @@ FileStreamReader reader(NULL, file_url_, initial_offset, base::Time::Max()); scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer( - base::CheckedNumeric<size_t>(fake_file_->metadata->size).ValueOrDie())); + base::CheckedNumeric<size_t>(*fake_file_->metadata->size).ValueOrDie())); const int result = - reader.Read(io_buffer.get(), - fake_file_->metadata->size, + reader.Read(io_buffer.get(), *fake_file_->metadata->size, base::Bind(&EventLogger::OnRead, logger.GetWeakPtr())); EXPECT_EQ(net::ERR_IO_PENDING, result); @@ -270,19 +265,18 @@ FileStreamReader reader(NULL, file_url_, initial_offset, base::Time()); scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer( - base::CheckedNumeric<size_t>(fake_file_->metadata->size).ValueOrDie())); + base::CheckedNumeric<size_t>(*fake_file_->metadata->size).ValueOrDie())); const int result = - reader.Read(io_buffer.get(), - fake_file_->metadata->size, + reader.Read(io_buffer.get(), *fake_file_->metadata->size, base::Bind(&EventLogger::OnRead, logger.GetWeakPtr())); EXPECT_EQ(net::ERR_IO_PENDING, result); base::RunLoop().RunUntilIdle(); ASSERT_EQ(1u, logger.results().size()); - EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]); + EXPECT_EQ(*fake_file_->metadata->size, logger.results()[0]); - std::string buffer_as_string(io_buffer->data(), fake_file_->metadata->size); + std::string buffer_as_string(io_buffer->data(), *fake_file_->metadata->size); EXPECT_EQ(fake_file_->contents, buffer_as_string); } @@ -290,8 +284,8 @@ EventLogger logger; const int64 initial_offset = 0; - FileStreamReader reader( - NULL, file_url_, initial_offset, fake_file_->metadata->modification_time); + FileStreamReader reader(NULL, file_url_, initial_offset, + *fake_file_->metadata->modification_time); const int result = reader.GetLength( base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr())); @@ -300,17 +294,15 @@ ASSERT_EQ(1u, logger.results().size()); EXPECT_LT(0, logger.results()[0]); - EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]); + EXPECT_EQ(*fake_file_->metadata->size, logger.results()[0]); } TEST_F(FileSystemProviderFileStreamReader, GetLength_WrongFile) { EventLogger logger; const int64 initial_offset = 0; - FileStreamReader reader(NULL, - wrong_file_url_, - initial_offset, - fake_file_->metadata->modification_time); + FileStreamReader reader(NULL, wrong_file_url_, initial_offset, + *fake_file_->metadata->modification_time); const int result = reader.GetLength( base::Bind(&EventLogger::OnGetLength, logger.GetWeakPtr())); @@ -350,7 +342,7 @@ ASSERT_EQ(1u, logger.results().size()); EXPECT_LT(0, logger.results()[0]); - EXPECT_EQ(fake_file_->metadata->size, logger.results()[0]); + EXPECT_EQ(*fake_file_->metadata->size, logger.results()[0]); } } // namespace file_system_provider
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer_unittest.cc b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer_unittest.cc index 10df3e7..c05b2526 100644 --- a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer_unittest.cc +++ b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer_unittest.cc
@@ -214,7 +214,7 @@ ASSERT_TRUE(entry); const std::string original_contents = entry->contents; - const int64 initial_offset = entry->metadata->size; + const int64 initial_offset = *entry->metadata->size; ASSERT_LT(0, initial_offset); FileStreamWriter writer(file_url_, initial_offset);
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc index f1ad803f..a79799a 100644 --- a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc +++ b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc
@@ -26,7 +26,7 @@ void GetFileInfoOnUIThread( scoped_ptr<storage::FileSystemOperationContext> context, const storage::FileSystemURL& url, - int /* fields */, + int fields, const ProvidedFileSystemInterface::GetMetadataCallback& callback) { util::FileSystemURLParser parser(url); if (!parser.Parse()) { @@ -35,17 +35,21 @@ return; } - // TODO(mtomasz): Pass fields to FSP extensions so only requested fields are - // returned. - parser.file_system()->GetMetadata( - parser.file_path(), - ProvidedFileSystemInterface::METADATA_FIELD_DEFAULT, - callback); + int fsp_fields = 0; + if (fields & storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY) + fsp_fields |= ProvidedFileSystemInterface::METADATA_FIELD_IS_DIRECTORY; + if (fields & storage::FileSystemOperation::GET_METADATA_FIELD_SIZE) + fsp_fields |= ProvidedFileSystemInterface::METADATA_FIELD_SIZE; + if (fields & storage::FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED) + fsp_fields |= ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME; + + parser.file_system()->GetMetadata(parser.file_path(), fsp_fields, callback); } // Routes the response of GetFileInfo back to the IO thread with a type // conversion. -void OnGetFileInfo(const storage::AsyncFileUtil::GetFileInfoCallback& callback, +void OnGetFileInfo(int fields, + const storage::AsyncFileUtil::GetFileInfoCallback& callback, scoped_ptr<EntryMetadata> metadata, base::File::Error result) { if (result != base::File::FILE_OK) { @@ -58,14 +62,20 @@ DCHECK(metadata.get()); base::File::Info file_info; - // TODO(mtomasz): Add support for last modified time and creation time. - // See: crbug.com/388540. - file_info.size = metadata->size; - file_info.is_directory = metadata->is_directory; + if (fields & storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY) + file_info.is_directory = *metadata->is_directory; + if (fields & storage::FileSystemOperation::GET_METADATA_FIELD_SIZE) + file_info.size = *metadata->size; + + if (fields & storage::FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED) { + file_info.last_modified = *metadata->modification_time; + // TODO(mtomasz): Add support for last modified time and creation time. + // See: crbug.com/388540. + file_info.last_accessed = *metadata->modification_time; // Not supported. + file_info.creation_time = *metadata->modification_time; // Not supported. + } + file_info.is_symbolic_link = false; // Not supported. - file_info.last_modified = metadata->modification_time; - file_info.last_accessed = metadata->modification_time; // Not supported. - file_info.creation_time = metadata->modification_time; // Not supported. BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, @@ -326,7 +336,7 @@ BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&GetFileInfoOnUIThread, base::Passed(&context), url, fields, - base::Bind(&OnGetFileInfo, callback))); + base::Bind(&OnGetFileInfo, fields, callback))); } void ProviderAsyncFileUtil::ReadDirectory(
diff --git a/chrome/browser/chromeos/file_system_provider/operations/get_metadata.cc b/chrome/browser/chromeos/file_system_provider/operations/get_metadata.cc index 0cc8389..9bbefe1 100644 --- a/chrome/browser/chromeos/file_system_provider/operations/get_metadata.cc +++ b/chrome/browser/chromeos/file_system_provider/operations/get_metadata.cc
@@ -17,6 +17,7 @@ // Convert |value| into |output|. If parsing fails, then returns false. bool ConvertRequestValueToFileInfo(scoped_ptr<RequestValue> value, + int fields, bool root_entry, EntryMetadata* output) { using extensions::api::file_system_provider::EntryMetadata; @@ -27,29 +28,40 @@ if (!params) return false; - if (!ValidateIDLEntryMetadata(params->metadata, root_entry)) + if (!ValidateIDLEntryMetadata(params->metadata, fields, root_entry)) return false; - output->name = params->metadata.name; - output->is_directory = params->metadata.is_directory; - output->size = static_cast<int64>(*params->metadata.size); + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_NAME) + output->name.reset(new std::string(*params->metadata.name)); - std::string input_modification_time; - if (!params->metadata.modification_time->additional_properties.GetString( - "value", &input_modification_time)) { - NOTREACHED(); + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_IS_DIRECTORY) + output->is_directory.reset(new bool(*params->metadata.is_directory)); + + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_SIZE) + output->size.reset(new int64(static_cast<int64>(*params->metadata.size))); + + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME) { + std::string input_modification_time; + params->metadata.modification_time->additional_properties.GetString( + "value", &input_modification_time); + + // Allow to pass invalid modification time, since there is no way to verify + // it easily on any earlier stage. + base::Time output_modification_time; + base::Time::FromString(input_modification_time.c_str(), + &output_modification_time); + output->modification_time.reset(new base::Time(output_modification_time)); } - // Allow to pass invalid modification time, since there is no way to verify - // it easily on any earlier stage. - base::Time::FromString(input_modification_time.c_str(), - &output->modification_time); + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_MIME_TYPE && + params->metadata.mime_type.get()) { + output->mime_type.reset(new std::string(*params->metadata.mime_type.get())); + } - if (params->metadata.mime_type.get()) - output->mime_type = *params->metadata.mime_type.get(); - - if (params->metadata.thumbnail.get()) - output->thumbnail = *params->metadata.thumbnail.get(); + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL && + params->metadata.thumbnail.get()) { + output->thumbnail.reset(new std::string(*params->metadata.thumbnail.get())); + } return true; } @@ -58,23 +70,43 @@ bool ValidateIDLEntryMetadata( const extensions::api::file_system_provider::EntryMetadata& metadata, + int fields, bool root_entry) { using extensions::api::file_system_provider::EntryMetadata; - if (!ValidateName(metadata.name, root_entry)) - return false; - - std::string input_modification_time; - if (metadata.modification_time.get() && - !metadata.modification_time->additional_properties.GetString( - "value", &input_modification_time)) { + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_IS_DIRECTORY && + !metadata.is_directory.get()) { return false; } - if (metadata.thumbnail.get()) { - // Sanity check for the thumbnail format. Note, that another, more granural - // check is done in custom bindings. Note, this is an extra check only for - // the security reasons. + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_NAME && + (!metadata.name.get() || !ValidateName(*metadata.name, root_entry))) { + return false; + } + + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_SIZE && + !metadata.size.get()) { + return false; + } + + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME) { + if (!metadata.modification_time) + return false; + std::string input_modification_time; + if (!metadata.modification_time->additional_properties.GetString( + "value", &input_modification_time)) { + return false; + } + } + + // Empty MIME type is not allowed, but for backward compability it's + // accepted. Note, that there is a warning in custom bindings for it. + + if (fields & ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL && + metadata.thumbnail.get()) { + // Sanity check for the thumbnail format. Note, that another, more + // granural check is done in custom bindings. Note, this is an extra check + // only for the security reasons. const std::string expected_prefix = "data:"; std::string thumbnail_prefix = metadata.thumbnail.get()->substr(0, expected_prefix.size()); @@ -118,6 +150,14 @@ options.file_system_id = file_system_info_.file_system_id(); options.request_id = request_id; options.entry_path = entry_path_.AsUTF8Unsafe(); + options.is_directory = + fields_ & ProvidedFileSystemInterface::METADATA_FIELD_IS_DIRECTORY; + options.name = fields_ & ProvidedFileSystemInterface::METADATA_FIELD_NAME; + options.size = fields_ & ProvidedFileSystemInterface::METADATA_FIELD_SIZE; + options.modification_time = + fields_ & ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME; + options.mime_type = + fields_ & ProvidedFileSystemInterface::METADATA_FIELD_MIME_TYPE; options.thumbnail = fields_ & ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL; @@ -134,8 +174,8 @@ bool has_more) { scoped_ptr<EntryMetadata> metadata(new EntryMetadata); const bool convert_result = ConvertRequestValueToFileInfo( - result.Pass(), entry_path_.AsUTF8Unsafe() == FILE_PATH_LITERAL("/"), - metadata.get()); + result.Pass(), fields_, + entry_path_.AsUTF8Unsafe() == FILE_PATH_LITERAL("/"), metadata.get()); if (!convert_result) { LOG(ERROR) << "Failed to parse a response for the get metadata operation."; @@ -152,6 +192,7 @@ base::File::Error error) { callback_.Run(make_scoped_ptr<EntryMetadata>(NULL), error); } + } // namespace operations } // namespace file_system_provider } // namespace chromeos
diff --git a/chrome/browser/chromeos/file_system_provider/operations/get_metadata.h b/chrome/browser/chromeos/file_system_provider/operations/get_metadata.h index 06252d4..cfb8e87 100644 --- a/chrome/browser/chromeos/file_system_provider/operations/get_metadata.h +++ b/chrome/browser/chromeos/file_system_provider/operations/get_metadata.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OPERATIONS_GET_METADATA_H_ #define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OPERATIONS_GET_METADATA_H_ +#include <string> + #include "base/files/file.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/chromeos/file_system_provider/operations/operation.h" @@ -29,6 +31,7 @@ // name or empty for non-root), then returns false. bool ValidateIDLEntryMetadata( const extensions::api::file_system_provider::EntryMetadata& metadata, + int fields, bool root_entry); // Checks whether the passed name is valid or not.
diff --git a/chrome/browser/chromeos/file_system_provider/operations/get_metadata_unittest.cc b/chrome/browser/chromeos/file_system_provider/operations/get_metadata_unittest.cc index 59ec1aa..8f89f59 100644 --- a/chrome/browser/chromeos/file_system_provider/operations/get_metadata_unittest.cc +++ b/chrome/browser/chromeos/file_system_provider/operations/get_metadata_unittest.cc
@@ -129,73 +129,91 @@ // Correct metadata for non-root. { EntryMetadata metadata; - metadata.name = kValidFileName; + metadata.name.reset(new std::string(kValidFileName)); metadata.modification_time.reset(new ModificationTime()); metadata.modification_time->additional_properties.SetString( "value", "invalid-date-time"); // Invalid modification time is OK. metadata.thumbnail.reset(new std::string(kValidThumbnailUrl)); - EXPECT_TRUE(ValidateIDLEntryMetadata(metadata, false /* root_path */)); + EXPECT_TRUE(ValidateIDLEntryMetadata( + metadata, + ProvidedFileSystemInterface::METADATA_FIELD_NAME | + ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME | + ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, + false /* root_path */)); } // Correct metadata for non-root (without thumbnail). { EntryMetadata metadata; - metadata.name = kValidFileName; + metadata.name.reset(new std::string(kValidFileName)); metadata.modification_time.reset(new ModificationTime()); metadata.modification_time->additional_properties.SetString( "value", "invalid-date-time"); // Invalid modification time is OK. - EXPECT_TRUE(ValidateIDLEntryMetadata(metadata, false /* root_path */)); + EXPECT_TRUE(ValidateIDLEntryMetadata( + metadata, + ProvidedFileSystemInterface::METADATA_FIELD_NAME | + ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME | + ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, + false /* root_path */)); } // Correct metadata for root. { EntryMetadata metadata; - metadata.name = ""; + metadata.name.reset(new std::string()); metadata.modification_time.reset(new ModificationTime()); metadata.modification_time->additional_properties.SetString( "value", "invalid-date-time"); // Invalid modification time is OK. - EXPECT_TRUE(ValidateIDLEntryMetadata(metadata, true /* root_path */)); + EXPECT_TRUE(ValidateIDLEntryMetadata( + metadata, + ProvidedFileSystemInterface::METADATA_FIELD_NAME | + ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME | + ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, + true /* root_path */)); } // Invalid characters in the name. { EntryMetadata metadata; - metadata.name = "hello/world"; - metadata.modification_time.reset(new ModificationTime()); - metadata.modification_time->additional_properties.SetString( - "value", "invalid-date-time"); // Invalid modification time is OK. - metadata.thumbnail.reset(new std::string(kValidThumbnailUrl)); - EXPECT_FALSE(ValidateIDLEntryMetadata(metadata, false /* root_path */)); + metadata.name.reset(new std::string("hello/world")); + EXPECT_FALSE(ValidateIDLEntryMetadata( + metadata, ProvidedFileSystemInterface::METADATA_FIELD_NAME, + false /* root_path */)); } // Empty name for non-root. { EntryMetadata metadata; - metadata.name = ""; - metadata.modification_time.reset(new ModificationTime()); - metadata.modification_time->additional_properties.SetString( - "value", "invalid-date-time"); // Invalid modification time is OK. - metadata.thumbnail.reset(new std::string(kValidThumbnailUrl)); - EXPECT_FALSE(ValidateIDLEntryMetadata(metadata, false /* root_path */)); + metadata.name.reset(new std::string()); + EXPECT_FALSE(ValidateIDLEntryMetadata( + metadata, ProvidedFileSystemInterface::METADATA_FIELD_NAME, + false /* root_path */)); } - // Missing last modification time is allowed. + // Missing last modification time. { EntryMetadata metadata; - metadata.name = kValidFileName; - metadata.thumbnail.reset(new std::string(kValidThumbnailUrl)); - EXPECT_TRUE(ValidateIDLEntryMetadata(metadata, false /* root_path */)); + EXPECT_FALSE(ValidateIDLEntryMetadata( + metadata, ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME, + false /* root_path */)); } // Invalid thumbnail. { EntryMetadata metadata; - metadata.name = kValidFileName; - metadata.modification_time.reset(new ModificationTime()); - metadata.modification_time->additional_properties.SetString( - "value", "invalid-date-time"); // Invalid modification time is OK. metadata.thumbnail.reset(new std::string("http://invalid-scheme")); - EXPECT_FALSE(ValidateIDLEntryMetadata(metadata, false /* root_path */)); + EXPECT_FALSE(ValidateIDLEntryMetadata( + metadata, ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, + false /* root_path */)); + } + + // Empty string for thumbnail. + { + EntryMetadata metadata; + metadata.thumbnail.reset(new std::string()); + EXPECT_FALSE(ValidateIDLEntryMetadata( + metadata, ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, + false /* root_path */)); } } @@ -258,7 +276,12 @@ GetMetadata get_metadata( NULL, file_system_info_, base::FilePath(kDirectoryPath), - ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, + ProvidedFileSystemInterface::METADATA_FIELD_IS_DIRECTORY | + ProvidedFileSystemInterface::METADATA_FIELD_NAME | + ProvidedFileSystemInterface::METADATA_FIELD_SIZE | + ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME | + ProvidedFileSystemInterface::METADATA_FIELD_MIME_TYPE | + ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, base::Bind(&CallbackLogger::OnGetMetadata, base::Unretained(&callback_logger))); get_metadata.SetDispatchEventImplForTesting( @@ -297,14 +320,14 @@ EXPECT_EQ(base::File::FILE_OK, event->result()); const EntryMetadata* metadata = event->metadata(); - EXPECT_FALSE(metadata->is_directory); - EXPECT_EQ(4096, metadata->size); + EXPECT_FALSE(*metadata->is_directory); + EXPECT_EQ(4096, *metadata->size); base::Time expected_time; EXPECT_TRUE( base::Time::FromString("Thu Apr 24 00:46:52 UTC 2014", &expected_time)); - EXPECT_EQ(expected_time, metadata->modification_time); - EXPECT_EQ(kMimeType, metadata->mime_type); - EXPECT_EQ(kThumbnail, metadata->thumbnail); + EXPECT_EQ(expected_time, *metadata->modification_time); + EXPECT_EQ(kMimeType, *metadata->mime_type); + EXPECT_EQ(kThumbnail, *metadata->thumbnail); } TEST_F(FileSystemProviderOperationsGetMetadataTest, OnSuccess_InvalidMetadata) { @@ -313,7 +336,12 @@ GetMetadata get_metadata( NULL, file_system_info_, base::FilePath(kDirectoryPath), - ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, + ProvidedFileSystemInterface::METADATA_FIELD_IS_DIRECTORY | + ProvidedFileSystemInterface::METADATA_FIELD_NAME | + ProvidedFileSystemInterface::METADATA_FIELD_SIZE | + ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME | + ProvidedFileSystemInterface::METADATA_FIELD_MIME_TYPE | + ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL, base::Bind(&CallbackLogger::OnGetMetadata, base::Unretained(&callback_logger))); get_metadata.SetDispatchEventImplForTesting(
diff --git a/chrome/browser/chromeos/file_system_provider/operations/read_directory.cc b/chrome/browser/chromeos/file_system_provider/operations/read_directory.cc index 72ec917..2f77ff7 100644 --- a/chrome/browser/chromeos/file_system_provider/operations/read_directory.cc +++ b/chrome/browser/chromeos/file_system_provider/operations/read_directory.cc
@@ -29,12 +29,17 @@ for (size_t i = 0; i < params->entries.size(); ++i) { const linked_ptr<EntryMetadata> entry_metadata = params->entries[i]; - if (!ValidateIDLEntryMetadata(*entry_metadata, false /* root_entry */)) + if (!ValidateIDLEntryMetadata( + *entry_metadata, + ProvidedFileSystemInterface::METADATA_FIELD_IS_DIRECTORY | + ProvidedFileSystemInterface::METADATA_FIELD_NAME, + false /* root_entry */)) { return false; + } storage::DirectoryEntry output_entry; - output_entry.is_directory = entry_metadata->is_directory; - output_entry.name = entry_metadata->name; + output_entry.is_directory = *entry_metadata->is_directory; + output_entry.name = *entry_metadata->name; output->push_back(output_entry); } @@ -65,6 +70,10 @@ options.request_id = request_id; options.directory_path = directory_path_.AsUTF8Unsafe(); + // Request only is_directory and name metadata fields. + options.is_directory = true; + options.name = true; + return SendEvent( request_id, extensions::events::FILE_SYSTEM_PROVIDER_ON_READ_DIRECTORY_REQUESTED,
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.cc index f91d8d8e..4f0fca9 100644 --- a/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.cc +++ b/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.cc
@@ -7,15 +7,13 @@ namespace chromeos { namespace file_system_provider { -EntryMetadata::EntryMetadata() : is_directory(false), size(0) { -} +EntryMetadata::EntryMetadata() {} EntryMetadata::~EntryMetadata() { } -OpenedFile::OpenedFile(const base::FilePath& file_path, OpenFileMode& mode) - : file_path(file_path), mode(mode) { -} +OpenedFile::OpenedFile(const base::FilePath& file_path, OpenFileMode mode) + : file_path(file_path), mode(mode) {} OpenedFile::OpenedFile() : mode(OPEN_FILE_MODE_READ) { }
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h b/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h index a611b9a..acb6ace 100644 --- a/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h +++ b/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_PROVIDED_FILE_SYSTEM_INTERFACE_H_ #define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_PROVIDED_FILE_SYSTEM_INTERFACE_H_ +#include <map> #include <string> #include <vector> @@ -40,12 +41,14 @@ EntryMetadata(); ~EntryMetadata(); - bool is_directory; - std::string name; - int64 size; - base::Time modification_time; - std::string mime_type; - std::string thumbnail; + // All of the metadata fields are optional. All strings which are set, are + // non-empty. + scoped_ptr<bool> is_directory; + scoped_ptr<std::string> name; + scoped_ptr<int64> size; + scoped_ptr<base::Time> modification_time; + scoped_ptr<std::string> mime_type; + scoped_ptr<std::string> thumbnail; private: DISALLOW_COPY_AND_ASSIGN(EntryMetadata); @@ -64,7 +67,7 @@ // Contains information about an opened file. struct OpenedFile { - OpenedFile(const base::FilePath& file_path, OpenFileMode& mode); + OpenedFile(const base::FilePath& file_path, OpenFileMode mode); OpenedFile(); ~OpenedFile(); @@ -83,10 +86,15 @@ // with either a success or an error. class ProvidedFileSystemInterface { public: - // Extra fields to be fetched with metadata. + // Fields to be fetched with metadata. enum MetadataField { - METADATA_FIELD_DEFAULT = 0, - METADATA_FIELD_THUMBNAIL = 1 << 0 + METADATA_FIELD_NONE = 0, + METADATA_FIELD_IS_DIRECTORY = 1 << 0, + METADATA_FIELD_NAME = 1 << 1, + METADATA_FIELD_SIZE = 1 << 2, + METADATA_FIELD_MODIFICATION_TIME = 1 << 3, + METADATA_FIELD_MIME_TYPE = 1 << 4, + METADATA_FIELD_THUMBNAIL = 1 << 5 }; // Callback for OpenFile(). In case of an error, file_handle is equal to 0
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index 83b988b..627ee4b 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -208,6 +208,7 @@ chromeos::switches::kDbusStub, chromeos::switches::kDbusUnstubClients, chromeos::switches::kDisableLoginAnimations, + chromeos::switches::kEnableArc, chromeos::switches::kEnableConsumerManagement, chromeos::switches::kEnterpriseEnableForcedReEnrollment, chromeos::switches::kHasChromeOSDiamondKey,
diff --git a/chrome/browser/download/download_danger_prompt.cc b/chrome/browser/download/download_danger_prompt.cc index f581e42..b6f0a09 100644 --- a/chrome/browser/download/download_danger_prompt.cc +++ b/chrome/browser/download/download_danger_prompt.cc
@@ -6,19 +6,24 @@ #include "base/bind.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/download/chrome_download_manager_delegate.h" #include "chrome/browser/download/download_stats.h" #include "chrome/browser/extensions/api/experience_sampling_private/experience_sampling.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/ui/tab_modal_confirm_dialog.h" #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h" +#include "chrome/common/safe_browsing/csd.pb.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/download_danger_type.h" #include "content/public/browser/download_item.h" #include "ui/base/l10n/l10n_util.h" using extensions::ExperienceSamplingEvent; +using safe_browsing::ClientSafeBrowsingReportRequest; namespace { @@ -80,10 +85,8 @@ // ExperienceSampling: A malicious download warning is being shown to the // user, so we start a new SamplingEvent and track it. sampling_event_.reset(new ExperienceSamplingEvent( - ExperienceSamplingEvent::kDownloadDangerPrompt, - download->GetURL(), - download->GetReferrerUrl(), - download->GetBrowserContext())); + ExperienceSamplingEvent::kDownloadDangerPrompt, download->GetURL(), + download->GetReferrerUrl(), download->GetBrowserContext())); } DownloadDangerPromptImpl::~DownloadDangerPromptImpl() { @@ -94,8 +97,12 @@ void DownloadDangerPromptImpl::InvokeActionForTesting(Action action) { switch (action) { - case ACCEPT: Accept(); break; - case CANCEL: Cancel(); break; + case ACCEPT: + Accept(); + break; + case CANCEL: + Cancel(); + break; case DISMISS: RunDone(DISMISS); Cancel(); @@ -140,7 +147,7 @@ IDS_PROMPT_DANGEROUS_DOWNLOAD, download_->GetFileNameToReportUser().LossyDisplayName()); } - case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // Fall through + case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // Fall through case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: { return l10n_util::GetStringFUTF16( @@ -170,10 +177,10 @@ case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: { return l10n_util::GetStringUTF16( - IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_LEAD) + - base::ASCIIToUTF16("\n\n") + - l10n_util::GetStringUTF16( - IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_BODY); + IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_LEAD) + + base::ASCIIToUTF16("\n\n") + + l10n_util::GetStringUTF16( + IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_BODY); } default: { return l10n_util::GetStringUTF16( @@ -240,6 +247,11 @@ OnDone done = done_; done_.Reset(); if (download_ != NULL) { + if (!download_->GetURL().is_empty() && + !download_->GetBrowserContext()->IsOffTheRecord()) { + SendSafeBrowsingDownloadRecoveryReport( + action == DownloadDangerPrompt::ACCEPT, download_->GetURL()); + } download_->RemoveObserver(this); download_ = NULL; } @@ -256,10 +268,27 @@ content::WebContents* web_contents, bool show_context, const OnDone& done) { - DownloadDangerPromptImpl* prompt = new DownloadDangerPromptImpl( - item, web_contents, show_context, done); + DownloadDangerPromptImpl* prompt = + new DownloadDangerPromptImpl(item, web_contents, show_context, done); // |prompt| will be deleted when the dialog is done. TabModalConfirmDialog::Create(prompt, web_contents); return prompt; } #endif + +void DownloadDangerPrompt::SendSafeBrowsingDownloadRecoveryReport( + bool did_proceed, + const GURL& url) { + safe_browsing::SafeBrowsingService* sb_service = + g_browser_process->safe_browsing_service(); + ClientSafeBrowsingReportRequest report; + report.set_type(ClientSafeBrowsingReportRequest::MALICIOUS_DOWNLOAD_RECOVERY); + report.set_url(url.spec()); + report.set_did_proceed(did_proceed); + + std::string serialized_report; + if (report.SerializeToString(&serialized_report)) + sb_service->SendDownloadRecoveryReport(serialized_report); + else + DLOG(ERROR) << "Unable to serialize the threat report."; +}
diff --git a/chrome/browser/download/download_danger_prompt.h b/chrome/browser/download/download_danger_prompt.h index e1b5c612..4ca7bd2a 100644 --- a/chrome/browser/download/download_danger_prompt.h +++ b/chrome/browser/download/download_danger_prompt.h
@@ -7,6 +7,8 @@ #include "base/callback_forward.h" +class GURL; + namespace content { class DownloadItem; class WebContents; @@ -37,15 +39,23 @@ // caller does not own the object and receive no guarantees about lifetime. // If |show_context|, then the prompt message will contain some information // about the download and its danger; otherwise it won't. - static DownloadDangerPrompt* Create( - content::DownloadItem* item, - content::WebContents* web_contents, - bool show_context, - const OnDone& done); + static DownloadDangerPrompt* Create(content::DownloadItem* item, + content::WebContents* web_contents, + bool show_context, + const OnDone& done); // Only to be used by tests. Subclasses must override to manually call the // respective button click handler. virtual void InvokeActionForTesting(Action action) = 0; + + protected: + // Sends download recovery report to safe browsing backend. + // Since it only records download url (DownloadItem::GetURL()) and user's + // action (click through or not), it isn't gated by user's extended reporting + // preference (i.e. prefs::kSafeBrowsingExtendedReportingEnabled). We + // should not put any extra information in this report. + static void SendSafeBrowsingDownloadRecoveryReport(bool did_proceed, + const GURL& url); }; #endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_DANGER_PROMPT_H_
diff --git a/chrome/browser/download/download_danger_prompt_browsertest.cc b/chrome/browser/download/download_danger_prompt_browsertest.cc index 2b33e0e7..a0cde01e4 100644 --- a/chrome/browser/download/download_danger_prompt_browsertest.cc +++ b/chrome/browser/download/download_danger_prompt_browsertest.cc
@@ -6,10 +6,13 @@ #include "base/files/file_path.h" #include "chrome/browser/download/download_danger_prompt.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/safe_browsing/database_manager.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/safe_browsing/csd.pb.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/mock_download_item.h" @@ -23,17 +26,71 @@ using ::testing::Return; using ::testing::ReturnRef; using ::testing::SaveArg; +using safe_browsing::ClientSafeBrowsingReportRequest; +using safe_browsing::SafeBrowsingService; + +const char kTestDownloadUrl[] = "http://evildownload.com"; + +class FakeSafeBrowsingService : public SafeBrowsingService { + public: + FakeSafeBrowsingService() {} + + void SendDownloadRecoveryReport(const std::string& report) override { + report_ = report; + } + + std::string GetDownloadRecoveryReport() const { return report_; } + + protected: + ~FakeSafeBrowsingService() override {} + + private: + std::string report_; +}; + +// Factory that creates FakeSafeBrowsingService instances. +class TestSafeBrowsingServiceFactory + : public safe_browsing::SafeBrowsingServiceFactory { + public: + TestSafeBrowsingServiceFactory() : fake_safe_browsing_service_(nullptr) {} + ~TestSafeBrowsingServiceFactory() override {} + + SafeBrowsingService* CreateSafeBrowsingService() override { + if (!fake_safe_browsing_service_) { + fake_safe_browsing_service_ = new FakeSafeBrowsingService(); + } + return fake_safe_browsing_service_.get(); + } + + scoped_refptr<FakeSafeBrowsingService> fake_safe_browsing_service() { + return fake_safe_browsing_service_; + } + + private: + scoped_refptr<FakeSafeBrowsingService> fake_safe_browsing_service_; +}; class DownloadDangerPromptTest : public InProcessBrowserTest { public: DownloadDangerPromptTest() - : prompt_(NULL), - expected_action_(DownloadDangerPrompt::CANCEL), - did_receive_callback_(false) { - } + : prompt_(nullptr), + expected_action_(DownloadDangerPrompt::CANCEL), + did_receive_callback_(false), + test_safe_browsing_factory_(new TestSafeBrowsingServiceFactory()), + report_sent_(false) {} ~DownloadDangerPromptTest() override {} + void SetUp() override { + SafeBrowsingService::RegisterFactory(test_safe_browsing_factory_.get()); + InProcessBrowserTest::SetUp(); + } + + void TearDown() override { + SafeBrowsingService::RegisterFactory(nullptr); + InProcessBrowserTest::TearDown(); + } + // Opens a new tab and waits for navigations to finish. If there are pending // navigations, the constrained prompt might be dismissed when the navigation // completes. @@ -49,7 +106,10 @@ did_receive_callback_ = false; expected_action_ = expected_action; SetUpDownloadItemExpectations(); + SetUpSafeBrowsingReportExpectations(expected_action == + DownloadDangerPrompt::ACCEPT); CreatePrompt(); + report_sent_ = false; } void VerifyExpectations() { @@ -59,10 +119,16 @@ EXPECT_TRUE(did_receive_callback_); EXPECT_FALSE(prompt_); testing::Mock::VerifyAndClearExpectations(&download_); + if (report_sent_) { + EXPECT_EQ(expected_serialized_report_, + test_safe_browsing_factory_->fake_safe_browsing_service() + ->GetDownloadRecoveryReport()); + } } void SimulatePromptAction(DownloadDangerPrompt::Action action) { prompt_->InvokeActionForTesting(action); + report_sent_ = true; } content::MockDownloadItem& download() { return download_; } @@ -77,6 +143,15 @@ .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)); } + void SetUpSafeBrowsingReportExpectations(bool did_proceed) { + ClientSafeBrowsingReportRequest expected_report; + expected_report.set_url(GURL(kTestDownloadUrl).spec()); + expected_report.set_type( + ClientSafeBrowsingReportRequest::MALICIOUS_DOWNLOAD_RECOVERY); + expected_report.set_did_proceed(did_proceed); + expected_report.SerializeToString(&expected_serialized_report_); + } + void CreatePrompt() { prompt_ = DownloadDangerPrompt::Create( &download_, @@ -90,13 +165,16 @@ EXPECT_FALSE(did_receive_callback_); EXPECT_EQ(expected_action_, action); did_receive_callback_ = true; - prompt_ = NULL; + prompt_ = nullptr; } content::MockDownloadItem download_; DownloadDangerPrompt* prompt_; DownloadDangerPrompt::Action expected_action_; bool did_receive_callback_; + scoped_ptr<TestSafeBrowsingServiceFactory> test_safe_browsing_factory_; + std::string expected_serialized_report_; + bool report_sent_; DISALLOW_COPY_AND_ASSIGN(DownloadDangerPromptTest); }; @@ -109,7 +187,8 @@ #endif IN_PROC_BROWSER_TEST_F(DownloadDangerPromptTest, MAYBE_TestAll) { // ExperienceSampling: Set default actions for DownloadItem methods we need. - ON_CALL(download(), GetURL()).WillByDefault(ReturnRef(GURL::EmptyGURL())); + GURL download_url(kTestDownloadUrl); + ON_CALL(download(), GetURL()).WillByDefault(ReturnRef(download_url)); ON_CALL(download(), GetReferrerUrl()) .WillByDefault(ReturnRef(GURL::EmptyGURL())); ON_CALL(download(), GetBrowserContext())
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc index c263ce7..21aeda0b 100644 --- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -518,21 +518,16 @@ content_type, true /* overwrite */); } - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader( - &(bytes_1[0]), bytes_1.size())); - element_readers.push_back( - new net::UploadFileElementReader( - base::ThreadTaskRunnerHandle::Get() - .get(), - base::FilePath(), - 0, - 0, - base::Time())); - element_readers.push_back( - new net::UploadBytesElementReader(&(bytes_2[0]), bytes_2.size())); + std::vector<scoped_ptr<net::UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr( + new net::UploadBytesElementReader(&(bytes_1[0]), bytes_1.size()))); + element_readers.push_back(make_scoped_ptr(new net::UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), base::FilePath(), 0, 0, + base::Time()))); + element_readers.push_back(make_scoped_ptr( + new net::UploadBytesElementReader(&(bytes_2[0]), bytes_2.size()))); request->set_upload(make_scoped_ptr( - new net::ElementsUploadDataStream(element_readers.Pass(), 0))); + new net::ElementsUploadDataStream(std::move(element_readers), 0))); ipc_sender_.PushTask(base::Bind(&base::DoNothing)); request->Start(); }
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 1e4a738..56a5178e 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -27,6 +27,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/features.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/crx_file/id_util.h" @@ -382,7 +383,7 @@ } void ComponentLoader::AddGoogleNowExtension() { -#if defined(ENABLE_GOOGLE_NOW) +#if BUILDFLAG(ENABLE_GOOGLE_NOW) const char kEnablePrefix[] = "Enable"; const char kFieldTrialName[] = "GoogleNow"; std::string enable_prefix(kEnablePrefix); @@ -418,7 +419,7 @@ } else { DeleteData(google_now_manifest_id, root_directory); } -#endif // defined(ENABLE_GOOGLE_NOW) +#endif // BUILDFLAG(ENABLE_GOOGLE_NOW) } #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/policy/cloud/test_request_interceptor.cc b/chrome/browser/policy/cloud/test_request_interceptor.cc index 9f3a516..458fc06 100644 --- a/chrome/browser/policy/cloud/test_request_interceptor.cc +++ b/chrome/browser/policy/cloud/test_request_interceptor.cc
@@ -83,7 +83,7 @@ const net::UploadDataStream* stream = request->get_upload(); if (!stream) return false; - const ScopedVector<net::UploadElementReader>* readers = + const std::vector<scoped_ptr<net::UploadElementReader>>* readers = stream->GetElementReaders(); if (!readers || readers->size() != 1u) return false;
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index 04d5e9f3..8566442 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/common/features.h" #include "chrome/common/pref_names.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" @@ -98,7 +99,7 @@ registry->RegisterDictionaryPref(prefs::kSafeBrowsingIncidentsSent); registry->RegisterBooleanPref( prefs::kSafeBrowsingExtendedReportingOptInAllowed, true); -#if defined(ENABLE_GOOGLE_NOW) +#if BUILDFLAG(ENABLE_GOOGLE_NOW) registry->RegisterBooleanPref(prefs::kGoogleGeolocationAccessEnabled, false); #endif // This pref is intentionally outside the above #if. That flag corresponds
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index a5949a21..14de709 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -2,10 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//chrome/common/features.gni") import("//tools/grit/grit_rule.gni") grit("memory_internals_resources") { source = "memory_internals_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/memory_internals_resources.h", "memory_internals_resources.pak", @@ -15,6 +17,7 @@ grit("net_internals_resources") { source = "net_internals_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/net_internals_resources.h", "net_internals_resources.pak", @@ -24,6 +27,7 @@ grit("invalidations_resources") { source = "invalidations_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/invalidations_resources.h", "invalidations_resources.pak", @@ -33,6 +37,7 @@ grit("password_manager_internals_resources") { source = "password_manager_internals_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/password_manager_internals_resources.h", "password_manager_internals_resources.pak", @@ -42,6 +47,7 @@ grit("signin_internals_resources") { source = "signin_internals_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/signin_internals_resources.h", "signin_internals_resources.pak", @@ -51,6 +57,7 @@ grit("translate_internals_resources") { source = "translate_internals_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/translate_internals_resources.h", "translate_internals_resources.pak", @@ -71,6 +78,7 @@ if (!is_ios) { grit("component_extension_resources") { source = "component_extension_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/component_extension_resources.h", "grit/component_extension_resources_map.cc", @@ -82,6 +90,7 @@ grit("settings_resources") { source = "settings/settings_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/settings_resources.h", "grit/settings_resources_map.cc", @@ -93,6 +102,7 @@ grit("options_resources") { source = "options_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/options_resources.h", "options_resources.pak", @@ -102,6 +112,7 @@ grit("options_test_resources") { source = "options_test_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/options_test_resources.h", "options_test_resources.pak", @@ -111,6 +122,7 @@ grit("quota_internals_resources") { source = "quota_internals_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/quota_internals_resources.h", "quota_internals_resources.pak", @@ -120,6 +132,7 @@ grit("sync_file_system_internals_resources") { source = "sync_file_system_internals_resources.grd" + defines = chrome_grit_defines outputs = [ "grit/sync_file_system_internals_resources.h", "sync_file_system_internals_resources.pak",
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index 84328d5..0f32155b 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -645,4 +645,20 @@ #endif } +void SafeBrowsingService::SendDownloadRecoveryReport( + const std::string& report) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&SafeBrowsingService::OnSendDownloadRecoveryReport, this, + report)); +} + +void SafeBrowsingService::OnSendDownloadRecoveryReport( + const std::string& report) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (ping_manager()) + ping_manager()->ReportThreatDetails(report); +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h index 00b13e1..8ab58313 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -165,6 +165,9 @@ scoped_ptr<StateSubscription> RegisterStateCallback( const base::Callback<void(void)>& callback); + // Sends serialized download recovery report to backend. + virtual void SendDownloadRecoveryReport(const std::string& report); + protected: // Creates the safe browsing service. Need to initialize before using. SafeBrowsingService(); @@ -239,6 +242,8 @@ // starts or stops the service accordingly. void RefreshState(); + void OnSendDownloadRecoveryReport(const std::string& report); + // The factory used to instanciate a SafeBrowsingService object. // Useful for tests, so they can provide their own implementation of // SafeBrowsingService.
diff --git a/chrome/browser/sessions/better_session_restore_browsertest.cc b/chrome/browser/sessions/better_session_restore_browsertest.cc index 7b15d5ca6..ff8a81d 100644 --- a/chrome/browser/sessions/better_session_restore_browsertest.cc +++ b/chrome/browser/sessions/better_session_restore_browsertest.cc
@@ -98,7 +98,7 @@ const net::UploadDataStream* upload_data = request->get_upload(); last_upload_bytes_.clear(); if (upload_data) { - const ScopedVector<net::UploadElementReader>* readers = + const std::vector<scoped_ptr<net::UploadElementReader>>* readers = upload_data->GetElementReaders(); if (readers) { for (size_t i = 0; i < readers->size(); ++i) {
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc index af08422..6fbd5947 100644 --- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc +++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -75,6 +75,8 @@ GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction), GURL(google_apis::DriveApiUrlGenerator:: kBaseDownloadUrlForProduction), + GURL(google_apis::DriveApiUrlGenerator:: + kBaseThumbnailUrlForProduction), std::string() /* custom_user_agent */)); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index be6d20f..e8124cc4 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -5,6 +5,7 @@ import("//build/config/crypto.gni") import("//build/config/features.gni") import("//build/config/ui.gni") +import("//chrome/common/features.gni") gypi_values = exec_script("//build/gypi_to_gn.py", [ rebase_path("../../chrome_browser_ui.gypi") ],
diff --git a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm index 26ae628..e8bbc0a 100644 --- a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm
@@ -70,7 +70,6 @@ ManagePasswordsControllerTest::SetUp(); delegate_.reset([[ContentViewDelegateMock alloc] init]); avatar_manager_.reset([[AccountAvatarFetcherTestManager alloc] init]); - ui_controller()->SetState(password_manager::ui::CREDENTIAL_REQUEST_STATE); } ContentViewDelegateMock* delegate() { return delegate_.get(); } @@ -83,7 +82,7 @@ if (!controller_) { controller_.reset( [[ManagePasswordsBubbleAccountChooserViewController alloc] - initWithModel:model() + initWithModel:GetModelAndCreateIfNull() avatarManager:avatar_manager() delegate:delegate()]); [controller_ loadView]; @@ -99,15 +98,11 @@ }; TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, ConfiguresViews) { - ScopedVector<autofill::PasswordForm> local_forms; + ScopedVector<const autofill::PasswordForm> local_forms; local_forms.push_back(Credential("pizza")); - ScopedVector<autofill::PasswordForm> federated_forms; + ScopedVector<const autofill::PasswordForm> federated_forms; federated_forms.push_back(Credential("taco")); - EXPECT_TRUE(ui_controller()->OnChooseCredentials( - local_forms.Pass(), - federated_forms.Pass(), - GURL("http://example.com"), - base::Callback<void(const password_manager::CredentialInfo&)>())); + SetUpAccountChooser(local_forms.Pass(), federated_forms.Pass()); // Trigger creation of controller and check the views. NSTableView* view = controller().credentialsView; ASSERT_NSNE(nil, view); @@ -129,14 +124,12 @@ TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, ForwardsAvatarFetchToManager) { - ScopedVector<autofill::PasswordForm> local_forms; - local_forms.push_back(Credential("taco")); - local_forms.back()->icon_url = GURL("http://foo"); - EXPECT_TRUE(ui_controller()->OnChooseCredentials( - local_forms.Pass(), - ScopedVector<autofill::PasswordForm>(), - GURL("http://example.com"), - base::Callback<void(const password_manager::CredentialInfo&)>())); + ScopedVector<const autofill::PasswordForm> local_forms; + scoped_ptr<autofill::PasswordForm> form = Credential("taco"); + form->icon_url = GURL("http://foo"); + local_forms.push_back(form.Pass()); + SetUpAccountChooser(local_forms.Pass(), + ScopedVector<const autofill::PasswordForm>()); // Trigger creation of the controller and check the fetched URLs. controller(); EXPECT_FALSE(avatar_manager().fetchedAvatars.empty()); @@ -148,48 +141,47 @@ TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, SelectingCredentialInformsModelAndClosesDialog) { - ScopedVector<autofill::PasswordForm> local_forms; + ScopedVector<const autofill::PasswordForm> local_forms; local_forms.push_back(Credential("pizza")); - ScopedVector<autofill::PasswordForm> federated_forms; + ScopedVector<const autofill::PasswordForm> federated_forms; federated_forms.push_back(Credential("taco")); - EXPECT_TRUE(ui_controller()->OnChooseCredentials( - local_forms.Pass(), - federated_forms.Pass(), - GURL("http://example.com"), - base::Callback<void(const password_manager::CredentialInfo&)>())); + SetUpAccountChooser(local_forms.Pass(), federated_forms.Pass()); + EXPECT_CALL(*ui_controller(), + ChooseCredential( + *Credential("taco"), + password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED)); [controller().credentialsView selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO]; EXPECT_TRUE(delegate().dismissed); - EXPECT_TRUE(ui_controller()->choose_credential()); - EXPECT_EQ(base::ASCIIToUTF16("taco"), - ui_controller()->chosen_credential().username_value); } TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, SelectingNopeDismissesDialog) { - ScopedVector<autofill::PasswordForm> local_forms; + ScopedVector<const autofill::PasswordForm> local_forms; local_forms.push_back(Credential("pizza")); - EXPECT_TRUE(ui_controller()->OnChooseCredentials( - local_forms.Pass(), ScopedVector<autofill::PasswordForm>(), - GURL("http://example.com"), - base::Callback<void(const password_manager::CredentialInfo&)>())); + SetUpAccountChooser(local_forms.Pass(), + ScopedVector<const autofill::PasswordForm>()); [controller().cancelButton performClick:nil]; EXPECT_TRUE(delegate().dismissed); } TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, SelectingSettingsShowsSettingsPage) { + SetUpAccountChooser(ScopedVector<const autofill::PasswordForm>(), + ScopedVector<const autofill::PasswordForm>()); BubbleCombobox* moreButton = controller().moreButton; EXPECT_TRUE(moreButton); + EXPECT_CALL(*ui_controller(), NavigateToPasswordManagerSettingsPage()); [[moreButton menu] performActionForItemAtIndex: AccountChooserMoreComboboxModel::INDEX_SETTINGS]; - EXPECT_TRUE(ui_controller()->navigated_to_settings_page()); EXPECT_TRUE(delegate().dismissed); } TEST_F(ManagePasswordsBubbleAccountChooserViewControllerTest, SelectingLearnMoreShowsHelpCenterArticle) { + SetUpAccountChooser(ScopedVector<const autofill::PasswordForm>(), + ScopedVector<const autofill::PasswordForm>()); BubbleCombobox* moreButton = controller().moreButton; EXPECT_TRUE(moreButton); [[moreButton menu] performActionForItemAtIndex:
diff --git a/chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.h b/chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.h index 845c0d8..510a93ea 100644 --- a/chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.h +++ b/chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.h
@@ -24,7 +24,15 @@ void SetUp() override; ManagePasswordsUIControllerMock* ui_controller() { return ui_controller_; } - ManagePasswordsBubbleModel* model(); + ManagePasswordsBubbleModel* GetModelAndCreateIfNull(); + + // Sets the appropriate state for ManagePasswordsBubbleModel. + void SetUpPendingState(); + void SetUpConfirmationState(); + void SetUpManageState(); + void SetUpAccountChooser( + ScopedVector<const autofill::PasswordForm> local, + ScopedVector<const autofill::PasswordForm> federations); // An opportunity for tests to override the constructor parameter of // ManagePasswordsBubbleModel.
diff --git a/chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.mm b/chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.mm index 61be389..b6a7c9f5 100644 --- a/chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.mm +++ b/chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.mm
@@ -10,6 +10,13 @@ #include "components/password_manager/core/browser/password_manager_test_utils.h" #include "content/public/test/web_contents_tester.h" +namespace { +const char kSiteOrigin[] = "http://example.com/login"; +} + +using testing::Return; +using testing::ReturnRef; + ManagePasswordsControllerTest:: ManagePasswordsControllerTest() { } @@ -24,8 +31,8 @@ // |test_web_contents_| and therefore accessible to the model. test_web_contents_.reset( content::WebContentsTester::CreateTestWebContents(profile(), NULL)); - ui_controller_ = - new ManagePasswordsUIControllerMock(test_web_contents_.get()); + ui_controller_ = new testing::NiceMock<ManagePasswordsUIControllerMock>( + test_web_contents_.get()); PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse( profile(), password_manager::BuildPasswordStore< content::BrowserContext, @@ -33,7 +40,7 @@ } ManagePasswordsBubbleModel* -ManagePasswordsControllerTest::model() { +ManagePasswordsControllerTest::GetModelAndCreateIfNull() { if (!model_) { model_.reset(new ManagePasswordsBubbleModel(test_web_contents_.get(), GetDisplayReason())); @@ -41,6 +48,54 @@ return model_.get(); } +void ManagePasswordsControllerTest::SetUpPendingState() { + autofill::PasswordForm form; + EXPECT_CALL(*ui_controller_, GetPendingPassword()).WillOnce(ReturnRef(form)); + std::vector<const autofill::PasswordForm*> forms; + EXPECT_CALL(*ui_controller_, GetCurrentForms()).WillOnce(ReturnRef(forms)); + GURL origin(kSiteOrigin); + EXPECT_CALL(*ui_controller_, GetOrigin()).WillOnce(ReturnRef(origin)); + EXPECT_CALL(*ui_controller_, GetState()) + .WillOnce(Return(password_manager::ui::PENDING_PASSWORD_STATE)); + GetModelAndCreateIfNull(); + ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(ui_controller_)); +} + +void ManagePasswordsControllerTest::SetUpConfirmationState() { + GURL origin(kSiteOrigin); + EXPECT_CALL(*ui_controller_, GetOrigin()).WillOnce(ReturnRef(origin)); + EXPECT_CALL(*ui_controller_, GetState()) + .WillOnce(Return(password_manager::ui::CONFIRMATION_STATE)); + GetModelAndCreateIfNull(); + ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(ui_controller_)); +} + +void ManagePasswordsControllerTest::SetUpManageState() { + std::vector<const autofill::PasswordForm*> forms; + EXPECT_CALL(*ui_controller_, GetCurrentForms()).WillOnce(ReturnRef(forms)); + GURL origin(kSiteOrigin); + EXPECT_CALL(*ui_controller_, GetOrigin()).WillOnce(ReturnRef(origin)); + EXPECT_CALL(*ui_controller_, GetState()) + .WillOnce(Return(password_manager::ui::MANAGE_STATE)); + GetModelAndCreateIfNull(); + ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(ui_controller_)); +} + +void ManagePasswordsControllerTest::SetUpAccountChooser( + ScopedVector<const autofill::PasswordForm> local, + ScopedVector<const autofill::PasswordForm> federations) { + EXPECT_CALL(*ui_controller_, GetCurrentForms()) + .WillOnce(ReturnRef(local.get())); + EXPECT_CALL(*ui_controller_, GetFederatedForms()) + .WillOnce(ReturnRef(federations.get())); + EXPECT_CALL(*ui_controller_, GetState()) + .WillOnce(Return(password_manager::ui::CREDENTIAL_REQUEST_STATE)); + GURL origin(kSiteOrigin); + EXPECT_CALL(*ui_controller_, GetOrigin()).WillOnce(ReturnRef(origin)); + GetModelAndCreateIfNull(); + ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(ui_controller_)); +} + ManagePasswordsBubbleModel::DisplayReason ManagePasswordsControllerTest::GetDisplayReason() const { return ManagePasswordsBubbleModel::AUTOMATIC;
diff --git a/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller_unittest.mm index 6c6783e..6aa5990 100644 --- a/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller_unittest.mm
@@ -25,7 +25,7 @@ void SetUp() override { ManagePasswordsControllerTest::SetUp(); delegate_.reset([[ContentViewDelegateMock alloc] init]); - ui_controller()->SetState(password_manager::ui::CONFIRMATION_STATE); + SetUpConfirmationState(); } ContentViewDelegateMock* delegate() { return delegate_.get(); } @@ -33,7 +33,7 @@ ManagePasswordsBubbleConfirmationViewController* controller() { if (!controller_) { controller_.reset([[ManagePasswordsBubbleConfirmationViewController alloc] - initWithModel:model() + initWithModel:GetModelAndCreateIfNull() delegate:delegate()]); [controller_ loadView]; } @@ -54,9 +54,9 @@ TEST_F(ManagePasswordsBubbleConfirmationViewControllerTest, ShouldOpenPasswordsAndDismissWhenLinkClicked) { + EXPECT_CALL(*ui_controller(), NavigateToPasswordManagerSettingsPage()); [controller().confirmationText clickedOnLink:@"about:blank" atIndex:0]; EXPECT_TRUE([delegate() dismissed]); - EXPECT_TRUE(ui_controller()->navigated_to_settings_page()); } } // namespace
diff --git a/chrome/browser/ui/cocoa/passwords/manage_passwords_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/manage_passwords_view_controller_unittest.mm index 2045c7d..2689adb 100644 --- a/chrome/browser/ui/cocoa/passwords/manage_passwords_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/manage_passwords_view_controller_unittest.mm
@@ -15,6 +15,9 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" +using testing::Return; +using testing::ReturnRef; + namespace { class ManagePasswordsBubbleManageViewControllerTest @@ -25,7 +28,6 @@ void SetUp() override { ManagePasswordsControllerTest::SetUp(); delegate_.reset([[ContentViewDelegateMock alloc] init]); - ui_controller()->SetState(password_manager::ui::MANAGE_STATE); } ContentViewDelegateMock* delegate() { return delegate_.get(); } @@ -33,7 +35,7 @@ ManagePasswordsBubbleManageViewController* controller() { if (!controller_) { controller_.reset([[ManagePasswordsBubbleManageViewController alloc] - initWithModel:model() + initWithModel:GetModelAndCreateIfNull() delegate:delegate()]); [controller_ loadView]; } @@ -52,20 +54,23 @@ TEST_F(ManagePasswordsBubbleManageViewControllerTest, ShouldDismissWhenDoneClicked) { + SetUpManageState(); [controller().doneButton performClick:nil]; EXPECT_TRUE([delegate() dismissed]); } TEST_F(ManagePasswordsBubbleManageViewControllerTest, ShouldOpenPasswordsWhenManageClicked) { + SetUpManageState(); + EXPECT_CALL(*ui_controller(), NavigateToPasswordManagerSettingsPage()); [controller().manageButton performClick:nil]; EXPECT_TRUE([delegate() dismissed]); - EXPECT_TRUE(ui_controller()->navigated_to_settings_page()); } TEST_F(ManagePasswordsBubbleManageViewControllerTest, ShouldShowNoPasswordsWhenNoPasswordsExistForSite) { - EXPECT_TRUE(model()->local_credentials().empty()); + SetUpManageState(); + EXPECT_TRUE(GetModelAndCreateIfNull()->local_credentials().empty()); EXPECT_TRUE([controller() noPasswordsView]); EXPECT_FALSE([controller() passwordsListController]); } @@ -73,23 +78,26 @@ TEST_F(ManagePasswordsBubbleManageViewControllerTest, ShouldShowAllPasswordItemsWhenPasswordsExistForSite) { // Add a few password entries. - autofill::PasswordFormMap map; - scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm); - form1->username_value = base::ASCIIToUTF16("username1"); - form1->password_value = base::ASCIIToUTF16("password1"); - map.insert(base::ASCIIToUTF16("username1"), form1.Pass()); + autofill::PasswordForm form1; + form1.username_value = base::ASCIIToUTF16("username1"); + form1.password_value = base::ASCIIToUTF16("password1"); - scoped_ptr<autofill::PasswordForm> form2(new autofill::PasswordForm); - form2->username_value = base::ASCIIToUTF16("username2"); - form2->password_value = base::ASCIIToUTF16("password2"); - map.insert(base::ASCIIToUTF16("username2"), form2.Pass()); + autofill::PasswordForm form2; + form2.username_value = base::ASCIIToUTF16("username2"); + form2.password_value = base::ASCIIToUTF16("password2"); // Add the entries to the model. - ui_controller()->OnPasswordAutofilled(map, map.begin()->second->origin); - model()->set_state(password_manager::ui::MANAGE_STATE); + std::vector<const autofill::PasswordForm*> forms; + forms.push_back(&form1); + forms.push_back(&form2); + EXPECT_CALL(*ui_controller(), GetCurrentForms()).WillOnce(ReturnRef(forms)); + GURL origin; + EXPECT_CALL(*ui_controller(), GetOrigin()).WillOnce(ReturnRef(origin)); + EXPECT_CALL(*ui_controller(), GetState()) + .WillOnce(Return(password_manager::ui::MANAGE_STATE)); // Check the view state. - EXPECT_FALSE(model()->local_credentials().empty()); + EXPECT_FALSE(GetModelAndCreateIfNull()->local_credentials().empty()); ASSERT_TRUE([controller() passwordsListController]); EXPECT_FALSE([controller() noPasswordsView]); NSArray* items = [[controller() passwordsListController] itemViews];
diff --git a/chrome/browser/ui/cocoa/passwords/passwords_bubble_cocoa_unittest.mm b/chrome/browser/ui/cocoa/passwords/passwords_bubble_cocoa_unittest.mm index 7e1c456..6f35b926 100644 --- a/chrome/browser/ui/cocoa/passwords/passwords_bubble_cocoa_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/passwords_bubble_cocoa_unittest.mm
@@ -31,6 +31,9 @@ #include "testing/gtest_mac.h" #include "testing/platform_test.h" +using testing::Return; +using testing::ReturnRef; + class ManagePasswordsBubbleCocoaTest : public CocoaProfileTest { public: void SetUp() override { @@ -44,19 +47,15 @@ // |test_web_contents_| and therefore accessible to the model. It should be // done before AppendWebContents() so the real ManagePasswordsUIController // isn't created. - ManagePasswordsUIControllerMock* ui_controller = - new ManagePasswordsUIControllerMock(test_web_contents_); + new testing::NiceMock<ManagePasswordsUIControllerMock>(test_web_contents_); + EXPECT_CALL(*UIController(), GetState()) + .WillOnce(Return(password_manager::ui::INACTIVE_STATE)); browser()->tab_strip_model()->AppendWebContents( test_web_contents_, /*foreground=*/true); PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse( profile(), password_manager::BuildPasswordStore< content::BrowserContext, testing::NiceMock<password_manager::MockPasswordStore>>); - // Set the initial state. - ScopedVector<autofill::PasswordForm> forms; - forms.push_back(new autofill::PasswordForm); - forms.back()->origin = GURL("http://example.com"); - ui_controller->PretendSubmittedPassword(forms.Pass()); } content::WebContents* CreateWebContents() { @@ -65,6 +64,17 @@ } void ShowBubble(bool user_action) { + ManagePasswordsUIControllerMock* mock = UIController(); + ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(mock)); + autofill::PasswordForm form; + EXPECT_CALL(*mock, GetPendingPassword()).WillOnce(ReturnRef(form)); + std::vector<const autofill::PasswordForm*> forms; + EXPECT_CALL(*mock, GetCurrentForms()).WillOnce(ReturnRef(forms)); + GURL origin; + EXPECT_CALL(*mock, GetOrigin()).WillOnce(ReturnRef(origin)); + EXPECT_CALL(*mock, GetState()) + .WillOnce(Return(password_manager::ui::PENDING_PASSWORD_STATE)); + TabDialogs::FromWebContents(test_web_contents_) ->ShowManagePasswordsBubble(user_action); if (ManagePasswordsBubbleCocoa::instance()) { @@ -73,6 +83,7 @@ [ManagePasswordsBubbleCocoa::instance()->controller_ window]); [bubbleWindow setAllowedAnimations:info_bubble::kAnimateNone]; } + ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(mock)); } void CloseBubble() { @@ -84,6 +95,11 @@ return bubble ? [bubble->controller_ window] : nil; } + ManagePasswordsUIControllerMock* UIController() { + return static_cast<ManagePasswordsUIControllerMock*>( + PasswordsModelDelegateFromWebContents(test_web_contents_)); + } + ManagePasswordsBubbleController* controller() { ManagePasswordsBubbleCocoa* bubble = ManagePasswordsBubbleCocoa::instance(); return bubble ? bubble->controller_ : nil; @@ -91,7 +107,7 @@ ManagePasswordsIconCocoa* icon() { return static_cast<ManagePasswordsIconCocoa*>( - ManagePasswordsBubbleCocoa::instance()->icon_); + ManagePasswordsBubbleCocoa::instance()->icon_); } private: @@ -131,15 +147,22 @@ TabStripModel* tabStripModel = browser()->tab_strip_model(); EXPECT_EQ(0, tabStripModel->active_index()); - // Open a second tab and make it active. + // Open a second tab as inactive. content::WebContents* webContents2 = CreateWebContents(); - tabStripModel->AppendWebContents(webContents2, /*foreground=*/true); - EXPECT_EQ(1, tabStripModel->active_index()); + new testing::StrictMock<ManagePasswordsUIControllerMock>(webContents2); + tabStripModel->AppendWebContents(webContents2, /*foreground=*/false); + EXPECT_EQ(0, tabStripModel->active_index()); EXPECT_EQ(2, tabStripModel->count()); // Try to show the bubble on the inactive tab. Nothing should happen. - ShowBubble(false); + TabDialogs::FromWebContents(tabStripModel->GetWebContentsAt(1)) + ->ShowManagePasswordsBubble(false); EXPECT_FALSE(ManagePasswordsBubbleCocoa::instance()); + + // Show the bubble for the active tab. + ShowBubble(false); + EXPECT_TRUE(ManagePasswordsBubbleCocoa::instance()); + EXPECT_TRUE([bubbleWindow() isVisible]); } TEST_F(ManagePasswordsBubbleCocoaTest, HideBubbleOnChangedState) {
diff --git a/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller_unittest.mm index ca219da7..510da060 100644 --- a/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller_unittest.mm
@@ -34,7 +34,7 @@ if (!controller_) { controller_ = [[ManagePasswordsBubbleController alloc] initWithParentWindow:browser()->window()->GetNativeWindow() - model:model()]; + model:GetModelAndCreateIfNull()]; } return controller_; } @@ -48,13 +48,13 @@ }; TEST_F(ManagePasswordsBubbleControllerTest, PendingStateShouldHavePendingView) { - ui_controller()->SetState(password_manager::ui::PENDING_PASSWORD_STATE); + SetUpPendingState(); EXPECT_EQ([ManagePasswordsBubblePendingViewController class], [[controller() currentController] class]); } TEST_F(ManagePasswordsBubbleControllerTest, DismissingShouldCloseWindow) { - ui_controller()->SetState(password_manager::ui::PENDING_PASSWORD_STATE); + SetUpPendingState(); [controller() showWindow:nil]; // Turn off animations so that closing happens immediately. @@ -68,7 +68,7 @@ } TEST_F(ManagePasswordsBubbleControllerTest, ManageStateShouldHaveManageView) { - ui_controller()->SetState(password_manager::ui::MANAGE_STATE); + SetUpManageState(); EXPECT_EQ([ManagePasswordsBubbleManageViewController class], [[controller() currentController] class]); }
diff --git a/chrome/browser/ui/cocoa/passwords/passwords_list_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/passwords_list_view_controller_unittest.mm index 43753d7..cc35b99 100644 --- a/chrome/browser/ui/cocoa/passwords/passwords_list_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/passwords_list_view_controller_unittest.mm
@@ -43,16 +43,16 @@ void SetUpManageState( const std::vector<const autofill::PasswordForm*>& forms) { - ui_controller()->SetState(password_manager::ui::MANAGE_STATE); + ManagePasswordsControllerTest::SetUpManageState(); controller_.reset([[PasswordsListViewController alloc] - initWithModel:model() + initWithModel:GetModelAndCreateIfNull() forms:forms]); } void SetUpPendingState(const autofill::PasswordForm* form) { - ui_controller()->SetState(password_manager::ui::PENDING_PASSWORD_STATE); + ManagePasswordsControllerTest::SetUpPendingState(); controller_.reset([[PasswordsListViewController alloc] - initWithModel:model() + initWithModel:GetModelAndCreateIfNull() forms:std::vector<const autofill::PasswordForm*>(1, form)]); }
diff --git a/chrome/browser/ui/cocoa/passwords/pending_password_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/pending_password_view_controller_unittest.mm index 85c69184..dd204b7 100644 --- a/chrome/browser/ui/cocoa/passwords/pending_password_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/pending_password_view_controller_unittest.mm
@@ -26,7 +26,7 @@ void SetUp() override { ManagePasswordsControllerTest::SetUp(); delegate_.reset([[ContentViewDelegateMock alloc] init]); - ui_controller()->SetState(password_manager::ui::PENDING_PASSWORD_STATE); + SetUpPendingState(); } ContentViewDelegateMock* delegate() { return delegate_.get(); } @@ -34,7 +34,7 @@ ManagePasswordsBubblePendingViewController* controller() { if (!controller_) { controller_.reset([[ManagePasswordsBubblePendingViewController alloc] - initWithModel:model() + initWithModel:GetModelAndCreateIfNull() delegate:delegate()]); [controller_ loadView]; } @@ -48,29 +48,29 @@ TEST_F(ManagePasswordsBubblePendingViewControllerTest, ShouldSavePasswordAndDismissWhenSaveClicked) { + EXPECT_CALL(*ui_controller(), SavePassword()); + EXPECT_CALL(*ui_controller(), NeverSavePassword()).Times(0); [controller().saveButton performClick:nil]; EXPECT_TRUE([delegate() dismissed]); - EXPECT_TRUE(ui_controller()->saved_password()); - EXPECT_FALSE(ui_controller()->never_saved_password()); } TEST_F(ManagePasswordsBubblePendingViewControllerTest, ShouldNeverAndDismissWhenNeverClicked) { + EXPECT_CALL(*ui_controller(), SavePassword()).Times(0); + EXPECT_CALL(*ui_controller(), NeverSavePassword()); [controller().neverButton performClick:nil]; EXPECT_TRUE([delegate() dismissed]); - EXPECT_FALSE(ui_controller()->saved_password()); - EXPECT_TRUE(ui_controller()->never_saved_password()); } TEST_F(ManagePasswordsBubblePendingViewControllerTest, ShouldDismissWhenCrossClicked) { + EXPECT_CALL(*ui_controller(), SavePassword()).Times(0); + EXPECT_CALL(*ui_controller(), NeverSavePassword()).Times(0); [controller().closeButton performClick:nil]; EXPECT_TRUE([delegate() dismissed]); - EXPECT_FALSE(ui_controller()->saved_password()); - EXPECT_FALSE(ui_controller()->never_saved_password()); } } // namespace
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc index a1abf30..b8354944 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
@@ -11,6 +11,7 @@ #include "base/command_line.h" #include "base/prefs/pref_service.h" #include "base/strings/utf_string_conversions.h" +#include "base/time/default_clock.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" @@ -73,15 +74,16 @@ content::WebContents* web_contents, DisplayReason display_reason) : content::WebContentsObserver(web_contents), + password_overridden_(false), display_disposition_(metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING), dismissal_reason_(metrics_util::NO_DIRECT_INTERACTION), - update_password_submission_event_(metrics_util::NO_UPDATE_SUBMISSION) { + update_password_submission_event_(metrics_util::NO_UPDATE_SUBMISSION), + clock_(new base::DefaultClock) { PasswordsModelDelegate* delegate = PasswordsModelDelegateFromWebContents(web_contents); origin_ = delegate->GetOrigin(); state_ = delegate->GetState(); - password_overridden_ = delegate->IsPasswordOverridden(); if (state_ == password_manager::ui::PENDING_PASSWORD_STATE || state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { pending_password_ = delegate->GetPendingPassword(); @@ -143,13 +145,15 @@ } else if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) { interaction_stats_.origin_domain = origin_.GetOrigin(); interaction_stats_.username_value = pending_password_.username_value; - interaction_stats_.update_time = base::Time::Now(); password_manager::InteractionsStats* stats = delegate->GetCurrentInteractionStats(); if (stats) { - // TODO(vasilii): DCHECK that username and origin are the same. + DCHECK_EQ(interaction_stats_.username_value, stats->username_value); + DCHECK_EQ(interaction_stats_.origin_domain, stats->origin_domain); interaction_stats_.dismissal_count = stats->dismissal_count; } + } else if (state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { + password_overridden_ = delegate->IsPasswordOverridden(); } manage_link_ = @@ -220,6 +224,7 @@ std::numeric_limits<decltype( interaction_stats_.dismissal_count)>::max()) interaction_stats_.dismissal_count++; + interaction_stats_.update_time = clock_->Now(); password_manager::PasswordStore* password_store = PasswordStoreFactory::GetForProfile( profile, ServiceAccessType::EXPLICIT_ACCESS)
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.h b/chrome/browser/ui/passwords/manage_passwords_bubble_model.h index 00ee2abc..ad74c570 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.h +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_BUBBLE_MODEL_H_ #include "base/memory/scoped_vector.h" +#include "base/time/clock.h" #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/statistics_table.h" @@ -135,19 +136,12 @@ bool ShouldShowAutoSigninWarmWelcome() const; #if defined(UNIT_TEST) - // Gets and sets the reason the bubble was displayed. - password_manager::metrics_util::UIDisplayDisposition display_disposition() - const { - return display_disposition_; - } - // Gets the reason the bubble was dismissed. password_manager::metrics_util::UIDismissalReason dismissal_reason() const { return dismissal_reason_; } - // State setter. - void set_state(password_manager::ui::State state) { state_ = state; } + void set_clock(scoped_ptr<base::Clock> clock) { clock_ = clock.Pass(); } #endif private: @@ -187,6 +181,9 @@ // Current statistics for the save password bubble; password_manager::InteractionsStats interaction_stats_; + // Used to retrieve the current time, in base::Time units. + scoped_ptr<base::Clock> clock_; + DISALLOW_COPY_AND_ASSIGN(ManagePasswordsBubbleModel); };
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc index 1cec681..6af21fd 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
@@ -7,6 +7,7 @@ #include "base/prefs/pref_service.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" +#include "base/test/simple_test_clock.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/profile_sync_service_mock.h" @@ -31,11 +32,13 @@ using password_bubble_experiment::kSmartLockBrandingSavePromptOnlyGroupName; using ::testing::AnyNumber; using ::testing::Return; +using ::testing::ReturnRef; using ::testing::_; namespace { const char kSiteOrigin[] = "http://example.com/login"; +const char kUsername[] = "Admin"; const char kUIDismissalReasonMetric[] = "PasswordManager.UIDismissalReason"; class TestSyncService : public ProfileSyncServiceMock { @@ -71,36 +74,11 @@ return make_scoped_ptr(new TestSyncService(static_cast<Profile*>(context))); } -// TODO(vabr): Merge the two mocks together. http://crbug.com/546604 -class ManagePasswordsUIControllerMockWithMockNavigation - : public ManagePasswordsUIControllerMock { - public: - explicit ManagePasswordsUIControllerMockWithMockNavigation( - content::WebContents* contents) - : ManagePasswordsUIControllerMock(contents) {} - - ~ManagePasswordsUIControllerMockWithMockNavigation() override {} - - MOCK_METHOD0(NavigateToPasswordManagerSettingsPage, void()); - MOCK_METHOD0(NavigateToExternalPasswordManager, void()); - MOCK_METHOD0(NavigateToSmartLockHelpPage, void()); - MOCK_CONST_METHOD0(GetCurrentInteractionStats, - password_manager::InteractionsStats*()); -}; - -// TODO(vasilii): get rid of the matcher when it's possible to test the whole -// InteractionsStats. -MATCHER_P(DissmisalCountIs, count, "") { - return count == arg.dismissal_count; -} - } // namespace class ManagePasswordsBubbleModelTest : public ::testing::Test { public: - ManagePasswordsBubbleModelTest() - : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), - field_trials_(nullptr) {} + ManagePasswordsBubbleModelTest() : field_trials_(nullptr) {} ~ManagePasswordsBubbleModelTest() override = default; void SetUp() override { @@ -108,7 +86,7 @@ content::WebContentsTester::CreateTestWebContents(&profile_, nullptr)); // Create the test UIController here so that it's bound to // |test_web_contents_| and therefore accessible to the model. - new testing::StrictMock<ManagePasswordsUIControllerMockWithMockNavigation>( + new testing::StrictMock<ManagePasswordsUIControllerMock>( test_web_contents_.get()); PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse( profile(), @@ -134,255 +112,265 @@ .get()); } - password_manager::InteractionsStats GetTestStats() { - password_manager::InteractionsStats result; - result.origin_domain = GURL(kSiteOrigin); - result.username_value = base::ASCIIToUTF16("username"); - result.dismissal_count = 5; - result.update_time = base::Time::FromTimeT(1); - return result; - } - - protected: - void SetUpWithState(password_manager::ui::State state, - ManagePasswordsBubbleModel::DisplayReason reason) { - ManagePasswordsUIControllerMock* mock = controller(); - mock->SetState(state); - model_.reset( - new ManagePasswordsBubbleModel(test_web_contents_.get(), reason)); - mock->UnsetState(); - } - - void PretendPasswordWaiting() { - SetUpWithState(password_manager::ui::PENDING_PASSWORD_STATE, - ManagePasswordsBubbleModel::AUTOMATIC); - } - - void PretendUpdatePasswordWaiting() { - SetUpWithState(password_manager::ui::PENDING_PASSWORD_UPDATE_STATE, - ManagePasswordsBubbleModel::AUTOMATIC); - } - - void PretendCredentialsWaiting() { - SetUpWithState(password_manager::ui::CREDENTIAL_REQUEST_STATE, - ManagePasswordsBubbleModel::AUTOMATIC); - } - - void PretendAutoSigningIn() { - SetUpWithState(password_manager::ui::AUTO_SIGNIN_STATE, - ManagePasswordsBubbleModel::AUTOMATIC); - } - - void PretendManagingPasswords() { - SetUpWithState(password_manager::ui::MANAGE_STATE, - ManagePasswordsBubbleModel::USER_ACTION); - } - - ManagePasswordsUIControllerMockWithMockNavigation* controller() { - return static_cast<ManagePasswordsUIControllerMockWithMockNavigation*>( - ManagePasswordsUIController::FromWebContents(test_web_contents_.get())); + ManagePasswordsUIControllerMock* controller() { + return static_cast<ManagePasswordsUIControllerMock*>( + PasswordsModelDelegateFromWebContents(test_web_contents_.get())); } content::WebContents* test_web_contents() { return test_web_contents_.get(); } - scoped_ptr<ManagePasswordsBubbleModel> model_; + ManagePasswordsBubbleModel* model() { return model_.get(); } + + void SetUpWithState(password_manager::ui::State state, + ManagePasswordsBubbleModel::DisplayReason reason); + void PretendPasswordWaiting(); + void PretendUpdatePasswordWaiting(); + void PretendCredentialsWaiting(); + void PretendAutoSigningIn(); + void PretendManagingPasswords(); + + void DestroyModel(); + void DestroyModelExpectReason( + password_manager::metrics_util::UIDismissalReason dismissal_reason); + + static password_manager::InteractionsStats GetTestStats(); + static autofill::PasswordForm GetPendingPassword(); private: content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; scoped_ptr<content::WebContents> test_web_contents_; base::FieldTrialList field_trials_; + scoped_ptr<ManagePasswordsBubbleModel> model_; }; -TEST_F(ManagePasswordsBubbleModelTest, CloseWithoutInteraction) { - base::HistogramTester histogram_tester; +void ManagePasswordsBubbleModelTest::SetUpWithState( + password_manager::ui::State state, + ManagePasswordsBubbleModel::DisplayReason reason) { + ManagePasswordsUIControllerMock* mock = controller(); + GURL origin(kSiteOrigin); + EXPECT_CALL(*mock, GetOrigin()).WillOnce(ReturnRef(origin)); + EXPECT_CALL(*mock, GetState()).WillOnce(Return(state)); + EXPECT_CALL(*mock, OnBubbleShown()); + model_.reset( + new ManagePasswordsBubbleModel(test_web_contents_.get(), reason)); + ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(mock)); +} + +void ManagePasswordsBubbleModelTest::PretendPasswordWaiting() { + autofill::PasswordForm form = GetPendingPassword(); + EXPECT_CALL(*controller(), GetPendingPassword()).WillOnce(ReturnRef(form)); + std::vector<const autofill::PasswordForm*> forms; + EXPECT_CALL(*controller(), GetCurrentForms()).WillOnce(ReturnRef(forms)); password_manager::InteractionsStats stats = GetTestStats(); EXPECT_CALL(*controller(), GetCurrentInteractionStats()) .WillOnce(Return(&stats)); - PretendPasswordWaiting(); - EXPECT_EQ(model_->dismissal_reason(), - password_manager::metrics_util::NO_DIRECT_INTERACTION); - EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, - model_->state()); - stats.dismissal_count++; - EXPECT_CALL(*GetStore(), - AddSiteStatsImpl(DissmisalCountIs(stats.dismissal_count))); - model_.reset(); - EXPECT_FALSE(controller()->saved_password()); - EXPECT_FALSE(controller()->never_saved_password()); + SetUpWithState(password_manager::ui::PENDING_PASSWORD_STATE, + ManagePasswordsBubbleModel::AUTOMATIC); +} - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, - password_manager::metrics_util::NO_DIRECT_INTERACTION, - 1); +void ManagePasswordsBubbleModelTest::PretendUpdatePasswordWaiting() { + autofill::PasswordForm form = GetPendingPassword(); + EXPECT_CALL(*controller(), GetPendingPassword()).WillOnce(ReturnRef(form)); + std::vector<const autofill::PasswordForm*> forms; + EXPECT_CALL(*controller(), GetCurrentForms()).WillOnce(ReturnRef(forms)); + EXPECT_CALL(*controller(), IsPasswordOverridden()).WillOnce(Return(false)); + SetUpWithState(password_manager::ui::PENDING_PASSWORD_UPDATE_STATE, + ManagePasswordsBubbleModel::AUTOMATIC); +} + +void ManagePasswordsBubbleModelTest::PretendCredentialsWaiting() { + std::vector<const autofill::PasswordForm*> forms; + EXPECT_CALL(*controller(), GetCurrentForms()).WillOnce(ReturnRef(forms)); + EXPECT_CALL(*controller(), GetFederatedForms()).WillOnce(ReturnRef(forms)); + SetUpWithState(password_manager::ui::CREDENTIAL_REQUEST_STATE, + ManagePasswordsBubbleModel::AUTOMATIC); +} + +void ManagePasswordsBubbleModelTest::PretendAutoSigningIn() { + autofill::PasswordForm form = GetPendingPassword(); + EXPECT_CALL(*controller(), GetPendingPassword()).WillOnce(ReturnRef(form)); + SetUpWithState(password_manager::ui::AUTO_SIGNIN_STATE, + ManagePasswordsBubbleModel::AUTOMATIC); +} + +void ManagePasswordsBubbleModelTest::PretendManagingPasswords() { + autofill::PasswordForm form = GetPendingPassword(); + std::vector<const autofill::PasswordForm*> forms(1, &form); + EXPECT_CALL(*controller(), GetCurrentForms()).WillOnce(ReturnRef(forms)); + SetUpWithState(password_manager::ui::MANAGE_STATE, + ManagePasswordsBubbleModel::USER_ACTION); +} + +void ManagePasswordsBubbleModelTest::DestroyModel() { + ManagePasswordsUIControllerMock* mock = + test_web_contents_ ? controller() : nullptr; + if (mock) + EXPECT_CALL(*mock, OnBubbleHidden()); + model_.reset(); + if (mock) + ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(mock)); +} + +void ManagePasswordsBubbleModelTest::DestroyModelExpectReason( + password_manager::metrics_util::UIDismissalReason dismissal_reason) { + base::HistogramTester histogram_tester; + DestroyModel(); + histogram_tester.ExpectUniqueSample(kUIDismissalReasonMetric, + dismissal_reason, 1); +} + +// static +password_manager::InteractionsStats +ManagePasswordsBubbleModelTest::GetTestStats() { + password_manager::InteractionsStats result; + result.origin_domain = GURL(kSiteOrigin).GetOrigin(); + result.username_value = base::ASCIIToUTF16(kUsername); + result.dismissal_count = 5; + result.update_time = base::Time::FromTimeT(1); + return result; +} + +// static +autofill::PasswordForm ManagePasswordsBubbleModelTest::GetPendingPassword() { + autofill::PasswordForm form; + form.origin = GURL(kSiteOrigin); + form.signon_realm = kSiteOrigin; + form.username_value = base::ASCIIToUTF16(kUsername); + form.password_value = base::ASCIIToUTF16("12345"); + return form; +} + +TEST_F(ManagePasswordsBubbleModelTest, CloseWithoutInteraction) { + PretendPasswordWaiting(); + + EXPECT_EQ(model()->dismissal_reason(), + password_manager::metrics_util::NO_DIRECT_INTERACTION); + EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, model()->state()); + scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); + base::Time now = base::Time::Now(); + clock->SetNow(now); + model()->set_clock(clock.Pass()); + password_manager::InteractionsStats stats = GetTestStats(); + stats.dismissal_count++; + stats.update_time = now; + EXPECT_CALL(*GetStore(), AddSiteStatsImpl(stats)); + EXPECT_CALL(*controller(), SavePassword()).Times(0); + EXPECT_CALL(*controller(), NeverSavePassword()).Times(0); + DestroyModelExpectReason( + password_manager::metrics_util::NO_DIRECT_INTERACTION); } TEST_F(ManagePasswordsBubbleModelTest, ClickSave) { - base::HistogramTester histogram_tester; - password_manager::InteractionsStats stats = GetTestStats(); - EXPECT_CALL(*controller(), GetCurrentInteractionStats()) - .WillOnce(Return(&stats)); PretendPasswordWaiting(); - EXPECT_CALL(*GetStore(), RemoveSiteStatsImpl(_)); - model_->OnSaveClicked(); - EXPECT_EQ(model_->dismissal_reason(), - password_manager::metrics_util::CLICKED_SAVE); - model_.reset(); - EXPECT_TRUE(controller()->saved_password()); - EXPECT_FALSE(controller()->never_saved_password()); - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, - password_manager::metrics_util::CLICKED_SAVE, - 1); + EXPECT_CALL(*GetStore(), RemoveSiteStatsImpl(GURL(kSiteOrigin).GetOrigin())); + EXPECT_CALL(*controller(), SavePassword()); + EXPECT_CALL(*controller(), NeverSavePassword()).Times(0); + model()->OnSaveClicked(); + EXPECT_EQ(model()->dismissal_reason(), + password_manager::metrics_util::CLICKED_SAVE); + DestroyModelExpectReason(password_manager::metrics_util::CLICKED_SAVE); } TEST_F(ManagePasswordsBubbleModelTest, ClickNever) { - base::HistogramTester histogram_tester; - password_manager::InteractionsStats stats = GetTestStats(); - EXPECT_CALL(*controller(), GetCurrentInteractionStats()) - .WillOnce(Return(&stats)); PretendPasswordWaiting(); - EXPECT_CALL(*GetStore(), RemoveSiteStatsImpl(_)); - model_->OnNeverForThisSiteClicked(); - EXPECT_EQ(model_->dismissal_reason(), - password_manager::metrics_util::CLICKED_NEVER); - EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, model_->state()); - model_.reset(); - EXPECT_FALSE(controller()->saved_password()); - EXPECT_TRUE(controller()->never_saved_password()); - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, - password_manager::metrics_util::CLICKED_NEVER, - 1); + EXPECT_CALL(*GetStore(), RemoveSiteStatsImpl(GURL(kSiteOrigin).GetOrigin())); + EXPECT_CALL(*controller(), SavePassword()).Times(0); + EXPECT_CALL(*controller(), NeverSavePassword()); + model()->OnNeverForThisSiteClicked(); + EXPECT_EQ(model()->dismissal_reason(), + password_manager::metrics_util::CLICKED_NEVER); + EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, model()->state()); + DestroyModelExpectReason(password_manager::metrics_util::CLICKED_NEVER); } TEST_F(ManagePasswordsBubbleModelTest, ClickManage) { - base::HistogramTester histogram_tester; PretendManagingPasswords(); EXPECT_CALL(*controller(), NavigateToPasswordManagerSettingsPage()); - model_->OnManageLinkClicked(); + model()->OnManageLinkClicked(); - EXPECT_EQ(model_->dismissal_reason(), + EXPECT_EQ(model()->dismissal_reason(), password_manager::metrics_util::CLICKED_MANAGE); - EXPECT_EQ(password_manager::ui::MANAGE_STATE, model_->state()); - model_.reset(); - EXPECT_FALSE(controller()->saved_password()); - EXPECT_FALSE(controller()->never_saved_password()); - - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, - password_manager::metrics_util::CLICKED_MANAGE, - 1); + EXPECT_EQ(password_manager::ui::MANAGE_STATE, model()->state()); + DestroyModelExpectReason(password_manager::metrics_util::CLICKED_MANAGE); } TEST_F(ManagePasswordsBubbleModelTest, ClickDone) { - base::HistogramTester histogram_tester; PretendManagingPasswords(); - model_->OnDoneClicked(); - EXPECT_EQ(model_->dismissal_reason(), - password_manager::metrics_util::CLICKED_DONE); - EXPECT_EQ(password_manager::ui::MANAGE_STATE, model_->state()); - model_.reset(); - EXPECT_FALSE(controller()->saved_password()); - EXPECT_FALSE(controller()->never_saved_password()); - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, - password_manager::metrics_util::CLICKED_DONE, - 1); + model()->OnDoneClicked(); + EXPECT_EQ(model()->dismissal_reason(), + password_manager::metrics_util::CLICKED_DONE); + EXPECT_EQ(password_manager::ui::MANAGE_STATE, model()->state()); + DestroyModelExpectReason(password_manager::metrics_util::CLICKED_DONE); } TEST_F(ManagePasswordsBubbleModelTest, ClickCredential) { - base::HistogramTester histogram_tester; PretendCredentialsWaiting(); - EXPECT_FALSE(controller()->choose_credential()); - autofill::PasswordForm form; - model_->OnChooseCredentials( - form, password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD); - EXPECT_EQ(model_->dismissal_reason(), - password_manager::metrics_util::CLICKED_CREDENTIAL); - model_.reset(); - EXPECT_FALSE(controller()->saved_password()); - EXPECT_FALSE(controller()->never_saved_password()); - EXPECT_TRUE(controller()->choose_credential()); - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, - password_manager::metrics_util::CLICKED_CREDENTIAL, - 1); + autofill::PasswordForm form; + EXPECT_CALL( + *controller(), + ChooseCredential( + form, password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD)); + model()->OnChooseCredentials( + form, password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD); + EXPECT_EQ(model()->dismissal_reason(), + password_manager::metrics_util::CLICKED_CREDENTIAL); + DestroyModelExpectReason(password_manager::metrics_util::CLICKED_CREDENTIAL); } TEST_F(ManagePasswordsBubbleModelTest, ClickCancelCredential) { - base::HistogramTester histogram_tester; PretendCredentialsWaiting(); - EXPECT_FALSE(controller()->choose_credential()); - model_->OnCancelClicked(); - EXPECT_EQ(model_->dismissal_reason(), - password_manager::metrics_util::CLICKED_CANCEL); - model_.reset(); - EXPECT_FALSE(controller()->saved_password()); - EXPECT_FALSE(controller()->never_saved_password()); - EXPECT_FALSE(controller()->choose_credential()); - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, password_manager::metrics_util::CLICKED_CANCEL, - 1); + EXPECT_CALL(*controller(), ChooseCredential(_, _)).Times(0); + model()->OnCancelClicked(); + EXPECT_EQ(model()->dismissal_reason(), + password_manager::metrics_util::CLICKED_CANCEL); + DestroyModelExpectReason(password_manager::metrics_util::CLICKED_CANCEL); } TEST_F(ManagePasswordsBubbleModelTest, DismissCredential) { - base::HistogramTester histogram_tester; PretendCredentialsWaiting(); - EXPECT_FALSE(controller()->choose_credential()); - EXPECT_EQ(model_->dismissal_reason(), - password_manager::metrics_util::NO_DIRECT_INTERACTION); - model_.reset(); - EXPECT_FALSE(controller()->saved_password()); - EXPECT_FALSE(controller()->never_saved_password()); - EXPECT_FALSE(controller()->choose_credential()); - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, - password_manager::metrics_util::NO_DIRECT_INTERACTION, - 1); + EXPECT_CALL(*controller(), ChooseCredential(_, _)).Times(0); + EXPECT_EQ(model()->dismissal_reason(), + password_manager::metrics_util::NO_DIRECT_INTERACTION); + DestroyModelExpectReason( + password_manager::metrics_util::NO_DIRECT_INTERACTION); } TEST_F(ManagePasswordsBubbleModelTest, PopupAutoSigninToast) { - base::HistogramTester histogram_tester; // Pop up the first time with the warm welcome. PretendAutoSigningIn(); - EXPECT_TRUE(model_->ShouldShowAutoSigninWarmWelcome()); - model_->OnAutoSignOKClicked(); - EXPECT_EQ(model_->dismissal_reason(), + + EXPECT_TRUE(model()->ShouldShowAutoSigninWarmWelcome()); + model()->OnAutoSignOKClicked(); + EXPECT_EQ(model()->dismissal_reason(), password_manager::metrics_util::CLICKED_OK); - EXPECT_FALSE(model_->ShouldShowAutoSigninWarmWelcome()); - model_.reset(); - histogram_tester.ExpectUniqueSample( - kUIDismissalReasonMetric, - password_manager::metrics_util::CLICKED_OK, - 1); + EXPECT_FALSE(model()->ShouldShowAutoSigninWarmWelcome()); + DestroyModelExpectReason(password_manager::metrics_util::CLICKED_OK); // Pop up the second time without the warm welcome. PretendAutoSigningIn(); - EXPECT_FALSE(model_->ShouldShowAutoSigninWarmWelcome()); - model_->OnAutoSignInToastTimeout(); - EXPECT_EQ(model_->dismissal_reason(), + EXPECT_FALSE(model()->ShouldShowAutoSigninWarmWelcome()); + model()->OnAutoSignInToastTimeout(); + EXPECT_EQ(model()->dismissal_reason(), password_manager::metrics_util::AUTO_SIGNIN_TOAST_TIMEOUT); - model_.reset(); - histogram_tester.ExpectBucketCount( - kUIDismissalReasonMetric, - password_manager::metrics_util::AUTO_SIGNIN_TOAST_TIMEOUT, - 1); + DestroyModelExpectReason( + password_manager::metrics_util::AUTO_SIGNIN_TOAST_TIMEOUT); } TEST_F(ManagePasswordsBubbleModelTest, ClickUpdate) { PretendUpdatePasswordWaiting(); - model_->OnUpdateClicked(autofill::PasswordForm()); - model_.reset(); - EXPECT_TRUE(controller()->updated_password()); - EXPECT_FALSE(controller()->never_saved_password()); + + autofill::PasswordForm form; + EXPECT_CALL(*controller(), UpdatePassword(form)); + model()->OnUpdateClicked(form); + DestroyModel(); } TEST_F(ManagePasswordsBubbleModelTest, ShowSmartLockWarmWelcome) { @@ -393,14 +381,14 @@ base::FieldTrialList::CreateFieldTrial(kBrandingExperimentName, kSmartLockBrandingGroupName); - EXPECT_CALL(*controller(), GetCurrentInteractionStats()) - .WillRepeatedly(Return(nullptr)); - EXPECT_CALL(*GetStore(), AddSiteStatsImpl(_)).Times(AnyNumber()); PretendPasswordWaiting(); - EXPECT_TRUE(model_->ShouldShowGoogleSmartLockWelcome()); - model_.reset(); + + EXPECT_TRUE(model()->ShouldShowGoogleSmartLockWelcome()); + EXPECT_CALL(*GetStore(), AddSiteStatsImpl(_)); + DestroyModel(); PretendPasswordWaiting(); - EXPECT_FALSE(model_->ShouldShowGoogleSmartLockWelcome()); + + EXPECT_FALSE(model()->ShouldShowGoogleSmartLockWelcome()); EXPECT_TRUE(prefs()->GetBoolean( password_manager::prefs::kWasSavePrompFirstRunExperienceShown)); } @@ -413,14 +401,14 @@ base::FieldTrialList::CreateFieldTrial(kBrandingExperimentName, kSmartLockBrandingGroupName); - EXPECT_CALL(*controller(), GetCurrentInteractionStats()) - .WillRepeatedly(Return(nullptr)); - EXPECT_CALL(*GetStore(), AddSiteStatsImpl(_)).Times(AnyNumber()); PretendPasswordWaiting(); - EXPECT_FALSE(model_->ShouldShowGoogleSmartLockWelcome()); - model_.reset(); + + EXPECT_FALSE(model()->ShouldShowGoogleSmartLockWelcome()); + EXPECT_CALL(*GetStore(), AddSiteStatsImpl(_)); + DestroyModel(); PretendPasswordWaiting(); - EXPECT_FALSE(model_->ShouldShowGoogleSmartLockWelcome()); + + EXPECT_FALSE(model()->ShouldShowGoogleSmartLockWelcome()); EXPECT_FALSE(prefs()->GetBoolean( password_manager::prefs::kWasSavePrompFirstRunExperienceShown)); } @@ -453,10 +441,8 @@ test_case.experiment_group); } - EXPECT_CALL(*controller(), GetCurrentInteractionStats()) - .WillOnce(Return(nullptr)); PretendPasswordWaiting(); - EXPECT_THAT(base::UTF16ToUTF8(model_->title()), + EXPECT_THAT(base::UTF16ToUTF8(model()->title()), testing::HasSubstr(test_case.expected_title)); } @@ -523,7 +509,7 @@ break; } - model_->OnManageLinkClicked(); + model()->OnManageLinkClicked(); } namespace { @@ -584,7 +570,7 @@ break; } - model_->OnBrandLinkClicked(); + model()->OnBrandLinkClicked(); } namespace {
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.h b/chrome/browser/ui/passwords/manage_passwords_test.h index a314213..49112b1e 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.h +++ b/chrome/browser/ui/passwords/manage_passwords_test.h
@@ -18,9 +18,8 @@ class ManagePasswordsIconView; class PasswordsClientUIDelegate; -// Test class for the various password management view bits and pieces. Sets -// up a ManagePasswordsUIControllerMock, and provides some helper methods -// to poke at the bubble, icon, and controller's state. +// Test class for the various password management view bits and pieces. Provides +// some helper methods to poke at the bubble, icon, and controller's state. class ManagePasswordsTest : public InProcessBrowserTest { public: ManagePasswordsTest();
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.cc index 9c05be16..98e9d174 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.cc
@@ -12,99 +12,11 @@ ManagePasswordsUIControllerMock::ManagePasswordsUIControllerMock( content::WebContents* contents) - : ManagePasswordsUIController(contents), - navigated_to_settings_page_(false), - saved_password_(false), - updated_password_(false), - never_saved_password_(false), - choose_credential_(false), - state_overridden_(false), - state_(password_manager::ui::INACTIVE_STATE), - password_manager_(&client_) { + : ManagePasswordsUIController(contents) { // Do not silently replace an existing ManagePasswordsUIController because it // unregisters itself in WebContentsDestroyed(). EXPECT_FALSE(contents->GetUserData(UserDataKey())); contents->SetUserData(UserDataKey(), this); - set_client(&client_); } -ManagePasswordsUIControllerMock:: - ~ManagePasswordsUIControllerMock() {} - -void ManagePasswordsUIControllerMock:: - NavigateToPasswordManagerSettingsPage() { - navigated_to_settings_page_ = true; -} - -const autofill::PasswordForm& - ManagePasswordsUIControllerMock::GetPendingPassword() const { - return pending_password_; -} - -void ManagePasswordsUIControllerMock::SetPendingPassword( - autofill::PasswordForm pending_password) { - pending_password_ = pending_password; -} - -password_manager::ui::State ManagePasswordsUIControllerMock::GetState() const { - return state_overridden_ ? state_ : ManagePasswordsUIController::GetState(); -} - -void ManagePasswordsUIControllerMock::SetState( - password_manager::ui::State state) { - state_overridden_ = true; - state_ = state; -} - -void ManagePasswordsUIControllerMock::UnsetState() { - state_overridden_ = false; -} - -void ManagePasswordsUIControllerMock::UpdateBubbleAndIconVisibility() { - OnBubbleShown(); -} - -void ManagePasswordsUIControllerMock:: - UpdateAndroidAccountChooserInfoBarVisibility() { - OnBubbleShown(); -} - -void ManagePasswordsUIControllerMock::OnBubbleHidden() {} - -void ManagePasswordsUIControllerMock::SavePassword() { - saved_password_ = true; -} - -void ManagePasswordsUIControllerMock::UpdatePassword( - const autofill::PasswordForm& password_form) { - updated_password_ = true; -} -void ManagePasswordsUIControllerMock::NeverSavePassword() { - never_saved_password_ = true; -} - -void ManagePasswordsUIControllerMock::ChooseCredential( - const autofill::PasswordForm& form, - password_manager::CredentialType form_type) { - EXPECT_FALSE(choose_credential_); - choose_credential_ = true; - chosen_credential_ = form; -} - -password_manager::InteractionsStats* -ManagePasswordsUIControllerMock::GetCurrentInteractionStats() const { - return nullptr; -} - -void ManagePasswordsUIControllerMock::PretendSubmittedPassword( - ScopedVector<autofill::PasswordForm> best_matches) { - ASSERT_FALSE(best_matches.empty()); - autofill::PasswordForm observed_form = *best_matches[0]; - scoped_ptr<password_manager::PasswordFormManager> form_manager( - new password_manager::PasswordFormManager(&password_manager_, &client_, - driver_.AsWeakPtr(), - observed_form, true)); - form_manager->SimulateFetchMatchingLoginsFromPasswordStore(); - form_manager->OnGetPasswordStoreResults(best_matches.Pass()); - OnPasswordSubmitted(form_manager.Pass()); -} +ManagePasswordsUIControllerMock::~ManagePasswordsUIControllerMock() {}
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h b/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h index 3d105458..3838ab2f 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h
@@ -5,102 +5,45 @@ #ifndef CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_MOCK_H_ #define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_MOCK_H_ -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" -#include "components/password_manager/core/browser/password_manager.h" -#include "components/password_manager/core/browser/stub_password_manager_client.h" -#include "components/password_manager/core/browser/stub_password_manager_driver.h" -#include "components/password_manager/core/common/password_manager_ui.h" -#include "content/public/browser/navigation_details.h" +#include "testing/gmock/include/gmock/gmock.h" namespace content { class WebContents; } // namespace content -namespace password_manager { -class PasswordManager; -class PasswordManagerClient; -class PasswordManagerDriver; -enum class CredentialType; -} - -// This mock is used in tests to ensure that we're just testing the controller -// behavior, and not the behavior of the bits and pieces it relies upon (like -// FormManager). -class ManagePasswordsUIControllerMock - : public ManagePasswordsUIController { +class ManagePasswordsUIControllerMock : public ManagePasswordsUIController { public: explicit ManagePasswordsUIControllerMock( content::WebContents* contents); ~ManagePasswordsUIControllerMock() override; - // Navigation, surprisingly, is platform-specific; Android's settings page - // is native UI and therefore isn't available in a tab for unit tests. - // - // TODO(mkwst): Determine how to reasonably test this on that platform. - void NavigateToPasswordManagerSettingsPage() override; - bool navigated_to_settings_page() const { - return navigated_to_settings_page_; - } - - // We don't have a FormManager in tests, so stub these out. - void SavePassword() override; - bool saved_password() const { return saved_password_; } - - void UpdatePassword(const autofill::PasswordForm& password_form) override; - bool updated_password() const { return updated_password_; } - - void NeverSavePassword() override; - bool never_saved_password() const { return never_saved_password_; } - - void ChooseCredential(const autofill::PasswordForm& form, - password_manager::CredentialType form_type) override; - bool choose_credential() const { return choose_credential_; } - autofill::PasswordForm chosen_credential() { return chosen_credential_; } - - const autofill::PasswordForm& GetPendingPassword() const override; - void SetPendingPassword(autofill::PasswordForm pending_password); - - password_manager::ui::State GetState() const override; - void SetState(password_manager::ui::State state); - void UnsetState(); - - void UpdateBubbleAndIconVisibility() override; - - void UpdateAndroidAccountChooserInfoBarVisibility() override; - - void OnBubbleHidden() override; - - password_manager::InteractionsStats* GetCurrentInteractionStats() - const override; - - // Simulate the pending password state. |best_matches| can't be empty. - void PretendSubmittedPassword( - ScopedVector<autofill::PasswordForm> best_matches); - - static scoped_ptr<password_manager::PasswordFormManager> CreateFormManager( - password_manager::PasswordManagerClient* client, - const autofill::PasswordForm& observed_form, - ScopedVector<autofill::PasswordForm> best_matches); + MOCK_CONST_METHOD0(GetOrigin, const GURL&()); + MOCK_CONST_METHOD0(GetState, password_manager::ui::State()); + MOCK_CONST_METHOD0(GetPendingPassword, const autofill::PasswordForm&()); + MOCK_CONST_METHOD0(IsPasswordOverridden, bool()); + MOCK_CONST_METHOD0(GetCurrentForms, + const std::vector<const autofill::PasswordForm*>&()); + MOCK_CONST_METHOD0(GetFederatedForms, + const std::vector<const autofill::PasswordForm*>&()); + MOCK_CONST_METHOD0(GetCurrentInteractionStats, + password_manager::InteractionsStats*()); + MOCK_METHOD0(OnBubbleShown, void()); + MOCK_METHOD0(OnBubbleHidden, void()); + MOCK_METHOD0(OnNoInteractionOnUpdate, void()); + MOCK_METHOD0(OnNopeUpdateClicked, void()); + MOCK_METHOD0(NeverSavePassword, void()); + MOCK_METHOD0(SavePassword, void()); + MOCK_METHOD1(UpdatePassword, void(const autofill::PasswordForm&)); + MOCK_METHOD2(ChooseCredential, + void(const autofill::PasswordForm&, + password_manager::CredentialType)); + MOCK_METHOD0(NavigateToExternalPasswordManager, void()); + MOCK_METHOD0(NavigateToSmartLockPage, void()); + MOCK_METHOD0(NavigateToSmartLockHelpPage, void()); + MOCK_METHOD0(NavigateToPasswordManagerSettingsPage, void()); private: - bool navigated_to_settings_page_; - bool saved_password_; - bool updated_password_; - bool never_saved_password_; - bool choose_credential_; - bool state_overridden_; - password_manager::ui::State state_; - base::TimeDelta elapsed_; - - autofill::PasswordForm chosen_credential_; - autofill::PasswordForm pending_password_; - - password_manager::StubPasswordManagerClient client_; - password_manager::StubPasswordManagerDriver driver_; - password_manager::PasswordManager password_manager_; - DISALLOW_COPY_AND_ASSIGN(ManagePasswordsUIControllerMock); };
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc index e70815d..8991d50 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -263,15 +263,14 @@ TEST_F(ManagePasswordsUIControllerTest, PasswordSubmitted) { scoped_ptr<password_manager::PasswordFormManager> test_form_manager( CreateFormManager()); + test_form_manager->ProvisionallySave( + test_local_form(), + password_manager::PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); controller()->OnPasswordSubmitted(test_form_manager.Pass()); EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, controller()->GetState()); EXPECT_TRUE(controller()->opened_bubble()); - - // TODO(mkwst): This should be the value of test_local_form().origin, but - // it's being masked by the stub implementation of - // ManagePasswordsUIControllerMock::PendingCredentials. - EXPECT_EQ(GURL::EmptyGURL(), controller()->GetOrigin()); + EXPECT_EQ(test_local_form().origin, controller()->GetOrigin()); ExpectIconStateIs(password_manager::ui::PENDING_PASSWORD_STATE); } @@ -408,12 +407,11 @@ scoped_ptr<password_manager::PasswordFormManager> test_form_manager( CreateFormManager()); + test_form_manager->ProvisionallySave( + test_local_form(), + password_manager::PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); controller()->OnPasswordSubmitted(test_form_manager.Pass()); EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->GetState()); - - // TODO(mkwst): This should be the value of test_local_form().origin, but - // it's being masked by the stub implementation of - // ManagePasswordsUIControllerMock::PendingCredentials. EXPECT_EQ(GURL::EmptyGURL(), controller()->GetOrigin()); ExpectIconStateIs(password_manager::ui::INACTIVE_STATE);
diff --git a/chrome/browser/ui/views/download/download_danger_prompt_views.cc b/chrome/browser/ui/views/download/download_danger_prompt_views.cc index ef7bbfb..cef28d1 100644 --- a/chrome/browser/ui/views/download/download_danger_prompt_views.cc +++ b/chrome/browser/ui/views/download/download_danger_prompt_views.cc
@@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/compiler_specific.h" #include "chrome/browser/download/download_danger_prompt.h" + +#include "base/compiler_specific.h" #include "chrome/browser/download/download_stats.h" #include "chrome/browser/extensions/api/experience_sampling_private/experience_sampling.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/constrained_window/constrained_window_views.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_danger_type.h" #include "content/public/browser/download_item.h" @@ -21,6 +23,7 @@ #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_client_view.h" #include "ui/views/window/dialog_delegate.h" +#include "url/gurl.h" using extensions::ExperienceSamplingEvent; @@ -333,6 +336,11 @@ OnDone done = done_; done_.Reset(); if (download_ != NULL) { + if (!download_->GetURL().is_empty() && + !download_->GetBrowserContext()->IsOffTheRecord()) { + SendSafeBrowsingDownloadRecoveryReport( + action == DownloadDangerPrompt::ACCEPT, download_->GetURL()); + } download_->RemoveObserver(this); download_ = NULL; }
diff --git a/chrome/browser/ui/webui/bookmarks_ui_browsertest.cc b/chrome/browser/ui/webui/bookmarks_ui_browsertest.cc index 81afc7f..8560489 100644 --- a/chrome/browser/ui/webui/bookmarks_ui_browsertest.cc +++ b/chrome/browser/ui/webui/bookmarks_ui_browsertest.cc
@@ -20,11 +20,7 @@ void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); - - // Re-enable accessibility checks when audit failures are resolved. - // AX_TEXT_01: http://crbug.com/559201 - // AX_ARIA_08: http://crbug.com/559202 - // EnableAccessibilityChecksForTestCase(true); + EnableAccessibilityChecksForTestCase(true); } void OpenBookmarksManager() {
diff --git a/chrome/browser/ui/webui/downloads_ui_browsertest.js b/chrome/browser/ui/webui/downloads_ui_browsertest.js index 8ffba04..89fc311 100644 --- a/chrome/browser/ui/webui/downloads_ui_browsertest.js +++ b/chrome/browser/ui/webui/downloads_ui_browsertest.js
@@ -120,8 +120,6 @@ setUp: function() { // Doesn't create any fake downloads. assertEquals(0, downloads.Manager.size()); - - this.updateAccessibilityAuditConfig(); }, };
diff --git a/chrome/browser/ui/webui/downloads_ui_browsertest_base.js b/chrome/browser/ui/webui/downloads_ui_browsertest_base.js index 24ec279..4af9e7e 100644 --- a/chrome/browser/ui/webui/downloads_ui_browsertest_base.js +++ b/chrome/browser/ui/webui/downloads_ui_browsertest_base.js
@@ -47,8 +47,6 @@ * @override */ setUp: function() { - testing.Test.prototype.setUp.call(this); - this.createdDownloads = []; // The entries will begin at 1:00 AM on Sept 2, 2008, and will be spaced @@ -60,26 +58,6 @@ } downloads.Manager.updateAll(this.createdDownloads); expectEquals(downloads.Manager.size(), TOTAL_RESULT_COUNT); - - this.updateAccessibilityAuditConfig(); - }, - - /** - * Disables failing accessibility audits. This should be removed when all - * audit issues have been resolved. - */ - updateAccessibilityAuditConfig: function() { - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/559217 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - '#term'); - - // Enable when failure is resolved. - // AX_FOCUS_03: http://crbug.com/559219 - this.accessibilityAuditConfig.ignoreSelectors( - 'tabIndexGreaterThanZero', - '#term'); }, /**
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js index 1aca91b..d7847ef 100644 --- a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js +++ b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js
@@ -51,14 +51,7 @@ /** @override */ setUp: function() { - testing.Test.prototype.setUp.call(this); testing.Test.disableAnimationsAndTransitions(); - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/560903 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - '#kiosk-app-list'); }, /**
diff --git a/chrome/browser/ui/webui/options/content_settings_handler.cc b/chrome/browser/ui/webui/options/content_settings_handler.cc index 0ecb0dc..60990ff7 100644 --- a/chrome/browser/ui/webui/options/content_settings_handler.cc +++ b/chrome/browser/ui/webui/options/content_settings_handler.cc
@@ -29,6 +29,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" +#include "chrome/common/features.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" @@ -451,7 +452,7 @@ {"cookiesShowCookies", IDS_COOKIES_SHOW_COOKIES_BUTTON}, {"flashStorageSettings", IDS_FLASH_STORAGE_SETTINGS}, {"flashStorageUrl", IDS_FLASH_STORAGE_URL}, -#if defined(ENABLE_GOOGLE_NOW) +#if BUILDFLAG(ENABLE_GOOGLE_NOW) {"googleGeolocationAccessEnable", IDS_GEOLOCATION_GOOGLE_ACCESS_ENABLE_CHKBOX}, #endif
diff --git a/chrome/browser/ui/webui/options/language_options_browsertest.js b/chrome/browser/ui/webui/options/language_options_browsertest.js index bfd3acb6..fc5ffba 100644 --- a/chrome/browser/ui/webui/options/language_options_browsertest.js +++ b/chrome/browser/ui/webui/options/language_options_browsertest.js
@@ -16,23 +16,6 @@ /** @override */ browsePreload: 'chrome://settings-frame/languages', - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559266 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#language-options-list'); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559271 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#languagePage > .content-area > .language-options-header > A'); - } }; // Test opening language options has correct location.
diff --git a/chrome/browser/ui/webui/options/multilanguage_options_webui_browsertest.js b/chrome/browser/ui/webui/options/multilanguage_options_webui_browsertest.js index deeff84..56419fa4 100644 --- a/chrome/browser/ui/webui/options/multilanguage_options_webui_browsertest.js +++ b/chrome/browser/ui/webui/options/multilanguage_options_webui_browsertest.js
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -GEN_INCLUDE(['options_browsertest_base.js']); GEN('#include "chrome/browser/ui/webui/options/' + 'multilanguage_options_browsertest.h"'); @@ -14,7 +13,7 @@ function MultilanguageOptionsWebUIBrowserTest() {} MultilanguageOptionsWebUIBrowserTest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, + __proto__: testing.Test.prototype, /** @override */ browsePreload: 'chrome://settings-frame/languages', @@ -33,7 +32,7 @@ /** @override */ setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); + testing.Test.prototype.setUp.call(this); assertTrue(loadTimeData.getBoolean('enableMultilingualSpellChecker')); assertFalse(cr.isMac); @@ -41,29 +40,6 @@ expectFalse($('edit-custom-dictionary-button').hidden); this.expectEnableSpellcheckCheckboxHidden(); this.expectCurrentlySelected('fr'); - - var requiredOwnedAriaRoleMissingSelectors = [ - '#default-search-engine-list', - '#other-search-engine-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/559320 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - requiredOwnedAriaRoleMissingSelectors); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559266 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#language-options-list'); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559271 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#languagePage > .content-area > .language-options-header > A'); }, /** @override */ @@ -164,7 +140,7 @@ /** @override */ setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); + testing.Test.prototype.setUp.call(this); assertTrue(loadTimeData.getBoolean('enableMultilingualSpellChecker')); assertFalse(cr.isMac); @@ -173,18 +149,6 @@ this.expectEnableSpellcheckCheckboxHidden(); this.expectCurrentlySelected(''); this.expectRegisteredDictionariesPref(''); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559266 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#language-options-list'); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559271 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#languagePage > .content-area > .language-options-header > A'); }, };
diff --git a/chrome/browser/ui/webui/options/options_browsertest.js b/chrome/browser/ui/webui/options/options_browsertest.js index 4de8c19..895928a 100644 --- a/chrome/browser/ui/webui/options/options_browsertest.js +++ b/chrome/browser/ui/webui/options/options_browsertest.js
@@ -79,31 +79,6 @@ this.mockHandler.stubs().observePrefs(ANYTHING); this.mockHandler.stubs().coreOptionsUserMetricsAction(ANYTHING); }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559329 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#profiles-list'); - - var linkWithUnclearPurposeSelectors = [ - '#sync-overview > A', - '#privacy-explanation > A', - '#languages-section > .settings-row > A', - '#cloudprint-options-mdns > .settings-row > A', - '#do-not-track-confirm-overlay > .action-area > .hbox.stretch > A', - ]; - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559318 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - linkWithUnclearPurposeSelectors); - }, }; /** @@ -403,44 +378,6 @@ /** @override */ typedefCppFixture: 'OptionsBrowserTest', - /** @override */ - setUp: function() { - OptionsWebUITest.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559329 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#profiles-list'); - - var controlsWithoutLabelSelectors = [ - '#cookies-view-page > .content-area.cookies-list-content-area > *', - '#other-search-engine-list > .deletable-item > DIV > *', - ]; - - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/559330 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - controlsWithoutLabelSelectors); - - var linkWithUnclearPurposeSelectors = [ - '#sync-overview > A', - '#privacy-explanation > A', - '#languages-section > .settings-row > A', - '#cloudprint-options-mdns > .settings-row > A', - // Selectors below only affect ChromeOS tests. - '#privacy-section > DIV > DIV:nth-of-type(9) > A', - '#accessibility-learn-more', - ]; - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559326 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - linkWithUnclearPurposeSelectors); - }, - testGenPreamble: function() { // Start with no supervised users managed by this profile. GEN(' ClearPref("' + SUPERVISED_USERS_PREF + '");');
diff --git a/chrome/browser/ui/webui/options/options_browsertest_base.js b/chrome/browser/ui/webui/options/options_browsertest_base.js index e298ea1..1483ba32 100644 --- a/chrome/browser/ui/webui/options/options_browsertest_base.js +++ b/chrome/browser/ui/webui/options/options_browsertest_base.js
@@ -16,54 +16,4 @@ /** @override */ accessibilityIssuesAreErrors: true, - - /** @override */ - setUp: function() { - testing.Test.prototype.setUp.call(this); - - var requiredOwnedAriaRoleMissingSelectors = [ - '#address-list', - '#creditcard-list', - '#home-page-overlay > .autocomplete-suggestions', - '#language-options-list', - '#manage-profile-icon-grid', - '#create-profile-icon-grid', - '#saved-passwords-list', - '#password-exceptions-list', - '#extension-keyword-list', - '#startup-overlay > .autocomplete-suggestions', - '#content-settings-exceptions-area > .content-area > *', - '#cookies-list', - '#handlers-list', - '#ignored-handlers-list', - '#supervised-user-list', - '#select-avatar-grid', - '#language-dictionary-overlay-word-list', - // Selectors below only affect ChromeOS tests. - '#bluetooth-unpaired-devices-list', - '#ignored-host-list', - '#remembered-network-list', - '#bluetooth-paired-devices-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/559265 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - requiredOwnedAriaRoleMissingSelectors); - - var tabIndexGreaterThanZeroSelectors = [ - '#user-image-grid', - '#discard-photo', - '#take-photo', - '#flip-photo', - '#change-picture-overlay-confirm', - ]; - - // Enable when failure is resolved. - // AX_FOCUS_03: http://crbug.com/560910 - this.accessibilityAuditConfig.ignoreSelectors( - 'tabIndexGreaterThanZero', - tabIndexGreaterThanZeroSelectors); - }, };
diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc index e69c199..56e784c2 100644 --- a/chrome/browser/ui/webui/options/options_ui.cc +++ b/chrome/browser/ui/webui/options/options_ui.cc
@@ -47,6 +47,7 @@ #include "chrome/browser/ui/webui/options/startup_pages_handler.h" #include "chrome/browser/ui/webui/options/sync_setup_handler.h" #include "chrome/browser/ui/webui/theme_source.h" +#include "chrome/common/features.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/locale_settings.h" @@ -100,7 +101,7 @@ #include "chrome/browser/ui/webui/options/certificate_manager_handler.h" #endif -#if defined(ENABLE_GOOGLE_NOW) +#if BUILDFLAG(ENABLE_GOOGLE_NOW) #include "chrome/browser/ui/webui/options/geolocation_options_handler.h" #endif @@ -279,7 +280,7 @@ AddOptionsPageUIHandler(localized_strings, new CreateProfileHandler()); AddOptionsPageUIHandler(localized_strings, new EasyUnlockHandler()); AddOptionsPageUIHandler(localized_strings, new FontSettingsHandler()); -#if defined(ENABLE_GOOGLE_NOW) +#if BUILDFLAG(ENABLE_GOOGLE_NOW) AddOptionsPageUIHandler(localized_strings, new GeolocationOptionsHandler()); #endif AddOptionsPageUIHandler(localized_strings, new options::HelpOverlayHandler());
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index cfd46cc..9495002 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp
@@ -104,6 +104,7 @@ 'chrome_browser_ui.gypi', 'chrome_common.gypi', 'chrome_installer_util.gypi', + 'chrome_features.gypi', ], 'conditions': [ ['OS!="ios"', {
diff --git a/chrome/chrome_android.gypi b/chrome/chrome_android.gypi index 9c8b394..1f1d797f 100644 --- a/chrome/chrome_android.gypi +++ b/chrome/chrome_android.gypi
@@ -14,6 +14,7 @@ 'chrome.gyp:browser', 'chrome.gyp:browser_ui', 'chrome.gyp:child', + 'chrome_features.gyp:chrome_common_features', 'chrome.gyp:plugin', 'chrome.gyp:renderer', 'chrome.gyp:utility',
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index cba3bcc..d6df1df0 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi
@@ -3066,6 +3066,7 @@ # NOTE: New dependencies should generally be added in the OS!="ios" # dependencies block below, rather than here. 'browser_ui', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:chrome_extra_resources', 'chrome_resources.gyp:chrome_resources', 'chrome_resources.gyp:chrome_strings',
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index 8c0ca4fa..9871077 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi
@@ -956,6 +956,7 @@ # browser, then we can clean up these dependencies. 'dependencies': [ 'browser/extensions/api/api_registration.gyp:chrome_api_registration', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:chrome_extra_resources', 'chrome_resources.gyp:chrome_resources', 'chrome_resources.gyp:chrome_strings',
diff --git a/chrome/chrome_child.gypi b/chrome/chrome_child.gypi index 6464a39..645dd5a 100644 --- a/chrome/chrome_child.gypi +++ b/chrome/chrome_child.gypi
@@ -11,6 +11,7 @@ 'dependencies': [ '../base/base.gyp:base', '../content/content.gyp:content_child', + 'chrome_features.gyp:chrome_common_features', ], 'include_dirs': [ '..',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 1438853..d26010f 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi
@@ -297,6 +297,7 @@ # GN: //chrome/common:common 'target_name': 'common', 'type': 'static_library', + 'hard_dependency': 1, # Because of transitive dep on version_header. 'variables': { 'chrome_common_target': 1, 'enable_wexit_time_destructors': 1, @@ -320,6 +321,7 @@ '<(DEPTH)/base/base.gyp:base_i18n', '<(DEPTH)/base/base.gyp:base_prefs', '<(DEPTH)/base/base.gyp:base_static', + '<(DEPTH)/chrome/chrome_features.gyp:chrome_common_features', '<(DEPTH)/chrome/chrome_resources.gyp:chrome_resources', '<(DEPTH)/chrome/chrome_resources.gyp:chrome_strings', '<(DEPTH)/chrome/chrome_resources.gyp:theme_resources', @@ -565,6 +567,7 @@ ], 'dependencies': [ '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/chrome/chrome_features.gyp:chrome_common_features', '<(DEPTH)/chrome/chrome_resources.gyp:chrome_resources', '<(DEPTH)/chrome/chrome_resources.gyp:chrome_strings', '<(DEPTH)/components/url_formatter/url_formatter.gyp:url_formatter',
diff --git a/chrome/chrome_debugger.gypi b/chrome/chrome_debugger.gypi index 31991c6d..aefbb4d 100644 --- a/chrome/chrome_debugger.gypi +++ b/chrome/chrome_debugger.gypi
@@ -15,6 +15,7 @@ '../net/net.gyp:net', 'browser/devtools/webrtc_device_provider_resources.gyp:webrtc_device_provider_resources', 'browser/devtools/devtools_protocol_constants.gyp:devtools_protocol_constants', + 'chrome_features.gyp:chrome_common_features', ], 'include_dirs': [ '..',
diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi index f593901..a2fa6432 100644 --- a/chrome/chrome_exe.gypi +++ b/chrome/chrome_exe.gypi
@@ -46,7 +46,10 @@ # GN version: //chrome:chrome_initial 'target_name': 'chrome_initial', 'type': 'executable', - 'dependencies' : [ '../chrome/common_constants.gyp:version_header', ], + 'dependencies' : [ + '../chrome/common_constants.gyp:version_header', + '../chrome/chrome_features.gyp:chrome_common_features', + ], # Name the exe chrome.exe, not chrome_initial.exe. 'product_name': 'chrome', 'mac_bundle': 1,
diff --git a/chrome/chrome_features.gyp b/chrome/chrome_features.gyp new file mode 100644 index 0000000..0d29f18 --- /dev/null +++ b/chrome/chrome_features.gyp
@@ -0,0 +1,22 @@ +# Copyright 2015 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. + +{ + 'includes': [ + 'chrome_features.gypi', + ], + 'targets': [ + { + # GN version: //chrome/common:features + 'target_name': 'chrome_common_features', + 'includes': [ '../build/buildflag_header.gypi' ], + 'variables': { + 'buildflag_header_path': 'chrome/common/features.h', + 'buildflag_flags': [ + 'ENABLE_GOOGLE_NOW=<(enable_google_now)', + ], + }, + }, + ] +}
diff --git a/chrome/chrome_features.gypi b/chrome/chrome_features.gypi new file mode 100644 index 0000000..a4d8756 --- /dev/null +++ b/chrome/chrome_features.gypi
@@ -0,0 +1,31 @@ +# Copyright 2015 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 GYP equivalent of //chrome/common/features.gni. +# Please keep in sync! + +{ + 'variables': { + 'variables': { + # Conditional variables. + 'conditions': [ + ['OS=="android" or OS=="ios"', { + 'enable_google_now%': 0, + }, { + 'enable_google_now%': 1, + }] + ], + }, + + # Anything in the conditions needs to be copied to the outer scope to be + # accessible. + 'enable_google_now%': '<(enable_google_now)', + + # Grit defines based on the feature flags. These must be manually added to + # grit targets. + 'chrome_grit_defines': [ + '-D', 'enable_google_now=<(enable_google_now)', + ] + }, +}
diff --git a/chrome/chrome_plugin.gypi b/chrome/chrome_plugin.gypi index 718666c..1cf98f8 100644 --- a/chrome/chrome_plugin.gypi +++ b/chrome/chrome_plugin.gypi
@@ -12,6 +12,7 @@ '../base/base.gyp:base', '../content/content.gyp:content_plugin', '../gin/gin.gyp:gin', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:chrome_strings', ], 'include_dirs': [
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index b12ac525..40f12959 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi
@@ -239,6 +239,7 @@ 'dependencies': [ 'common', 'common_mojo_bindings', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:chrome_resources', 'chrome_resources.gyp:chrome_strings', '../third_party/re2/re2.gyp:re2',
diff --git a/chrome/chrome_resources.gyp b/chrome/chrome_resources.gyp index 6edb8194..85116d4 100644 --- a/chrome/chrome_resources.gyp +++ b/chrome/chrome_resources.gyp
@@ -2,8 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. { + 'includes': [ + 'chrome_features.gypi', + ], 'variables': { + # Apply Chrome-specific grit settings to all grit actions in this file. 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome', + 'grit_additional_defines': [ '<@(chrome_grit_defines)' ], + 'additional_modules_list_file': '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/internal/additional_modules_list.txt', }, 'targets': [
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 28cbfb0..19ecd3b 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -1617,6 +1617,7 @@ 'type': 'executable', 'dependencies': [ 'browser', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:chrome_resources', 'chrome_resources.gyp:chrome_strings', 'chrome_resources.gyp:packed_extra_resources', @@ -2111,6 +2112,7 @@ 'type': 'executable', 'dependencies': [ 'browser', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:browser_tests_pak', 'chrome_resources.gyp:chrome_resources', 'chrome_resources.gyp:chrome_strings', @@ -2655,6 +2657,7 @@ 'type': 'executable', 'dependencies': [ 'browser', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:chrome_resources', 'chrome_resources.gyp:chrome_strings', 'chrome_resources.gyp:packed_extra_resources',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 1dc2c8c..efa77982 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -1658,6 +1658,7 @@ # NOTE: New dependencies should generally be added in the OS!="ios" # dependencies block below, rather than here. 'browser', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:chrome_resources', 'chrome_resources.gyp:chrome_strings', 'chrome_resources.gyp:theme_resources', @@ -2212,6 +2213,7 @@ '../ui/base/ui_base.gyp:ui_base_test_support', '../ui/gfx/gfx.gyp:gfx_test_support', '../ui/resources/ui_resources.gyp:ui_resources', + 'chrome_features.gyp:chrome_common_features', 'chrome_resources.gyp:chrome_resources', 'chrome_resources.gyp:chrome_strings', ],
diff --git a/chrome/chrome_utility.gypi b/chrome/chrome_utility.gypi index d70f335..fb2f15d 100644 --- a/chrome/chrome_utility.gypi +++ b/chrome/chrome_utility.gypi
@@ -124,6 +124,7 @@ '../media/media.gyp:media', '../skia/skia.gyp:skia', '../third_party/libxml/libxml.gyp:libxml', + '<(DEPTH)/chrome/chrome_features.gyp:chrome_common_features', '<(DEPTH)/chrome/chrome_resources.gyp:chrome_resources', '<(DEPTH)/chrome/chrome_resources.gyp:chrome_strings', 'common',
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 0e8b0543..d0cbe2a4 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") +import("//chrome/common/features.gni") import("//chrome/version.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//tools/grit/grit_rule.gni") @@ -36,6 +38,11 @@ } } +buildflag_header("features") { + header = "features.h" + flags = [ "ENABLE_GOOGLE_NOW=$enable_google_now" ] +} + # GYP version: chrome/chrome_common.gypi:common static_library("common") { sources = rebase_path(gypi_values.chrome_common_sources, ".", "//chrome") @@ -47,6 +54,7 @@ ] public_deps = [ + ":features", "//base:base", "//base:base_static", "//base:i18n", @@ -316,6 +324,7 @@ "//content/public/common:result_codes", ] deps = [ + ":features", ":version_header", "//base", "//base/third_party/dynamic_annotations",
diff --git a/chrome/common/extensions/api/file_system_provider.idl b/chrome/common/extensions/api/file_system_provider.idl index b6ab86d..b18d46af 100644 --- a/chrome/common/extensions/api/file_system_provider.idl +++ b/chrome/common/extensions/api/file_system_provider.idl
@@ -54,21 +54,24 @@ // Represents metadata of a file or a directory. dictionary EntryMetadata { - // True if it is a directory. - boolean isDirectory; + // True if it is a directory. Must be provided if requested in + // <code>options</code>. + boolean? isDirectory; // Name of this entry (not full path name). Must not contain '/'. For root - // it must be empty. - DOMString name; + // it must be empty. Must be provided if requested in <code>options</code>. + DOMString? name; - // File size in bytes. Required for <code>OnGetMetadataRequested</code>. + // File size in bytes. Must be provided if requested in + // <code>options</code>. double? size; - // The last modified time of this entry. Required for - // <code>OnGetMetadataRequested</code>. + // The last modified time of this entry. Must be provided if requested in + // <code>options</code>. [instanceOf=Date] object? modificationTime; - // Mime type for the entry. + // Mime type for the entry. Always optional, but should be provided if + // requested in <code>options</code>. DOMString? mimeType; // Thumbnail image as a data URI in either PNG, JPEG or WEBP format, at most @@ -177,6 +180,22 @@ // The path of the entry to fetch metadata about. DOMString entryPath; + // Set to <code>true</code> if <code>is_directory</code> value is requested. + boolean isDirectory; + + // Set to <code>true</code> if <code>name</code> value is requested. + boolean name; + + // Set to <code>true</code> if <code>size</code> value is requested. + boolean size; + + // Set to <code>true</code> if <code>modificationTime</code> value is + // requested. + boolean modificationTime; + + // Set to <code>true</code> if <code>mimeType</code> value is requested. + boolean mimeType; + // Set to <code>true</code> if the thumbnail is requested. boolean thumbnail; }; @@ -203,6 +222,25 @@ // The path of the directory which contents are requested. DOMString directoryPath; + + // Set to <code>true</code> if <code>is_directory</code> value is requested. + boolean isDirectory; + + // Set to <code>true</code> if <code>name</code> value is requested. + boolean name; + + // Set to <code>true</code> if <code>size</code> value is requested. + boolean size; + + // Set to <code>true</code> if <code>modificationTime</code> value is + // requested. + boolean modificationTime; + + // Set to <code>true</code> if <code>mimeType</code> value is requested. + boolean mimeType; + + // Set to <code>true</code> if the thumbnail is requested. + boolean thumbnail; }; // Options for the $(ref:onOpenFileRequested) event.
diff --git a/chrome/common/features.gni b/chrome/common/features.gni new file mode 100644 index 0000000..2e92745c --- /dev/null +++ b/chrome/common/features.gni
@@ -0,0 +1,12 @@ +# Copyright 2015 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 GN version of //chrome/chrome_features.gypi. +# Please keep in sync! + +declare_args() { + enable_google_now = !is_ios && !is_android +} + +chrome_grit_defines = [ "enable_google_now=$enable_google_now" ]
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index f3bfd8e..d546cb0 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -5,6 +5,7 @@ #include "chrome/common/pref_names.h" #include "base/basictypes.h" +#include "chrome/common/features.h" #include "chrome/common/pref_font_webkit_names.h" namespace prefs { @@ -1557,7 +1558,7 @@ const char kGeolocationEnabled[] = "geolocation.enabled"; #endif -#if defined(ENABLE_GOOGLE_NOW) +#if BUILDFLAG(ENABLE_GOOGLE_NOW) // Boolean that is true when Google services can use the user's location. const char kGoogleGeolocationAccessEnabled[] = "googlegeolocationaccess.enabled";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index f82326b4..79e1d12a 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -10,6 +10,7 @@ #include <stddef.h> #include "build/build_config.h" +#include "chrome/common/features.h" namespace prefs { @@ -557,7 +558,7 @@ extern const char kGeolocationEnabled[]; #endif -#if defined(ENABLE_GOOGLE_NOW) +#if BUILDFLAG(ENABLE_GOOGLE_NOW) extern const char kGoogleGeolocationAccessEnabled[]; #endif extern const char kGoogleNowLauncherEnabled[];
diff --git a/chrome/common_constants.gyp b/chrome/common_constants.gyp index 134878e..a8d701f 100644 --- a/chrome/common_constants.gyp +++ b/chrome/common_constants.gyp
@@ -72,6 +72,7 @@ # GN version: //chrome/common:constants 'target_name': 'common_constants', 'type': 'static_library', + 'hard_dependency': 1, # Because of transitive dep on version_header. 'sources': [ '<@(common_constants_sources)' ], @@ -80,6 +81,7 @@ ], 'dependencies': [ 'version_header', + 'chrome_features.gyp:chrome_common_features', '../base/base.gyp:base', '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../components/components.gyp:bookmarks_common', @@ -108,6 +110,7 @@ 'targets': [ { 'target_name': 'common_constants_win64', + 'hard_dependency': 1, # Because of transitive dep on version_header. 'type': 'static_library', 'sources': [ '<@(common_constants_sources)' @@ -117,6 +120,7 @@ ], 'dependencies': [ 'version_header', + 'chrome_features.gyp:chrome_common_features', '../base/base.gyp:base_win64', '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64', '../components/nacl.gyp:nacl_switches_win64',
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc index 76873331..bc7a762 100644 --- a/chrome/renderer/autofill/form_autofill_browsertest.cc +++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -13,7 +13,6 @@ #include "components/autofill/content/renderer/form_cache.h" #include "components/autofill/core/common/autofill_data_validation.h" #include "components/autofill/core/common/form_data.h" -#include "components/autofill/core/common/web_element_descriptor.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebVector.h" @@ -56,6 +55,20 @@ // or Preview. }; +struct WebElementDescriptor { + enum RetrievalMethod { + CSS_SELECTOR, + ID, + NONE, + }; + + // Information to retrieve element with. + std::string descriptor; + + // Which retrieval method to use. + RetrievalMethod retrieval_method = NONE; +}; + const char kFormHtml[] = "<FORM name='TestForm' action='http://buh.com' method='post'>" " <INPUT type='text' id='firstname'/>"
diff --git a/chrome/renderer/resources/extensions/file_system_provider_custom_bindings.js b/chrome/renderer/resources/extensions/file_system_provider_custom_bindings.js index b43a9d7..59c43e54 100644 --- a/chrome/renderer/resources/extensions/file_system_provider_custom_bindings.js +++ b/chrome/renderer/resources/extensions/file_system_provider_custom_bindings.js
@@ -51,16 +51,86 @@ } /** + * Verifies if the passed metadata is valid. + * @param {!GetMetadataOptions|!ReadDirectoryOptions} options + * @return {boolean} True if valid, false if invalid. + */ +function verifyMetadata(options, metadata) { + // Ideally we'd like to consider the following as errors, but for backward + // compatibility they are warnings only. + if (!options.isDirectory && metadata.isDirectory !== undefined) + console.warn('IsDirectory specified, but not requested.'); + if (!options.name && metadata.name !== undefined) + console.warn('Name specified, but not requested.'); + if (!options.size && metadata.size !== undefined) + console.warn('Size specified, but not requested.'); + if (!options.modificationTime && metadata.modificationTime !== undefined) + console.warn('Last modification time specified, but not requested.'); + if (!options.mimeType && metadata.mimeType !== undefined) { + console.warn('MIME type specified, but not requested.'); + } else { + if (metadata.mimeType === '') { + warning = 'MIME type must not be an empty string.' + + 'If unknown, then do not set it.'; + } + } + + if (options.isDirectory && metadata.isDirectory === undefined) { + console.error('IsDirectory is required for this request.'); + return false; + } + + if (options.name && metadata.name === undefined) { + console.error('Name is required for this request.'); + return false; + } + + if (options.size && metadata.size === undefined) { + console.error('Size is required for this request.'); + return false; + } + + if (options.modificationTime && metadata.modificationTime === undefined) { + console.error('Last modification time is required for this request.'); + return false; + } + + // It is invalid to return a thumbnail when it's not requested. The + // restriction is added in order to avoid fetching the thumbnail while + // it's not needed. + if (!options.thumbnail && metadata.thumbnail !== undefined) { + console.error('Thumbnail data provided, but not requested.'); + return false; + } + + // Check the format and size. Note, that in the C++ layer, there is + // another sanity check to avoid passing any evil URL. + if (metadata.thumbnail !== undefined && !verifyImageURI(metadata.thumbnail)) { + console.error('Thumbnail format invalid.'); + return false; + } + + if (metadata.thumbnail !== undefined && + metadata.thumbnail.length > METADATA_THUMBNAIL_SIZE_LIMIT) { + console.error('Thumbnail data too large.'); + return false; + } + + return true; +} + +/** * Annotates an entry metadata by serializing its modifiedTime value. * @param {EntryMetadata} metadata Input metadata. * @return {EntryMetadata} metadata Annotated metadata, which can be passed * back to the C++ layer. */ function annotateMetadata(metadata) { - var result = { - isDirectory: metadata.isDirectory, - name: metadata.name, - }; + var result = {}; + if (metadata.isDirectory !== undefined) + result.isDirectory = metadata.isDirectory; + if (metadata.name !== undefined) + result.name = metadata.name; if (metadata.size !== undefined) result.size = metadata.size; if (metadata.modificationTime !== undefined) @@ -103,32 +173,7 @@ var executionStart = Date.now(); var options = args[0]; var onSuccessCallback = function(metadata) { - var error; - // TODO(mtomasz): Remove the following two fields once crbug.com/413161 - // is landed. - if (options.size !== undefined) - error = 'Size is required for this event.'; - if (options.modificationTime !== undefined) - error = 'Last modified time is required for this event.'; - - // It is invalid to return a thumbnail when it's not requested. The - // restriction is added in order to avoid fetching the thumbnail while - // it's not needed. - if (!options.thumbnail && metadata.thumbnail) - error = 'Thumbnail data provided, but not requested.'; - - // Check the format and size. Note, that in the C++ layer, there is - // another sanity check to avoid passing any evil URL. - if ('thumbnail' in metadata && !verifyImageURI(metadata.thumbnail)) - error = 'Thumbnail format invalid.'; - - if ('thumbnail' in metadata && - metadata.thumbnail.length > METADATA_THUMBNAIL_SIZE_LIMIT) { - error = 'Thumbnail data too large.'; - } - - if (error) { - console.error(error); + if (!verifyMetadata(options, metadata)) { fileSystemProviderInternal.operationRequestedError( options.fileSystemId, options.requestId, 'FAILED', Date.now() - executionStart); @@ -179,25 +224,22 @@ var executionStart = Date.now(); var options = args[0]; var onSuccessCallback = function(entries, hasNext) { - var annotatedEntries = entries.map(annotateMetadata); - // It is invalid to return a thumbnail when it's not requested. - var error; - annotatedEntries.forEach(function(metadata) { - if (metadata.thumbnail) { - var error = - 'Thumbnails must not be provided when reading a directory.'; + var error = false; + for (var i = 0; i < entries; i++) { + if (!validateMetadata(options, entries[i])) { + error = true; return; } - }); + } if (error) { - console.error(error); fileSystemProviderInternal.operationRequestedError( options.fileSystemId, options.requestId, 'FAILED', Date.now() - executionStart); return; } + var annotatedEntries = entries.map(annotateMetadata); fileSystemProviderInternal.readDirectoryRequestedSuccess( options.fileSystemId, options.requestId, annotatedEntries, hasNext, Date.now() - executionStart);
diff --git a/chrome/test/data/chromeos/oobe_webui_browsertest.js b/chrome/test/data/chromeos/oobe_webui_browsertest.js index c14bff61..e2c4ce57 100644 --- a/chrome/test/data/chromeos/oobe_webui_browsertest.js +++ b/chrome/test/data/chromeos/oobe_webui_browsertest.js
@@ -57,62 +57,6 @@ this.accessibilityAuditConfig.ignoreSelectors( 'focusableElementNotVisibleAndNotAriaHidden', '#iconButton'); - - // Enable when failure is resolved. - // AX_ARIA_02: http://crbug.com/560932 - this.accessibilityAuditConfig.ignoreSelectors( - 'nonExistentAriaRelatedElement', - '#cancelConfirmDlg'); - - var requiredOwnedAriaRoleMissingSelectors = [ - '#networks-list-dropdown-container', - '#offline-networks-list-dropdown-container', - '#supervised-user-creation-image-grid', - 'body > .decorated', - ]; - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/560924 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - requiredOwnedAriaRoleMissingSelectors); - - var badAriaAttributeSelectors = [ - '#forgotPasswordDlg', - '#cancelConfirmDlg', - ]; - - // Enable when failure is resolved. - // AX_ARIA_11: http://crbug.com/560935 - this.accessibilityAuditConfig.ignoreSelectors( - 'badAriaAttribute', - badAriaAttributeSelectors); - - var tabIndexGreaterThanZeroSelectors = [ - '#user-image-grid', - '#discard-photo', - '#take-photo', - '#flip-photo', - ]; - - // Enable when failure is resolved. - // AX_FOCUS_03: http://crbug.com/560928 - this.accessibilityAuditConfig.ignoreSelectors( - 'tabIndexGreaterThanZero', - tabIndexGreaterThanZeroSelectors); - - var controlsWithoutLabelSelectors = [ - '#supervised-user-creation-managers-pane', - '#supervised-user-creation-name', - '#supervised-user-creation-password', - '#supervised-user-creation-password-confirm', - ]; - - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/560939 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - controlsWithoutLabelSelectors); }, };
diff --git a/chrome/test/data/extensions/api_test/file_system_provider/get_metadata/test.js b/chrome/test/data/extensions/api_test/file_system_provider/get_metadata/test.js index 680ac3d7..a7a57a9 100644 --- a/chrome/test/data/extensions/api_test/file_system_provider/get_metadata/test.js +++ b/chrome/test/data/extensions/api_test/file_system_provider/get_metadata/test.js
@@ -38,6 +38,36 @@ }); /** + * @type {Object} + * @const + */ +var TESTING_ONLY_BASIC_FILE = Object.freeze({ + isDirectory: false, + name: 'invalid-time.txt', +}); + +/** + * @type {string} + * @const + */ +var TESTING_ONLY_BASIC_FILE_NAME = 'basic.txt'; + +/** + * @type {Object} + * @const + */ +var TESTING_ONLY_SIZE_FILE = Object.freeze({ + isDirectory: false, + size: 4096 +}); + +/** + * @type {string} + * @const + */ +var TESTING_ONLY_SIZE_FILE_NAME = 'only-size.txt'; + +/** * Returns metadata for a requested entry. * * @param {GetMetadataRequestedOptions} options Options. @@ -66,6 +96,16 @@ return; } + if (options.entryPath === '/' + TESTING_ONLY_BASIC_FILE_NAME) { + onSuccess(TESTING_ONLY_BASIC_FILE); + return; + } + + if (options.entryPath === '/' + TESTING_ONLY_SIZE_FILE_NAME) { + onSuccess(TESTING_ONLY_SIZE_FILE); + return; + } + onError('NOT_FOUND'); // enum ProviderError. } @@ -170,6 +210,59 @@ chrome.test.callbackPass(function(error) { chrome.test.assertEq('TypeMismatchError', error.name); })); + }, + + // Resolving a file should only request is_directory and name fields. + function getMetadataForGetFile() { + test_util.fileSystem.root.getFile( + TESTING_ONLY_BASIC_FILE_NAME, + {create: false}, + chrome.test.callbackPass(function(fileEntry) { + chrome.test.assertTrue(!!fileEntry); + }), + function(error) { + chrome.test.fail(error.name); + }); + }, + + // Check that if a requested mandatory field is missing, then the error + // callback is invoked. + function getMetadataMissingFields() { + test_util.fileSystem.root.getFile( + TESTING_ONLY_SIZE_FILE_NAME, + {create: false}, + chrome.test.callbackPass(function(fileEntry) { + fileEntry.getMetadata( + function(metadata) { + chrome.test.fail('Unexpected success'); + }, + chrome.test.callbackPass(function(error) { + chrome.test.assertEq('InvalidStateError', error.name); + })); + }), + function(error) { + chrome.test.fail(error.name); + }); + }, + + // Fetch only requested fields. + function getEntryPropertiesFewFields() { + test_util.fileSystem.root.getFile( + TESTING_ONLY_SIZE_FILE_NAME, + {create: false}, + chrome.test.callbackPass(function(fileEntry) { + chrome.fileManagerPrivate.getEntryProperties( + [fileEntry], + ['size'], + chrome.test.callbackPass(function(fileProperties) { + chrome.test.assertEq(1, fileProperties.length); + chrome.test.assertEq( + TESTING_ONLY_SIZE_FILE.size, fileProperties[0].size); + })); + }), + function(error) { + chrome.test.fail(error.name); + }); } ]); }
diff --git a/chrome/test/data/extensions/api_test/file_system_provider/read_directory/test.js b/chrome/test/data/extensions/api_test/file_system_provider/read_directory/test.js index 3879a7f..10c96c7 100644 --- a/chrome/test/data/extensions/api_test/file_system_provider/read_directory/test.js +++ b/chrome/test/data/extensions/api_test/file_system_provider/read_directory/test.js
@@ -10,9 +10,7 @@ */ var TESTING_HELLO_DIR = Object.freeze({ isDirectory: true, - name: 'hello', - size: 0, - modificationTime: new Date(2014, 3, 27, 9, 38, 14) + name: 'hello' }); /** @@ -21,9 +19,7 @@ */ var TESTING_CANDIES_DIR = Object.freeze({ isDirectory: true, - name: 'candies', - size: 0, - modificationTime: new Date(2014, 2, 26, 8, 37, 13) + name: 'candies' }); /** @@ -32,9 +28,7 @@ */ var TESTING_TIRAMISU_FILE = Object.freeze({ isDirectory: false, - name: 'tiramisu.txt', - size: 1986, - modificationTime: new Date(2014, 1, 25, 7, 36, 12) + name: 'tiramisu.txt' }); /**
diff --git a/chrome/test/data/webui/history_browsertest.js b/chrome/test/data/webui/history_browsertest.js index d49ee8b..d8792ea 100644 --- a/chrome/test/data/webui/history_browsertest.js +++ b/chrome/test/data/webui/history_browsertest.js
@@ -775,17 +775,6 @@ // Add a visit on the next day. GEN(' AddPageToHistory(36, "http://google.com", "Google");'); }, - - /** @override */ - setUp: function() { - BaseHistoryWebUITest.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/560914 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#notification-bar > A'); - }, }; /**
diff --git a/chrome/test/data/webui/net_internals/net_internals_test.js b/chrome/test/data/webui/net_internals/net_internals_test.js index b381ec82..56bc93f6 100644 --- a/chrome/test/data/webui/net_internals/net_internals_test.js +++ b/chrome/test/data/webui/net_internals/net_internals_test.js
@@ -56,8 +56,6 @@ isAsync: true, setUp: function() { - testing.Test.prototype.setUp.call(this); - // Enforce accessibility auditing, but suppress some false positives. this.accessibilityIssuesAreErrors = true; // False positive because a unicode character is used to draw a square. @@ -81,25 +79,6 @@ this.accessibilityAuditConfig.auditRulesToIgnore.push( 'focusableElementNotVisibleAndNotAriaHidden'); - var controlsWithoutLabelSelectors = [ - '#export-view-user-comments', - '#hsts-view-add-input', - '#hsts-view-delete-input', - '#hsts-view-query-input', - ]; - - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/559203 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - controlsWithoutLabelSelectors); - - // Enable when warning is resolved. - // AX_HTML_01: http://crbug.com/559204 - this.accessibilityAuditConfig.ignoreSelectors( - 'humanLangMissing', - 'html'); - // Wrap g_browser.receive around a test function so that assert and expect // functions can be called from observers. g_browser.receive =
diff --git a/chrome/test/data/webui/print_preview.js b/chrome/test/data/webui/print_preview.js index 7d84ef9..2ef9260 100644 --- a/chrome/test/data/webui/print_preview.js +++ b/chrome/test/data/webui/print_preview.js
@@ -166,7 +166,6 @@ * @override */ setUp: function() { - testing.Test.prototype.setUp.call(this); Mock4JS.clearMocksToVerify(); this.initialSettings_ = new print_preview.NativeInitialSettings( @@ -190,12 +189,6 @@ this.nativeLayer_ = printPreview.nativeLayer_; testing.Test.disableAnimationsAndTransitions(); - - // Enable when failure is resolved. - // AX_TEXT_03: http://crbug.com/559209 - this.accessibilityAuditConfig.ignoreSelectors( - 'multipleLabelableElementsPerLabel', - '#page-settings > .right-column > *'); } };
diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js index 248929b..4c2243ed 100644 --- a/chrome/test/data/webui/test_api.js +++ b/chrome/test/data/webui/test_api.js
@@ -168,10 +168,15 @@ /** * Returns the configuration for the accessibility audit, creating it * on-demand. - * @return {!axs.AuditConfiguration} + * @return {axs.AuditConfiguration} */ get accessibilityAuditConfig() { - if (!this.accessibilityAuditConfig_) { + // The axs namespace is not available in chromevox tests. + // Further, 'window' is not available in unit tests, but since the + // accessibility audit library pulls in the closure library, + // 'goog.global' has to be present if axs is, so we use that here. + if (!this.accessibilityAuditConfig_ && + goog && goog.global && goog.global.axs) { this.accessibilityAuditConfig_ = new axs.AuditConfiguration(); this.accessibilityAuditConfig_.showUnsupportedRulesWarning = false; @@ -191,10 +196,6 @@ // TODO(aboxhall): re-enable when crbug.com/267035 is fixed. // Until then it's just noise. "lowContrastElements", - - // TODO(apacible): re-enable when following issue is fixed. - // github.com/GoogleChrome/accessibility-developer-tools/issues/251 - "tableHasAppropriateHeaders", ]; } return this.accessibilityAuditConfig_; @@ -306,14 +307,17 @@ * @type {Function} */ setUp: function() { - // These should be ignored in many of the web UI tests. - // user-image-stream and supervised-user-creation-image-stream are - // streaming video elements used for capturing a user image so they - // won't have captions and should be ignored everywhere. - this.accessibilityAuditConfig.ignoreSelectors('videoWithoutCaptions', - '.user-image-stream'); - this.accessibilityAuditConfig.ignoreSelectors( - 'videoWithoutCaptions', '.supervised-user-creation-image-stream'); + var auditConfig = this.accessibilityAuditConfig; + if (auditConfig) { + // These should be ignored in many of the web UI tests. + // user-image-stream and supervised-user-creation-image-stream are + // streaming video elements used for capturing a user image so they + // won't have captions and should be ignored everywhere. + auditConfig.ignoreSelectors('videoWithoutCaptions', + '.user-image-stream'); + auditConfig.ignoreSelectors( + 'videoWithoutCaptions', '.supervised-user-creation-image-stream'); + } }, /**
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index fe4d52d..afdc5c7 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -7673.0.0 \ No newline at end of file +7678.0.0 \ No newline at end of file
diff --git a/components/arc.gypi b/components/arc.gypi index ccff1f3..3773f09 100644 --- a/components/arc.gypi +++ b/components/arc.gypi
@@ -19,6 +19,8 @@ 'sources': [ 'arc/arc_bridge_service.cc', 'arc/arc_bridge_service.h', + 'arc/arc_bridge_service_impl.cc', + 'arc/arc_bridge_service_impl.h', 'arc/common/arc_host_messages.h', 'arc/common/arc_instance_messages.h', 'arc/common/arc_message_generator.cc',
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index e6d6cae..e6f40684 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn
@@ -6,6 +6,8 @@ sources = [ "arc_bridge_service.cc", "arc_bridge_service.h", + "arc_bridge_service_impl.cc", + "arc_bridge_service_impl.h", "common/arc_message_generator.cc", ]
diff --git a/components/arc/arc_bridge_service.cc b/components/arc/arc_bridge_service.cc index e2146c22..af2835d 100644 --- a/components/arc/arc_bridge_service.cc +++ b/components/arc/arc_bridge_service.cc
@@ -5,57 +5,40 @@ #include "components/arc/arc_bridge_service.h" #include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/prefs/pref_registry_simple.h" -#include "base/prefs/pref_service.h" -#include "base/task_runner_util.h" +#include "base/sequenced_task_runner.h" #include "base/thread_task_runner_handle.h" #include "chromeos/chromeos_switches.h" -#include "chromeos/dbus/dbus_method_call_status.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/session_manager_client.h" -#include "components/arc/common/arc_host_messages.h" -#include "components/arc/common/arc_instance_messages.h" -#include "ipc/ipc_channel.h" +#include "components/arc/arc_bridge_service_impl.h" namespace arc { namespace { -const base::FilePath::CharType kArcBridgeSocketPath[] = - FILE_PATH_LITERAL("/home/chronos/ArcBridge/bridge.sock"); - // Weak pointer. This class is owned by ChromeBrowserMainPartsChromeos. ArcBridgeService* g_arc_bridge_service = nullptr; } // namespace -ArcBridgeService::ArcBridgeService( - const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, - const scoped_refptr<base::SequencedTaskRunner>& file_task_runner) +ArcBridgeService::ArcBridgeService() : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()), - ipc_task_runner_(ipc_task_runner), - file_task_runner_(file_task_runner), - session_started_(false), available_(false), - state_(State::STOPPED), - weak_factory_(this) { + state_(State::STOPPED) { DCHECK(!g_arc_bridge_service); g_arc_bridge_service = this; } ArcBridgeService::~ArcBridgeService() { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(state_ == State::STOPPING || state_ == State::STOPPED); - DCHECK(g_arc_bridge_service); + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(state() == State::STOPPING || state() == State::STOPPED); + DCHECK(g_arc_bridge_service == this); g_arc_bridge_service = nullptr; } // static ArcBridgeService* ArcBridgeService::Get() { DCHECK(g_arc_bridge_service); - DCHECK(g_arc_bridge_service->origin_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(g_arc_bridge_service->origin_task_runner()-> + RunsTasksOnCurrentThread()); return g_arc_bridge_service; } @@ -64,233 +47,37 @@ return command_line->HasSwitch(chromeos::switches::kEnableArc); } -void ArcBridgeService::DetectAvailability() { - chromeos::SessionManagerClient* session_manager_client = - chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); - session_manager_client->CheckArcAvailability(base::Bind( - &ArcBridgeService::OnArcAvailable, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::HandleStartup() { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - session_started_ = true; - PrerequisitesChanged(); -} - -void ArcBridgeService::Shutdown() { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - session_started_ = false; - PrerequisitesChanged(); -} - void ArcBridgeService::AddObserver(Observer* observer) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); observer_list_.AddObserver(observer); } void ArcBridgeService::RemoveObserver(Observer* observer) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); observer_list_.RemoveObserver(observer); } -void ArcBridgeService::PrerequisitesChanged() { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (state_ == State::STOPPED) { - if (!available_ || !session_started_) - return; - SocketConnect(base::FilePath(kArcBridgeSocketPath)); - } else { - if (available_ && session_started_) - return; - StopInstance(); - } -} - -void ArcBridgeService::StopInstance() { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (state_ == State::STOPPED || state_ == State::STOPPING) { - VLOG(1) << "StopInstance() called when ARC is not running"; - return; - } - if (state_ == State::CONNECTED || state_ == State::CONNECTING) { - // This was stopped before the D-Bus command to start the instance. Just - // close the socket (if it was opened). - if (state_ == State::CONNECTED) { - ipc_channel_.reset(); - } - SetState(State::STOPPED); - return; - } - - SetState(State::STOPPING); - chromeos::SessionManagerClient* session_manager_client = - chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); - session_manager_client->StopArcInstance(base::Bind( - &ArcBridgeService::OnInstanceStopped, weak_factory_.GetWeakPtr())); -} - -bool ArcBridgeService::RegisterInputDevice(const std::string& name, - const std::string& device_type, - base::ScopedFD fd) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (state_ != State::READY) { - LOG(ERROR) << "Called RegisterInputDevice when the service is not ready"; - return false; - } - return ipc_channel_->Send(new ArcInstanceMsg_RegisterInputDevice( - name, device_type, base::FileDescriptor(fd.Pass()))); -} - -void ArcBridgeService::SocketConnect(const base::FilePath& socket_path) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (state_ != State::STOPPED) { - VLOG(1) << "SocketConnect() called when instance is not stopped"; - return; - } - SetState(State::CONNECTING); - base::PostTaskAndReplyWithResult( - file_task_runner_.get(), FROM_HERE, - base::Bind(&base::CreateDirectory, socket_path.DirName()), - base::Bind(&ArcBridgeService::SocketConnectAfterEnsureParentDirectory, - weak_factory_.GetWeakPtr(), socket_path)); -} - -void ArcBridgeService::SocketConnectAfterEnsureParentDirectory( - const base::FilePath& socket_path, - bool directory_present) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (state_ != State::CONNECTING) { - VLOG(1) << "StopInstance() called while connecting"; - return; - } - if (!directory_present) { - LOG(ERROR) << "Error creating directory for " << socket_path.value(); - StopInstance(); - return; - } - - if (!Connect(IPC::ChannelHandle(socket_path.value()), - IPC::Channel::MODE_OPEN_NAMED_SERVER)) { - LOG(ERROR) << "Error connecting to " << socket_path.value(); - StopInstance(); - return; - } - - base::PostTaskAndReplyWithResult( - file_task_runner_.get(), FROM_HERE, - // TODO(lhchavez): Tighten the security around the socket by tying it to - // the user the instance will run as. - base::Bind(&base::SetPosixFilePermissions, socket_path, 0777), - base::Bind(&ArcBridgeService::SocketConnectAfterSetSocketPermissions, - weak_factory_.GetWeakPtr(), socket_path)); -} - -bool ArcBridgeService::Connect(const IPC::ChannelHandle& handle, - IPC::Channel::Mode mode) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (state_ != State::CONNECTING) { - VLOG(1) << "StopInstance() called while connecting"; - return false; - } - - ipc_channel_ = - IPC::ChannelProxy::Create(handle, mode, this, ipc_task_runner_.get()); - if (!ipc_channel_) - return false; - SetState(State::CONNECTED); - return true; -} - -void ArcBridgeService::SocketConnectAfterSetSocketPermissions( - const base::FilePath& socket_path, - bool socket_permissions_success) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (state_ != State::CONNECTED) { - VLOG(1) << "StopInstance() called while connecting"; - return; - } - - if (!socket_permissions_success) { - LOG(ERROR) << "Error setting socket permissions for " - << socket_path.value(); - StopInstance(); - return; - } - - SetState(State::STARTING); - chromeos::SessionManagerClient* session_manager_client = - chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); - session_manager_client->StartArcInstance( - socket_path.value(), base::Bind(&ArcBridgeService::OnInstanceStarted, - weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnInstanceStarted(bool success) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (state_ != State::STARTING) { - VLOG(1) << "StopInstance() called while connecting"; - return; - } - if (!success) { - LOG(ERROR) << "ARC instance unable to start. Shutting down the bridge"; - StopInstance(); - return; - } -} - -void ArcBridgeService::OnInstanceBootPhase(InstanceBootPhase phase) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - // The state can be STARTING the first time this is called, and will then - // transition to READY after BRIDGE_READY has been passed. - if (state_ != State::STARTING && state_ != State::READY) { - VLOG(1) << "StopInstance() called while connecting"; - return; - } - if (phase == InstanceBootPhase::BRIDGE_READY) { - SetState(State::READY); - } - FOR_EACH_OBSERVER(Observer, observer_list_, OnInstanceBootPhase(phase)); -} - void ArcBridgeService::SetState(State state) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); // DCHECK on enum classes not supported. DCHECK(state_ != state); state_ = state; - FOR_EACH_OBSERVER(Observer, observer_list_, OnStateChanged(state_)); + FOR_EACH_OBSERVER(Observer, observer_list(), OnStateChanged(state_)); } -bool ArcBridgeService::OnMessageReceived(const IPC::Message& message) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - bool handled = true; - - IPC_BEGIN_MESSAGE_MAP(ArcBridgeService, message) - IPC_MESSAGE_HANDLER(ArcInstanceHostMsg_InstanceBootPhase, - OnInstanceBootPhase) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - if (!handled) - LOG(ERROR) << "Invalid message with type = " << message.type(); - return handled; -} - -void ArcBridgeService::OnArcAvailable(bool available) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - if (available_ == available) - return; +void ArcBridgeService::SetAvailable(bool available) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(available_ != available); available_ = available; - FOR_EACH_OBSERVER(Observer, observer_list_, OnAvailableChanged(available_)); - PrerequisitesChanged(); + FOR_EACH_OBSERVER(Observer, observer_list(), OnAvailableChanged(available_)); } -void ArcBridgeService::OnInstanceStopped(bool success) { - DCHECK(origin_task_runner_->RunsTasksOnCurrentThread()); - // STOPPING is the only valid state for this function. - // DCHECK on enum classes not supported. - DCHECK(state_ == State::STOPPING); - ipc_channel_.reset(); - SetState(State::STOPPED); +// static +scoped_ptr<ArcBridgeService> ArcBridgeService::Create( + const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, + const scoped_refptr<base::SequencedTaskRunner>& file_task_runner) { + return make_scoped_ptr(new ArcBridgeServiceImpl(ipc_task_runner, + file_task_runner)); } } // namespace arc
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h index 14fdf84..78e8fa8 100644 --- a/components/arc/arc_bridge_service.h +++ b/components/arc/arc_bridge_service.h
@@ -5,24 +5,24 @@ #ifndef COMPONENTS_ARC_ARC_BRIDGE_SERVICE_H_ #define COMPONENTS_ARC_ARC_BRIDGE_SERVICE_H_ +#include "base/files/scoped_file.h" #include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "base/observer_list.h" -#include "base/sequenced_task_runner.h" #include "components/arc/common/arc_message_types.h" -#include "ipc/ipc_channel_proxy.h" -#include "ipc/ipc_listener.h" -#include "ipc/ipc_message.h" namespace base { class CommandLine; -} +class SequencedTaskRunner; +class SingleThreadTaskRunner; +} // namespace base namespace arc { // The Chrome-side service that handles ARC instances and ARC bridge creation. // This service handles the lifetime of ARC instances and sets up the // communication channel (the ARC bridge) used to send and receive messages. -class ArcBridgeService : public IPC::Listener { +class ArcBridgeService { public: // The possible states of the bridge. In the normal flow, the state changes // in the following sequence: @@ -79,10 +79,12 @@ virtual ~Observer() {} }; - ArcBridgeService( + virtual ~ArcBridgeService(); + + // Creates instance of |ArcBridgeService| for normal use. + static scoped_ptr<ArcBridgeService> Create( const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, const scoped_refptr<base::SequencedTaskRunner>& file_task_runner); - ~ArcBridgeService() override; // Gets the global instance of the ARC Bridge Service. This can only be // called on the thread that this class was created on. @@ -95,16 +97,16 @@ // DetectAvailability() should be called once D-Bus is available. It will // call CheckArcAvailability() on the session_manager. This can only be // called on the thread that this class was created on. - void DetectAvailability(); + virtual void DetectAvailability() = 0; // HandleStartup() should be called upon profile startup. This will only // launch an instance if the instance service is available and it is enabled. // This can only be called on the thread that this class was created on. - void HandleStartup(); + virtual void HandleStartup() = 0; // Shutdown() should be called when the browser is shutting down. This can // only be called on the thread that this class was created on. - void Shutdown(); + virtual void Shutdown() = 0; // Adds or removes observers. This can only be called on the thread that this // class was created on. @@ -123,73 +125,36 @@ // OS Keyboard"), |device_type| the name of the device type (e.g. "keyboard") // and |fd| a file descriptor that emulates the kernel events of the device. // This can only be called on the thread that this class was created on. - bool RegisterInputDevice(const std::string& name, - const std::string& device_type, - base::ScopedFD fd); + virtual bool RegisterInputDevice(const std::string& name, + const std::string& device_type, + base::ScopedFD fd) = 0; - private: - friend class ArcBridgeTest; - FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, Basic); - FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, ShutdownMidStartup); - - // If all pre-requisites are true (ARC is available, it has been enabled, and - // the session has started), and ARC is stopped, start ARC. If ARC is running - // and the pre-requisites stop being true, stop ARC. - void PrerequisitesChanged(); - - // Binds to the socket specified by |socket_path|. - void SocketConnect(const base::FilePath& socket_path); - - // Binds to the socket specified by |socket_path| after creating its parent - // directory is present. - void SocketConnectAfterEnsureParentDirectory( - const base::FilePath& socket_path, - bool directory_present); - - // Internal connection method. Separated to make testing easier. - bool Connect(const IPC::ChannelHandle& handle, IPC::Channel::Mode mode); - - // Finishes connecting after setting socket permissions. - void SocketConnectAfterSetSocketPermissions(const base::FilePath& socket_path, - bool socket_permissions_success); - - // Stops the running instance. - void StopInstance(); - - // Called when the instance has reached a boot phase - void OnInstanceBootPhase(InstanceBootPhase phase); + protected: + ArcBridgeService(); // Changes the current state and notifies all observers. void SetState(State state); - // IPC::Listener: - bool OnMessageReceived(const IPC::Message& message) override; + // Changes the current availability and notifies all observers. + void SetAvailable(bool availability); - // DBus callbacks. - void OnArcAvailable(bool available); - void OnInstanceStarted(bool success); - void OnInstanceStopped(bool success); + const scoped_refptr<base::SequencedTaskRunner>& origin_task_runner() const { + return origin_task_runner_; + } + base::ObserverList<Observer>& observer_list() { return observer_list_; } + + private: scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_; - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; - - scoped_ptr<IPC::ChannelProxy> ipc_channel_; base::ObserverList<Observer> observer_list_; - // If the user's session has started. - bool session_started_; - // If the ARC instance service is available. bool available_; // The current state of the bridge. ArcBridgeService::State state_; - // WeakPtrFactory to use callbacks. - base::WeakPtrFactory<ArcBridgeService> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(ArcBridgeService); };
diff --git a/components/arc/arc_bridge_service_impl.cc b/components/arc/arc_bridge_service_impl.cc new file mode 100644 index 0000000..1a1c954 --- /dev/null +++ b/components/arc/arc_bridge_service_impl.cc
@@ -0,0 +1,254 @@ +// Copyright 2015 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/arc/arc_bridge_service_impl.h" + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/prefs/pref_registry_simple.h" +#include "base/prefs/pref_service.h" +#include "base/sequenced_task_runner.h" +#include "base/task_runner_util.h" +#include "base/thread_task_runner_handle.h" +#include "chromeos/chromeos_switches.h" +#include "chromeos/dbus/dbus_method_call_status.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/session_manager_client.h" +#include "components/arc/common/arc_host_messages.h" +#include "components/arc/common/arc_instance_messages.h" +#include "ipc/ipc_channel.h" + +namespace arc { + +namespace { + +const base::FilePath::CharType kArcBridgeSocketPath[] = + FILE_PATH_LITERAL("/home/chronos/ArcBridge/bridge.sock"); + +} // namespace + +ArcBridgeServiceImpl::ArcBridgeServiceImpl( + const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, + const scoped_refptr<base::SequencedTaskRunner>& file_task_runner) + : ipc_task_runner_(ipc_task_runner), + file_task_runner_(file_task_runner), + session_started_(false), + weak_factory_(this) { +} + +ArcBridgeServiceImpl::~ArcBridgeServiceImpl() { +} + +void ArcBridgeServiceImpl::DetectAvailability() { + chromeos::SessionManagerClient* session_manager_client = + chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); + session_manager_client->CheckArcAvailability(base::Bind( + &ArcBridgeServiceImpl::OnArcAvailable, weak_factory_.GetWeakPtr())); +} + +void ArcBridgeServiceImpl::HandleStartup() { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + session_started_ = true; + PrerequisitesChanged(); +} + +void ArcBridgeServiceImpl::Shutdown() { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + session_started_ = false; + PrerequisitesChanged(); +} + +void ArcBridgeServiceImpl::PrerequisitesChanged() { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (state() == State::STOPPED) { + if (!available() || !session_started_) + return; + SocketConnect(base::FilePath(kArcBridgeSocketPath)); + } else { + if (available() && session_started_) + return; + StopInstance(); + } +} + +void ArcBridgeServiceImpl::StopInstance() { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (state() == State::STOPPED || state() == State::STOPPING) { + VLOG(1) << "StopInstance() called when ARC is not running"; + return; + } + if (state() == State::CONNECTED || state() == State::CONNECTING) { + // This was stopped before the D-Bus command to start the instance. Just + // close the socket (if it was opened). + if (state() == State::CONNECTED) { + ipc_channel_.reset(); + } + SetState(State::STOPPED); + return; + } + + SetState(State::STOPPING); + chromeos::SessionManagerClient* session_manager_client = + chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); + session_manager_client->StopArcInstance(base::Bind( + &ArcBridgeServiceImpl::OnInstanceStopped, weak_factory_.GetWeakPtr())); +} + +bool ArcBridgeServiceImpl::RegisterInputDevice(const std::string& name, + const std::string& device_type, + base::ScopedFD fd) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (state() != State::READY) { + LOG(ERROR) << "Called RegisterInputDevice when the service is not ready"; + return false; + } + return ipc_channel_->Send(new ArcInstanceMsg_RegisterInputDevice( + name, device_type, base::FileDescriptor(fd.Pass()))); +} + +void ArcBridgeServiceImpl::SocketConnect(const base::FilePath& socket_path) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (state() != State::STOPPED) { + VLOG(1) << "SocketConnect() called when instance is not stopped"; + return; + } + SetState(State::CONNECTING); + base::PostTaskAndReplyWithResult( + file_task_runner_.get(), FROM_HERE, + base::Bind(&base::CreateDirectory, socket_path.DirName()), + base::Bind(&ArcBridgeServiceImpl::SocketConnectAfterEnsureParentDirectory, + weak_factory_.GetWeakPtr(), socket_path)); +} + +void ArcBridgeServiceImpl::SocketConnectAfterEnsureParentDirectory( + const base::FilePath& socket_path, + bool directory_present) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (state() != State::CONNECTING) { + VLOG(1) << "StopInstance() called while connecting"; + return; + } + if (!directory_present) { + LOG(ERROR) << "Error creating directory for " << socket_path.value(); + StopInstance(); + return; + } + + if (!Connect(IPC::ChannelHandle(socket_path.value()), + IPC::Channel::MODE_OPEN_NAMED_SERVER)) { + LOG(ERROR) << "Error connecting to " << socket_path.value(); + StopInstance(); + return; + } + + base::PostTaskAndReplyWithResult( + file_task_runner_.get(), FROM_HERE, + // TODO(lhchavez): Tighten the security around the socket by tying it to + // the user the instance will run as. + base::Bind(&base::SetPosixFilePermissions, socket_path, 0777), + base::Bind(&ArcBridgeServiceImpl::SocketConnectAfterSetSocketPermissions, + weak_factory_.GetWeakPtr(), socket_path)); +} + +bool ArcBridgeServiceImpl::Connect(const IPC::ChannelHandle& handle, + IPC::Channel::Mode mode) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (state() != State::CONNECTING) { + VLOG(1) << "StopInstance() called while connecting"; + return false; + } + + ipc_channel_ = + IPC::ChannelProxy::Create(handle, mode, this, ipc_task_runner_.get()); + if (!ipc_channel_) + return false; + SetState(State::CONNECTED); + return true; +} + +void ArcBridgeServiceImpl::SocketConnectAfterSetSocketPermissions( + const base::FilePath& socket_path, + bool socket_permissions_success) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (state() != State::CONNECTED) { + VLOG(1) << "StopInstance() called while connecting"; + return; + } + + if (!socket_permissions_success) { + LOG(ERROR) << "Error setting socket permissions for " + << socket_path.value(); + StopInstance(); + return; + } + + SetState(State::STARTING); + chromeos::SessionManagerClient* session_manager_client = + chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); + session_manager_client->StartArcInstance( + socket_path.value(), base::Bind(&ArcBridgeServiceImpl::OnInstanceStarted, + weak_factory_.GetWeakPtr())); +} + +void ArcBridgeServiceImpl::OnInstanceStarted(bool success) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (state() != State::STARTING) { + VLOG(1) << "StopInstance() called while connecting"; + return; + } + if (!success) { + LOG(ERROR) << "ARC instance unable to start. Shutting down the bridge"; + StopInstance(); + return; + } +} + +void ArcBridgeServiceImpl::OnInstanceBootPhase(InstanceBootPhase phase) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + // The state can be STARTING the first time this is called, and will then + // transition to READY after BRIDGE_READY has been passed. + if (state() != State::STARTING && state() != State::READY) { + VLOG(1) << "StopInstance() called while connecting"; + return; + } + if (phase == InstanceBootPhase::BRIDGE_READY) { + SetState(State::READY); + } + FOR_EACH_OBSERVER(Observer, observer_list(), OnInstanceBootPhase(phase)); +} + +bool ArcBridgeServiceImpl::OnMessageReceived(const IPC::Message& message) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + bool handled = true; + + IPC_BEGIN_MESSAGE_MAP(ArcBridgeServiceImpl, message) + IPC_MESSAGE_HANDLER(ArcInstanceHostMsg_InstanceBootPhase, + OnInstanceBootPhase) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + if (!handled) + LOG(ERROR) << "Invalid message with type = " << message.type(); + return handled; +} + +void ArcBridgeServiceImpl::OnArcAvailable(bool arc_available) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + if (available() == arc_available) + return; + SetAvailable(arc_available); + PrerequisitesChanged(); +} + +void ArcBridgeServiceImpl::OnInstanceStopped(bool success) { + DCHECK(origin_task_runner()->RunsTasksOnCurrentThread()); + // STOPPING is the only valid state for this function. + // DCHECK on enum classes not supported. + DCHECK(state() == State::STOPPING); + ipc_channel_.reset(); + SetState(State::STOPPED); +} + +} // namespace arc
diff --git a/components/arc/arc_bridge_service_impl.h b/components/arc/arc_bridge_service_impl.h new file mode 100644 index 0000000..d65e712 --- /dev/null +++ b/components/arc/arc_bridge_service_impl.h
@@ -0,0 +1,97 @@ +// Copyright 2015 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_ARC_ARC_BRIDGE_SERVICE_IMPL_H_ +#define COMPONENTS_ARC_ARC_BRIDGE_SERVICE_IMPL_H_ + +#include "base/files/scoped_file.h" +#include "base/macros.h" +#include "components/arc/arc_bridge_service.h" +#include "ipc/ipc_channel_proxy.h" +#include "ipc/ipc_listener.h" +#include "ipc/ipc_message.h" + +namespace base { +class SequencedTaskRunner; +class SingleThreadTaskRunner; +} // namespace base + +namespace arc { + +// Real IPC based ArcBridgeService that is used in production. +class ArcBridgeServiceImpl : public ArcBridgeService, + public IPC::Listener { + public: + ArcBridgeServiceImpl( + const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, + const scoped_refptr<base::SequencedTaskRunner>& file_task_runner); + ~ArcBridgeServiceImpl() override; + + void DetectAvailability() override; + + void HandleStartup() override; + + void Shutdown() override; + + bool RegisterInputDevice(const std::string& name, + const std::string& device_type, + base::ScopedFD fd) override; + + private: + friend class ArcBridgeTest; + FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, Basic); + FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, ShutdownMidStartup); + + // If all pre-requisites are true (ARC is available, it has been enabled, and + // the session has started), and ARC is stopped, start ARC. If ARC is running + // and the pre-requisites stop being true, stop ARC. + void PrerequisitesChanged(); + + // Binds to the socket specified by |socket_path|. + void SocketConnect(const base::FilePath& socket_path); + + // Binds to the socket specified by |socket_path| after creating its parent + // directory is present. + void SocketConnectAfterEnsureParentDirectory( + const base::FilePath& socket_path, + bool directory_present); + + // Internal connection method. Separated to make testing easier. + bool Connect(const IPC::ChannelHandle& handle, IPC::Channel::Mode mode); + + // Finishes connecting after setting socket permissions. + void SocketConnectAfterSetSocketPermissions(const base::FilePath& socket_path, + bool socket_permissions_success); + + // Stops the running instance. + void StopInstance(); + + // Called when the instance has reached a boot phase + void OnInstanceBootPhase(InstanceBootPhase phase); + + // IPC::Listener: + bool OnMessageReceived(const IPC::Message& message) override; + + // DBus callbacks. + void OnArcAvailable(bool available); + void OnInstanceStarted(bool success); + void OnInstanceStopped(bool success); + + scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_; + scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + + scoped_ptr<IPC::ChannelProxy> ipc_channel_; + + // If the user's session has started. + bool session_started_; + + // WeakPtrFactory to use callbacks. + base::WeakPtrFactory<ArcBridgeServiceImpl> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(ArcBridgeServiceImpl); +}; + +} // namespace arc + +#endif // COMPONENTS_ARC_ARC_BRIDGE_SERVICE_IMPL_H_
diff --git a/components/arc/arc_bridge_service_unittest.cc b/components/arc/arc_bridge_service_unittest.cc index 5b765caf..a7860be 100644 --- a/components/arc/arc_bridge_service_unittest.cc +++ b/components/arc/arc_bridge_service_unittest.cc
@@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/arc/arc_bridge_service.h" - #include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "components/arc/arc_bridge_service_impl.h" #include "components/arc/common/arc_host_messages.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_channel_proxy.h" @@ -79,7 +78,7 @@ protected: scoped_ptr<IPCSenderFake> fake_sender_; - scoped_ptr<ArcBridgeService> service_; + scoped_ptr<ArcBridgeServiceImpl> service_; private: void SetUp() override { @@ -91,8 +90,8 @@ ipc_thread_.reset(new base::Thread("IPC thread")); ipc_thread_->StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); - service_.reset(new ArcBridgeService(ipc_thread_->task_runner(), - message_loop_.task_runner())); + service_.reset(new ArcBridgeServiceImpl(ipc_thread_->task_runner(), + message_loop_.task_runner())); service_->AddObserver(this);
diff --git a/components/autofill.gypi b/components/autofill.gypi index e494a094..af4f855 100644 --- a/components/autofill.gypi +++ b/components/autofill.gypi
@@ -50,8 +50,6 @@ 'autofill/core/common/password_generation_util.h', 'autofill/core/common/save_password_progress_logger.cc', 'autofill/core/common/save_password_progress_logger.h', - 'autofill/core/common/web_element_descriptor.cc', - 'autofill/core/common/web_element_descriptor.h', ], # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. @@ -77,9 +75,9 @@ '../third_party/fips181/fips181.gyp:fips181', '../third_party/icu/icu.gyp:icui18n', '../third_party/icu/icu.gyp:icuuc', - '../third_party/libjingle/libjingle.gyp:libjingle', '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_util', '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber', + '../third_party/libxml/libxml.gyp:libxml', '../third_party/re2/re2.gyp:re2', '../ui/base/ui_base.gyp:ui_base', '../ui/gfx/gfx.gyp:gfx',
diff --git a/components/autofill/content/common/autofill_messages.h b/components/autofill/content/common/autofill_messages.h index ed6e6d4..b3878cb 100644 --- a/components/autofill/content/common/autofill_messages.h +++ b/components/autofill/content/common/autofill_messages.h
@@ -17,7 +17,6 @@ #include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/password_form_field_prediction_map.h" #include "components/autofill/core/common/password_form_fill_data.h" -#include "components/autofill/core/common/web_element_descriptor.h" #include "content/public/common/common_param_traits.h" #include "content/public/common/common_param_traits_macros.h" #include "ipc/ipc_message_macros.h" @@ -39,14 +38,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(base::i18n::TextDirection, base::i18n::TEXT_DIRECTION_NUM_DIRECTIONS - 1) -IPC_STRUCT_TRAITS_BEGIN(autofill::WebElementDescriptor) - IPC_STRUCT_TRAITS_MEMBER(descriptor) - IPC_STRUCT_TRAITS_MEMBER(retrieval_method) -IPC_STRUCT_TRAITS_END() - -IPC_ENUM_TRAITS_MAX_VALUE(autofill::WebElementDescriptor::RetrievalMethod, - autofill::WebElementDescriptor::NONE) - IPC_STRUCT_TRAITS_BEGIN(autofill::FormFieldData) IPC_STRUCT_TRAITS_MEMBER(label) IPC_STRUCT_TRAITS_MEMBER(name)
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index dae948b..d2bea33 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -30,7 +30,6 @@ #include "components/autofill/core/common/form_data_predictions.h" #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/password_form.h" -#include "components/autofill/core/common/web_element_descriptor.h" #include "content/public/common/content_switches.h" #include "content/public/common/ssl_status.h" #include "content/public/common/url_constants.h"
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h index 6072eda..2471403 100644 --- a/components/autofill/content/renderer/autofill_agent.h +++ b/components/autofill/content/renderer/autofill_agent.h
@@ -30,7 +30,6 @@ struct FormData; struct FormFieldData; -struct WebElementDescriptor; class PasswordAutofillAgent; class PasswordGenerationAgent;
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h index 5632c66..dd1b1271b 100644 --- a/components/autofill/content/renderer/form_autofill_util.h +++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -30,7 +30,6 @@ struct FormData; struct FormFieldData; -struct WebElementDescriptor; namespace form_util {
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index ee20687..1dcf74f 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -180,8 +180,8 @@ "//third_party/fips181", "//third_party/icu", "//third_party/libaddressinput:util", - "//third_party/libjingle", "//third_party/libphonenumber", + "//third_party/libxml", "//third_party/re2", "//ui/base", "//ui/gfx", @@ -309,7 +309,6 @@ "//testing/gmock", "//testing/gtest", "//third_party/libaddressinput:util", - "//third_party/libjingle", "//third_party/libphonenumber", "//ui/base", "//url",
diff --git a/components/autofill/core/browser/DEPS b/components/autofill/core/browser/DEPS index 164b1d9a..b19a8c84 100644 --- a/components/autofill/core/browser/DEPS +++ b/components/autofill/core/browser/DEPS
@@ -15,10 +15,9 @@ "+sql", "+sync", "+third_party/fips181", - "+third_party/libjingle", - "+third_party/webrtc/libjingle", "+third_party/libaddressinput", # For address i18n. "+third_party/libphonenumber", # For phone number i18n. + "+third_party/libxml", "+third_party/re2", "+ui/base", "+ui/gfx",
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc index 17ffec1..38c8484 100644 --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -4,6 +4,8 @@ #include "components/autofill/core/browser/autofill_download_manager.h" +#include <utility> + #include "base/logging.h" #include "base/prefs/pref_service.h" #include "base/rand_util.h" @@ -21,7 +23,6 @@ #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_fetcher.h" -#include "third_party/webrtc/libjingle/xmllite/xmlparser.h" #include "url/gurl.h" namespace autofill { @@ -119,7 +120,7 @@ VLOG(1) << "AutofillDownloadManager: query request has been retrieved " << "from the cache, form signatures: " << GetCombinedSignature(request_data.form_signatures); - observer_->OnLoadedServerPredictions(query_data, + observer_->OnLoadedServerPredictions(std::move(query_data), request_data.form_signatures); return true; } @@ -342,16 +343,14 @@ << " request has succeeded with response body: " << response_body; if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) { CacheQueryRequest(it->second.form_signatures, response_body); - observer_->OnLoadedServerPredictions(response_body, + observer_->OnLoadedServerPredictions(std::move(response_body), it->second.form_signatures); } else { double new_positive_upload_rate = 0; double new_negative_upload_rate = 0; - AutofillUploadXmlParser parse_handler(&new_positive_upload_rate, - &new_negative_upload_rate); - buzz::XmlParser parser(&parse_handler); - parser.Parse(response_body.data(), response_body.length(), true); - if (parse_handler.succeeded()) { + if (ParseAutofillUploadXml(std::move(response_body), + &new_positive_upload_rate, + &new_negative_upload_rate)) { SetPositiveUploadRate(new_positive_upload_rate); SetNegativeUploadRate(new_negative_upload_rate); }
diff --git a/components/autofill/core/browser/autofill_download_manager.h b/components/autofill/core/browser/autofill_download_manager.h index b48764c..8dedb72 100644 --- a/components/autofill/core/browser/autofill_download_manager.h +++ b/components/autofill/core/browser/autofill_download_manager.h
@@ -41,7 +41,7 @@ // server. |response_xml| contains the server response for the forms // represented by |form_signatures|. virtual void OnLoadedServerPredictions( - const std::string& response_xml, + std::string response_xml, const std::vector<std::string>& form_signatures) = 0; // These notifications are used to help with testing.
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc index 2373091..2982ae12 100644 --- a/components/autofill/core/browser/autofill_download_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -5,6 +5,7 @@ #include "components/autofill/core/browser/autofill_download_manager.h" #include <list> +#include <utility> #include "base/prefs/pref_service.h" #include "base/strings/string_number_conversions.h" @@ -81,10 +82,10 @@ // AutofillDownloadManager::Observer implementation. void OnLoadedServerPredictions( - const std::string& response_xml, + std::string response_xml, const std::vector<std::string>& form_signatures) override { ResponseData response; - response.response = response_xml; + response.response = std::move(response_xml); response.type_of_response = QUERY_SUCCESSFULL; responses_.push_back(response); } @@ -173,7 +174,7 @@ field.form_control_type = "submit"; form.fields.push_back(field); - FormStructure *form_structure = new FormStructure(form); + FormStructure* form_structure = new FormStructure(form); ScopedVector<FormStructure> form_structures; form_structures.push_back(form_structure); @@ -431,7 +432,7 @@ field.name = ASCIIToUTF16("lastname"); form.fields.push_back(field); - FormStructure *form_structure = new FormStructure(form); + FormStructure* form_structure = new FormStructure(form); ScopedVector<FormStructure> form_structures0; form_structures0.push_back(form_structure); @@ -562,13 +563,13 @@ TEST_F(AutofillDownloadTest, QueryRequestIsGzipped) { // Expected query (uncompressed for visual verification). const char* kExpectedQueryXml = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"14546501144368603154\">" "<field signature=\"239111655\"/>" "<field signature=\"3763331450\"/>" "<field signature=\"3494530716\"/>" - "</form></autofillquery>"; + "</form></autofillquery>\n"; // Create and register factory. net::TestURLFetcherFactory factory; @@ -613,16 +614,16 @@ EXPECT_EQ("gzip", header); // Expect that the compression is logged. - histogram.ExpectUniqueSample("Autofill.PayloadCompressionRatio.Query", 73, 1); + histogram.ExpectUniqueSample("Autofill.PayloadCompressionRatio.Query", 72, 1); } TEST_F(AutofillDownloadTest, UploadRequestIsGzipped) { // Expected upload (uncompressed for visual verification). const char* kExpectedUploadXml = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<?xml version=\"1.0\"?>\n" "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" " formsignature=\"14546501144368603154\" autofillused=\"true\"" - " datapresent=\"\"/>"; + " datapresent=\"\"/>\n"; // Create and register factory. net::TestURLFetcherFactory factory; @@ -670,7 +671,7 @@ EXPECT_EQ("gzip", header); // Expect that the compression is logged. - histogram.ExpectUniqueSample("Autofill.PayloadCompressionRatio.Upload", 92, + histogram.ExpectUniqueSample("Autofill.PayloadCompressionRatio.Upload", 95, 1); }
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 0d3c169..e3c5e3c6 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -743,7 +743,7 @@ } void AutofillManager::OnLoadedServerPredictions( - const std::string& response_xml, + std::string response_xml, const std::vector<std::string>& form_signatures) { // We obtain the current valid FormStructures represented by // |form_signatures|. We invert both lists because most recent forms are at @@ -765,7 +765,7 @@ return; // Parse and store the server predictions. - FormStructure::ParseQueryResponse(response_xml, queried_forms, + FormStructure::ParseQueryResponse(std::move(response_xml), queried_forms, client_->GetRapporService()); // Forward form structures to the password generation manager to detect
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index 03438286..aac1d95 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -247,7 +247,7 @@ private: // AutofillDownloadManager::Observer: void OnLoadedServerPredictions( - const std::string& response_xml, + std::string response_xml, const std::vector<std::string>& form_signatures) override; // CardUnmaskDelegate:
diff --git a/components/autofill/core/browser/autofill_xml_parser.cc b/components/autofill/core/browser/autofill_xml_parser.cc index 6059b57..7dec347 100644 --- a/components/autofill/core/browser/autofill_xml_parser.cc +++ b/components/autofill/core/browser/autofill_xml_parser.cc
@@ -4,176 +4,112 @@ #include "components/autofill/core/browser/autofill_xml_parser.h" -#include <string.h> +#include <utility> #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "components/autofill/core/browser/autofill_server_field_info.h" -#include "third_party/webrtc/libjingle/xmllite/qname.h" +#include "components/autofill/core/browser/field_types.h" +#include "third_party/libxml/chromium/libxml_utils.h" namespace autofill { -AutofillXmlParser::AutofillXmlParser() - : succeeded_(true) { -} +bool ParseAutofillQueryXml(std::string xml, + std::vector<AutofillServerFieldInfo>* field_infos, + UploadRequired* upload_required) { + DCHECK(field_infos); + DCHECK(upload_required); -AutofillXmlParser::~AutofillXmlParser() {} + XmlReader reader; + if (!reader.Load(xml)) + return false; -void AutofillXmlParser::CharacterData( - buzz::XmlParseContext* context, const char* text, int len) { -} + // Seek to the first opening tag. + if (!reader.Read()) + return false; // Malformed input. -void AutofillXmlParser::EndElement(buzz::XmlParseContext* context, - const char* name) { -} + if (reader.NodeName() != "autofillqueryresponse") + return false; // Malformed input. -void AutofillXmlParser::Error(buzz::XmlParseContext* context, - XML_Error error_code) { - succeeded_ = false; -} + *upload_required = USE_UPLOAD_RATES; + std::string upload_required_value; + if (reader.NodeAttribute("uploadrequired", &upload_required_value)) { + if (upload_required_value == "true") + *upload_required = UPLOAD_REQUIRED; + else if (upload_required_value == "false") + *upload_required = UPLOAD_NOT_REQUIRED; + } -AutofillQueryXmlParser::AutofillQueryXmlParser( - std::vector<AutofillServerFieldInfo>* field_infos, - UploadRequired* upload_required) - : field_infos_(field_infos), - upload_required_(upload_required) { - DCHECK(upload_required_); -} + field_infos->clear(); + if (reader.IsClosingElement()) + return true; -AutofillQueryXmlParser::~AutofillQueryXmlParser() {} - -void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context, - const char* name, - const char** attrs) { - buzz::QName qname = context->ResolveQName(name, false); - const std::string& element = qname.LocalPart(); - if (element.compare("autofillqueryresponse") == 0) { - // We check for the upload required attribute below, but if it's not - // present, we use the default upload rates. - *upload_required_ = USE_UPLOAD_RATES; - - // |attrs| is a NULL-terminated list of (attribute, value) pairs. - while (*attrs) { - buzz::QName attribute_qname = context->ResolveQName(*attrs, true); - ++attrs; - const std::string& attribute_name = attribute_qname.LocalPart(); - if (attribute_name.compare("uploadrequired") == 0) { - if (strcmp(*attrs, "true") == 0) - *upload_required_ = UPLOAD_REQUIRED; - else if (strcmp(*attrs, "false") == 0) - *upload_required_ = UPLOAD_NOT_REQUIRED; - } - ++attrs; - } - } else if (element.compare("field") == 0) { - if (!*attrs) { - // Missing the "autofilltype" attribute, abort. - context->RaiseError(XML_ERROR_ABORTED); - return; - } - - // Determine the field type from the attribute value. There should be one - // attribute (autofilltype) with an integer value. + if (!reader.Read()) + return false; // Malformed input. + while (reader.NodeName() == "field") { AutofillServerFieldInfo field_info; field_info.field_type = UNKNOWN_TYPE; - // |attrs| is a NULL-terminated list of (attribute, value) pairs. - while (*attrs) { - buzz::QName attribute_qname = context->ResolveQName(*attrs, true); - ++attrs; - const std::string& attribute_name = attribute_qname.LocalPart(); - if (attribute_name.compare("autofilltype") == 0) { - int value = GetIntValue(context, *attrs); - if (value >= 0 && value < MAX_VALID_FIELD_TYPE) - field_info.field_type = static_cast<ServerFieldType>(value); - else - field_info.field_type = NO_SERVER_DATA; - } else if (field_info.field_type == FIELD_WITH_DEFAULT_VALUE && - attribute_name.compare("defaultvalue") == 0) { - field_info.default_value = *attrs; - } - ++attrs; + std::string autofill_type_value; + if (!reader.NodeAttribute("autofilltype", &autofill_type_value)) + return false; // Missing required attribute. + int parsed_type = 0; + if (!base::StringToInt(autofill_type_value, &parsed_type) || + parsed_type < 0 || parsed_type >= MAX_VALID_FIELD_TYPE) { + // Invalid attribute value should not make the whole parse fail. + field_info.field_type = NO_SERVER_DATA; + } else { + field_info.field_type = static_cast<ServerFieldType>(parsed_type); } - // Record this field type, default value pair. - field_infos_->push_back(field_info); - } -} - -void AutofillQueryXmlParser::ParseElementDescriptor( - buzz::XmlParseContext* context, - const char* const* attrs, - WebElementDescriptor* element_descriptor) { - // If both id and css_selector are set, the first one to appear will take - // precedence. - // |attrs| is a NULL-terminated list of (attribute, value) pairs. - while (*attrs) { - buzz::QName attribute_qname = context->ResolveQName(*attrs, true); - ++attrs; - const std::string& attribute_name = attribute_qname.LocalPart(); - buzz::QName value_qname = context->ResolveQName(*attrs, true); - ++attrs; - const std::string& attribute_value = value_qname.LocalPart(); - if (attribute_name.compare("id") == 0 && !attribute_value.empty()) { - element_descriptor->retrieval_method = WebElementDescriptor::ID; - element_descriptor->descriptor = attribute_value; - break; - } else if (attribute_name.compare("css_selector") == 0 && - !attribute_value.empty()) { - element_descriptor->retrieval_method = WebElementDescriptor::CSS_SELECTOR; - element_descriptor->descriptor = attribute_value; - break; + std::string default_value; + if (field_info.field_type == FIELD_WITH_DEFAULT_VALUE && + reader.NodeAttribute("defaultvalue", &default_value)) { + field_info.default_value = std::move(default_value); } + + field_infos->push_back(field_info); + + if (!reader.Read()) + return false; // Malformed input. } + + if (reader.NodeName() != "autofillqueryresponse" || + !reader.IsClosingElement()) { + return false; // Malformed input. + } + return true; } -int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context, - const char* attribute) { - int value = 0; - if (!base::StringToInt(attribute, &value)) { - context->RaiseError(XML_ERROR_SYNTAX); - return 0; - } - return value; -} +bool ParseAutofillUploadXml(std::string xml, + double* positive_upload_rate, + double* negative_upload_rate) { + DCHECK(positive_upload_rate); + DCHECK(negative_upload_rate); -AutofillUploadXmlParser::AutofillUploadXmlParser(double* positive_upload_rate, - double* negative_upload_rate) - : succeeded_(false), - positive_upload_rate_(positive_upload_rate), - negative_upload_rate_(negative_upload_rate) { - DCHECK(positive_upload_rate_); - DCHECK(negative_upload_rate_); -} + XmlReader reader; + if (!reader.Load(xml)) + return false; -void AutofillUploadXmlParser::StartElement(buzz::XmlParseContext* context, - const char* name, - const char** attrs) { - buzz::QName qname = context->ResolveQName(name, false); - const std::string &element = qname.LocalPart(); - if (element.compare("autofilluploadresponse") == 0) { - // Loop over all attributes to get the upload rates. - while (*attrs) { - buzz::QName attribute_qname = context->ResolveQName(attrs[0], true); - const std::string &attribute_name = attribute_qname.LocalPart(); - if (attribute_name.compare("positiveuploadrate") == 0) { - *positive_upload_rate_ = GetDoubleValue(context, attrs[1]); - } else if (attribute_name.compare("negativeuploadrate") == 0) { - *negative_upload_rate_ = GetDoubleValue(context, attrs[1]); - } - attrs += 2; // We peeked at attrs[0] and attrs[1], skip past both. - } - } -} + // Seek to the first opening tag. + if (!reader.Read()) + return false; // Malformed input. -double AutofillUploadXmlParser::GetDoubleValue(buzz::XmlParseContext* context, - const char* attribute) { - double value = 0; - if (!base::StringToDouble(attribute, &value)) { - context->RaiseError(XML_ERROR_SYNTAX); - return 0.0; - } - return value; + if (reader.NodeName() != "autofilluploadresponse") + return false; // Malformed input. + + std::string attribute_value; + // TODO(crbug.com/561619) Make the two attributes non-required and use 1 as + // the default value. + if (!reader.NodeAttribute("positiveuploadrate", &attribute_value)) + return false; // Missing required attribute. + if (!base::StringToDouble(attribute_value, positive_upload_rate)) + return false; // Invalid attribute value. + if (!reader.NodeAttribute("negativeuploadrate", &attribute_value)) + return false; // Missing required attribute. + if (!base::StringToDouble(attribute_value, negative_upload_rate)) + return false; // Invalid attribute value. + return true; } } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_xml_parser.h b/components/autofill/core/browser/autofill_xml_parser.h index 1f4e102..460dd3f 100644 --- a/components/autofill/core/browser/autofill_xml_parser.h +++ b/components/autofill/core/browser/autofill_xml_parser.h
@@ -8,107 +8,37 @@ #include <string> #include <vector> -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "components/autofill/core/browser/autofill_server_field_info.h" -#include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_structure.h" -#include "third_party/webrtc/libjingle/xmllite/xmlparser.h" namespace autofill { -// The base class that contains common functionality between -// AutofillQueryXmlParser and AutofillUploadXmlParser. -class AutofillXmlParser : public buzz::XmlParseHandler { - public: - AutofillXmlParser(); - ~AutofillXmlParser() override; +struct AutofillServerFieldInfo; - // Returns true if no parsing errors were encountered. - bool succeeded() const { return succeeded_; } - - private: - // A callback for the end of an </element>, called by Expat. - // |context| is a parsing context used to resolve element/attribute names. - // |name| is the name of the element. - void EndElement(buzz::XmlParseContext* context, const char* name) override; - - // The callback for character data between tags (<element>text...</element>). - // |context| is a parsing context used to resolve element/attribute names. - // |text| is a pointer to the beginning of character data (not null - // terminated). - // |len| is the length of the string pointed to by text. - void CharacterData(buzz::XmlParseContext* context, - const char* text, - int len) override; - - // The callback for parsing errors. - // |context| is a parsing context used to resolve names. - // |error_code| is a code representing the parsing error. - void Error(buzz::XmlParseContext* context, XML_Error error_code) override; - - // True if parsing succeeded. - bool succeeded_; - - DISALLOW_COPY_AND_ASSIGN(AutofillXmlParser); -}; - -// The XML parse handler for parsing Autofill query responses. A typical -// response looks like: +// The XML parser for parsing Autofill query responses. A typical response +// looks like: // -// <autofillqueryresponse> +// <autofillqueryresponse uploadrequired="true"> // <field autofilltype="0" /> // <field autofilltype="1" /> // <field autofilltype="3" /> // <field autofilltype="2" /> +// <field autofilltype="61" defaultvalue="default" /> // </autofillqueryresponse> // // Fields are returned in the same order they were sent to the server. // autofilltype: The server's guess at what type of field this is. 0 // is unknown, other types are documented in // components/autofill/core/browser/field_types.h. -class AutofillQueryXmlParser : public AutofillXmlParser { - public: - AutofillQueryXmlParser(std::vector<AutofillServerFieldInfo>* field_infos, - UploadRequired* upload_required); - ~AutofillQueryXmlParser() override; +// +// Parses |xml| and on success returns true and fills |field_infos| based on the +// <field> tags and |upload_required| based on the uploadrequired attribute of +// the autofillqueryresponse tag. On failure returns false. +bool ParseAutofillQueryXml(std::string xml, + std::vector<AutofillServerFieldInfo>* field_infos, + UploadRequired* upload_required); - private: - // A callback for the beginning of a new <element>, called by Expat. - // |context| is a parsing context used to resolve element/attribute names. - // |name| is the name of the element. - // |attrs| is the list of attributes (names and values) for the element. - void StartElement(buzz::XmlParseContext* context, - const char* name, - const char** attrs) override; - - // A helper function to parse a |WebElementDescriptor|. - // |context| is the current parsing context. - // |attrs| is the list of attributes (names and values) for the element. - // |element_descriptor| will be populated by this function. - void ParseElementDescriptor(buzz::XmlParseContext* context, - const char* const* attrs, - WebElementDescriptor* element_descriptor); - - // A helper function to retrieve integer values from strings. Raises an - // XML parse error if it fails. - // |context| is the current parsing context. - // |value| is the string to convert. - int GetIntValue(buzz::XmlParseContext* context, const char* attribute); - - // The parsed <field type, default value> pairs. - std::vector<AutofillServerFieldInfo>* field_infos_; - - // A flag indicating whether the client should upload Autofill data when this - // form is submitted. - UploadRequired* upload_required_; - - DISALLOW_COPY_AND_ASSIGN(AutofillQueryXmlParser); -}; - -// The XML parser for handling Autofill upload responses. Typical upload -// responses look like: +// The XML parser for Autofill upload responses. Typical upload responses look +// like: // // <autofilluploadresponse negativeuploadrate="0.00125" positiveuploadrate="1"/> // @@ -118,34 +48,12 @@ // the form matches what's in the users profile. // The negative upload rate is typically much lower than the positive upload // rate. -class AutofillUploadXmlParser : public AutofillXmlParser { - public: - AutofillUploadXmlParser(double* positive_upload_rate, - double* negative_upload_rate); - - private: - // A callback for the beginning of a new <element>, called by Expat. - // |context| is a parsing context used to resolve element/attribute names. - // |name| is the name of the element. - // |attrs| is the list of attributes (names and values) for the element. - void StartElement(buzz::XmlParseContext* context, - const char* name, - const char** attrs) override; - - // A helper function to retrieve double values from strings. Raises an XML - // parse error if it fails. - // |context| is the current parsing context. - // |value| is the string to convert. - double GetDoubleValue(buzz::XmlParseContext* context, const char* attribute); - - // True if parsing succeeded. - bool succeeded_; - - double* positive_upload_rate_; - double* negative_upload_rate_; - - DISALLOW_COPY_AND_ASSIGN(AutofillUploadXmlParser); -}; +// +// Parses |xml| and on success returns true and fills the upload rates based on +// the attributes of the autofilluploadresponse tag. On failure returns false. +bool ParseAutofillUploadXml(std::string xml, + double* positive_upload_rate, + double* negative_upload_rate); } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_xml_parser_unittest.cc b/components/autofill/core/browser/autofill_xml_parser_unittest.cc index 929b4759..8552b53 100644 --- a/components/autofill/core/browser/autofill_xml_parser_unittest.cc +++ b/components/autofill/core/browser/autofill_xml_parser_unittest.cc
@@ -3,14 +3,15 @@ // found in the LICENSE file. #include <string> +#include <utility> #include <vector> #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" +#include "components/autofill/core/browser/autofill_server_field_info.h" #include "components/autofill/core/browser/autofill_xml_parser.h" #include "components/autofill/core/browser/field_types.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/webrtc/libjingle/xmllite/xmlparser.h" namespace autofill { namespace { @@ -21,13 +22,10 @@ ~AutofillQueryXmlParserTest() override{}; protected: - void ParseQueryXML(const std::string& xml, bool should_succeed) { - // Create a parser. - AutofillQueryXmlParser parse_handler(&field_infos_, - &upload_required_); - buzz::XmlParser parser(&parse_handler); - parser.Parse(xml.c_str(), xml.length(), true); - EXPECT_EQ(should_succeed, parse_handler.succeeded()); + void ParseQueryXML(std::string xml, bool should_succeed) { + EXPECT_EQ(should_succeed, + ParseAutofillQueryXml(std::move(xml), &field_infos_, + &upload_required_)); } std::vector<AutofillServerFieldInfo> field_infos_; @@ -40,13 +38,9 @@ ~AutofillUploadXmlParserTest() override{}; protected: - void ParseUploadXML(const std::string& xml, bool should_succeed) { - // Create a parser. - AutofillUploadXmlParser parse_handler(&positive_, &negative_); - buzz::XmlParser parser(&parse_handler); - parser.Parse(xml.c_str(), xml.length(), true); - - EXPECT_EQ(should_succeed, parse_handler.succeeded()); + void ParseUploadXML(std::string xml, bool should_succeed) { + EXPECT_EQ(should_succeed, + ParseAutofillUploadXml(std::move(xml), &positive_, &negative_)); } double positive_; @@ -62,7 +56,7 @@ "<field autofilltype=\"2\" />" "<field autofilltype=\"61\" defaultvalue=\"default\"/>" "</autofillqueryresponse>"; - ParseQueryXML(xml, true); + ParseQueryXML(std::move(xml), true); EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); ASSERT_EQ(5U, field_infos_.size()); @@ -81,7 +75,7 @@ "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; - ParseQueryXML(xml, true); + ParseQueryXML(std::move(xml), true); EXPECT_EQ(upload_required_, upload_required_); ASSERT_EQ(1U, field_infos_.size()); @@ -92,7 +86,7 @@ "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; - ParseQueryXML(xml, true); + ParseQueryXML(std::move(xml), true); EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required_); ASSERT_EQ(1U, field_infos_.size()); @@ -103,7 +97,7 @@ "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; - ParseQueryXML(xml, true); + ParseQueryXML(std::move(xml), true); EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); ASSERT_EQ(1U, field_infos_.size()); @@ -117,17 +111,14 @@ "<field/>" "</autofillqueryresponse>"; - ParseQueryXML(xml, false); - - EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); - EXPECT_EQ(0U, field_infos_.size()); + ParseQueryXML(std::move(xml), false); // Test an incorrect Autofill type. xml = "<autofillqueryresponse>" "<field autofilltype=\"-1\"/>" "</autofillqueryresponse>"; - ParseQueryXML(xml, true); + ParseQueryXML(std::move(xml), true); EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); ASSERT_EQ(1U, field_infos_.size()); @@ -139,7 +130,7 @@ xml = "<autofillqueryresponse><field autofilltype=\"" + base::IntToString(MAX_VALID_FIELD_TYPE) + "\"/></autofillqueryresponse>"; - ParseQueryXML(xml, true); + ParseQueryXML(std::move(xml), true); EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); ASSERT_EQ(1U, field_infos_.size()); @@ -152,8 +143,8 @@ "<field autofilltype=\"No Type\"/>" "</autofillqueryresponse>"; - // Parse fails but an entry is still added to field_infos_. - ParseQueryXML(xml, false); + // Unknown autofill type is handled gracefully. + ParseQueryXML(std::move(xml), true); EXPECT_EQ(USE_UPLOAD_RATES, upload_required_); ASSERT_EQ(1U, field_infos_.size()); @@ -176,26 +167,13 @@ "negativeuploadrate=\"0.3\"/>", false); - EXPECT_DOUBLE_EQ(0, positive_); - EXPECT_DOUBLE_EQ(0.3, negative_); // Partially parsed. - negative_ = 0; - ParseUploadXML("<autofilluploadresponse positiveuploadrate=\"0.5\" " "negativeuploadrate=\"0.3\"", false); - EXPECT_DOUBLE_EQ(0, positive_); - EXPECT_DOUBLE_EQ(0, negative_); - ParseUploadXML("bad data", false); - EXPECT_DOUBLE_EQ(0, positive_); - EXPECT_DOUBLE_EQ(0, negative_); - ParseUploadXML(std::string(), false); - - EXPECT_DOUBLE_EQ(0, positive_); - EXPECT_DOUBLE_EQ(0, negative_); } } // namespace
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 1c7be13..351acbc 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -4,6 +4,7 @@ #include "components/autofill/core/browser/form_structure.h" +#include <map> #include <utility> #include "base/basictypes.h" @@ -20,6 +21,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/autofill_server_field_info.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/autofill_xml_parser.h" #include "components/autofill/core/browser/field_types.h" @@ -31,8 +33,8 @@ #include "components/autofill/core/common/form_field_data_predictions.h" #include "components/rappor/rappor_service.h" #include "components/rappor/rappor_utils.h" +#include "third_party/libxml/chromium/libxml_utils.h" #include "third_party/re2/re2/re2.h" -#include "third_party/webrtc/libjingle/xmllite/xmlelement.h" namespace autofill { namespace { @@ -54,7 +56,6 @@ const char kAttributeAutocomplete[] = "autocomplete"; const char kAttributeLoginFormSignature[] = "loginformsignature"; const char kClientVersion[] = "6.1.1715.1442/en (GGLL)"; -const char kXMLDeclaration[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; const char kXMLElementAutofillQuery[] = "autofillquery"; const char kXMLElementAutofillUpload[] = "autofillupload"; const char kXMLElementFieldAssignments[] = "fieldassignments"; @@ -115,75 +116,86 @@ return data_presence; } -// Helper for |EncodeFormRequest()| and |EncodeFieldForUpload| that returns an -// XmlElement for the given field in query xml, and also add it to the parent -// XmlElement. -buzz::XmlElement* EncodeFieldForQuery(const AutofillField& field, - buzz::XmlElement* parent) { - buzz::XmlElement* field_element = new buzz::XmlElement( - buzz::QName(kXMLElementField)); - field_element->SetAttr(buzz::QName(kAttributeSignature), - field.FieldSignature()); +// Assumes that |xml_writer| has just started an element with name +// |kXMLElementField|, and adds some field attributes based on |field|. Returns +// true on success, false on failure. +bool EncodeFieldForQuery(const AutofillField& field, XmlWriter* xml_writer) { + if (!xml_writer->AddAttribute(kAttributeSignature, field.FieldSignature())) + return false; if (IsAutofillFieldMetadataEnabled()) { if (!field.name.empty()) { - field_element->SetAttr(buzz::QName(kAttributeName), - base::UTF16ToUTF8(field.name)); + if (!xml_writer->AddAttribute(kAttributeName, + base::UTF16ToUTF8(field.name))) + return false; } - field_element->SetAttr(buzz::QName(kAttributeControlType), - field.form_control_type); + if (!xml_writer->AddAttribute(kAttributeControlType, + field.form_control_type)) + return false; if (!field.label.empty()) { std::string truncated; base::TruncateUTF8ToByteSize(base::UTF16ToUTF8(field.label), kMaxFieldLabelNumChars, &truncated); - field_element->SetAttr(buzz::QName(kAttributeFieldLabel), truncated); + if (!xml_writer->AddAttribute(kAttributeFieldLabel, truncated)) + return false; } } - parent->AddElement(field_element); - return field_element; + return true; } -// Helper for |EncodeFormRequest()| that creates XmlElements for the given field -// in upload xml, and also add them to the parent XmlElement. -void EncodeFieldForUpload(const AutofillField& field, - buzz::XmlElement* parent) { +// Uses |xml_writer| to write one tag named |kXMLElementField| for each item in +// |field.possible_types()|, and adds some field attributes based on |field|. +// Returns true on success, false on failure. +bool EncodeFieldForUpload(const AutofillField& field, XmlWriter* xml_writer) { // Don't upload checkable fields. if (field.is_checkable) - return; + return true; - ServerFieldTypeSet types = field.possible_types(); - // |types| could be empty in unit-tests only. + const ServerFieldTypeSet& types = field.possible_types(); for (const auto& field_type : types) { - // We use the same field elements as the query and add a few more below. - buzz::XmlElement* field_element = EncodeFieldForQuery(field, parent); + if (!xml_writer->StartElement(kXMLElementField)) + return false; + // Add the same field elements as the query and a few more below. + if (!EncodeFieldForQuery(field, xml_writer)) + return false; if (IsAutofillFieldMetadataEnabled() && !field.autocomplete_attribute.empty()) { - field_element->SetAttr(buzz::QName(kAttributeAutocomplete), - field.autocomplete_attribute); + if (!xml_writer->AddAttribute(kAttributeAutocomplete, + field.autocomplete_attribute)) + return false; } - field_element->SetAttr(buzz::QName(kAttributeAutofillType), - base::IntToString(field_type)); + if (!xml_writer->AddAttribute(kAttributeAutofillType, + base::IntToString(field_type))) + return false; + if (!xml_writer->EndElement()) + return false; } + return true; } -// Helper for |EncodeFormRequest()| that creates XmlElements for the given field -// in field assignments xml, and also add them to the parent XmlElement. -void EncodeFieldForFieldAssignments(const AutofillField& field, - buzz::XmlElement* parent) { - ServerFieldTypeSet types = field.possible_types(); +// Uses |xml_writer| to write one tag named |kXMLElementFields| for each item in +// |field.possible_types()|, and adds some field attributes based on |field|. +// Returns true on success, false on failure. +bool EncodeFieldForFieldAssignments(const AutofillField& field, + XmlWriter* xml_writer) { + const ServerFieldTypeSet& types = field.possible_types(); for (const auto& field_type : types) { - buzz::XmlElement *field_element = new buzz::XmlElement( - buzz::QName(kXMLElementFields)); + if (!xml_writer->StartElement(kXMLElementFields)) + return false; - field_element->SetAttr(buzz::QName(kAttributeFieldID), - field.FieldSignature()); - field_element->SetAttr(buzz::QName(kAttributeFieldType), - base::IntToString(field_type)); - field_element->SetAttr(buzz::QName(kAttributeName), - base::UTF16ToUTF8(field.name)); - parent->AddElement(field_element); + if (!xml_writer->AddAttribute(kAttributeFieldID, field.FieldSignature())) + return false; + if (!xml_writer->AddAttribute(kAttributeFieldType, + base::IntToString(field_type))) + return false; + if (!xml_writer->AddAttribute(kAttributeName, + base::UTF16ToUTF8(field.name))) + return false; + if (!xml_writer->EndElement()) + return false; } + return true; } // Returns |true| iff the |token| is a type hint for a contact field, as @@ -442,49 +454,59 @@ bool form_was_autofilled, const std::string& login_form_signature, std::string* encoded_xml) const { + DCHECK(encoded_xml); DCHECK(ShouldBeCrowdsourced()); // Verify that |available_field_types| agrees with the possible field types we // are uploading. for (const AutofillField* field : *this) { for (const auto& type : field->possible_types()) { - DCHECK(type == UNKNOWN_TYPE || - type == EMPTY_TYPE || + DCHECK(type == UNKNOWN_TYPE || type == EMPTY_TYPE || available_field_types.count(type)); } } // Set up the <autofillupload> element and its attributes. - buzz::XmlElement autofill_request_xml( - (buzz::QName(kXMLElementAutofillUpload))); - autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion), - kClientVersion); - autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature), - FormSignature()); - autofill_request_xml.SetAttr(buzz::QName(kAttributeAutofillUsed), - form_was_autofilled ? "true" : "false"); - autofill_request_xml.SetAttr(buzz::QName(kAttributeDataPresent), - EncodeFieldTypes(available_field_types).c_str()); + XmlWriter xml_writer; + xml_writer.StartWriting(); + xml_writer.StopIndenting(); + if (!xml_writer.StartElement(kXMLElementAutofillUpload)) + return false; + if (!xml_writer.AddAttribute(kAttributeClientVersion, kClientVersion)) + return false; + if (!xml_writer.AddAttribute(kAttributeFormSignature, FormSignature())) + return false; + if (!xml_writer.AddAttribute(kAttributeAutofillUsed, + form_was_autofilled ? "true" : "false")) + return false; + if (!xml_writer.AddAttribute(kAttributeDataPresent, + EncodeFieldTypes(available_field_types))) + return false; if (IsAutofillFieldMetadataEnabled()) { - autofill_request_xml.SetAttr(buzz::QName(kAttributeFormActionHostSignature), - Hash64Bit(target_url_.host())); - if(!form_name().empty()) { - autofill_request_xml.SetAttr(buzz::QName(kAttributeFormName), - base::UTF16ToUTF8(form_name())); + if (!xml_writer.AddAttribute(kAttributeFormActionHostSignature, + Hash64Bit(target_url_.host()))) + return false; + if (!form_name().empty()) { + if (!xml_writer.AddAttribute(kAttributeFormName, + base::UTF16ToUTF8(form_name()))) + return false; } } if (!login_form_signature.empty()) { - autofill_request_xml.SetAttr(buzz::QName(kAttributeLoginFormSignature), - login_form_signature); + if (!xml_writer.AddAttribute(kAttributeLoginFormSignature, + login_form_signature)) + return false; } - if (!EncodeFormRequest(FormStructure::UPLOAD, &autofill_request_xml)) + if (IsMalformed() || !EncodeFormRequest(FormStructure::UPLOAD, &xml_writer)) return false; // Malformed form, skip it. + if (!xml_writer.EndElement()) + return false; // Obtain the XML structure as a string. - *encoded_xml = kXMLDeclaration; - *encoded_xml += autofill_request_xml.Str().c_str(); + xml_writer.StopWriting(); + *encoded_xml = xml_writer.GetWrittenString(); // To enable this logging, run with the flag --vmodule="form_structure=2". VLOG(2) << "\n" << *encoded_xml; @@ -495,21 +517,28 @@ bool FormStructure::EncodeFieldAssignments( const ServerFieldTypeSet& available_field_types, std::string* encoded_xml) const { + DCHECK(encoded_xml); DCHECK(ShouldBeCrowdsourced()); // Set up the <fieldassignments> element and its attributes. - buzz::XmlElement autofill_request_xml( - (buzz::QName(kXMLElementFieldAssignments))); - autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature), - FormSignature()); + XmlWriter xml_writer; + xml_writer.StartWriting(); + xml_writer.StopIndenting(); + if (!xml_writer.StartElement(kXMLElementFieldAssignments)) + return false; + if (!xml_writer.AddAttribute(kAttributeFormSignature, FormSignature())) + return false; - if (!EncodeFormRequest(FormStructure::FIELD_ASSIGNMENTS, - &autofill_request_xml)) + if (IsMalformed() || + !EncodeFormRequest(FormStructure::FIELD_ASSIGNMENTS, &xml_writer)) { return false; // Malformed form, skip it. + } + if (!xml_writer.EndElement()) + return false; // Obtain the XML structure as a string. - *encoded_xml = kXMLDeclaration; - *encoded_xml += autofill_request_xml.Str().c_str(); + xml_writer.StopWriting(); + *encoded_xml = xml_writer.GetWrittenString(); return true; } @@ -521,37 +550,43 @@ std::string* encoded_xml) { DCHECK(encoded_signatures); DCHECK(encoded_xml); - encoded_xml->clear(); encoded_signatures->clear(); encoded_signatures->reserve(forms.size()); // Set up the <autofillquery> element and attributes. - buzz::XmlElement autofill_request_xml( - (buzz::QName(kXMLElementAutofillQuery))); - autofill_request_xml.SetAttr(buzz::QName(kAttributeClientVersion), - kClientVersion); + XmlWriter xml_writer; + xml_writer.StartWriting(); + xml_writer.StopIndenting(); + if (!xml_writer.StartElement(kXMLElementAutofillQuery)) + return false; + if (!xml_writer.AddAttribute(kAttributeClientVersion, kClientVersion)) + return false; // Some badly formatted web sites repeat forms - detect that and encode only // one form as returned data would be the same for all the repeated forms. std::set<std::string> processed_forms; - for (const auto& it : forms) { - std::string signature(it->FormSignature()); + for (const auto& form : forms) { + std::string signature(form->FormSignature()); if (processed_forms.find(signature) != processed_forms.end()) continue; processed_forms.insert(signature); - scoped_ptr<buzz::XmlElement> encompassing_xml_element( - new buzz::XmlElement(buzz::QName(kXMLElementForm))); - encompassing_xml_element->SetAttr(buzz::QName(kAttributeSignature), - signature); + if (form->IsMalformed()) + continue; + if (!xml_writer.StartElement(kXMLElementForm)) + return false; + if (!xml_writer.AddAttribute(kAttributeSignature, signature)) + return false; - if (!it->EncodeFormRequest(FormStructure::QUERY, - encompassing_xml_element.get())) { - continue; // Malformed form, skip it. - } + if (!form->EncodeFormRequest(FormStructure::QUERY, &xml_writer)) + continue; - autofill_request_xml.AddElement(encompassing_xml_element.release()); + if (!xml_writer.EndElement()) + return false; + encoded_signatures->push_back(signature); } + if (!xml_writer.EndElement()) + return false; if (!encoded_signatures->size()) return false; @@ -561,14 +596,14 @@ // it ever resurfaces, re-add code here to set the attribute accordingly. // Obtain the XML structure as a string. - *encoded_xml = kXMLDeclaration; - *encoded_xml += autofill_request_xml.Str().c_str(); + xml_writer.StopWriting(); + *encoded_xml = xml_writer.GetWrittenString(); return true; } // static -void FormStructure::ParseQueryResponse(const std::string& response_xml, +void FormStructure::ParseQueryResponse(std::string response_xml, const std::vector<FormStructure*>& forms, rappor::RapporService* rappor_service) { AutofillMetrics::LogServerQueryMetric( @@ -577,11 +612,7 @@ // Parse the field types from the server response to the query. std::vector<AutofillServerFieldInfo> field_infos; UploadRequired upload_required; - AutofillQueryXmlParser parse_handler(&field_infos, - &upload_required); - buzz::XmlParser parser(&parse_handler); - parser.Parse(response_xml.c_str(), response_xml.length(), true); - if (!parse_handler.succeeded()) + if (!ParseAutofillQueryXml(response_xml, &field_infos, &upload_required)) return; AutofillMetrics::LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED); @@ -1027,11 +1058,9 @@ return base::Uint64ToString(hash64); } -bool FormStructure::EncodeFormRequest( - FormStructure::EncodeRequestType request_type, - buzz::XmlElement* encompassing_xml_element) const { +bool FormStructure::IsMalformed() const { if (!field_count()) // Nothing to add. - return false; + return true; // Some badly formatted web sites repeat fields - limit number of fields to // 48, which is far larger than any valid form and XML still fits into 2K. @@ -1039,22 +1068,33 @@ // near certainly not valid/auto-fillable. const size_t kMaxFieldsOnTheForm = 48; if (field_count() > kMaxFieldsOnTheForm) - return false; + return true; + return false; +} +bool FormStructure::EncodeFormRequest(EncodeRequestType request_type, + XmlWriter* xml_writer) const { + DCHECK(!IsMalformed()); // Add the child nodes for the form fields. - for (size_t index = 0; index < field_count(); ++index) { - const AutofillField* field = fields_[index]; + for (const AutofillField* field : fields_) { switch (request_type) { case FormStructure::UPLOAD: - EncodeFieldForUpload(*field, encompassing_xml_element); + if (!EncodeFieldForUpload(*field, xml_writer)) + return false; break; case FormStructure::QUERY: if (ShouldSkipField(*field)) continue; - EncodeFieldForQuery(*field, encompassing_xml_element); + if (!xml_writer->StartElement(kXMLElementField)) + return false; + if (!EncodeFieldForQuery(*field, xml_writer)) + return false; + if (!xml_writer->EndElement()) + return false; break; case FormStructure::FIELD_ASSIGNMENTS: - EncodeFieldForFieldAssignments(*field, encompassing_xml_element); + if (!EncodeFieldForFieldAssignments(*field, xml_writer)) + return false; break; } }
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index fa7747b..670f1c23 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -17,9 +17,10 @@ #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/common/web_element_descriptor.h" #include "url/gurl.h" +class XmlWriter; + enum UploadRequired { UPLOAD_NOT_REQUIRED, UPLOAD_REQUIRED, @@ -83,7 +84,7 @@ // Parses the field types from the server query response. |forms| must be the // same as the one passed to EncodeQueryRequest when constructing the query. // |rappor_service| may be null. - static void ParseQueryResponse(const std::string& response_xml, + static void ParseQueryResponse(std::string response_xml, const std::vector<FormStructure*>& forms, rappor::RapporService* rappor_service); @@ -223,10 +224,14 @@ FIELD_ASSIGNMENTS, }; - // Adds form info to |encompassing_xml_element|. |request_type| indicates if - // it is a query or upload. + // Returns true if the form has no fields, or too many. + bool IsMalformed() const; + + // Takes |xml_writer| and writes description for |fields_|, according to + // |request_type|. Returns false on failure, including when there are no + // fields, and true on success. bool EncodeFormRequest(EncodeRequestType request_type, - buzz::XmlElement* encompassing_xml_element) const; + XmlWriter* xml_writer) const; // Classifies each field in |fields_| into a logical section. // Sections are identified by the heuristic that a logical section should not
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc index 5aad585..b1acd4b 100644 --- a/components/autofill/core/browser/form_structure_unittest.cc +++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -1510,7 +1510,8 @@ std::vector<std::string> encoded_signatures; std::string encoded_xml; const char kSignature1[] = "11337937696949187602"; - const char kResponse1[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + const char kResponse1[] = + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"11337937696949187602\">" "<field signature=\"412125936\" name=\"name_on_card\" type=\"text\"" @@ -1520,7 +1521,7 @@ " label=\"Card Number\"/><field signature=\"747221617\"" " name=\"expiration_month\" type=\"text\" label=\"Expiration Date\"/>" "<field signature=\"4108155786\" name=\"expiration_year\" type=\"text\"" - " label=\"Expiration Year\"/></form></autofillquery>"; + " label=\"Expiration Year\"/></form></autofillquery>\n"; ASSERT_TRUE(FormStructure::EncodeQueryRequest( forms.get(), &encoded_signatures, &encoded_xml)); ASSERT_EQ(1U, encoded_signatures.size()); @@ -1549,32 +1550,35 @@ EXPECT_EQ(kSignature1, encoded_signatures[0]); const char kSignature2[] = "8308881815906226214"; EXPECT_EQ(kSignature2, encoded_signatures[1]); - const char kResponse2[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" - "<form signature=\"11337937696949187602\"><field signature=\"412125936\"" - " name=\"name_on_card\" type=\"text\" label=\"Name on Card\"/>" - "<field signature=\"1917667676\" name=\"billing_address\" type=\"text\"" - " label=\"Address\"/><field signature=\"2226358947\" name=\"card_number\"" - " type=\"text\" label=\"Card Number\"/>" - "<field signature=\"747221617\" name=\"expiration_month\" type=\"text\"" - " label=\"Expiration Date\"/>" - "<field signature=\"4108155786\" name=\"expiration_year\" type=\"text\"" - " label=\"Expiration Year\"/></form>" - "<form signature=\"8308881815906226214\">" - "<field signature=\"412125936\" name=\"name_on_card\" type=\"text\"" - " label=\"Name on Card\"/><field signature=\"1917667676\"" - " name=\"billing_address\" type=\"text\" label=\"Address\"/>" - "<field signature=\"2226358947\" name=\"card_number\" type=\"text\"" - " label=\"Card Number\"/><field signature=\"747221617\"" - " name=\"expiration_month\" type=\"text\" label=\"Expiration Date\"/>" - "<field signature=\"4108155786\" name=\"expiration_year\" type=\"text\"" - " label=\"Expiration Year\"/><field signature=\"509334676\" name=\"address\"" - " type=\"text\" label=\"Address\"/><field signature=\"509334676\"" - " name=\"address\" type=\"text\" label=\"Address\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\"/><field signature=\"509334676\" name=\"address\"" - " type=\"text\" label=\"Address\"/><field signature=\"509334676\"" - " name=\"address\" type=\"text\" label=\"Address\"/></form></autofillquery>"; + const char kResponse2[] = + "<?xml version=\"1.0\"?>\n" + "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" + "<form signature=\"11337937696949187602\"><field signature=\"412125936\"" + " name=\"name_on_card\" type=\"text\" label=\"Name on Card\"/>" + "<field signature=\"1917667676\" name=\"billing_address\" type=\"text\"" + " label=\"Address\"/><field signature=\"2226358947\" name=\"card_number\"" + " type=\"text\" label=\"Card Number\"/>" + "<field signature=\"747221617\" name=\"expiration_month\" type=\"text\"" + " label=\"Expiration Date\"/>" + "<field signature=\"4108155786\" name=\"expiration_year\" type=\"text\"" + " label=\"Expiration Year\"/></form>" + "<form signature=\"8308881815906226214\">" + "<field signature=\"412125936\" name=\"name_on_card\" type=\"text\"" + " label=\"Name on Card\"/><field signature=\"1917667676\"" + " name=\"billing_address\" type=\"text\" label=\"Address\"/>" + "<field signature=\"2226358947\" name=\"card_number\" type=\"text\"" + " label=\"Card Number\"/><field signature=\"747221617\"" + " name=\"expiration_month\" type=\"text\" label=\"Expiration Date\"/>" + "<field signature=\"4108155786\" name=\"expiration_year\" type=\"text\"" + " label=\"Expiration Year\"/><field signature=\"509334676\" " + "name=\"address\"" + " type=\"text\" label=\"Address\"/><field signature=\"509334676\"" + " name=\"address\" type=\"text\" label=\"Address\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\"/><field signature=\"509334676\" name=\"address\"" + " type=\"text\" label=\"Address\"/><field signature=\"509334676\"" + " name=\"address\" type=\"text\" " + "label=\"Address\"/></form></autofillquery>\n"; EXPECT_EQ(kResponse2, encoded_xml); FormData malformed_form(form); @@ -1599,8 +1603,6 @@ bad_forms.push_back(new FormStructure(malformed_form)); EXPECT_FALSE(FormStructure::EncodeQueryRequest( bad_forms.get(), &encoded_signatures, &encoded_xml)); - EXPECT_EQ(0U, encoded_signatures.size()); - EXPECT_EQ("", encoded_xml); } TEST_F(FormStructureTest, EncodeUploadRequest) { @@ -1675,42 +1677,44 @@ std::string encoded_xml; EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"8736493185895608956\" autofillused=\"false\"" - " datapresent=\"144200030e\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"3763331450\" name=\"firstname\" type=\"text\"" - " label=\"First Name\" autofilltype=\"3\"/>" - "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"5\"/>" - "<field signature=\"1029417091\" name=\"email\" type=\"email\"" - " label=\"Email\" autofilltype=\"9\"/>" - "<field signature=\"466116101\" name=\"phone\" type=\"number\"" - " label=\"Phone\" autofilltype=\"14\"/>" - "<field signature=\"2799270304\" name=\"country\"" - " type=\"select-one\" label=\"Country\" autofilltype=\"36\"/>" - "</autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"8736493185895608956\" autofillused=\"false\"" + " datapresent=\"144200030e\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"3763331450\" name=\"firstname\" type=\"text\"" + " label=\"First Name\" autofilltype=\"3\"/>" + "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"5\"/>" + "<field signature=\"1029417091\" name=\"email\" type=\"email\"" + " label=\"Email\" autofilltype=\"9\"/>" + "<field signature=\"466116101\" name=\"phone\" type=\"number\"" + " label=\"Phone\" autofilltype=\"14\"/>" + "<field signature=\"2799270304\" name=\"country\"" + " type=\"select-one\" label=\"Country\" autofilltype=\"36\"/>" + "</autofillupload>\n", + encoded_xml); EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, true, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"8736493185895608956\"" - " autofillused=\"true\" datapresent=\"144200030e\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"3763331450\" name=\"firstname\" type=\"text\"" - " label=\"First Name\" autofilltype=\"3\"/>" - "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"5\"/>" - "<field signature=\"1029417091\" name=\"email\" type=\"email\"" - " label=\"Email\" autofilltype=\"9\"/>" - "<field signature=\"466116101\" name=\"phone\" type=\"number\"" - " label=\"Phone\" autofilltype=\"14\"/>" - "<field signature=\"2799270304\" name=\"country\"" - " type=\"select-one\" label=\"Country\" autofilltype=\"36\"/>" - "</autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"8736493185895608956\"" + " autofillused=\"true\" datapresent=\"144200030e\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"3763331450\" name=\"firstname\" type=\"text\"" + " label=\"First Name\" autofilltype=\"3\"/>" + "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"5\"/>" + "<field signature=\"1029417091\" name=\"email\" type=\"email\"" + " label=\"Email\" autofilltype=\"9\"/>" + "<field signature=\"466116101\" name=\"phone\" type=\"number\"" + " label=\"Phone\" autofilltype=\"14\"/>" + "<field signature=\"2799270304\" name=\"country\"" + " type=\"select-one\" label=\"Country\" autofilltype=\"36\"/>" + "</autofillupload>\n", + encoded_xml); // Add 2 address fields - this should be still a valid form. for (size_t i = 0; i < 2; ++i) { @@ -1732,38 +1736,39 @@ EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"7816485729218079147\" autofillused=\"false\"" - " datapresent=\"144200030e\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"3763331450\" name=\"firstname\" type=\"text\"" - " label=\"First Name\" autofilltype=\"3\"/>" - "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"5\"/>" - "<field signature=\"1029417091\" name=\"email\" type=\"email\"" - " label=\"Email\" autofilltype=\"9\"/>" - "<field signature=\"466116101\" name=\"phone\" type=\"number\"" - " label=\"Phone\" autofilltype=\"14\"/>" - "<field signature=\"2799270304\" name=\"country\"" - " type=\"select-one\" label=\"Country\" autofilltype=\"36\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"30\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"31\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"37\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"38\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"30\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"31\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"37\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"38\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"7816485729218079147\" autofillused=\"false\"" + " datapresent=\"144200030e\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"3763331450\" name=\"firstname\" type=\"text\"" + " label=\"First Name\" autofilltype=\"3\"/>" + "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"5\"/>" + "<field signature=\"1029417091\" name=\"email\" type=\"email\"" + " label=\"Email\" autofilltype=\"9\"/>" + "<field signature=\"466116101\" name=\"phone\" type=\"number\"" + " label=\"Phone\" autofilltype=\"14\"/>" + "<field signature=\"2799270304\" name=\"country\"" + " type=\"select-one\" label=\"Country\" autofilltype=\"36\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"30\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"31\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"37\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"38\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"30\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"31\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"37\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"38\"/></autofillupload>\n", + encoded_xml); // Add 50 address fields - now the form is invalid, as it has too many fields. for (size_t i = 0; i < 50; ++i) { @@ -1847,7 +1852,7 @@ EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, true, "42", &encoded_xml)); EXPECT_EQ( - "<?xml version=\"1.0\" encoding=\"UTF-8\"?><autofillupload " + "<?xml version=\"1.0\"?>\n<autofillupload " "clientversion=\"6.1.1715.1442/en (GGLL)\" " "formsignature=\"5810032074788446513\" autofillused=\"true\" " "datapresent=\"1440000000000000000802\" " @@ -1863,7 +1868,7 @@ "label=\"username\" autocomplete=\"email\" autofilltype=\"86\"/><field " "signature=\"2051817934\" name=\"password\" type=\"password\" " "label=\"password\" autocomplete=\"email\" " - "autofilltype=\"76\"/></autofillupload>", + "autofilltype=\"76\"/></autofillupload>\n", encoded_xml); } @@ -1913,19 +1918,20 @@ std::string encoded_xml; EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, true, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"14746822798145140279\" autofillused=\"true\"" - " datapresent=\"1440\" actionsignature=\"15724779818122431245\">" - "<field signature=\"3763331450\" name=\"firstname\" type=\"text\"" - " label=\"First Name\" autocomplete=\"given-name\"" - " autofilltype=\"3\"/>" - "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" - " label=\"Last Name\" autocomplete=\"family-name\"" - " autofilltype=\"5\"/><field signature=\"1029417091\"" - " name=\"email\" type=\"email\" label=\"Email\"" - " autocomplete=\"email\" autofilltype=\"9\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"14746822798145140279\" autofillused=\"true\"" + " datapresent=\"1440\" actionsignature=\"15724779818122431245\">" + "<field signature=\"3763331450\" name=\"firstname\" type=\"text\"" + " label=\"First Name\" autocomplete=\"given-name\"" + " autofilltype=\"3\"/>" + "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" + " label=\"Last Name\" autocomplete=\"family-name\"" + " autofilltype=\"5\"/><field signature=\"1029417091\"" + " name=\"email\" type=\"email\" label=\"Email\"" + " autocomplete=\"email\" autofilltype=\"9\"/></autofillupload>\n", + encoded_xml); } TEST_F(FormStructureTest, EncodeUploadRequest_WithLabels) { @@ -1968,16 +1974,17 @@ EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, true, std::string(), &encoded_xml)); // Expected that the first field does not send the label but others do. - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"6949133589768631292\" autofillused=\"true\"" - " datapresent=\"1440\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"1318412689\" type=\"text\" autofilltype=\"3\"/>" - "<field signature=\"1318412689\" type=\"text\" label=\"Last Name\"" - " autofilltype=\"5\"/><field signature=\"1318412689\" type=\"text\"" - " label=\"Email\" autofilltype=\"9\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"6949133589768631292\" autofillused=\"true\"" + " datapresent=\"1440\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"1318412689\" type=\"text\" autofilltype=\"3\"/>" + "<field signature=\"1318412689\" type=\"text\" label=\"Last Name\"" + " autofilltype=\"5\"/><field signature=\"1318412689\" type=\"text\"" + " label=\"Email\" autofilltype=\"9\"/></autofillupload>\n", + encoded_xml); } // Test that the form name is sent in the upload request. @@ -2019,15 +2026,16 @@ std::string encoded_xml; EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, true, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?><autofillupload" - " clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"2345951786066580868\" autofillused=\"true\"" - " datapresent=\"1440\" actionsignature=\"15724779818122431245\"" - " formname=\"myform\"><field signature=\"1318412689\" type=\"text\"" - " autofilltype=\"3\"/><field signature=\"1318412689\" type=\"text\"" - " autofilltype=\"5\"/><field signature=\"1318412689\" type=\"text\"" - " autofilltype=\"9\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n<autofillupload" + " clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"2345951786066580868\" autofillused=\"true\"" + " datapresent=\"1440\" actionsignature=\"15724779818122431245\"" + " formname=\"myform\"><field signature=\"1318412689\" type=\"text\"" + " autofilltype=\"3\"/><field signature=\"1318412689\" type=\"text\"" + " autofilltype=\"5\"/><field signature=\"1318412689\" type=\"text\"" + " autofilltype=\"9\"/></autofillupload>\n", + encoded_xml); } TEST_F(FormStructureTest, EncodeUploadRequestPartialMetadata) { @@ -2075,18 +2083,19 @@ std::string encoded_xml; EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, true, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"13043654279838250996\" autofillused=\"true\"" - " datapresent=\"1440\" actionsignature=\"15724779818122431245\">" - "<field signature=\"1318412689\" type=\"text\" autofilltype=\"3\"/>" - "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" - " label=\"Last Name\" autocomplete=\"family-name\"" - " autofilltype=\"5\"/>" - "<field signature=\"1545468175\" name=\"lastname\" type=\"email\"" - " label=\"Email\" autocomplete=\"email\" autofilltype=\"9\"/>" - "</autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"13043654279838250996\" autofillused=\"true\"" + " datapresent=\"1440\" actionsignature=\"15724779818122431245\">" + "<field signature=\"1318412689\" type=\"text\" autofilltype=\"3\"/>" + "<field signature=\"3494530716\" name=\"lastname\" type=\"text\"" + " label=\"Last Name\" autocomplete=\"family-name\"" + " autofilltype=\"5\"/>" + "<field signature=\"1545468175\" name=\"lastname\" type=\"email\"" + " label=\"Email\" autocomplete=\"email\" autofilltype=\"9\"/>" + "</autofillupload>\n", + encoded_xml); } // Sending field metadata to the server is disabled. @@ -2138,14 +2147,15 @@ std::string encoded_xml; EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, true, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"14746822798145140279\" autofillused=\"true\"" - " datapresent=\"1440\"><field signature=\"3763331450\"" - " autofilltype=\"3\"/><field signature=\"3494530716\"" - " autofilltype=\"5\"/><field signature=\"1029417091\"" - " autofilltype=\"9\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"14746822798145140279\" autofillused=\"true\"" + " datapresent=\"1440\"><field signature=\"3763331450\"" + " autofilltype=\"3\"/><field signature=\"3494530716\"" + " autofilltype=\"5\"/><field signature=\"1029417091\"" + " autofilltype=\"9\"/></autofillupload>\n", + encoded_xml); } TEST_F(FormStructureTest, EncodeFieldAssignments) { @@ -2221,7 +2231,7 @@ EXPECT_TRUE(form_structure->EncodeFieldAssignments( available_field_types, &encoded_xml)); EXPECT_EQ( - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<?xml version=\"1.0\"?>\n" "<fieldassignments formsignature=\"8736493185895608956\">" "<fields fieldid=\"3763331450\" fieldtype=\"3\" name=\"firstname\"/>" "<fields fieldid=\"3494530716\" fieldtype=\"5\" name=\"lastname\"/>" @@ -2229,7 +2239,7 @@ "<fields fieldid=\"466116101\" fieldtype=\"14\" name=\"phone\"/>" "<fields fieldid=\"2799270304\" fieldtype=\"36\" name=\"country\"/>" "<fields fieldid=\"3410250678\" fieldtype=\"36\" name=\"Checkable1\"/>" - "</fieldassignments>", + "</fieldassignments>\n", encoded_xml); // Add 2 address fields - this should be still a valid form. @@ -2253,7 +2263,7 @@ EXPECT_TRUE(form_structure->EncodeFieldAssignments( available_field_types, &encoded_xml)); EXPECT_EQ( - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<?xml version=\"1.0\"?>\n" "<fieldassignments formsignature=\"7816485729218079147\">" "<fields fieldid=\"3763331450\" fieldtype=\"3\" name=\"firstname\"/>" "<fields fieldid=\"3494530716\" fieldtype=\"5\" name=\"lastname\"/>" @@ -2269,7 +2279,7 @@ "<fields fieldid=\"509334676\" fieldtype=\"31\" name=\"address\"/>" "<fields fieldid=\"509334676\" fieldtype=\"37\" name=\"address\"/>" "<fields fieldid=\"509334676\" fieldtype=\"38\" name=\"address\"/>" - "</fieldassignments>", + "</fieldassignments>\n", encoded_xml); } @@ -2308,17 +2318,18 @@ std::string encoded_xml; EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"6402244543831589061\" autofillused=\"false\"" - " datapresent=\"\" actionsignature=\"15724779818122431245\">" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"1\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"1\"/>" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"Email\" autofilltype=\"1\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"6402244543831589061\" autofillused=\"false\"" + " datapresent=\"\" actionsignature=\"15724779818122431245\">" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"1\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"1\"/>" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"Email\" autofilltype=\"1\"/></autofillupload>\n", + encoded_xml); // Only a few types available. // datapresent should be "1540000240" == trimmmed(0x1540000240000000) == @@ -2340,18 +2351,19 @@ EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"6402244543831589061\" autofillused=\"false\"" - " datapresent=\"1540000240\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"1\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"1\"/>" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"Email\" autofilltype=\"1\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"6402244543831589061\" autofillused=\"false\"" + " datapresent=\"1540000240\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"1\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"1\"/>" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"Email\" autofilltype=\"1\"/></autofillupload>\n", + encoded_xml); // All supported non-credit card types available. // datapresent should be "1f7e000378000008" == trimmmed(0x1f7e000378000008) == @@ -2397,18 +2409,19 @@ EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"6402244543831589061\" autofillused=\"false\"" - " datapresent=\"1f7e000378000008\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"1\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"1\"/>" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"Email\" autofilltype=\"1\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"6402244543831589061\" autofillused=\"false\"" + " datapresent=\"1f7e000378000008\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"1\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"1\"/>" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"Email\" autofilltype=\"1\"/></autofillupload>\n", + encoded_xml); // All supported credit card types available. // datapresent should be "0000000000001fc0" == trimmmed(0x0000000000001fc0) == @@ -2432,18 +2445,19 @@ EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"6402244543831589061\" autofillused=\"false\"" - " datapresent=\"0000000000001fc0\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"1\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"1\"/>" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"Email\" autofilltype=\"1\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"6402244543831589061\" autofillused=\"false\"" + " datapresent=\"0000000000001fc0\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"1\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"1\"/>" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"Email\" autofilltype=\"1\"/></autofillupload>\n", + encoded_xml); // All supported types available. // datapresent should be "1f7e000378001fc8" == trimmmed(0x1f7e000378001fc8) == @@ -2503,18 +2517,19 @@ EXPECT_TRUE(form_structure.EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"6402244543831589061\" autofillused=\"false\"" - " datapresent=\"1f7e000378001fc8\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"1\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"1\"/>" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"Email\" autofilltype=\"1\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"6402244543831589061\" autofillused=\"false\"" + " datapresent=\"1f7e000378001fc8\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"1\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"1\"/>" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"Email\" autofilltype=\"1\"/></autofillupload>\n", + encoded_xml); } TEST_F(FormStructureTest, CheckMultipleTypes) { @@ -2581,64 +2596,67 @@ // Now we matched both fields singularly. EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"18062476096658145866\" autofillused=\"false\"" - " datapresent=\"1440000360000008\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"email\" autofilltype=\"9\"/>" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"3\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"5\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"30\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"18062476096658145866\" autofillused=\"false\"" + " datapresent=\"1440000360000008\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"email\" autofilltype=\"9\"/>" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"3\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"5\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"30\"/></autofillupload>\n", + encoded_xml); // Match third field as both first and last. possible_field_types[2].insert(NAME_FIRST); form_structure->field(2)->set_possible_types(possible_field_types[2]); EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"18062476096658145866\" autofillused=\"false\"" - " datapresent=\"1440000360000008\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"email\" autofilltype=\"9\"/>" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"3\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"3\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"5\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"30\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"18062476096658145866\" autofillused=\"false\"" + " datapresent=\"1440000360000008\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"email\" autofilltype=\"9\"/>" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"3\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"3\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"5\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"30\"/></autofillupload>\n", + encoded_xml); possible_field_types[3].insert(ADDRESS_HOME_LINE2); form_structure->field(form_structure->field_count() - 1)->set_possible_types( possible_field_types[form_structure->field_count() - 1]); EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"18062476096658145866\" autofillused=\"false\"" - " datapresent=\"1440000360000008\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"email\" autofilltype=\"9\"/>" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"3\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"3\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"5\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"30\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"31\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"18062476096658145866\" autofillused=\"false\"" + " datapresent=\"1440000360000008\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"email\" autofilltype=\"9\"/>" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"3\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"3\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"5\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"30\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"31\"/></autofillupload>\n", + encoded_xml); possible_field_types[3].clear(); possible_field_types[3].insert(ADDRESS_HOME_LINE1); possible_field_types[3].insert(COMPANY_NAME); @@ -2646,24 +2664,25 @@ possible_field_types[form_structure->field_count() - 1]); EXPECT_TRUE(form_structure->EncodeUploadRequest(available_field_types, false, std::string(), &encoded_xml)); - EXPECT_EQ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" - " formsignature=\"18062476096658145866\" autofillused=\"false\"" - " datapresent=\"1440000360000008\"" - " actionsignature=\"15724779818122431245\">" - "<field signature=\"420638584\" name=\"email\" type=\"text\"" - " label=\"email\" autofilltype=\"9\"/>" - "<field signature=\"1089846351\" name=\"first\" type=\"text\"" - " label=\"First Name\" autofilltype=\"3\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"3\"/>" - "<field signature=\"2404144663\" name=\"last\" type=\"text\"" - " label=\"Last Name\" autofilltype=\"5\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"30\"/>" - "<field signature=\"509334676\" name=\"address\" type=\"text\"" - " label=\"Address\" autofilltype=\"60\"/></autofillupload>", - encoded_xml); + EXPECT_EQ( + "<?xml version=\"1.0\"?>\n" + "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\"" + " formsignature=\"18062476096658145866\" autofillused=\"false\"" + " datapresent=\"1440000360000008\"" + " actionsignature=\"15724779818122431245\">" + "<field signature=\"420638584\" name=\"email\" type=\"text\"" + " label=\"email\" autofilltype=\"9\"/>" + "<field signature=\"1089846351\" name=\"first\" type=\"text\"" + " label=\"First Name\" autofilltype=\"3\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"3\"/>" + "<field signature=\"2404144663\" name=\"last\" type=\"text\"" + " label=\"Last Name\" autofilltype=\"5\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"30\"/>" + "<field signature=\"509334676\" name=\"address\" type=\"text\"" + " label=\"Address\" autofilltype=\"60\"/></autofillupload>\n", + encoded_xml); } TEST_F(FormStructureTest, CheckFormSignature) { @@ -2789,13 +2808,14 @@ std::string encoded_xml; const char kSignature[] = "18006745212084723782"; - const char kResponse[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + const char kResponse[] = + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"18006745212084723782\">" "<field signature=\"239111655\" name=\"username\" type=\"text\"" " label=\"username\"/>" "<field signature=\"420638584\" name=\"email\" type=\"text\"/>" - "</form></autofillquery>"; + "</form></autofillquery>\n"; ASSERT_TRUE(FormStructure::EncodeQueryRequest( forms.get(), &encoded_signatures, &encoded_xml)); ASSERT_EQ(1U, encoded_signatures.size()); @@ -2830,14 +2850,15 @@ std::vector<std::string> encoded_signatures; std::string encoded_xml; - const char kRequest[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + const char kRequest[] = + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"13906559713264665730\">" "<field signature=\"239111655\" name=\"username\" type=\"text\"/>" "<field signature=\"420638584\" name=\"email\" type=\"text\"" " label=\"Enter your Email address\"/>" "<field signature=\"2051817934\" name=\"password\" type=\"password\"" - " label=\"Enter your Password\"/></form></autofillquery>"; + " label=\"Enter your Password\"/></form></autofillquery>\n"; EXPECT_TRUE(FormStructure::EncodeQueryRequest( forms.get(), &encoded_signatures, &encoded_xml)); EXPECT_EQ(kRequest, encoded_xml); @@ -2876,7 +2897,7 @@ std::string encoded_xml; const char kRequest[] = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"13906559713264665730\">" "<field signature=\"239111655\" name=\"username\" type=\"text\"/>" @@ -2886,7 +2907,7 @@ " That's What Marketers Do! We Know That Your Email Address Has The" " Poss\"/>" "<field signature=\"2051817934\" name=\"password\" type=\"password\"" - " label=\"Enter your Password\"/></form></autofillquery>"; + " label=\"Enter your Password\"/></form></autofillquery>\n"; EXPECT_TRUE(FormStructure::EncodeQueryRequest( forms.get(), &encoded_signatures, &encoded_xml)); EXPECT_EQ(kRequest, encoded_xml); @@ -2918,12 +2939,13 @@ std::string encoded_xml; const char kSignature[] = "16416961345885087496"; - const char kResponse[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + const char kResponse[] = + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"16416961345885087496\">" "<field signature=\"239111655\" name=\"username\" type=\"text\"" " label=\"username\"/><field signature=\"1318412689\" type=\"text\"/>" - "</form></autofillquery>"; + "</form></autofillquery>\n"; ASSERT_TRUE(FormStructure::EncodeQueryRequest( forms.get(), &encoded_signatures, &encoded_xml)); ASSERT_EQ(1U, encoded_signatures.size()); @@ -2958,12 +2980,13 @@ std::string encoded_xml; const char kSignature[] = "7635954436925888745"; - const char kResponse[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + const char kResponse[] = + "<?xml version=\"1.0\"?>\n" "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">" "<form signature=\"7635954436925888745\">" "<field signature=\"239111655\"/>" "<field signature=\"3654076265\"/>" - "</form></autofillquery>"; + "</form></autofillquery>\n"; ASSERT_TRUE(FormStructure::EncodeQueryRequest( forms.get(), &encoded_signatures, &encoded_xml)); ASSERT_EQ(1U, encoded_signatures.size());
diff --git a/components/autofill/core/common/BUILD.gn b/components/autofill/core/common/BUILD.gn index 9a53fe24..ca36439 100644 --- a/components/autofill/core/common/BUILD.gn +++ b/components/autofill/core/common/BUILD.gn
@@ -34,8 +34,6 @@ "password_generation_util.h", "save_password_progress_logger.cc", "save_password_progress_logger.h", - "web_element_descriptor.cc", - "web_element_descriptor.h", ] deps = [
diff --git a/components/autofill/core/common/web_element_descriptor.cc b/components/autofill/core/common/web_element_descriptor.cc deleted file mode 100644 index 76e0543..0000000 --- a/components/autofill/core/common/web_element_descriptor.cc +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2013 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/autofill/core/common/web_element_descriptor.h" - -namespace autofill { - -WebElementDescriptor::WebElementDescriptor() - : retrieval_method(NONE) {} - -} // namespace autofill
diff --git a/components/autofill/core/common/web_element_descriptor.h b/components/autofill/core/common/web_element_descriptor.h deleted file mode 100644 index 6f41cbb..0000000 --- a/components/autofill/core/common/web_element_descriptor.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2013 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_AUTOFILL_CORE_COMMON_WEB_ELEMENT_DESCRIPTOR_H_ -#define COMPONENTS_AUTOFILL_CORE_COMMON_WEB_ELEMENT_DESCRIPTOR_H_ - -#include <string> - -namespace autofill { - -// Holds information that can be used to retrieve an element. -struct WebElementDescriptor { - enum RetrievalMethod { - CSS_SELECTOR, - ID, - NONE, - }; - - WebElementDescriptor(); - - // Information to retrieve element with. - std::string descriptor; - - // Which retrieval method to use. - RetrievalMethod retrieval_method; -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_COMMON_WEB_ELEMENT_DESCRIPTOR_H_
diff --git a/components/drive/service/drive_api_service.cc b/components/drive/service/drive_api_service.cc index 2f47fe6..446503a 100644 --- a/components/drive/service/drive_api_service.cc +++ b/components/drive/service/drive_api_service.cc
@@ -248,11 +248,12 @@ base::SequencedTaskRunner* blocking_task_runner, const GURL& base_url, const GURL& base_download_url, + const GURL& base_thumbnail_url, const std::string& custom_user_agent) : oauth2_token_service_(oauth2_token_service), url_request_context_getter_(url_request_context_getter), blocking_task_runner_(blocking_task_runner), - url_generator_(base_url, base_download_url), + url_generator_(base_url, base_download_url, base_thumbnail_url), custom_user_agent_(custom_user_agent) { }
diff --git a/components/drive/service/drive_api_service.h b/components/drive/service/drive_api_service.h index 22bb7d4..374edc0 100644 --- a/components/drive/service/drive_api_service.h +++ b/components/drive/service/drive_api_service.h
@@ -93,6 +93,8 @@ // |base_url| is used to generate URLs for communication with the drive API. // |base_download_url| is used to generate URLs for downloading file from the // drive API. + // |base_thumbnail_url| is used to generate URLs for downloading thumbnail + // from image server. // |custom_user_agent| will be used for the User-Agent header in HTTP // requests issues through the service if the value is not empty. DriveAPIService( @@ -101,6 +103,7 @@ base::SequencedTaskRunner* blocking_task_runner, const GURL& base_url, const GURL& base_download_url, + const GURL& base_thumbnail_url, const std::string& custom_user_agent); ~DriveAPIService() override;
diff --git a/components/drive/service/drive_api_service_unittest.cc b/components/drive/service/drive_api_service_unittest.cc index 6655e68..c6a4e2f 100644 --- a/components/drive/service/drive_api_service_unittest.cc +++ b/components/drive/service/drive_api_service_unittest.cc
@@ -36,7 +36,8 @@ TEST(DriveAPIServiceTest, BatchRequestConfiguratorWithAuthFailure) { const GURL test_base_url("http://localhost/"); - google_apis::DriveApiUrlGenerator url_generator(test_base_url, test_base_url); + google_apis::DriveApiUrlGenerator url_generator( + test_base_url, test_base_url, test_base_url); scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner(); scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc index e8a0e60..f1983af 100644 --- a/components/exo/shell_surface.cc +++ b/components/exo/shell_surface.cc
@@ -112,6 +112,8 @@ void ShellSurface::OnSurfaceCommit() { if (widget_ || show_state_ == ui::SHOW_STATE_END) { surface_->CommitSurfaceHierarchy(); + if (widget_) + widget_->SetSize(widget_->non_client_view()->GetPreferredSize()); return; }
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc index 6ade2840..d04da9e 100644 --- a/components/exo/shell_surface_unittest.cc +++ b/components/exo/shell_surface_unittest.cc
@@ -3,11 +3,14 @@ // found in the LICENSE file. #include "base/strings/utf_string_conversions.h" +#include "components/exo/buffer.h" #include "components/exo/shell_surface.h" #include "components/exo/surface.h" #include "components/exo/test/exo_test_base.h" #include "components/exo/test/exo_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/khronos/GLES2/gl2.h" +#include "ui/views/widget/widget.h" namespace exo { namespace { @@ -15,11 +18,30 @@ using ShellSurfaceTest = test::ExoTestBase; TEST_F(ShellSurfaceTest, Show) { + gfx::Size small_buffer_size(64, 64); + scoped_ptr<Buffer> small_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(small_buffer_size), + GL_TEXTURE_2D)); + gfx::Size large_buffer_size(256, 256); + scoped_ptr<Buffer> large_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(large_buffer_size), + GL_TEXTURE_2D)); scoped_ptr<Surface> surface(new Surface); scoped_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); shell_surface->Show(); + surface->Attach(small_buffer.get()); surface->Commit(); + ASSERT_TRUE(shell_surface->GetWidget()); + EXPECT_EQ( + small_buffer_size.ToString(), + shell_surface->GetWidget()->GetWindowBoundsInScreen().size().ToString()); + + surface->Attach(large_buffer.get()); + surface->Commit(); + EXPECT_EQ( + large_buffer_size.ToString(), + shell_surface->GetWidget()->GetWindowBoundsInScreen().size().ToString()); } TEST_F(ShellSurfaceTest, SetToplevel) {
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc index e38cd6c..96d43fc 100644 --- a/components/exo/surface_unittest.cc +++ b/components/exo/surface_unittest.cc
@@ -10,7 +10,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/khronos/GLES2/gl2.h" #include "ui/gfx/gpu_memory_buffer.h" -#include "ui/views/test/widget_test.h" namespace exo { namespace {
diff --git a/components/flags_ui/flags_state.cc b/components/flags_ui/flags_state.cc index b7345b2..9583d9e5 100644 --- a/components/flags_ui/flags_state.cc +++ b/components/flags_ui/flags_state.cc
@@ -73,6 +73,7 @@ {kOsCrOS, "Chrome OS"}, {kOsAndroid, "Android"}, {kOsCrOSOwnerOnly, "Chrome OS (owner only)"}, + {kOsIos, "iOS"}, }; // Adds a |StringValue| to |list| for each platform where |bitmask| indicates @@ -427,6 +428,10 @@ supported = true; } #endif +#if defined(OS_IOS) + if (access == kAppleReviewAccessToFlags) + supported = ((entry.supported_platforms & kOsIosAppleReview) != 0); +#endif if (supported) supported_entries->Append(data); else @@ -436,7 +441,9 @@ // static int FlagsState::GetCurrentPlatform() { -#if defined(OS_MACOSX) +#if defined(OS_IOS) // Needs to be before the OS_MACOSX check. + return kOsIos; +#elif defined(OS_MACOSX) return kOsMac; #elif defined(OS_WIN) return kOsWin;
diff --git a/components/flags_ui/flags_state.h b/components/flags_ui/flags_state.h index 8f2a19ff..f1e91dc 100644 --- a/components/flags_ui/flags_state.h +++ b/components/flags_ui/flags_state.h
@@ -30,7 +30,9 @@ kOsLinux = 1 << 2, kOsCrOS = 1 << 3, kOsAndroid = 1 << 4, - kOsCrOSOwnerOnly = 1 << 5 + kOsCrOSOwnerOnly = 1 << 5, + kOsIos = 1 << 6, + kOsIosAppleReview = 1 << 7, }; // A flag controlling the behavior of the |ConvertFlagsToSwitches| function - @@ -41,7 +43,10 @@ // that influence the whole machine and can be said by the admin only. This flag // is relevant for ChromeOS for now only and dictates whether entries marked // with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not. -enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags }; +// On iOS, |kAppleReviewAccessToFlags| indicates that the flags shown should +// be the ones marked for Apple review (which otherwise will not be shown). +enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags, + kAppleReviewAccessToFlags }; // Stores and encapsulates the little state that about:flags has. class FlagsState {
diff --git a/components/html_viewer/html_frame.cc b/components/html_viewer/html_frame.cc index c58f5e20..8050f145 100644 --- a/components/html_viewer/html_frame.cc +++ b/components/html_viewer/html_frame.cc
@@ -678,11 +678,10 @@ SetWindow(window); SetReplicatedFrameStateFromClientProperties(properties, &state_); blink::WebLocalFrame* local_web_frame = - blink::WebLocalFrame::create(state_.tree_scope, this); - local_web_frame->initializeToReplaceRemoteFrame( - web_frame_->toWebRemoteFrame(), state_.name, state_.sandbox_flags, - // TODO(lazyboy): Figure out replicating WebFrameOwnerProperties. - blink::WebFrameOwnerProperties()); + blink::WebLocalFrame::createProvisional( + this, web_frame_->toWebRemoteFrame(), state_.sandbox_flags, + // TODO(lazyboy): Figure out replicating WebFrameOwnerProperties. + blink::WebFrameOwnerProperties()); // The swap() ends up calling to frameDetached() and deleting the old. web_frame_->swap(local_web_frame); web_frame_ = local_web_frame;
diff --git a/components/mus/public/interfaces/window_tree.mojom b/components/mus/public/interfaces/window_tree.mojom index f0c619f..ea172b3 100644 --- a/components/mus/public/interfaces/window_tree.mojom +++ b/components/mus/public/interfaces/window_tree.mojom
@@ -44,6 +44,8 @@ // embedded apps representation. enum SurfaceType { // Only the owner of a window may obtain this surface. + // The window manager can change the offset of this by way of + // SetUnderlaySurfaceOffsetAndExtendedHitArea(). UNDERLAY, // Only the embedded app may obtain this surface. If an app is not embedded
diff --git a/components/mus/public/interfaces/window_tree_host.mojom b/components/mus/public/interfaces/window_tree_host.mojom index 864b577..3209bdab 100644 --- a/components/mus/public/interfaces/window_tree_host.mojom +++ b/components/mus/public/interfaces/window_tree_host.mojom
@@ -33,6 +33,17 @@ RemoveActivationParent(uint32 window_id); ActivateNextWindow(); + + // Sets the underlay surface offset for the specified window and additional + // hit area. The underlay surface is drawn at the bounds of the window minus + // the offset. The hit area is extended from the bounds of the window by + // |hit_area|. + // TODO(sky): pull this into the WindowTree API exposed for the + // windowmanager. + SetUnderlaySurfaceOffsetAndExtendedHitArea(uint32 window_id, + int32 x_offset, + int32 y_offset, + mojo.Insets hit_area); }; interface WindowTreeHostClient {
diff --git a/components/mus/ws/display_manager.cc b/components/mus/ws/display_manager.cc index 03eb620d..afbe6e9 100644 --- a/components/mus/ws/display_manager.cc +++ b/components/mus/ws/display_manager.cc
@@ -98,21 +98,21 @@ if (!draw_default_surface && !underlay_surface) return; - const gfx::Rect bounds_at_origin(window->bounds().size()); - - gfx::Transform quad_to_target_transform; - quad_to_target_transform.Translate(absolute_bounds.x(), absolute_bounds.y()); - - cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); - // TODO(fsamuel): These clipping and visible rects are incorrect. They need - // to be populated from CompositorFrame structs. - sqs->SetAll( - quad_to_target_transform, bounds_at_origin.size() /* layer_bounds */, - bounds_at_origin /* visible_layer_bounds */, - bounds_at_origin /* clip_rect */, false /* is_clipped */, - window->opacity(), SkXfermode::kSrc_Mode, 0 /* sorting-context_id */); - if (draw_default_surface) { + gfx::Transform quad_to_target_transform; + quad_to_target_transform.Translate(absolute_bounds.x(), + absolute_bounds.y()); + + cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); + + const gfx::Rect bounds_at_origin(window->bounds().size()); + // TODO(fsamuel): These clipping and visible rects are incorrect. They need + // to be populated from CompositorFrame structs. + sqs->SetAll( + quad_to_target_transform, bounds_at_origin.size() /* layer_bounds */, + bounds_at_origin /* visible_layer_bounds */, + bounds_at_origin /* clip_rect */, false /* is_clipped */, + window->opacity(), SkXfermode::kSrc_Mode, 0 /* sorting-context_id */); auto quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); quad->SetAll(sqs, bounds_at_origin /* rect */, gfx::Rect() /* opaque_rect */, @@ -120,6 +120,20 @@ default_surface->id()); } if (underlay_surface) { + const gfx::Rect underlay_absolute_bounds = + absolute_bounds - window->underlay_offset(); + gfx::Transform quad_to_target_transform; + quad_to_target_transform.Translate(underlay_absolute_bounds.x(), + underlay_absolute_bounds.y()); + cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); + const gfx::Rect bounds_at_origin( + underlay_surface->last_submitted_frame_size()); + sqs->SetAll( + quad_to_target_transform, bounds_at_origin.size() /* layer_bounds */, + bounds_at_origin /* visible_layer_bounds */, + bounds_at_origin /* clip_rect */, false /* is_clipped */, + window->opacity(), SkXfermode::kSrc_Mode, 0 /* sorting-context_id */); + auto quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); quad->SetAll(sqs, bounds_at_origin /* rect */, gfx::Rect() /* opaque_rect */,
diff --git a/components/mus/ws/server_window.cc b/components/mus/ws/server_window.cc index 43fecc60..29b8ec1 100644 --- a/components/mus/ws/server_window.cc +++ b/components/mus/ws/server_window.cc
@@ -331,6 +331,14 @@ return surface_manager_.get(); } +void ServerWindow::SetUnderlayOffset(const gfx::Vector2d& offset) { + if (offset == underlay_offset_) + return; + + underlay_offset_ = offset; + delegate_->OnScheduleWindowPaint(this); +} + #if !defined(NDEBUG) std::string ServerWindow::GetDebugWindowHierarchy() const { std::string result;
diff --git a/components/mus/ws/server_window.h b/components/mus/ws/server_window.h index 9289125..89d291b3 100644 --- a/components/mus/ws/server_window.h +++ b/components/mus/ws/server_window.h
@@ -17,6 +17,7 @@ #include "mojo/public/cpp/bindings/binding.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/transform.h" #include "ui/platform_window/text_input_state.h" @@ -138,6 +139,10 @@ return surface_manager_.get(); } + // Offset of the underlay from the the window bounds (used for shadows). + const gfx::Vector2d& underlay_offset() const { return underlay_offset_; } + void SetUnderlayOffset(const gfx::Vector2d& offset); + ServerWindowDelegate* delegate() { return delegate_; } #if !defined(NDEBUG) @@ -183,6 +188,8 @@ Properties properties_; + gfx::Vector2d underlay_offset_; + base::ObserverList<ServerWindowObserver> observers_; DISALLOW_COPY_AND_ASSIGN(ServerWindow);
diff --git a/components/mus/ws/server_window_surface.h b/components/mus/ws/server_window_surface.h index 99e0e52..378c09d 100644 --- a/components/mus/ws/server_window_surface.h +++ b/components/mus/ws/server_window_surface.h
@@ -39,6 +39,10 @@ ~ServerWindowSurface() override; + const gfx::Size& last_submitted_frame_size() const { + return last_submitted_frame_size_; + } + // mojom::Surface: void SubmitCompositorFrame( mojom::CompositorFramePtr frame,
diff --git a/components/mus/ws/window_tree_host_impl.cc b/components/mus/ws/window_tree_host_impl.cc index bba8925b..87d2a4ff 100644 --- a/components/mus/ws/window_tree_host_impl.cc +++ b/components/mus/ws/window_tree_host_impl.cc
@@ -153,6 +153,21 @@ focus_controller_->ActivateNextWindow(); } +void WindowTreeHostImpl::SetUnderlaySurfaceOffsetAndExtendedHitArea( + Id window_id, + int32_t x_offset, + int32_t y_offset, + mojo::InsetsPtr hit_area) { + ServerWindow* window = + connection_manager_->GetWindow(WindowIdFromTransportId(window_id)); + if (!window) + return; + + window->SetUnderlayOffset(gfx::Vector2d(x_offset, y_offset)); + + // TODO(sky): support hit area. +} + void WindowTreeHostImpl::OnClientClosed() { // |display_manager_.reset()| destroys the display-manager first, and then // sets |display_manager_| to nullptr. However, destroying |display_manager_|
diff --git a/components/mus/ws/window_tree_host_impl.h b/components/mus/ws/window_tree_host_impl.h index 35a05c8..3850a3c 100644 --- a/components/mus/ws/window_tree_host_impl.h +++ b/components/mus/ws/window_tree_host_impl.h
@@ -99,6 +99,11 @@ void AddActivationParent(uint32_t window_id) override; void RemoveActivationParent(uint32_t window_id) override; void ActivateNextWindow() override; + void SetUnderlaySurfaceOffsetAndExtendedHitArea( + Id window_id, + int32_t x_offset, + int32_t y_offset, + mojo::InsetsPtr hit_area) override; private: void OnClientClosed();
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index b1fde40b..7133cdd 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -424,6 +424,8 @@ if (use_aura) { deps += [ "//components/bitmap_uploader", + "//components/mus/public/cpp", + "//components/mus/public/interfaces", "//ui/aura", "//ui/aura_extra", "//ui/strings",
diff --git a/content/browser/DEPS b/content/browser/DEPS index 298ec09..dec16bf 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -3,6 +3,7 @@ # depend on components which we share with the mojo html_viewer. "+components/mime_util", "+components/mus/public/interfaces", + "+components/mus/public", "+components/scheduler/common", "+components/tracing", "+components/url_formatter",
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 8f93e67..ad3d8ad4 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -933,6 +933,7 @@ #if defined(MOJO_SHELL_CLIENT) if (IsRunningInMojoShell()) { MojoShellConnectionImpl::Create(); + MojoShellConnectionImpl::Get()->BindToCommandLinePlatformChannel(); #if defined(USE_AURA) views::WindowManagerConnection::Create( MojoShellConnection::Get()->GetApplication());
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index 7562c0f..7e0a7669 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc
@@ -73,10 +73,9 @@ // plan on how to display the UI for that. DCHECK(params->prefer_cache()); DCHECK_EQ("POST", params->method()); - ScopedVector<net::UploadElementReader> element_readers; - request->set_upload(make_scoped_ptr( - new net::ElementsUploadDataStream(element_readers.Pass(), - params->post_id()))); + std::vector<scoped_ptr<net::UploadElementReader>> element_readers; + request->set_upload(make_scoped_ptr(new net::ElementsUploadDataStream( + std::move(element_readers), params->post_id()))); } // If we're not at the beginning of the file, retrieve only the remaining
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index 78fb9cf..8904071 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -288,7 +288,7 @@ void NavigationHandleImpl::ReadyToCommitNavigation( RenderFrameHostImpl* render_frame_host, scoped_refptr<net::HttpResponseHeaders> response_headers) { - DCHECK(!render_frame_host_); + DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host); render_frame_host_ = render_frame_host; response_headers_ = response_headers; state_ = READY_TO_COMMIT; @@ -304,7 +304,7 @@ void NavigationHandleImpl::DidCommitNavigation( bool same_page, RenderFrameHostImpl* render_frame_host) { - CHECK(!render_frame_host_ || render_frame_host_ == render_frame_host); + DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host); is_same_page_ = same_page; render_frame_host_ = render_frame_host; state_ = net_error_code_ == net::OK ? DID_COMMIT : DID_COMMIT_ERROR_PAGE;
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index ce8891c9..3e3a497 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -151,8 +151,6 @@ // DidStartProvisionalLoad should not correspond to a new navigation. DCHECK_EQ(url, render_frame_host->navigation_handle()->GetURL()); render_frame_host->navigation_handle()->set_is_transferring(false); - render_frame_host->navigation_handle()->set_render_frame_host( - render_frame_host); return; }
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 053f5bc..70c8818 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1041,6 +1041,8 @@ void RenderFrameHostImpl::SetNavigationHandle( scoped_ptr<NavigationHandleImpl> navigation_handle) { navigation_handle_ = navigation_handle.Pass(); + if (navigation_handle_) + navigation_handle_->set_render_frame_host(this); } scoped_ptr<NavigationHandleImpl>
diff --git a/content/browser/loader/upload_data_stream_builder.cc b/content/browser/loader/upload_data_stream_builder.cc index a79299c..7f6b517 100644 --- a/content/browser/loader/upload_data_stream_builder.cc +++ b/content/browser/loader/upload_data_stream_builder.cc
@@ -77,27 +77,25 @@ storage::BlobStorageContext* blob_context, storage::FileSystemContext* file_system_context, base::SingleThreadTaskRunner* file_task_runner) { - ScopedVector<net::UploadElementReader> element_readers; + std::vector<scoped_ptr<net::UploadElementReader>> element_readers; for (const auto& element : *body->elements()) { switch (element.type()) { case ResourceRequestBody::Element::TYPE_BYTES: - element_readers.push_back(new BytesElementReader(body, element)); + element_readers.push_back( + make_scoped_ptr(new BytesElementReader(body, element))); break; case ResourceRequestBody::Element::TYPE_FILE: - element_readers.push_back( - new FileElementReader(body, file_task_runner, element)); + element_readers.push_back(make_scoped_ptr( + new FileElementReader(body, file_task_runner, element))); break; case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM: // If |body| contains any filesystem URLs, the caller should have // supplied a FileSystemContext. DCHECK(file_system_context); element_readers.push_back( - new content::UploadFileSystemFileElementReader( - file_system_context, - element.filesystem_url(), - element.offset(), - element.length(), - element.expected_modification_time())); + make_scoped_ptr(new content::UploadFileSystemFileElementReader( + file_system_context, element.filesystem_url(), element.offset(), + element.length(), element.expected_modification_time()))); break; case ResourceRequestBody::Element::TYPE_BLOB: { DCHECK_EQ(std::numeric_limits<uint64_t>::max(), element.length()); @@ -105,9 +103,10 @@ scoped_ptr<storage::BlobDataHandle> handle = blob_context->GetBlobDataFromUUID(element.blob_uuid()); storage::BlobDataHandle* handle_ptr = handle.get(); - element_readers.push_back(new storage::UploadBlobElementReader( - handle_ptr->CreateReader(file_system_context, file_task_runner), - handle.Pass())); + element_readers.push_back( + make_scoped_ptr(new storage::UploadBlobElementReader( + handle_ptr->CreateReader(file_system_context, file_task_runner), + std::move(handle)))); break; } case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: @@ -118,9 +117,8 @@ } } - return make_scoped_ptr( - new net::ElementsUploadDataStream(element_readers.Pass(), - body->identifier())); + return make_scoped_ptr(new net::ElementsUploadDataStream( + std::move(element_readers), body->identifier())); } } // namespace content
diff --git a/content/browser/loader/upload_data_stream_builder_unittest.cc b/content/browser/loader/upload_data_stream_builder_unittest.cc index e323a4e9..c8f6b77 100644 --- a/content/browser/loader/upload_data_stream_builder_unittest.cc +++ b/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -81,7 +81,7 @@ const storage::UploadBlobElementReader* r3 = static_cast<storage::UploadBlobElementReader*>( - (*upload->GetElementReaders())[2]); + (*upload->GetElementReaders())[2].get()); ASSERT_TRUE(r3); EXPECT_EQ("blobuuid", r3->uuid()); }
diff --git a/content/browser/mojo/mojo_shell_client_host.cc b/content/browser/mojo/mojo_shell_client_host.cc index 3a1acdf..8616a37 100644 --- a/content/browser/mojo/mojo_shell_client_host.cc +++ b/content/browser/mojo/mojo_shell_client_host.cc
@@ -21,6 +21,7 @@ namespace { const char kMojoShellInstanceURL[] = "mojo_shell_instance_url"; +const char kMojoPlatformFile[] = "mojo_platform_file"; void DidCreateChannel(mojo::embedder::ChannelInfo* info) {} @@ -46,16 +47,35 @@ DISALLOW_COPY_AND_ASSIGN(InstanceURL); }; +class InstanceShellHandle : public base::SupportsUserData::Data { + public: + InstanceShellHandle(base::PlatformFile shell_handle) + : shell_handle_(shell_handle) {} + ~InstanceShellHandle() override {} + + base::PlatformFile get() const { return shell_handle_; } + + private: + base::PlatformFile shell_handle_; + + DISALLOW_COPY_AND_ASSIGN(InstanceShellHandle); +}; + void SetMojoApplicationInstanceURL(RenderProcessHost* render_process_host, const std::string& instance_url) { render_process_host->SetUserData(kMojoShellInstanceURL, new InstanceURL(instance_url)); } +void SetMojoPlatformFile(RenderProcessHost* render_process_host, + base::PlatformFile platform_file) { + render_process_host->SetUserData(kMojoPlatformFile, + new InstanceShellHandle(platform_file)); +} + } // namespace void RegisterChildWithExternalShell(int child_process_id, - base::ProcessHandle process_handle, RenderProcessHost* render_process_host) { // Some process types get created before the main message loop. if (!MojoShellConnection::Get()) @@ -96,8 +116,7 @@ // Send the other end to the child via Chrome IPC. base::PlatformFile client_file = PlatformFileFromScopedPlatformHandle( platform_channel_pair.PassClientHandle()); - render_process_host->Send(new MojoMsg_BindExternalMojoShellHandle( - IPC::GetFileHandleForProcess(client_file, process_handle, true))); + SetMojoPlatformFile(render_process_host, client_file); // Store the URL on the RPH so client code can access it later via // GetMojoApplicationInstanceURL(). @@ -111,4 +130,15 @@ return instance_url ? instance_url->get() : std::string(); } +void SendExternalMojoShellHandleToChild( + base::ProcessHandle process_handle, + RenderProcessHost* render_process_host) { + InstanceShellHandle* client_file = static_cast<InstanceShellHandle*>( + render_process_host->GetUserData(kMojoPlatformFile)); + if (!client_file) + return; + render_process_host->Send(new MojoMsg_BindExternalMojoShellHandle( + IPC::GetFileHandleForProcess(client_file->get(), process_handle, true))); +} + } // namespace content
diff --git a/content/browser/mojo/mojo_shell_client_host.h b/content/browser/mojo/mojo_shell_client_host.h index 6f61f71e..c59924f 100644 --- a/content/browser/mojo/mojo_shell_client_host.h +++ b/content/browser/mojo/mojo_shell_client_host.h
@@ -15,11 +15,9 @@ // Creates a communication channel between the external Mojo shell and the // child. The server handle of this channel is shared with the external shell -// via Mojo IPC and the client handle is shared with the child via Chrome IPC. -// |child_process_id| is used to uniquify the child in the external shell's -// instance map. +// via Mojo IPC. |child_process_id| is used to uniquify the child in the +// external shell's instance map. void RegisterChildWithExternalShell(int child_process_id, - base::ProcessHandle process_handle, RenderProcessHost* render_process_host); // Returns the URL associated with an instance corresponding to the renderer @@ -28,6 +26,10 @@ std::string GetMojoApplicationInstanceURL( RenderProcessHost* render_process_host); +// Shares a client handle to the Mojo Shell with the child via Chrome IPC. +void SendExternalMojoShellHandleToChild(base::ProcessHandle process_handle, + RenderProcessHost* render_process_host); + } // namespace content #endif // CONTENT_BROWSER_MOJO_MOJO_SHELL_CLIENT_HOST_H_
diff --git a/content/browser/renderer_host/DEPS b/content/browser/renderer_host/DEPS index 202bcdd..e20b5581 100644 --- a/content/browser/renderer_host/DEPS +++ b/content/browser/renderer_host/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+cc/switches.h", # For cc command line switches. + "+components/mus/public", "+media/base", # For media command line switches. "+media/audio/audio_util.h", # For audio hardware sample-rate. "+third_party/zlib",
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 87964b50..edf1f43 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -575,6 +575,10 @@ IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded(); #endif // defined(OS_MACOSX) && !defined(OS_IOS) #endif // USE_ATTACHMENT_BROKER + +#if defined(MOJO_SHELL_CLIENT) + RegisterChildWithExternalShell(id_, this); +#endif } // static @@ -2439,9 +2443,8 @@ NotificationService::NoDetails()); #if defined(MOJO_SHELL_CLIENT) - // Send a handle that the external Mojo shell can use to pass an Application - // request to the child. - RegisterChildWithExternalShell(id_, GetHandle(), this); + // Send the mojo shell handle to the renderer. + SendExternalMojoShellHandleToChild(GetHandle(), this); #endif #if defined(OS_WIN)
diff --git a/content/browser/renderer_host/render_widget_host_view_mus.cc b/content/browser/renderer_host/render_widget_host_view_mus.cc index e371035..08e0058c3 100644 --- a/content/browser/renderer_host/render_widget_host_view_mus.cc +++ b/content/browser/renderer_host/render_widget_host_view_mus.cc
@@ -4,7 +4,14 @@ #include "content/browser/renderer_host/render_widget_host_view_mus.h" +#include "components/mus/public/cpp/window.h" +#include "components/mus/public/cpp/window_tree_connection.h" +#include "content/browser/mojo/mojo_shell_client_host.h" +#include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/common/render_widget_window_tree_client_factory.mojom.h" +#include "content/public/common/mojo_shell_connection.h" +#include "mojo/application/public/cpp/application_impl.h" namespace blink { struct WebScreenInfo; @@ -13,10 +20,28 @@ namespace content { RenderWidgetHostViewMus::RenderWidgetHostViewMus( + mus::Window* parent_window, RenderWidgetHostImpl* host, base::WeakPtr<RenderWidgetHostViewBase> platform_view) : host_(host), platform_view_(platform_view) { + DCHECK(parent_window); + mus::Window* window = parent_window->connection()->NewWindow(); + window->SetVisible(true); + window->SetBounds(gfx::Rect(300, 300)); + parent_window->AddChild(window); + window_.reset(new mus::ScopedWindowPtr(window)); host_->SetView(this); + + // Connect to the renderer, pass it a WindowTreeClient interface request + // and embed that client inside our mus window. + std::string url = GetMojoApplicationInstanceURL(host_->GetProcess()); + mojom::RenderWidgetWindowTreeClientFactoryPtr factory; + MojoShellConnection::Get()->GetApplication()->ConnectToService(url, &factory); + + mus::mojom::WindowTreeClientPtr window_tree_client; + factory->CreateWindowTreeClientForRenderWidget( + host_->GetRoutingID(), mojo::GetProxy(&window_tree_client)); + window_->window()->Embed(window_tree_client.Pass()); } RenderWidgetHostViewMus::~RenderWidgetHostViewMus() {} @@ -37,6 +62,7 @@ void RenderWidgetHostViewMus::SetSize(const gfx::Size& size) { size_ = size; + window_->window()->SetBounds(gfx::Rect(size)); host_->WasResized(); }
diff --git a/content/browser/renderer_host/render_widget_host_view_mus.h b/content/browser/renderer_host/render_widget_host_view_mus.h index 9974e41..d3ae71dc 100644 --- a/content/browser/renderer_host/render_widget_host_view_mus.h +++ b/content/browser/renderer_host/render_widget_host_view_mus.h
@@ -6,7 +6,10 @@ #define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MUS_H_ #include "base/macros.h" +#include "components/mus/public/cpp/scoped_window_ptr.h" +#include "components/mus/public/cpp/window.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/public/browser/render_process_host_observer.h" namespace content { @@ -26,6 +29,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMus : public RenderWidgetHostViewBase { public: RenderWidgetHostViewMus( + mus::Window* parent_window, RenderWidgetHostImpl* widget, base::WeakPtr<RenderWidgetHostViewBase> platform_view); ~RenderWidgetHostViewMus() override; @@ -119,6 +123,7 @@ #endif RenderWidgetHostImpl* host_; + scoped_ptr<mus::ScopedWindowPtr> window_; gfx::Size size_; // The platform view for this RenderWidgetHostView. // RenderWidgetHostViewMus mostly only cares about stuff related to
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index c36e3a7..358754a 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -136,6 +136,7 @@ #if defined(MOJO_SHELL_CLIENT) #include "content/browser/web_contents/web_contents_view_mus.h" #include "content/public/common/mojo_shell_connection.h" +#include "ui/aura/mus/mus_util.h" #endif namespace content { @@ -1391,8 +1392,11 @@ if (MojoShellConnection::Get() && base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kUseMusInRenderer)) { - view_.reset(new WebContentsViewMus(this, view_.Pass(), - &render_view_host_delegate_view_)); + mus::Window* window = aura::GetMusWindow(params.context); + if (window) { + view_.reset(new WebContentsViewMus(this, window, view_.Pass(), + &render_view_host_delegate_view_)); + } } #endif
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 8d55780..e78f4363 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -43,13 +43,11 @@ #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h" -struct BrowserPluginHostMsg_ResizeGuest_Params; struct ViewHostMsg_DateTimeDialogValue_Params; namespace content { class BrowserPluginEmbedder; class BrowserPluginGuest; -class BrowserPluginGuestManager; class DateTimeChooserAndroid; class DownloadItem; class GeolocationServiceContext;
diff --git a/content/browser/web_contents/web_contents_view_mus.cc b/content/browser/web_contents/web_contents_view_mus.cc index 97e45f8..86de954 100644 --- a/content/browser/web_contents/web_contents_view_mus.cc +++ b/content/browser/web_contents/web_contents_view_mus.cc
@@ -5,6 +5,8 @@ #include "content/browser/web_contents/web_contents_view_mus.h" #include "build/build_config.h" +#include "components/mus/public/cpp/window.h" +#include "components/mus/public/cpp/window_tree_connection.h" #include "content/browser/renderer_host/render_widget_host_view_mus.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/render_widget_host_view.h" @@ -17,12 +19,19 @@ WebContentsViewMus::WebContentsViewMus( WebContentsImpl* web_contents, + mus::Window* parent_window, scoped_ptr<WebContentsView> platform_view, RenderViewHostDelegateView** delegate_view) : web_contents_(web_contents), platform_view_(platform_view.Pass()), platform_view_delegate_view_(*delegate_view) { + DCHECK(parent_window); *delegate_view = this; + mus::Window* window = parent_window->connection()->NewWindow(); + window->SetVisible(true); + window->SetBounds(gfx::Rect(300, 300)); + parent_window->AddChild(window); + window_.reset(new mus::ScopedWindowPtr(window)); } WebContentsViewMus::~WebContentsViewMus() {} @@ -52,6 +61,7 @@ RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView(); if (rwhv) rwhv->SetSize(size); + window_->window()->SetBounds(gfx::Rect(size)); } void WebContentsViewMus::SetInitialFocus() { @@ -85,7 +95,7 @@ platform_view_->CreateViewForWidget(render_widget_host, true); return new RenderWidgetHostViewMus( - RenderWidgetHostImpl::From(render_widget_host), + window_->window(), RenderWidgetHostImpl::From(render_widget_host), platform_widget->GetWeakPtr()); }
diff --git a/content/browser/web_contents/web_contents_view_mus.h b/content/browser/web_contents/web_contents_view_mus.h index 173e6dd..5e4e4ed 100644 --- a/content/browser/web_contents/web_contents_view_mus.h +++ b/content/browser/web_contents/web_contents_view_mus.h
@@ -9,6 +9,8 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "components/mus/public/cpp/scoped_window_ptr.h" +#include "components/mus/public/cpp/window.h" #include "content/browser/renderer_host/render_view_host_delegate_view.h" #include "content/browser/web_contents/web_contents_view.h" #include "content/common/content_export.h" @@ -28,6 +30,7 @@ // WebContentsViewMus always has a backing platform dependent view, // |platform_view|. WebContentsViewMus(WebContentsImpl* web_contents, + mus::Window* parent_window, scoped_ptr<WebContentsView> platform_view, RenderViewHostDelegateView** platform_view_delegate_view); ~WebContentsViewMus() override; @@ -80,6 +83,8 @@ // The WebContentsImpl whose contents we display. WebContentsImpl* web_contents_; + scoped_ptr<mus::ScopedWindowPtr> window_; + // The platform dependent view backing this WebContentsView. // Calls to this WebContentsViewMus are forwarded to |platform_view_|. scoped_ptr<WebContentsView> platform_view_;
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index cfae659..176a525d 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -728,7 +728,7 @@ mojo::ScopedMessagePipeHandle message_pipe = mojo_shell_channel_init_.Init(handle, GetIOTaskRunner()); DCHECK(message_pipe.is_valid()); - MojoShellConnectionImpl::CreateWithMessagePipe(message_pipe.Pass()); + MojoShellConnectionImpl::Get()->BindToMessagePipe(message_pipe.Pass()); #endif // defined(MOJO_SHELL_CLIENT) }
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 339032d..faf6e0d 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -534,6 +534,7 @@ "permission_service.mojom", "presentation/presentation_service.mojom", "process_control.mojom", + "render_widget_window_tree_client_factory.mojom", "routed_service_provider.mojom", "service_port_service.mojom", "service_worker/embedded_worker_setup.mojom",
diff --git a/content/common/mojo/mojo_shell_connection_impl.cc b/content/common/mojo/mojo_shell_connection_impl.cc index 25c8be1c..3c0714d 100644 --- a/content/common/mojo/mojo_shell_connection_impl.cc +++ b/content/common/mojo/mojo_shell_connection_impl.cc
@@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/lazy_instance.h" +#include "base/stl_util.h" #include "base/threading/thread_local.h" #include "mojo/application/public/cpp/application_delegate.h" #include "mojo/application/public/cpp/application_impl.h" @@ -30,21 +31,34 @@ // static void MojoShellConnectionImpl::Create() { - DCHECK(IsRunningInMojoShell()); - CreateWithMessagePipe(mojo::ScopedMessagePipeHandle()); -} - -// static -void MojoShellConnectionImpl::CreateWithMessagePipe( - mojo::ScopedMessagePipeHandle handle) { DCHECK(!lazy_tls_ptr.Pointer()->Get()); MojoShellConnectionImpl* connection = new MojoShellConnectionImpl; lazy_tls_ptr.Pointer()->Set(connection); - connection->WaitForShell(handle.Pass()); +} + +// static +MojoShellConnectionImpl* MojoShellConnectionImpl::Get() { + return static_cast<MojoShellConnectionImpl*>(MojoShellConnection::Get()); +} + +void MojoShellConnectionImpl::BindToCommandLinePlatformChannel() { + DCHECK(IsRunningInMojoShell()); + if (initialized_) + return; + WaitForShell(mojo::ScopedMessagePipeHandle()); +} + +void MojoShellConnectionImpl::BindToMessagePipe( + mojo::ScopedMessagePipeHandle handle) { + if (initialized_) + return; + WaitForShell(handle.Pass()); } MojoShellConnectionImpl::MojoShellConnectionImpl() : initialized_(false) {} -MojoShellConnectionImpl::~MojoShellConnectionImpl() {} +MojoShellConnectionImpl::~MojoShellConnectionImpl() { + STLDeleteElements(&listeners_); +} void MojoShellConnectionImpl::WaitForShell( mojo::ScopedMessagePipeHandle handle) {
diff --git a/content/common/mojo/mojo_shell_connection_impl.h b/content/common/mojo/mojo_shell_connection_impl.h index 8891acb..872ee2b 100644 --- a/content/common/mojo/mojo_shell_connection_impl.h +++ b/content/common/mojo/mojo_shell_connection_impl.h
@@ -28,13 +28,22 @@ public mojo::ApplicationDelegate { public: // Creates an instance of this class and stuffs it in TLS on the calling - // thread. Retrieve it using MojoShellConnection::Get(). Blocks the calling - // thread until calling GetApplication() will return an Initialized() - // application with a bound ShellPtr. + // thread. Retrieve it using MojoShellConnection::Get(). static void Create(); - // Same as Create(), but receives a handle instead of looking for one on the - // command line. - static void CreateWithMessagePipe(mojo::ScopedMessagePipeHandle handle); + + // Will return null if no connection has been established (either because it + // hasn't happened yet or the application was not spawned from the external + // Mojo shell). + static MojoShellConnectionImpl* Get(); + + // Blocks the calling thread until calling GetApplication() will return an + // Initialized() application with a bound ShellPtr. This call is a no-op + // if the connection has already been initialized. + void BindToCommandLinePlatformChannel(); + + // Same as BindToCommandLinePlatformChannel(), but receives a |handle| instead + // of looking for one on the command line. + void BindToMessagePipe(mojo::ScopedMessagePipeHandle handle); private: MojoShellConnectionImpl();
diff --git a/content/common/render_widget_window_tree_client_factory.mojom b/content/common/render_widget_window_tree_client_factory.mojom new file mode 100644 index 0000000..e6d88d7 --- /dev/null +++ b/content/common/render_widget_window_tree_client_factory.mojom
@@ -0,0 +1,13 @@ +// Copyright 2015 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. + +module content.mojom; + +import "components/mus/public/interfaces/window_tree.mojom"; + +interface RenderWidgetWindowTreeClientFactory { + CreateWindowTreeClientForRenderWidget( + uint32 routing_id, + mus.mojom.WindowTreeClient& window_tree_client); +};
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java index 159aa7b4..15159a26 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
@@ -119,8 +119,8 @@ /** * Default factory for AdapterInputConnection classes. */ - public static class AdapterInputConnectionFactory { - public AdapterInputConnection get(View view, ImeAdapter imeAdapter, int initialSelStart, + static class AdapterInputConnectionFactory { + AdapterInputConnection get(View view, ImeAdapter imeAdapter, int initialSelStart, int initialSelEnd, EditorInfo outAttrs) { return new AdapterInputConnection( view, imeAdapter, initialSelStart, initialSelEnd, outAttrs); @@ -162,15 +162,6 @@ mInputMethodManagerWrapper = immw; } - /** - * Should be only used by AdapterInputConnection. - * @return InputMethodManagerWrapper that should receive all the calls directed to - * InputMethodManager. - */ - InputMethodManagerWrapper getInputMethodManagerWrapper() { - return mInputMethodManagerWrapper; - } - @VisibleForTesting void setInputConnectionFactory(AdapterInputConnectionFactory factory) { mInputConnectionFactory = factory; @@ -370,7 +361,7 @@ } @VisibleForTesting - public void setInputTypeForTest(int textInputType) { + void setInputTypeForTest(int textInputType) { mTextInputType = textInputType; } @@ -469,7 +460,7 @@ } @VisibleForTesting - protected void finishComposingText() { + void finishComposingText() { if (mNativeImeAdapterAndroid == 0) return; nativeFinishComposingText(mNativeImeAdapterAndroid); } @@ -575,7 +566,7 @@ } @CalledByNative - void detach() { + private void detach() { Log.d(TAG, "detach"); mNativeImeAdapterAndroid = 0; }
diff --git a/content/public/common/mojo_shell_connection.h b/content/public/common/mojo_shell_connection.h index af4cce1..e42e3c0 100644 --- a/content/public/common/mojo_shell_connection.h +++ b/content/public/common/mojo_shell_connection.h
@@ -29,7 +29,6 @@ virtual bool ConfigureIncomingConnection( mojo::ApplicationConnection* connection) = 0; - protected: virtual ~Listener() {} }; @@ -47,6 +46,7 @@ // [De]Register an impl of Listener that will be consulted when the wrapped // ApplicationImpl exposes services to inbound connections. + // Registered listeners are owned by this MojoShellConnection. virtual void AddListener(Listener* listener) = 0; virtual void RemoveListener(Listener* listener) = 0;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 28e9fbd8e..7c75a47 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -19,6 +19,7 @@ configs += [ "//content:content_implementation", "//build/config/compiler:no_size_t_to_int_warning", + "//content/public/common:mojo_shell_client", ] deps = [ @@ -74,6 +75,15 @@ "//v8", ] + if (use_aura) { + sources += [ + "render_widget_mus_connection.cc", + "render_widget_mus_connection.h", + "render_widget_window_tree_client_factory.cc", + "render_widget_window_tree_client_factory.h", + ] + } + if (is_mac) { sources -= [ "webscrollbarbehavior_impl_gtkoraura.cc",
diff --git a/content/renderer/DEPS b/content/renderer/DEPS index e5367fc..b070955 100644 --- a/content/renderer/DEPS +++ b/content/renderer/DEPS
@@ -1,6 +1,7 @@ include_rules = [ # Allow inclusion of specific components that we depend on. We may only # depend on components which we share with the mojo html_viewer. + "+components/mus/public", "+components/scheduler", "+components/url_formatter",
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 1a9097e..982aedbe 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -662,12 +662,10 @@ RenderFrameProxy::FromRoutingID(proxy_routing_id); CHECK(proxy); render_frame = RenderFrameImpl::Create(proxy->render_view(), routing_id); - web_frame = - blink::WebLocalFrame::create(replicated_state.scope, render_frame); render_frame->proxy_routing_id_ = proxy_routing_id; - web_frame->initializeToReplaceRemoteFrame( - proxy->web_frame(), WebString::fromUTF8(replicated_state.name), - replicated_state.sandbox_flags, frame_owner_properties); + web_frame = blink::WebLocalFrame::createProvisional( + render_frame, proxy->web_frame(), replicated_state.sandbox_flags, + frame_owner_properties); } render_frame->SetWebFrame(web_frame); CHECK(parent_routing_id != MSG_ROUTING_NONE || !web_frame->parent()); @@ -3223,9 +3221,7 @@ void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame) { DCHECK(!frame_ || frame_ == frame); - // TODO(nasko): Move implementation here. Needed methods: - // * StartNavStateSyncTimerIfNecessary - render_view_->didUpdateCurrentHistoryItem(frame); + render_view_->StartNavStateSyncTimerIfNecessary(this); } void RenderFrameImpl::didChangeThemeColor() { @@ -3700,9 +3696,7 @@ void RenderFrameImpl::didChangeScrollOffset(blink::WebLocalFrame* frame) { DCHECK(!frame_ || frame_ == frame); - // TODO(nasko): Move implementation here. Needed methods: - // * StartNavStateSyncTimerIfNecessary - render_view_->didChangeScrollOffset(frame); + render_view_->StartNavStateSyncTimerIfNecessary(this); FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidChangeScrollOffset()); }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 43f61d7..80cafda 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -617,6 +617,9 @@ scoped_ptr<media::MediaPermission> CreateMediaPermissionProxy( scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner); + // Sends the current frame's navigation state to the browser. + void SendUpdateState(); + protected: explicit RenderFrameImpl(const CreateParams& params); @@ -844,9 +847,6 @@ blink::WebFrame* frame, blink::WebFrameLoadType load_type); - // Sends the current frame's navigation state to the browser. - void SendUpdateState(); - // Sends a proper FrameHostMsg_DidFailProvisionalLoadWithError_Params IPC for // the failed request |request|. void SendFailedProvisionalLoad(const blink::WebURLRequest& request,
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 3b17ea0d..bf5b570 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -199,6 +199,11 @@ #include "v8/src/third_party/vtune/v8-vtune.h" #endif +#if defined(MOJO_SHELL_CLIENT) +#include "content/public/common/mojo_shell_connection.h" +#include "content/renderer/render_widget_window_tree_client_factory.h" +#endif + using base::ThreadRestrictions; using blink::WebDocument; using blink::WebFrame; @@ -768,6 +773,13 @@ service_registry()->AddService<EmbeddedWorkerSetup>( base::Bind(CreateEmbeddedWorkerSetup)); + +#if defined(MOJO_SHELL_CLIENT) + // We may not have a MojoShellConnection object in tests that directly + // instantiate a RenderThreadImpl. + if (MojoShellConnection::Get()) + CreateRenderWidgetWindowTreeClientFactory(); +#endif } RenderThreadImpl::~RenderThreadImpl() {
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 1a9a23d..bcdc6afd 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -453,11 +453,6 @@ // Test that we get form state change notifications when input fields change. TEST_F(RenderViewImplTest, OnNavStateChanged) { - // TODO(creis): Make the UpdateState timer work in OOPIF modes. - // See https://crbug.com/545219. - if (SiteIsolationPolicy::UseSubframeNavigationEntries()) - return; - // Don't want any delay for form state sync changes. This will still post a // message so updates will get coalesced, but as soon as we spin the message // loop, it will generate an update. @@ -467,6 +462,8 @@ // We should NOT have gotten a form state change notification yet. EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( + FrameHostMsg_UpdateState::ID)); + EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching( ViewHostMsg_UpdateState::ID)); render_thread_->sink().ClearMessages(); @@ -475,8 +472,13 @@ ExecuteJavaScriptForTests( "document.getElementById('elt_text').value = 'foo';"); ProcessPendingMessages(); - EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( - ViewHostMsg_UpdateState::ID)); + if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { + EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( + FrameHostMsg_UpdateState::ID)); + } else { + EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching( + ViewHostMsg_UpdateState::ID)); + } } TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 019f894..a92388e 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1484,6 +1484,20 @@ routing_id_, page_id_, HistoryEntryToPageState(entry))); } +void RenderViewImpl::SendFrameStateUpdates() { + // We only use this path in OOPIF-enabled modes. + DCHECK(SiteIsolationPolicy::UseSubframeNavigationEntries()); + + // Tell each frame with pending state to send its UpdateState message. + for (int render_frame_routing_id : frames_with_pending_state_) { + RenderFrameImpl* frame = + RenderFrameImpl::FromRoutingID(render_frame_routing_id); + if (frame) + frame->SendUpdateState(); + } + frames_with_pending_state_.clear(); +} + void RenderViewImpl::ApplyWebPreferencesInternal( const WebPreferences& prefs, blink::WebView* web_view, @@ -1848,11 +1862,10 @@ return window_rect; } -void RenderViewImpl::StartNavStateSyncTimerIfNecessary() { - // TODO(creis): Move this to RenderFrameHost. In the meantime, we'll ignore - // state changes between navigation events in OOPIF-enabled modes. +void RenderViewImpl::StartNavStateSyncTimerIfNecessary(RenderFrameImpl* frame) { + // In OOPIF modes, keep track of which frames have pending updates. if (SiteIsolationPolicy::UseSubframeNavigationEntries()) - return; + frames_with_pending_state_.insert(frame->GetRoutingID()); int delay; if (send_content_state_immediately_) @@ -1871,8 +1884,15 @@ nav_state_sync_timer_.Stop(); } - nav_state_sync_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(delay), this, - &RenderViewImpl::SendUpdateState); + if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { + // In OOPIF modes, tell each frame with pending state to inform the browser. + nav_state_sync_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(delay), this, + &RenderViewImpl::SendFrameStateUpdates); + } else { + // By default, send an UpdateState for the current history item. + nav_state_sync_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(delay), this, + &RenderViewImpl::SendUpdateState); + } } void RenderViewImpl::setMouseOverURL(const WebURL& url) { @@ -2133,10 +2153,6 @@ SendUpdateFaviconURL(urls); } -void RenderViewImpl::didUpdateCurrentHistoryItem(WebLocalFrame* frame) { - StartNavStateSyncTimerIfNecessary(); -} - void RenderViewImpl::CheckPreferredSize() { // We don't always want to send the change messages over IPC, only if we've // been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode| @@ -2153,10 +2169,6 @@ preferred_size_)); } -void RenderViewImpl::didChangeScrollOffset(WebLocalFrame* frame) { - StartNavStateSyncTimerIfNecessary(); -} - void RenderViewImpl::SendFindReply(int request_id, int match_count, int ordinal,
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 4739a1e..78923fd 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -291,6 +291,11 @@ void TransferActiveWheelFlingAnimation( const blink::WebActiveWheelFlingParameters& params); + // Starts a timer to send an UpdateState message on behalf of |frame|, if the + // timer isn't already running. This allows multiple state changing events to + // be coalesced into one update. + void StartNavStateSyncTimerIfNecessary(RenderFrameImpl* frame); + // Synchronously sends the current navigation state to the browser. void SendUpdateState(); @@ -574,8 +579,6 @@ // are to be moved to RenderFrameImpl <http://crbug.com/361761>. void didChangeIcon(blink::WebLocalFrame*, blink::WebIconURL::Type); - void didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame); - void didChangeScrollOffset(blink::WebLocalFrame* frame); static Referrer GetReferrerFromRequest( blink::WebFrame* frame, @@ -714,15 +717,16 @@ const blink::WebRect& selection_rect, bool final_status_update); - // Starts nav_state_sync_timer_ if it isn't already running. - void StartNavStateSyncTimerIfNecessary(); - #if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX)) void UpdateFontRenderingFromRendererPrefs(); #else void UpdateFontRenderingFromRendererPrefs() {} #endif + // In OOPIF-enabled modes, this tells each RenderFrame with a pending state + // update to inform the browser process. + void SendFrameStateUpdates(); + // Update the target url and tell the browser that the target URL has changed. // If |url| is empty, show |fallback_url|. void UpdateTargetURL(const GURL& url, const GURL& fallback_url); @@ -825,6 +829,10 @@ // StartNavStateSyncTimerIfNecessary). base::OneShotTimer nav_state_sync_timer_; + // Set of RenderFrame routing IDs for frames that having pending UpdateState + // messages to send when the next |nav_state_sync_timer_| fires. + std::set<int> frames_with_pending_state_; + // Page IDs ------------------------------------------------------------------ // See documentation in RenderView. int32 page_id_;
diff --git a/content/renderer/render_widget_mus_connection.cc b/content/renderer/render_widget_mus_connection.cc new file mode 100644 index 0000000..297e0f22 --- /dev/null +++ b/content/renderer/render_widget_mus_connection.cc
@@ -0,0 +1,88 @@ +// Copyright 2015 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 "content/renderer/render_widget_mus_connection.h" + +#include "components/mus/public/interfaces/compositor_frame.mojom.h" +#include "components/mus/public/interfaces/window_tree.mojom.h" +#include "content/public/common/mojo_shell_connection.h" +#include "mojo/application/public/cpp/application_impl.h" +#include "mojo/converters/geometry/geometry_type_converters.h" +#include "mojo/converters/surfaces/surfaces_utils.h" + +namespace content { + +RenderWidgetMusConnection::RenderWidgetMusConnection( + int routing_id, + mojo::InterfaceRequest<mus::mojom::WindowTreeClient> request) + : routing_id_(routing_id), root_(nullptr) { + // TODO(fsamuel): We should probably introduce a + // RenderWidgetMusConnection::FromRoutingID that's usable from RenderWidget. + // TODO(fsamuel): We probably want to pause processing of incoming + // messages until we have an associated RenderWidget. + mus::WindowTreeConnection::Create( + this, request.Pass(), + mus::WindowTreeConnection::CreateType::DONT_WAIT_FOR_EMBED); +} + +RenderWidgetMusConnection::~RenderWidgetMusConnection() {} + +void RenderWidgetMusConnection::SubmitCompositorFrame() { + const gfx::Rect bounds(root_->bounds()); + mus::mojom::PassPtr pass = mojo::CreateDefaultPass(1, bounds); + mus::mojom::CompositorFramePtr frame = mus::mojom::CompositorFrame::New(); + + mus::mojom::CompositorFrameMetadataPtr meta = + mus::mojom::CompositorFrameMetadata::New(); + meta->device_scale_factor = 1.0f; + frame->metadata = meta.Pass(); + + frame->resources.resize(0u); + + pass->quads.resize(0u); + pass->shared_quad_states.push_back(mojo::CreateDefaultSQS(bounds.size())); + + mus::mojom::QuadPtr quad = mus::mojom::Quad::New(); + quad->material = mus::mojom::MATERIAL_SOLID_COLOR; + quad->rect = mojo::Rect::From(bounds); + quad->opaque_rect = mojo::Rect::New(); + quad->visible_rect = mojo::Rect::From(bounds); + quad->needs_blending = false; + quad->shared_quad_state_index = 0u; + + mus::mojom::SolidColorQuadStatePtr color_state = + mus::mojom::SolidColorQuadState::New(); + color_state->color = mus::mojom::Color::New(); + color_state->color->rgba = 0xff00ff00; + color_state->force_anti_aliasing_off = false; + + quad->solid_color_quad_state = color_state.Pass(); + pass->quads.push_back(quad.Pass()); + frame->passes.push_back(pass.Pass()); + surface_->SubmitCompositorFrame(frame.Pass(), mojo::Closure()); +} + +void RenderWidgetMusConnection::OnConnectionLost( + mus::WindowTreeConnection* connection) { + delete this; +} + +void RenderWidgetMusConnection::OnEmbed(mus::Window* root) { + root_ = root; + root_->AddObserver(this); + surface_ = root_->RequestSurface(mus::mojom::SURFACE_TYPE_DEFAULT); + surface_->BindToThread(); + SubmitCompositorFrame(); +} + +void RenderWidgetMusConnection::OnUnembed() {} + +void RenderWidgetMusConnection::OnWindowBoundsChanged( + mus::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + SubmitCompositorFrame(); +} + +} // namespace content
diff --git a/content/renderer/render_widget_mus_connection.h b/content/renderer/render_widget_mus_connection.h new file mode 100644 index 0000000..d82d67e --- /dev/null +++ b/content/renderer/render_widget_mus_connection.h
@@ -0,0 +1,46 @@ +// Copyright 2015 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 CONTENT_RENDERER_RENDER_WIDGET_MUS_CONNECTION_H_ +#define CONTENT_RENDERER_RENDER_WIDGET_MUS_CONNECTION_H_ + +#include "base/macros.h" +#include "components/mus/public/cpp/window.h" +#include "components/mus/public/cpp/window_observer.h" +#include "components/mus/public/cpp/window_surface.h" +#include "components/mus/public/cpp/window_tree_connection.h" +#include "components/mus/public/cpp/window_tree_delegate.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace content { + +class RenderWidgetMusConnection : public mus::WindowTreeDelegate, + public mus::WindowObserver { + public: + RenderWidgetMusConnection( + int routing_id, + mojo::InterfaceRequest<mus::mojom::WindowTreeClient> request); + ~RenderWidgetMusConnection() override; + + private: + void SubmitCompositorFrame(); + + // WindowTreeDelegate implementation: + void OnConnectionLost(mus::WindowTreeConnection* connection) override; + void OnEmbed(mus::Window* root) override; + void OnUnembed() override; + void OnWindowBoundsChanged(mus::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) override; + + const int routing_id_; + mus::Window* root_; + scoped_ptr<mus::WindowSurface> surface_; + + DISALLOW_COPY_AND_ASSIGN(RenderWidgetMusConnection); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_RENDER_WIDGET_MUS_CONNECTION_H_
diff --git a/content/renderer/render_widget_window_tree_client_factory.cc b/content/renderer/render_widget_window_tree_client_factory.cc new file mode 100644 index 0000000..fefec083 --- /dev/null +++ b/content/renderer/render_widget_window_tree_client_factory.cc
@@ -0,0 +1,69 @@ +// Copyright 2015 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 "content/renderer/render_widget_window_tree_client_factory.h" + +#include "base/logging.h" +#include "base/macros.h" +#include "components/mus/public/interfaces/window_tree.mojom.h" +#include "content/common/render_widget_window_tree_client_factory.mojom.h" +#include "content/public/common/mojo_shell_connection.h" +#include "content/renderer/render_widget_mus_connection.h" +#include "mojo/application/public/cpp/application_connection.h" +#include "mojo/application/public/cpp/interface_factory.h" +#include "mojo/common/weak_binding_set.h" +#include "url/gurl.h" + +namespace content { + +namespace { + +// This object's lifetime is managed by MojoShellConnection because it's a +// MojoShellConnection::Listener. +class RenderWidgetWindowTreeClientFactoryImpl + : public MojoShellConnection::Listener, + public mojo::InterfaceFactory<mojom::RenderWidgetWindowTreeClientFactory>, + public mojom::RenderWidgetWindowTreeClientFactory { + public: + RenderWidgetWindowTreeClientFactoryImpl() { + DCHECK(MojoShellConnection::Get()); + MojoShellConnection::Get()->AddListener(this); + } + + ~RenderWidgetWindowTreeClientFactoryImpl() override {} + + private: + // MojoShellConnection::Listener implementation: + bool ConfigureIncomingConnection( + mojo::ApplicationConnection* connection) override { + connection->AddService<mojom::RenderWidgetWindowTreeClientFactory>(this); + return true; + } + + // mojo::InterfaceFactory<mojom::RenderWidgetWindowTreeClientFactory>: + void Create(mojo::ApplicationConnection* connection, + mojo::InterfaceRequest<mojom::RenderWidgetWindowTreeClientFactory> + request) override { + bindings_.AddBinding(this, request.Pass()); + } + + // mojom::RenderWidgetWindowTreeClientFactory implementation. + void CreateWindowTreeClientForRenderWidget( + uint32_t routing_id, + mojo::InterfaceRequest<mus::mojom::WindowTreeClient> request) override { + new RenderWidgetMusConnection(routing_id, request.Pass()); + } + + mojo::WeakBindingSet<mojom::RenderWidgetWindowTreeClientFactory> bindings_; + + DISALLOW_COPY_AND_ASSIGN(RenderWidgetWindowTreeClientFactoryImpl); +}; + +} // namespace + +void CreateRenderWidgetWindowTreeClientFactory() { + new RenderWidgetWindowTreeClientFactoryImpl; +} + +} // namespace content
diff --git a/content/renderer/render_widget_window_tree_client_factory.h b/content/renderer/render_widget_window_tree_client_factory.h new file mode 100644 index 0000000..09eb36b98 --- /dev/null +++ b/content/renderer/render_widget_window_tree_client_factory.h
@@ -0,0 +1,14 @@ +// Copyright 2015 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 CONTENT_RENDERER_RENDER_WIDGET_WINDOW_TREE_CLIENT_FACTORY_H_ +#define CONTENT_RENDERER_RENDER_WIDGET_WINDOW_TREE_CLIENT_FACTORY_H_ + +namespace content { + +void CreateRenderWidgetWindowTreeClientFactory(); + +} // namespace content + +#endif // CONTENT_RENDERER_RENDER_WIDGET_WINDOW_TREE_CLIENT_FACTORY_H_
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc index ea7c913..8fb158d 100644 --- a/content/renderer/renderer_main.cc +++ b/content/renderer/renderer_main.cc
@@ -58,6 +58,10 @@ #include "ui/ozone/public/client_native_pixmap_factory.h" #endif +#if defined(MOJO_SHELL_CLIENT) +#include "content/common/mojo/mojo_shell_connection_impl.h" +#endif + namespace content { namespace { // This function provides some ways to test crash and assertion handling @@ -90,6 +94,10 @@ base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( kTraceEventRendererProcessSortIndex); +#if defined(MOJO_SHELL_CLIENT) + MojoShellConnectionImpl::Create(); +#endif + const base::CommandLine& parsed_command_line = parameters.command_line; #if defined(OS_MACOSX)
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index 793a68a0..e6c175c 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -5,12 +5,14 @@ #include "extensions/browser/api/web_request/web_request_api.h" #include <algorithm> +#include <vector> #include "base/bind.h" #include "base/bind_helpers.h" #include "base/json/json_writer.h" #include "base/lazy_instance.h" #include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -249,7 +251,7 @@ keys::kRequestBodyRawKey }; - const ScopedVector<net::UploadElementReader>* readers = + const std::vector<scoped_ptr<net::UploadElementReader>>* readers = upload_data->GetElementReaders(); bool some_succeeded = false; if (readers) {
diff --git a/google_apis/drive/drive_api_requests_unittest.cc b/google_apis/drive/drive_api_requests_unittest.cc index 817fffa..1df9680 100644 --- a/google_apis/drive/drive_api_requests_unittest.cc +++ b/google_apis/drive/drive_api_requests_unittest.cc
@@ -160,7 +160,7 @@ GURL test_base_url = test_util::GetBaseUrlForTesting(test_server_.port()); url_generator_.reset( - new DriveApiUrlGenerator(test_base_url, test_base_url)); + new DriveApiUrlGenerator(test_base_url, test_base_url, test_base_url)); // Reset the server's expected behavior just in case. ResetExpectedResponse();
diff --git a/google_apis/drive/drive_api_url_generator.cc b/google_apis/drive/drive_api_url_generator.cc index 14da8a3a..a097527b 100644 --- a/google_apis/drive/drive_api_url_generator.cc +++ b/google_apis/drive/drive_api_url_generator.cc
@@ -32,7 +32,8 @@ const char kDriveV2BatchUploadUrl[] = "upload/drive"; const char kDriveV2PermissionsUrlFormat[] = "drive/v2/files/%s/permissions"; const char kDriveV2DownloadUrlFormat[] = "host/%s"; -const char kDriveV2ThumbnailUrlFormat[] = "thumb/%s?width=%d&height=%d"; +const char kDriveV2ThumbnailUrlFormat[] = "d/%s=w%d-h%d"; +const char kDriveV2ThumbnailUrlWithCropFormat[] = "d/%s=w%d-h%d-c"; // apps.delete and file.authorize API is exposed through a special endpoint // v2internal that is accessible only by the official API key for Chrome. @@ -53,9 +54,11 @@ } // namespace DriveApiUrlGenerator::DriveApiUrlGenerator(const GURL& base_url, - const GURL& base_download_url) + const GURL& base_download_url, + const GURL& base_thumbnail_url) : base_url_(base_url), - base_download_url_(base_download_url) { + base_download_url_(base_download_url), + base_thumbnail_url_(base_thumbnail_url) { // Do nothing. } @@ -73,6 +76,9 @@ "https://www.googledrive.com"; #endif +const char DriveApiUrlGenerator::kBaseThumbnailUrlForProduction[] = + "https://lh3.googleusercontent.com"; + GURL DriveApiUrlGenerator::GetAboutGetUrl() const { return base_url_.Resolve(kDriveV2AboutUrl); } @@ -298,15 +304,10 @@ int width, int height, bool crop) const { - GURL url = base_download_url_.Resolve( - base::StringPrintf(kDriveV2ThumbnailUrlFormat, - net::EscapePath(resource_id).c_str(), width, height)); - - // crop is "false" by default. - if (crop) - url = net::AppendOrReplaceQueryParameter(url, "crop", "true"); - - return url; + return base_thumbnail_url_.Resolve( + base::StringPrintf( + crop ? kDriveV2ThumbnailUrlWithCropFormat : kDriveV2ThumbnailUrlFormat, + net::EscapePath(resource_id).c_str(), width, height)); } GURL DriveApiUrlGenerator::GetBatchUploadUrl() const {
diff --git a/google_apis/drive/drive_api_url_generator.h b/google_apis/drive/drive_api_url_generator.h index 7e498fb..67f402f6 100644 --- a/google_apis/drive/drive_api_url_generator.h +++ b/google_apis/drive/drive_api_url_generator.h
@@ -17,7 +17,9 @@ public: // |base_url| is the path to the target drive api server. // Note that this is an injecting point for a testing server. - DriveApiUrlGenerator(const GURL& base_url, const GURL& base_download_url); + DriveApiUrlGenerator(const GURL& base_url, + const GURL& base_download_url, + const GURL& base_thumbnail_url); ~DriveApiUrlGenerator(); // The base URL for communicating with the production drive api server. @@ -26,6 +28,9 @@ // The base URL for the file download server for production. static const char kBaseDownloadUrlForProduction[]; + // The base URL for the thumbnail download server for production. + static const char kBaseThumbnailUrlForProduction[]; + // Returns a URL to invoke "About: get" method. GURL GetAboutGetUrl() const; @@ -121,6 +126,7 @@ private: const GURL base_url_; const GURL base_download_url_; + const GURL base_thumbnail_url_; // This class is copyable hence no DISALLOW_COPY_AND_ASSIGN here. };
diff --git a/google_apis/drive/drive_api_url_generator_unittest.cc b/google_apis/drive/drive_api_url_generator_unittest.cc index 28e79c45..1240b24 100644 --- a/google_apis/drive/drive_api_url_generator_unittest.cc +++ b/google_apis/drive/drive_api_url_generator_unittest.cc
@@ -15,13 +15,15 @@ // OS, so use testing base urls. const char kBaseUrlForTesting[] = "https://www.example.com"; const char kBaseDownloadUrlForTesting[] = "https://download.example.com/p/"; +const char kBaseThumbnailUrlForTesting[] = "https://thumbnail.example.com"; } // namespace class DriveApiUrlGeneratorTest : public testing::Test { public: DriveApiUrlGeneratorTest() : url_generator_(GURL(kBaseUrlForTesting), - GURL(kBaseDownloadUrlForTesting)) {} + GURL(kBaseDownloadUrlForTesting), + GURL(kBaseThumbnailUrlForTesting)) {} protected: DriveApiUrlGenerator url_generator_; @@ -369,13 +371,12 @@ TEST_F(DriveApiUrlGeneratorTest, GenerateThumbnailUrl) { EXPECT_EQ( - "https://download.example.com/p/thumb/0ADK06pfg?width=500&height=500", - url_generator_.GetThumbnailUrl("0ADK06pfg", 500, 500, false).spec()); + "https://thumbnail.example.com/d/0ADK06pfg=w500-h480", + url_generator_.GetThumbnailUrl("0ADK06pfg", 500, 480, false).spec()); EXPECT_EQ( - "https://download.example.com/p/thumb/" - "0ADK06pfg?width=360&height=360&crop=true", - url_generator_.GetThumbnailUrl("0ADK06pfg", 360, 360, true).spec()); + "https://thumbnail.example.com/d/0ADK06pfg=w360-h380-c", + url_generator_.GetThumbnailUrl("0ADK06pfg", 360, 380, true).spec()); } TEST_F(DriveApiUrlGeneratorTest, BatchUploadUrl) {
diff --git a/google_apis/drive/files_list_request_runner_unittest.cc b/google_apis/drive/files_list_request_runner_unittest.cc index d8d8e78..51b72c6 100644 --- a/google_apis/drive/files_list_request_runner_unittest.cc +++ b/google_apis/drive/files_list_request_runner_unittest.cc
@@ -78,7 +78,8 @@ runner_.reset(new FilesListRequestRunner( request_sender_.get(), google_apis::DriveApiUrlGenerator(test_server_.base_url(), - test_server_.GetURL("/download/")))); + test_server_.GetURL("/download/"), + test_server_.GetURL("/thumbnail/")))); } void TearDown() override {
diff --git a/ios/chrome/browser/application_context.h b/ios/chrome/browser/application_context.h index d34d4afa..2c02c2e 100644 --- a/ios/chrome/browser/application_context.h +++ b/ios/chrome/browser/application_context.h
@@ -9,6 +9,10 @@ #include "base/macros.h" +namespace gcm { +class GCMDriver; +} + namespace ios { class ChromeBrowserStateManager; } @@ -37,6 +41,10 @@ class VariationsService; } +namespace web_resource { +class PromoResourceService; +} + class ApplicationContext; class IOSChromeIOThread; class PrefService; @@ -92,6 +100,12 @@ // Gets the IOSChromeIOThread. virtual IOSChromeIOThread* GetIOSChromeIOThread() = 0; + // Gets the GCMDriver. + virtual gcm::GCMDriver* GetGCMDriver() = 0; + + // Gets the PromoResourceService. + virtual web_resource::PromoResourceService* GetPromoResourceService() = 0; + protected: // Sets the global ApplicationContext instance. static void SetApplicationContext(ApplicationContext* context);
diff --git a/ios/chrome/browser/application_context_impl.cc b/ios/chrome/browser/application_context_impl.cc index f7351837..34833add 100644 --- a/ios/chrome/browser/application_context_impl.cc +++ b/ios/chrome/browser/application_context_impl.cc
@@ -15,6 +15,9 @@ #include "base/prefs/pref_registry_simple.h" #include "base/prefs/pref_service.h" #include "base/time/default_tick_clock.h" +#include "components/gcm_driver/gcm_client_factory.h" +#include "components/gcm_driver/gcm_desktop_utils.h" +#include "components/gcm_driver/gcm_driver.h" #include "components/history/core/browser/history_service.h" #include "components/keyed_service/core/service_access_type.h" #include "components/metrics/metrics_pref_names.h" @@ -23,20 +26,32 @@ #include "components/network_time/network_time_tracker.h" #include "components/translate/core/browser/translate_download_manager.h" #include "components/variations/service/variations_service.h" +#include "components/web_resource/promo_resource_service.h" #include "components/web_resource/web_resource_pref_names.h" #include "ios/chrome/browser/chrome_paths.h" +#include "ios/chrome/browser/chrome_switches.h" #include "ios/chrome/browser/history/history_service_factory.h" #include "ios/chrome/browser/ios_chrome_io_thread.h" #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/prefs/browser_prefs.h" #include "ios/chrome/browser/prefs/ios_chrome_pref_service_factory.h" +#include "ios/chrome/browser/web_resource/web_resource_util.h" #include "ios/chrome/common/channel_info.h" #include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state_manager.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#include "ios/web/public/web_thread.h" #include "net/log/net_log_capture_mode.h" #include "net/socket/client_socket_pool_manager.h" +namespace { + +// Dummy flag because iOS does not support disabling background networking. +extern const char kDummyDisableBackgroundNetworking[] = + "dummy-disable-background-networking"; + +} + ApplicationContextImpl::ApplicationContextImpl( base::SequencedTaskRunner* local_state_task_runner, const base::CommandLine& command_line, @@ -77,10 +92,28 @@ void ApplicationContextImpl::PreMainMessageLoopRun() { DCHECK(thread_checker_.CalledOnValidThread()); + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (!command_line.HasSwitch(switches::kDisableIOSWebResources)) { + DCHECK(!promo_resource_service_.get()); + promo_resource_service_.reset(new web_resource::PromoResourceService( + GetLocalState(), ::GetChannel(), GetApplicationLocale(), + GetSystemURLRequestContext(), kDummyDisableBackgroundNetworking, + web_resource::GetIOSChromeParseJSONCallback())); + promo_resource_service_->StartAfterDelay(); + } } void ApplicationContextImpl::StartTearDown() { DCHECK(thread_checker_.CalledOnValidThread()); + // PromoResourceService must be destroyed after the keyed services and before + // the IO thread. + promo_resource_service_.reset(); + + // The |gcm_driver_| must shut down while the IO thread is still alive. + if (gcm_driver_) + gcm_driver_->Shutdown(); + if (local_state_) { local_state_->CommitPendingWrite(); } @@ -213,6 +246,20 @@ return ios_chrome_io_thread_.get(); } +gcm::GCMDriver* ApplicationContextImpl::GetGCMDriver() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!gcm_driver_) + CreateGCMDriver(); + DCHECK(gcm_driver_); + return gcm_driver_.get(); +} + +web_resource::PromoResourceService* +ApplicationContextImpl::GetPromoResourceService() { + DCHECK(thread_checker_.CalledOnValidThread()); + return promo_resource_service_.get(); +} + void ApplicationContextImpl::SetApplicationLocale(const std::string& locale) { DCHECK(thread_checker_.CalledOnValidThread()); application_locale_ = locale; @@ -247,3 +294,23 @@ local_state_->GetBoolean(prefs::kLastSessionExitedCleanly); } } + +void ApplicationContextImpl::CreateGCMDriver() { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!gcm_driver_); + + base::FilePath store_path; + CHECK(PathService::Get(ios::DIR_GLOBAL_GCM_STORE, &store_path)); + base::SequencedWorkerPool* worker_pool = web::WebThread::GetBlockingPool(); + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( + worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( + worker_pool->GetSequenceToken(), + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); + + gcm_driver_ = gcm::CreateGCMDriverDesktop( + make_scoped_ptr(new gcm::GCMClientFactory), GetLocalState(), store_path, + GetSystemURLRequestContext(), ::GetChannel(), + web::WebThread::GetTaskRunnerForThread(web::WebThread::UI), + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO), + blocking_task_runner); +}
diff --git a/ios/chrome/browser/application_context_impl.h b/ios/chrome/browser/application_context_impl.h index e3da75d..39d1de5 100644 --- a/ios/chrome/browser/application_context_impl.h +++ b/ios/chrome/browser/application_context_impl.h
@@ -58,6 +58,8 @@ net_log::ChromeNetLog* GetNetLog() override; network_time::NetworkTimeTracker* GetNetworkTimeTracker() override; IOSChromeIOThread* GetIOSChromeIOThread() override; + gcm::GCMDriver* GetGCMDriver() override; + web_resource::PromoResourceService* GetPromoResourceService() override; private: // Sets the locale used by the application. @@ -66,11 +68,16 @@ // Create the local state. void CreateLocalState(); + // Create the gcm driver. + void CreateGCMDriver(); + base::ThreadChecker thread_checker_; scoped_ptr<PrefService> local_state_; scoped_ptr<net_log::ChromeNetLog> net_log_; scoped_ptr<network_time::NetworkTimeTracker> network_time_tracker_; scoped_ptr<IOSChromeIOThread> ios_chrome_io_thread_; + scoped_ptr<gcm::GCMDriver> gcm_driver_; + scoped_ptr<web_resource::PromoResourceService> promo_resource_service_; std::string application_locale_; // Sequenced task runner for local state related I/O tasks.
diff --git a/ios/chrome/browser/chrome_switches.cc b/ios/chrome/browser/chrome_switches.cc index c069fd53..47711ff 100644 --- a/ios/chrome/browser/chrome_switches.cc +++ b/ios/chrome/browser/chrome_switches.cc
@@ -27,6 +27,9 @@ const char kDisableIOSPasswordSuggestions[] = "disable-ios-password-suggestions"; +// Disables the backend service for web resources. +const char kDisableIOSWebResources[] = "disable-web-resources"; + // Disables the use of WKWebView instead of UIWebView. const char kDisableIOSWKWebView[] = "disable-wkwebview";
diff --git a/ios/chrome/browser/chrome_switches.h b/ios/chrome/browser/chrome_switches.h index f7eea29..9436fb05 100644 --- a/ios/chrome/browser/chrome_switches.h +++ b/ios/chrome/browser/chrome_switches.h
@@ -13,6 +13,7 @@ extern const char kDisableIOSFastWebScrollViewInsets[]; extern const char kDisableIOSPasswordGeneration[]; extern const char kDisableIOSPasswordSuggestions[]; +extern const char kDisableIOSWebResources[]; extern const char kDisableIOSWKWebView[]; extern const char kDisableKeyboardCommands[]; extern const char kDisableNTPFavicons[];
diff --git a/ios/chrome/test/testing_application_context.cc b/ios/chrome/test/testing_application_context.cc index 2623244..3861344 100644 --- a/ios/chrome/test/testing_application_context.cc +++ b/ios/chrome/test/testing_application_context.cc
@@ -115,3 +115,14 @@ DCHECK(thread_checker_.CalledOnValidThread()); return nullptr; } + +gcm::GCMDriver* TestingApplicationContext::GetGCMDriver() { + DCHECK(thread_checker_.CalledOnValidThread()); + return nullptr; +} + +web_resource::PromoResourceService* +TestingApplicationContext::GetPromoResourceService() { + DCHECK(thread_checker_.CalledOnValidThread()); + return nullptr; +}
diff --git a/ios/chrome/test/testing_application_context.h b/ios/chrome/test/testing_application_context.h index 949c60c9..beda41a9 100644 --- a/ios/chrome/test/testing_application_context.h +++ b/ios/chrome/test/testing_application_context.h
@@ -42,6 +42,8 @@ net_log::ChromeNetLog* GetNetLog() override; network_time::NetworkTimeTracker* GetNetworkTimeTracker() override; IOSChromeIOThread* GetIOSChromeIOThread() override; + gcm::GCMDriver* GetGCMDriver() override; + web_resource::PromoResourceService* GetPromoResourceService() override; private: base::ThreadChecker thread_checker_;
diff --git a/ios/net/crn_http_protocol_handler.mm b/ios/net/crn_http_protocol_handler.mm index ba7ca57d..05609b0 100644 --- a/ios/net/crn_http_protocol_handler.mm +++ b/ios/net/crn_http_protocol_handler.mm
@@ -4,11 +4,14 @@ #import "ios/net/crn_http_protocol_handler.h" +#include <vector> + #include "base/command_line.h" #include "base/logging.h" #include "base/mac/bind_objc_block.h" #include "base/mac/scoped_nsobject.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" @@ -193,7 +196,7 @@ // Stream delegate to read the HTTPBodyStream. base::scoped_nsobject<CRWHTTPStreamDelegate> stream_delegate_; // Vector of readers used to accumulate a POST data stream. - ScopedVector<UploadElementReader> post_data_readers_; + std::vector<scoped_ptr<UploadElementReader>> post_data_readers_; // This cannot be a scoped pointer because it must be deleted on the IO // thread. @@ -238,7 +241,7 @@ // NOTE: This call will result in |post_data_readers_| being cleared, // which is the desired behavior. net_request_->set_upload(make_scoped_ptr( - new ElementsUploadDataStream(post_data_readers_.Pass(), 0))); + new ElementsUploadDataStream(std::move(post_data_readers_), 0))); DCHECK(post_data_readers_.empty()); } net_request_->Start(); @@ -253,7 +256,7 @@ if (length) { std::vector<char> owned_data(buffer_->data(), buffer_->data() + length); post_data_readers_.push_back( - new UploadOwnedBytesElementReader(&owned_data)); + make_scoped_ptr(new UploadOwnedBytesElementReader(&owned_data))); } break; }
diff --git a/mash/wm/BUILD.gn b/mash/wm/BUILD.gn index 3cad781..30f27cc7 100644 --- a/mash/wm/BUILD.gn +++ b/mash/wm/BUILD.gn
@@ -40,6 +40,8 @@ "non_client_frame_controller.h", "property_util.cc", "property_util.h", + "shadow.cc", + "shadow.h", "shelf_layout.cc", "shelf_layout.h", "window_layout.cc", @@ -68,6 +70,7 @@ "//ui/gfx", "//ui/gfx/geometry", "//ui/mojo/init", + "//ui/resources", "//ui/strings", "//ui/views", "//ui/views/mus:for_mojo_application",
diff --git a/mash/wm/non_client_frame_controller.cc b/mash/wm/non_client_frame_controller.cc index 3009fc46..54471b68 100644 --- a/mash/wm/non_client_frame_controller.cc +++ b/mash/wm/non_client_frame_controller.cc
@@ -5,16 +5,84 @@ #include "mash/wm/non_client_frame_controller.h" #include "components/mus/public/cpp/window.h" +#include "components/mus/public/interfaces/window_tree_host.mojom.h" #include "mash/wm/frame/non_client_frame_view_mash.h" #include "mash/wm/property_util.h" +#include "mash/wm/shadow.h" +#include "mojo/converters/geometry/geometry_type_converters.h" +#include "ui/aura/layout_manager.h" +#include "ui/aura/window.h" +#include "ui/aura/window_tree_host.h" +#include "ui/compositor/layer.h" #include "ui/views/mus/native_widget_mus.h" #include "ui/views/widget/widget.h" namespace mash { namespace wm { - namespace { +enum class ShadowStyle { + NORMAL, + SMALL, +}; + +// LayoutManager associated with the window created by WindowTreeHost. Resizes +// all children of the parent to match the bounds of the parent. Additionally +// handles sizing of a Shadow. +class ContentWindowLayoutManager : public aura::LayoutManager { + public: + explicit ContentWindowLayoutManager(aura::Window* window, + ShadowStyle style, + Shadow* shadow) + : window_(window), style_(style), shadow_(shadow) { + OnWindowResized(); + } + ~ContentWindowLayoutManager() override {} + + void SetShadow(Shadow* shadow) { + shadow_ = shadow; + if (shadow_) + shadow_->SetContentBounds(child_bounds()); + } + + private: + // Bounds for child windows. + gfx::Rect child_bounds() const { + return gfx::Rect(0, 0, window_->bounds().size().width(), + window_->bounds().size().height()); + } + + void UpdateChildBounds(aura::Window* child) { + child->SetBounds(child_bounds()); + } + + // aura::LayoutManager: + void OnWindowResized() override { + for (aura::Window* child : window_->children()) + UpdateChildBounds(child); + // Shadow takes care of resizing the layer appropriately. + if (shadow_) + shadow_->SetContentBounds(child_bounds()); + } + void OnWindowAddedToLayout(aura::Window* child) override { + UpdateChildBounds(child); + } + void OnWillRemoveWindowFromLayout(aura::Window* child) override {} + void OnWindowRemovedFromLayout(aura::Window* child) override {} + void OnChildWindowVisibilityChanged(aura::Window* child, + bool visible) override {} + void SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) override { + SetChildBoundsDirect(child, requested_bounds); + } + + aura::Window* window_; + const ShadowStyle style_; + Shadow* shadow_; + + DISALLOW_COPY_AND_ASSIGN(ContentWindowLayoutManager); +}; + class WmNativeWidgetMus : public views::NativeWidgetMus { public: WmNativeWidgetMus(views::internal::NativeWidgetDelegate* delegate, @@ -34,6 +102,21 @@ new NonClientFrameViewMash(widget, window()); return frame_view; } + void InitNativeWidget(const views::Widget::InitParams& params) override { + views::NativeWidgetMus::InitNativeWidget(params); + aura::WindowTreeHost* window_tree_host = GetNativeView()->GetHost(); + // TODO(sky): shadow should be determined by window type. + shadow_.reset(new Shadow); + shadow_->Init(Shadow::STYLE_ACTIVE); + ContentWindowLayoutManager* layout_manager = new ContentWindowLayoutManager( + window_tree_host->window(), ShadowStyle::NORMAL, shadow_.get()); + window_tree_host->window()->SetLayoutManager(layout_manager); + const int inset = Shadow::GetInteriorInsetForStyle(Shadow::STYLE_ACTIVE); + window_tree_host->SetOutputSurfacePadding( + gfx::Insets(inset, inset, inset, inset)); + window_tree_host->window()->layer()->Add(shadow_->layer()); + shadow_->layer()->parent()->StackAtBottom(shadow_->layer()); + } void CenterWindow(const gfx::Size& size) override { // Do nothing. The client controls the size, not us. } @@ -43,14 +126,21 @@ } private: + // The shadow, may be null. + scoped_ptr<Shadow> shadow_; + DISALLOW_COPY_AND_ASSIGN(WmNativeWidgetMus); }; } // namespace -NonClientFrameController::NonClientFrameController(mojo::Shell* shell, - mus::Window* window) - : widget_(new views::Widget), window_(window) { +NonClientFrameController::NonClientFrameController( + mojo::Shell* shell, + mus::Window* window, + mus::mojom::WindowTreeHost* window_tree_host) + : widget_(new views::Widget), + window_(window), + mus_window_tree_host_(window_tree_host) { window_->AddObserver(this); views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); @@ -58,6 +148,12 @@ params.native_widget = new WmNativeWidgetMus(widget_, shell, window); widget_->Init(params); widget_->Show(); + + const int shadow_inset = + Shadow::GetInteriorInsetForStyle(Shadow::STYLE_ACTIVE); + mus_window_tree_host_->SetUnderlaySurfaceOffsetAndExtendedHitArea( + window->id(), shadow_inset, shadow_inset, + mojo::Insets::From(gfx::Insets())); } // static
diff --git a/mash/wm/non_client_frame_controller.h b/mash/wm/non_client_frame_controller.h index 9e4d121..492500d 100644 --- a/mash/wm/non_client_frame_controller.h +++ b/mash/wm/non_client_frame_controller.h
@@ -19,6 +19,9 @@ namespace mus { class Window; +namespace mojom { +class WindowTreeHost; +} } namespace mash { @@ -29,7 +32,9 @@ public mus::WindowObserver { public: // NonClientFrameController deletes itself when |window| is destroyed. - NonClientFrameController(mojo::Shell* shell, mus::Window* window); + NonClientFrameController(mojo::Shell* shell, + mus::Window* window, + mus::mojom::WindowTreeHost* window_tree_host); // Returns the preferred client area insets. static gfx::Insets GetPreferredClientAreaInsets(); @@ -57,6 +62,8 @@ // is null. mus::Window* window_; + mus::mojom::WindowTreeHost* mus_window_tree_host_; + DISALLOW_COPY_AND_ASSIGN(NonClientFrameController); };
diff --git a/mash/wm/shadow.cc b/mash/wm/shadow.cc new file mode 100644 index 0000000..07a1809 --- /dev/null +++ b/mash/wm/shadow.cc
@@ -0,0 +1,196 @@ +// Copyright 2015 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 "mash/wm/shadow.h" + +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/resources/grit/ui_resources.h" + +namespace mash { +namespace wm { + +namespace { + +// The opacity used for active shadow when animating between +// inactive/active shadow. +const float kInactiveShadowAnimationOpacity = 0.2f; + +// Shadow aperture for different styles. +// Note that this may be greater than interior inset to allow shadows with +// curved corners that extend inwards beyond a window's borders. +const int kActiveInteriorAperture = 134; +const int kInactiveInteriorAperture = 134; +const int kSmallInteriorAperture = 9; + +// Interior inset for different styles. +const int kActiveInteriorInset = 64; +const int kInactiveInteriorInset = 64; +const int kSmallInteriorInset = 4; + +// Duration for opacity animation in milliseconds. +const int kShadowAnimationDurationMs = 100; + +int GetShadowApertureForStyle(wm::Shadow::Style style) { + switch (style) { + case wm::Shadow::STYLE_ACTIVE: + return kActiveInteriorAperture; + case wm::Shadow::STYLE_INACTIVE: + return kInactiveInteriorAperture; + case wm::Shadow::STYLE_SMALL: + return kSmallInteriorAperture; + } + return 0; +} + +} // namespace + +Shadow::Shadow() : style_(STYLE_ACTIVE), interior_inset_(0) { +} + +Shadow::~Shadow() { +} + +void Shadow::Init(Style style) { + style_ = style; + + layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN)); + shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH)); + layer()->Add(shadow_layer_.get()); + + UpdateImagesForStyle(); + shadow_layer_->set_name("Shadow"); + shadow_layer_->SetVisible(true); + shadow_layer_->SetFillsBoundsOpaquely(false); +} + +// static +int Shadow::GetInteriorInsetForStyle(Shadow::Style style) { + switch (style) { + case Shadow::STYLE_ACTIVE: + return kActiveInteriorInset; + case Shadow::STYLE_INACTIVE: + return kInactiveInteriorInset; + case Shadow::STYLE_SMALL: + return kSmallInteriorInset; + } + return 0; +} + +void Shadow::SetContentBounds(const gfx::Rect& content_bounds) { + content_bounds_ = content_bounds; + UpdateLayerBounds(); +} + +void Shadow::SetStyle(Style style) { + if (style_ == style) + return; + + Style old_style = style_; + style_ = style; + + // Stop waiting for any as yet unfinished implicit animations. + StopObservingImplicitAnimations(); + + // If we're switching to or from the small style, don't bother with + // animations. + if (style == STYLE_SMALL || old_style == STYLE_SMALL) { + UpdateImagesForStyle(); + // Make sure the shadow is fully opaque. + shadow_layer_->SetOpacity(1.0f); + return; + } + + // If we're becoming active, switch images now. Because the inactive image + // has a very low opacity the switch isn't noticeable and this approach + // allows us to use only a single set of shadow images at a time. + if (style == STYLE_ACTIVE) { + UpdateImagesForStyle(); + // Opacity was baked into inactive image, start opacity low to match. + shadow_layer_->SetOpacity(kInactiveShadowAnimationOpacity); + } + + { + // Property sets within this scope will be implicitly animated. + ui::ScopedLayerAnimationSettings settings(shadow_layer_->GetAnimator()); + settings.AddObserver(this); + settings.SetTransitionDuration( + base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); + switch (style_) { + case STYLE_ACTIVE: + // Animate the active shadow from kInactiveShadowAnimationOpacity to + // 1.0f. + shadow_layer_->SetOpacity(1.0f); + break; + case STYLE_INACTIVE: + // The opacity will be reset to 1.0f when animation is completed. + shadow_layer_->SetOpacity(kInactiveShadowAnimationOpacity); + break; + default: + NOTREACHED() << "Unhandled style " << style_; + break; + } + } +} + +void Shadow::OnImplicitAnimationsCompleted() { + // If we just finished going inactive, switch images. This doesn't cause + // a visual pop because the inactive image opacity is so low. + if (style_ == STYLE_INACTIVE) { + UpdateImagesForStyle(); + // Opacity is baked into inactive image, so set fully opaque. + shadow_layer_->SetOpacity(1.0f); + } +} + +void Shadow::UpdateImagesForStyle() { + ResourceBundle& res = ResourceBundle::GetSharedInstance(); + gfx::Image image; + switch (style_) { + case STYLE_ACTIVE: + image = res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE); + break; + case STYLE_INACTIVE: + image = res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE); + break; + case STYLE_SMALL: + image = res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL); + break; + default: + NOTREACHED() << "Unhandled style " << style_; + break; + } + + shadow_layer_->UpdateNinePatchLayerImage(image.AsImageSkia()); + image_size_ = image.Size(); + interior_inset_ = GetInteriorInsetForStyle(style_); + + // Image sizes may have changed. + UpdateLayerBounds(); +} + +void Shadow::UpdateLayerBounds() { + // Update bounds based on content bounds and interior inset. + gfx::Rect layer_bounds = content_bounds_; + layer_bounds.Inset(-interior_inset_, -interior_inset_); + layer()->SetBounds(layer_bounds); + shadow_layer_->SetBounds(gfx::Rect(layer_bounds.size())); + + // Update the shadow aperture and border for style. Note that border is in + // layer space and it cannot exceed the bounds of the layer. + int aperture = GetShadowApertureForStyle(style_); + int aperture_x = std::min(aperture, layer_bounds.width() / 2); + int aperture_y = std::min(aperture, layer_bounds.height() / 2); + shadow_layer_->UpdateNinePatchLayerAperture( + gfx::Rect(aperture_x, aperture_y, + image_size_.width() - aperture_x * 2, + image_size_.height() - aperture_y * 2)); + shadow_layer_->UpdateNinePatchLayerBorder( + gfx::Rect(aperture_x, aperture_y, aperture_x * 2, aperture_y * 2)); +} + +} // namespace wm +} // namespace mash
diff --git a/mash/wm/shadow.h b/mash/wm/shadow.h new file mode 100644 index 0000000..db8aa0c --- /dev/null +++ b/mash/wm/shadow.h
@@ -0,0 +1,100 @@ +// Copyright 2015 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 MASH_WM_SHADOW_H_ +#define MASH_WM_SHADOW_H_ + +#include "base/basictypes.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "ui/compositor/layer_animation_observer.h" +#include "ui/gfx/geometry/rect.h" + +namespace ui { +class Layer; +} // namespace ui + +namespace mash { +namespace wm { + +// Simple class that draws a drop shadow around content at given bounds. +class Shadow : public ui::ImplicitAnimationObserver { + public: + enum Style { + // Active windows have more opaque shadows, shifted down to make the window + // appear "higher". + STYLE_ACTIVE, + + // Inactive windows have less opaque shadows. + STYLE_INACTIVE, + + // Small windows like tooltips and context menus have lighter, smaller + // shadows. + STYLE_SMALL, + }; + + Shadow(); + ~Shadow() override; + + void Init(Style style); + + // Returns the interio inset for the specified style. The interior inset + // is the amount of padding added to each side of the content bounds that the + // shadow renders into. In other words the shadow extends from all sides of + // the layer by this value. + static int GetInteriorInsetForStyle(Style style); + + // Returns |layer_.get()|. This is exposed so it can be added to the same + // layer as the content and stacked below it. SetContentBounds() should be + // used to adjust the shadow's size and position (rather than applying + // transformations to this layer). + ui::Layer* layer() const { return layer_.get(); } + + const gfx::Rect& content_bounds() const { return content_bounds_; } + Style style() const { return style_; } + + // Moves and resizes the shadow layer to frame |content_bounds|. + void SetContentBounds(const gfx::Rect& content_bounds); + + // Sets the shadow's style, animating opacity as necessary. + void SetStyle(Style style); + + // ui::ImplicitAnimationObserver overrides: + void OnImplicitAnimationsCompleted() override; + + private: + // Updates the shadow images to the current |style_|. + void UpdateImagesForStyle(); + + // Updates the shadow layer bounds based on the inteior inset and the current + // |content_bounds_|. + void UpdateLayerBounds(); + + // The current style, set when the transition animation starts. + Style style_; + + // The parent layer of the shadow layer. It serves as a container accessible + // from the outside to control the visibility of the shadow. + scoped_ptr<ui::Layer> layer_; + + // The actual shadow layer corresponding to a cc::NinePatchLayer. + scoped_ptr<ui::Layer> shadow_layer_; + + // Size of the current shadow image. + gfx::Size image_size_; + + // Bounds of the content that the shadow encloses. + gfx::Rect content_bounds_; + + // The interior inset of the shadow images. The content bounds of the image + // grid should be set to |content_bounds_| inset by this amount. + int interior_inset_; + + DISALLOW_COPY_AND_ASSIGN(Shadow); +}; + +} // namespace wm +} // namespace mash + +#endif // MASH_WM_SHADOW_H_
diff --git a/mash/wm/window_manager_application.cc b/mash/wm/window_manager_application.cc index b86bec5..bc85268 100644 --- a/mash/wm/window_manager_application.cc +++ b/mash/wm/window_manager_application.cc
@@ -45,7 +45,7 @@ } void WindowManagerApplication::AddAccelerators() { - host_->AddAccelerator( + window_tree_host_->AddAccelerator( kWindowSwitchCmd, mus::CreateKeyMatcher(mus::mojom::KEYBOARD_CODE_TAB, mus::mojom::EVENT_FLAGS_CONTROL_DOWN)); @@ -61,8 +61,9 @@ mojo::GetProxy(&window_manager))); mus::mojom::WindowTreeHostClientPtr host_client; host_client_binding_.Bind(GetProxy(&host_client)); - mus::CreateSingleWindowTreeHost(app, host_client.Pass(), this, &host_, - window_manager.Pass(), window_manager_.get()); + mus::CreateSingleWindowTreeHost(app, host_client.Pass(), this, + &window_tree_host_, window_manager.Pass(), + window_manager_.get()); } bool WindowManagerApplication::ConfigureIncomingConnection( @@ -75,7 +76,7 @@ mus::mojom::EventPtr event) { switch (id) { case kWindowSwitchCmd: - host_->ActivateNextWindow(); + window_tree_host_->ActivateNextWindow(); break; default: NOTREACHED() << "Unknown accelerator command: " << id; @@ -94,7 +95,7 @@ mus::Window* window = GetWindowForContainer(mojom::CONTAINER_USER_WINDOWS); window_layout_.reset( new WindowLayout(GetWindowForContainer(mojom::CONTAINER_USER_WINDOWS))); - host_->AddActivationParent(window->id()); + window_tree_host_->AddActivationParent(window->id()); AddAccelerators();
diff --git a/mash/wm/window_manager_application.h b/mash/wm/window_manager_application.h index 8cd4a3d..51c1a227 100644 --- a/mash/wm/window_manager_application.h +++ b/mash/wm/window_manager_application.h
@@ -57,6 +57,10 @@ mojo::ApplicationImpl* app() { return app_; } + mus::mojom::WindowTreeHost* window_tree_host() { + return window_tree_host_.get(); + } + private: void AddAccelerators(); @@ -91,7 +95,7 @@ mojo::TracingImpl tracing_; - mus::mojom::WindowTreeHostPtr host_; + mus::mojom::WindowTreeHostPtr window_tree_host_; mojo::Binding<mus::mojom::WindowTreeHostClient> host_client_binding_; scoped_ptr<ui::mojo::UIInit> ui_init_;
diff --git a/mash/wm/window_manager_impl.cc b/mash/wm/window_manager_impl.cc index ca88265..761099f 100644 --- a/mash/wm/window_manager_impl.cc +++ b/mash/wm/window_manager_impl.cc
@@ -79,8 +79,9 @@ GetContainerForChild(child_window)->AddChild(child_window); child_window->Embed(client.Pass()); - // NonClientFrameController deletes itself when the window is destroyed. - new NonClientFrameController(state_->app()->shell(), child_window); + // NonClientFrameController deletes itself when |child_window| is destroyed. + new NonClientFrameController(state_->app()->shell(), child_window, + state_->window_tree_host()); state_->IncrementWindowCount(); }
diff --git a/media/base/audio_buffer.cc b/media/base/audio_buffer.cc index 115efa5..168d371e 100644 --- a/media/base/audio_buffer.cc +++ b/media/base/audio_buffer.cc
@@ -37,7 +37,8 @@ timestamp_(timestamp), duration_(end_of_stream_ ? base::TimeDelta() - : CalculateDuration(adjusted_frame_count_, sample_rate_)) { + : CalculateDuration(adjusted_frame_count_, sample_rate_)), + data_size_(0) { CHECK_GE(channel_count_, 0); CHECK_LE(channel_count_, limits::kMaxChannels); CHECK_GE(frame_count, 0); @@ -46,49 +47,46 @@ int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); DCHECK_LE(bytes_per_channel, kChannelAlignment); - int data_size = frame_count * bytes_per_channel; // Empty buffer? if (!create_buffer) return; - if (sample_format == kSampleFormatPlanarF32 || - sample_format == kSampleFormatPlanarS16 || - sample_format == kSampleFormatPlanarS32) { + int data_size_per_channel = frame_count * bytes_per_channel; + if (IsPlanar(sample_format)) { // Planar data, so need to allocate buffer for each channel. // Determine per channel data size, taking into account alignment. int block_size_per_channel = - (data_size + kChannelAlignment - 1) & ~(kChannelAlignment - 1); - DCHECK_GE(block_size_per_channel, data_size); + (data_size_per_channel + kChannelAlignment - 1) & + ~(kChannelAlignment - 1); + DCHECK_GE(block_size_per_channel, data_size_per_channel); // Allocate a contiguous buffer for all the channel data. - data_.reset(static_cast<uint8*>(base::AlignedAlloc( - channel_count_ * block_size_per_channel, kChannelAlignment))); + data_size_ = channel_count_ * block_size_per_channel; + data_.reset( + static_cast<uint8*>(base::AlignedAlloc(data_size_, kChannelAlignment))); channel_data_.reserve(channel_count_); // Copy each channel's data into the appropriate spot. for (int i = 0; i < channel_count_; ++i) { channel_data_.push_back(data_.get() + i * block_size_per_channel); if (data) - memcpy(channel_data_[i], data[i], data_size); + memcpy(channel_data_[i], data[i], data_size_per_channel); } return; } // Remaining formats are interleaved data. - DCHECK(sample_format_ == kSampleFormatU8 || - sample_format_ == kSampleFormatS16 || - sample_format_ == kSampleFormatS32 || - sample_format_ == kSampleFormatF32) << sample_format_; + DCHECK(IsInterleaved(sample_format)) << sample_format_; // Allocate our own buffer and copy the supplied data into it. Buffer must // contain the data for all channels. - data_size *= channel_count_; + data_size_ = data_size_per_channel * channel_count_; data_.reset( - static_cast<uint8*>(base::AlignedAlloc(data_size, kChannelAlignment))); + static_cast<uint8*>(base::AlignedAlloc(data_size_, kChannelAlignment))); channel_data_.reserve(1); channel_data_.push_back(data_.get()); if (data) - memcpy(data_.get(), data[0], data_size); + memcpy(data_.get(), data[0], data_size_); } AudioBuffer::~AudioBuffer() {}
diff --git a/media/base/audio_buffer.h b/media/base/audio_buffer.h index 63390d47..bf8e433 100644 --- a/media/base/audio_buffer.h +++ b/media/base/audio_buffer.h
@@ -15,9 +15,20 @@ #include "media/base/media_export.h" #include "media/base/sample_format.h" +namespace mojo { +template <typename T, typename U> +struct TypeConverter; +template <typename T> +class StructPtr; +}; + namespace media { class AudioBus; +namespace interfaces { +class AudioBuffer; +} + // An audio buffer that takes a copy of the data passed to it, holds it, and // copies it into an AudioBus when needed. Also supports an end of stream // marker. @@ -123,6 +134,11 @@ private: friend class base::RefCountedThreadSafe<AudioBuffer>; + // mojo::TypeConverter added as a friend so that AudioBuffer can be + // transferred across a mojo connection. + friend struct mojo::TypeConverter<mojo::StructPtr<interfaces::AudioBuffer>, + scoped_refptr<AudioBuffer>>; + // Allocates aligned contiguous buffer to hold all channel data (1 block for // interleaved data, |channel_count| blocks for planar data), copies // [data,data+data_size) to the allocated buffer(s). If |data| is null, no @@ -151,6 +167,7 @@ // Contiguous block of channel data. scoped_ptr<uint8, base::AlignedFreeDeleter> data_; + size_t data_size_; // For planar data, points to each channels data. std::vector<uint8*> channel_data_;
diff --git a/media/base/sample_format.cc b/media/base/sample_format.cc index 0c84f55..0ee7f5e 100644 --- a/media/base/sample_format.cc +++ b/media/base/sample_format.cc
@@ -54,4 +54,42 @@ return ""; } +bool IsPlanar(SampleFormat sample_format) { + switch (sample_format) { + case kSampleFormatPlanarS16: + case kSampleFormatPlanarF32: + case kSampleFormatPlanarS32: + return true; + case kUnknownSampleFormat: + case kSampleFormatU8: + case kSampleFormatS16: + case kSampleFormatS24: + case kSampleFormatS32: + case kSampleFormatF32: + return false; + } + + NOTREACHED() << "Invalid sample format provided: " << sample_format; + return false; +} + +bool IsInterleaved(SampleFormat sample_format) { + switch (sample_format) { + case kSampleFormatU8: + case kSampleFormatS16: + case kSampleFormatS24: + case kSampleFormatS32: + case kSampleFormatF32: + return true; + case kUnknownSampleFormat: + case kSampleFormatPlanarS16: + case kSampleFormatPlanarF32: + case kSampleFormatPlanarS32: + return false; + } + + NOTREACHED() << "Invalid sample format provided: " << sample_format; + return false; +} + } // namespace media
diff --git a/media/base/sample_format.h b/media/base/sample_format.h index 12ebeb8..53d0cb9 100644 --- a/media/base/sample_format.h +++ b/media/base/sample_format.h
@@ -35,6 +35,12 @@ // Returns the name of the sample format as a string MEDIA_EXPORT const char* SampleFormatToString(SampleFormat sample_format); +// Returns true if |sample_format| is planar, false otherwise. +MEDIA_EXPORT bool IsPlanar(SampleFormat sample_format); + +// Returns true if |sample_format| is interleaved, false otherwise. +MEDIA_EXPORT bool IsInterleaved(SampleFormat sample_format); + } // namespace media #endif // MEDIA_BASE_SAMPLE_FORMAT_H
diff --git a/media/mojo/interfaces/decryptor.mojom b/media/mojo/interfaces/decryptor.mojom index 9c5d678..e25df3e 100644 --- a/media/mojo/interfaces/decryptor.mojom +++ b/media/mojo/interfaces/decryptor.mojom
@@ -7,10 +7,6 @@ import "media/mojo/interfaces/demuxer_stream.mojom"; import "media/mojo/interfaces/media_types.mojom"; -// TODO(xhwang): Add mojo types for AudioBuffer and VideoFrame. -struct AudioBuffer {}; -struct VideoFrame {}; - // Interface for decrypting (and decoding) encrypted streams. // See media/base/decryptor.h for details. interface Decryptor {
diff --git a/media/mojo/interfaces/media_types.mojom b/media/mojo/interfaces/media_types.mojom index 74f5383..befd80a 100644 --- a/media/mojo/interfaces/media_types.mojom +++ b/media/mojo/interfaces/media_types.mojom
@@ -232,3 +232,58 @@ // Indicates this buffer is part of a splice around |splice_timestamp_usec|. int64 splice_timestamp_usec; }; + +// This defines a mojo transport format for media::AudioBuffer. +struct AudioBuffer { + // Format of the audio. + SampleFormat sample_format; + + // How the channels are laid out. + ChannelLayout channel_layout; + + // Number of channels. + int32 channel_count; + + // Sample rate of the buffer. + int32 sample_rate; + + // Number of frames in the buffer. + int32 frame_count; + + // True if end of stream. + bool end_of_stream; + + // Timestamp in microseconds of the first frame. + int64 timestamp_usec; + + // Channel data. Will be null for EOS buffers. + array<uint8>? data; +}; + +// This defines a mojo transport format for media::VideoFrame. +// TODO(jrummell): Support shared memory based VideoFrame to avoid copying +// the data multiple times. +struct VideoFrame { + // Format of the frame. + VideoFormat format; + + // Width and height of the video frame, in pixels. + mojo.Size coded_size; + + // Visible size of the frame. + mojo.Rect visible_rect; + + // Natural size of the frame. + mojo.Size natural_size; + + // True if end of stream. + bool end_of_stream; + + // Timestamp in microseconds of the associated frame. + int64 timestamp_usec; + + // Frame data for each plane. Will be null for EOS buffers. + array<uint8>? y_data; + array<uint8>? u_data; + array<uint8>? v_data; +};
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 24fcdfc..23690f80 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -183,8 +183,10 @@ "//base", "//base/test:test_support", "//media", + "//media/base:test_support", "//media/mojo/interfaces", "//mojo/environment:chromium", + "//testing/gmock", "//testing/gtest", "//third_party/mojo/src/mojo/edk/system", "//third_party/mojo/src/mojo/edk/test:run_all_unittests",
diff --git a/media/mojo/services/media_type_converters.cc b/media/mojo/services/media_type_converters.cc index 5f84a49a..fc733aa 100644 --- a/media/mojo/services/media_type_converters.cc +++ b/media/mojo/services/media_type_converters.cc
@@ -4,6 +4,7 @@ #include "media/mojo/services/media_type_converters.h" +#include "media/base/audio_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/buffering_state.h" #include "media/base/cdm_config.h" @@ -13,6 +14,7 @@ #include "media/base/demuxer_stream.h" #include "media/base/media_keys.h" #include "media/base/video_decoder_config.h" +#include "media/base/video_frame.h" #include "media/mojo/interfaces/demuxer_stream.mojom.h" #include "mojo/converters/geometry/geometry_type_converters.h" @@ -529,4 +531,124 @@ return config; } +// static +media::interfaces::AudioBufferPtr +TypeConverter<media::interfaces::AudioBufferPtr, + scoped_refptr<media::AudioBuffer>>:: + Convert(const scoped_refptr<media::AudioBuffer>& input) { + media::interfaces::AudioBufferPtr buffer( + media::interfaces::AudioBuffer::New()); + buffer->sample_format = + static_cast<media::interfaces::SampleFormat>(input->sample_format_); + buffer->channel_layout = + static_cast<media::interfaces::ChannelLayout>(input->channel_layout()); + buffer->channel_count = input->channel_count(); + buffer->sample_rate = input->sample_rate(); + buffer->frame_count = input->frame_count(); + buffer->end_of_stream = input->end_of_stream(); + buffer->timestamp_usec = input->timestamp().InMicroseconds(); + + if (!input->end_of_stream()) { + std::vector<uint8_t> input_data(input->data_.get(), + input->data_.get() + input->data_size_); + buffer->data.Swap(&input_data); + } + + return buffer.Pass(); +} + +// static +scoped_refptr<media::AudioBuffer> +TypeConverter<scoped_refptr<media::AudioBuffer>, + media::interfaces::AudioBufferPtr>:: + Convert(const media::interfaces::AudioBufferPtr& input) { + if (input->end_of_stream) + return media::AudioBuffer::CreateEOSBuffer(); + + // Setup channel pointers. AudioBuffer::CopyFrom() will only use the first + // one in the case of interleaved data. + std::vector<const uint8_t*> channel_ptrs(input->channel_count, nullptr); + std::vector<uint8_t> storage = input->data.storage(); + const size_t size_per_channel = storage.size() / input->channel_count; + DCHECK_EQ(0u, storage.size() % input->channel_count); + for (int i = 0; i < input->channel_count; ++i) + channel_ptrs[i] = storage.data() + i * size_per_channel; + + return media::AudioBuffer::CopyFrom( + static_cast<media::SampleFormat>(input->sample_format), + static_cast<media::ChannelLayout>(input->channel_layout), + input->channel_count, input->sample_rate, input->frame_count, + &channel_ptrs[0], + base::TimeDelta::FromMicroseconds(input->timestamp_usec)); +} + +// static +media::interfaces::VideoFramePtr +TypeConverter<media::interfaces::VideoFramePtr, + scoped_refptr<media::VideoFrame>>:: + Convert(const scoped_refptr<media::VideoFrame>& input) { + media::interfaces::VideoFramePtr buffer(media::interfaces::VideoFrame::New()); + buffer->end_of_stream = + input->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM); + if (buffer->end_of_stream) + return buffer.Pass(); + + // handle non EOS buffer. + buffer->format = static_cast<media::interfaces::VideoFormat>(input->format()); + buffer->coded_size = Size::From(input->coded_size()); + buffer->visible_rect = Rect::From(input->visible_rect()); + buffer->natural_size = Size::From(input->natural_size()); + buffer->timestamp_usec = input->timestamp().InMicroseconds(); + + if (!input->coded_size().IsEmpty()) { + // TODO(jrummell): Use a shared buffer rather than copying the data for + // each plane. + std::vector<uint8_t> y_data( + input->data(media::VideoFrame::kYPlane), + input->data(media::VideoFrame::kYPlane) + + input->rows(media::VideoFrame::kYPlane) * + input->stride(media::VideoFrame::kYPlane)); + buffer->y_data.Swap(&y_data); + + std::vector<uint8_t> u_data( + input->data(media::VideoFrame::kUPlane), + input->data(media::VideoFrame::kUPlane) + + input->rows(media::VideoFrame::kUPlane) * + input->stride(media::VideoFrame::kUPlane)); + buffer->u_data.Swap(&u_data); + + std::vector<uint8_t> v_data( + input->data(media::VideoFrame::kVPlane), + input->data(media::VideoFrame::kVPlane) + + input->rows(media::VideoFrame::kVPlane) * + input->stride(media::VideoFrame::kVPlane)); + buffer->v_data.Swap(&v_data); + } + + return buffer.Pass(); +} + +// static +scoped_refptr<media::VideoFrame> +TypeConverter<scoped_refptr<media::VideoFrame>, + media::interfaces::VideoFramePtr>:: + Convert(const media::interfaces::VideoFramePtr& input) { + if (input->end_of_stream) + return media::VideoFrame::CreateEOSFrame(); + + scoped_refptr<media::VideoFrame> frame = media::VideoFrame::CreateFrame( + static_cast<media::VideoPixelFormat>(input->format), + input->coded_size.To<gfx::Size>(), input->visible_rect.To<gfx::Rect>(), + input->natural_size.To<gfx::Size>(), + base::TimeDelta::FromMicroseconds(input->timestamp_usec)); + memcpy(frame->data(media::VideoFrame::kYPlane), + input->y_data.storage().data(), input->y_data.storage().size()); + memcpy(frame->data(media::VideoFrame::kUPlane), + input->u_data.storage().data(), input->u_data.storage().size()); + memcpy(frame->data(media::VideoFrame::kVPlane), + input->v_data.storage().data(), input->v_data.storage().size()); + + return frame.Pass(); +} + } // namespace mojo
diff --git a/media/mojo/services/media_type_converters.h b/media/mojo/services/media_type_converters.h index 0133a99..92450c8 100644 --- a/media/mojo/services/media_type_converters.h +++ b/media/mojo/services/media_type_converters.h
@@ -12,10 +12,12 @@ #include "mojo/public/cpp/bindings/type_converter.h" namespace media { +class AudioBuffer; class AudioDecoderConfig; class DecoderBuffer; class DecryptConfig; class VideoDecoderConfig; +class VideoFrame; struct CdmConfig; struct CdmKeyInformation; struct SubsampleEntry; @@ -112,6 +114,32 @@ static media::CdmConfig Convert(const media::interfaces::CdmConfigPtr& input); }; +template <> +struct TypeConverter<media::interfaces::AudioBufferPtr, + scoped_refptr<media::AudioBuffer>> { + static media::interfaces::AudioBufferPtr Convert( + const scoped_refptr<media::AudioBuffer>& input); +}; +template <> +struct TypeConverter<scoped_refptr<media::AudioBuffer>, + media::interfaces::AudioBufferPtr> { + static scoped_refptr<media::AudioBuffer> Convert( + const media::interfaces::AudioBufferPtr& input); +}; + +template <> +struct TypeConverter<media::interfaces::VideoFramePtr, + scoped_refptr<media::VideoFrame>> { + static media::interfaces::VideoFramePtr Convert( + const scoped_refptr<media::VideoFrame>& input); +}; +template <> +struct TypeConverter<scoped_refptr<media::VideoFrame>, + media::interfaces::VideoFramePtr> { + static scoped_refptr<media::VideoFrame> Convert( + const media::interfaces::VideoFramePtr& input); +}; + } // namespace mojo #endif // MEDIA_MOJO_SERVICES_MEDIA_TYPE_CONVERTERS_H_
diff --git a/media/mojo/services/media_type_converters_unittest.cc b/media/mojo/services/media_type_converters_unittest.cc index 38559f3..dae82d4c 100644 --- a/media/mojo/services/media_type_converters_unittest.cc +++ b/media/mojo/services/media_type_converters_unittest.cc
@@ -4,14 +4,87 @@ #include "media/mojo/services/media_type_converters.h" +#include <string.h> + +#include "media/base/audio_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/cdm_config.h" #include "media/base/decoder_buffer.h" #include "media/base/media_util.h" +#include "media/base/sample_format.h" +#include "media/base/test_helpers.h" +#include "media/base/video_frame.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { +namespace { + +void CompareBytes(uint8* original_data, uint8* result_data, size_t length) { + EXPECT_GT(length, 0u); + EXPECT_EQ(memcmp(original_data, result_data, length), 0); +} + +void CompareAudioBuffers(SampleFormat sample_format, + const scoped_refptr<AudioBuffer>& original, + const scoped_refptr<AudioBuffer>& result) { + EXPECT_EQ(original->frame_count(), result->frame_count()); + EXPECT_EQ(original->timestamp(), result->timestamp()); + EXPECT_EQ(original->duration(), result->duration()); + EXPECT_EQ(original->sample_rate(), result->sample_rate()); + EXPECT_EQ(original->channel_count(), result->channel_count()); + EXPECT_EQ(original->channel_layout(), result->channel_layout()); + EXPECT_EQ(original->end_of_stream(), result->end_of_stream()); + + // Compare bytes in buffer. + int bytes_per_channel = + original->frame_count() * SampleFormatToBytesPerChannel(sample_format); + if (IsPlanar(sample_format)) { + for (int i = 0; i < original->channel_count(); ++i) { + CompareBytes(original->channel_data()[i], result->channel_data()[i], + bytes_per_channel); + } + return; + } + + DCHECK(IsInterleaved(sample_format)) << sample_format; + CompareBytes(original->channel_data()[0], result->channel_data()[0], + bytes_per_channel * original->channel_count()); +} + +void CompareVideoPlane(size_t plane, + const scoped_refptr<VideoFrame>& original, + const scoped_refptr<VideoFrame>& result) { + EXPECT_EQ(original->stride(plane), result->stride(plane)); + EXPECT_EQ(original->row_bytes(plane), result->row_bytes(plane)); + EXPECT_EQ(original->rows(plane), result->rows(plane)); + CompareBytes(original->data(plane), result->data(plane), + original->rows(plane) * original->row_bytes(plane)); +} + +void CompareVideoFrames(const scoped_refptr<VideoFrame>& original, + const scoped_refptr<VideoFrame>& result) { + if (original->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM)) { + EXPECT_TRUE( + result->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM)); + return; + } + + EXPECT_EQ(original->format(), result->format()); + EXPECT_EQ(original->coded_size().height(), result->coded_size().height()); + EXPECT_EQ(original->coded_size().width(), result->coded_size().width()); + EXPECT_EQ(original->visible_rect().height(), result->visible_rect().height()); + EXPECT_EQ(original->visible_rect().width(), result->visible_rect().width()); + EXPECT_EQ(original->natural_size().height(), result->natural_size().height()); + EXPECT_EQ(original->natural_size().width(), result->natural_size().width()); + + CompareVideoPlane(media::VideoFrame::kYPlane, original, result); + CompareVideoPlane(media::VideoFrame::kUPlane, original, result); + CompareVideoPlane(media::VideoFrame::kVPlane, original, result); +} + +} // namespace + TEST(MediaTypeConvertersTest, ConvertDecoderBuffer_Normal) { const uint8 kData[] = "hello, world"; const uint8 kSideData[] = "sideshow bob"; @@ -172,4 +245,88 @@ EXPECT_EQ(config.use_hw_secure_codecs, result.use_hw_secure_codecs); } +TEST(MediaTypeConvertersTest, ConvertAudioBuffer_EOS) { + // Original. + scoped_refptr<AudioBuffer> buffer(AudioBuffer::CreateEOSBuffer()); + + // Convert to and back. + interfaces::AudioBufferPtr ptr(interfaces::AudioBuffer::From(buffer)); + scoped_refptr<AudioBuffer> result(ptr.To<scoped_refptr<AudioBuffer>>()); + + // Compare. + EXPECT_TRUE(result->end_of_stream()); +} + +TEST(MediaTypeConvertersTest, ConvertAudioBuffer_MONO) { + // Original. + const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_MONO; + const int kSampleRate = 48000; + scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<uint8>( + kSampleFormatU8, kChannelLayout, + ChannelLayoutToChannelCount(kChannelLayout), kSampleRate, 1, 1, + kSampleRate / 100, base::TimeDelta()); + + // Convert to and back. + interfaces::AudioBufferPtr ptr(interfaces::AudioBuffer::From(buffer)); + scoped_refptr<AudioBuffer> result(ptr.To<scoped_refptr<AudioBuffer>>()); + + // Compare. + CompareAudioBuffers(kSampleFormatU8, buffer, result); +} + +TEST(MediaTypeConvertersTest, ConvertAudioBuffer_FLOAT) { + // Original. + const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_4_0; + const int kSampleRate = 48000; + const base::TimeDelta start_time = base::TimeDelta::FromSecondsD(1000.0); + scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<float>( + kSampleFormatPlanarF32, kChannelLayout, + ChannelLayoutToChannelCount(kChannelLayout), kSampleRate, 0.0f, 1.0f, + kSampleRate / 10, start_time); + // Convert to and back. + interfaces::AudioBufferPtr ptr(interfaces::AudioBuffer::From(buffer)); + scoped_refptr<AudioBuffer> result(ptr.To<scoped_refptr<AudioBuffer>>()); + + // Compare. + CompareAudioBuffers(kSampleFormatPlanarF32, buffer, result); +} + +TEST(MediaTypeConvertersTest, ConvertVideoFrame_EOS) { + // Original. + scoped_refptr<VideoFrame> buffer(VideoFrame::CreateEOSFrame()); + + // Convert to and back. + interfaces::VideoFramePtr ptr(interfaces::VideoFrame::From(buffer)); + scoped_refptr<VideoFrame> result(ptr.To<scoped_refptr<VideoFrame>>()); + + // Compare. + CompareVideoFrames(buffer, result); +} + +TEST(MediaTypeConvertersTest, ConvertVideoFrame_BlackFrame) { + // Original. + scoped_refptr<VideoFrame> buffer( + VideoFrame::CreateBlackFrame(gfx::Size(100, 100))); + + // Convert to and back. + interfaces::VideoFramePtr ptr(interfaces::VideoFrame::From(buffer)); + scoped_refptr<VideoFrame> result(ptr.To<scoped_refptr<VideoFrame>>()); + + // Compare. + CompareVideoFrames(buffer, result); +} + +TEST(MediaTypeConvertersTest, ConvertVideoFrame_ColorFrame) { + // Original. + scoped_refptr<VideoFrame> buffer(VideoFrame::CreateColorFrame( + gfx::Size(50, 100), 255, 128, 128, base::TimeDelta::FromSeconds(26))); + + // Convert to and back. + interfaces::VideoFramePtr ptr(interfaces::VideoFrame::From(buffer)); + scoped_refptr<VideoFrame> result(ptr.To<scoped_refptr<VideoFrame>>()); + + // Compare. + CompareVideoFrames(buffer, result); +} + } // namespace media
diff --git a/mojo/services/network/url_loader_impl.cc b/mojo/services/network/url_loader_impl.cc index 002f2ee4..dfb1566 100644 --- a/mojo/services/network/url_loader_impl.cc +++ b/mojo/services/network/url_loader_impl.cc
@@ -4,7 +4,9 @@ #include "mojo/services/network/url_loader_impl.h" -#include "base/memory/scoped_vector.h" +#include <vector> + +#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "mojo/common/common_type_converters.h" #include "mojo/common/url_type_converters.h" @@ -190,13 +192,13 @@ url_request_->SetExtraRequestHeaders(headers); } if (request->body) { - ScopedVector<net::UploadElementReader> element_readers; + std::vector<scoped_ptr<net::UploadElementReader>> element_readers; for (size_t i = 0; i < request->body.size(); ++i) { - element_readers.push_back( - new UploadDataPipeElementReader(request->body[i].Pass())); + element_readers.push_back(make_scoped_ptr( + new UploadDataPipeElementReader(request->body[i].Pass()))); } url_request_->set_upload(make_scoped_ptr<net::UploadDataStream>( - new net::ElementsUploadDataStream(element_readers.Pass(), 0))); + new net::ElementsUploadDataStream(std::move(element_readers), 0))); } if (request->bypass_cache) url_request_->SetLoadFlags(net::LOAD_BYPASS_CACHE);
diff --git a/net/base/elements_upload_data_stream.cc b/net/base/elements_upload_data_stream.cc index e23f632a..29b77ba 100644 --- a/net/base/elements_upload_data_stream.cc +++ b/net/base/elements_upload_data_stream.cc
@@ -15,14 +15,13 @@ namespace net { ElementsUploadDataStream::ElementsUploadDataStream( - ScopedVector<UploadElementReader> element_readers, + std::vector<scoped_ptr<UploadElementReader>> element_readers, int64_t identifier) : UploadDataStream(false, identifier), - element_readers_(element_readers.Pass()), + element_readers_(std::move(element_readers)), element_index_(0), read_failed_(false), - weak_ptr_factory_(this) { -} + weak_ptr_factory_(this) {} ElementsUploadDataStream::~ElementsUploadDataStream() { } @@ -30,10 +29,10 @@ scoped_ptr<UploadDataStream> ElementsUploadDataStream::CreateWithReader( scoped_ptr<UploadElementReader> reader, int64_t identifier) { - ScopedVector<UploadElementReader> readers; - readers.push_back(reader.Pass()); + std::vector<scoped_ptr<UploadElementReader>> readers; + readers.push_back(std::move(reader)); return scoped_ptr<UploadDataStream>( - new ElementsUploadDataStream(readers.Pass(), identifier)); + new ElementsUploadDataStream(std::move(readers), identifier)); } int ElementsUploadDataStream::InitInternal() { @@ -48,14 +47,14 @@ } bool ElementsUploadDataStream::IsInMemory() const { - for (size_t i = 0; i < element_readers_.size(); ++i) { - if (!element_readers_[i]->IsInMemory()) + for (const scoped_ptr<UploadElementReader>& it : element_readers_) { + if (!it->IsInMemory()) return false; } return true; } -const ScopedVector<UploadElementReader>* +const std::vector<scoped_ptr<UploadElementReader>>* ElementsUploadDataStream::GetElementReaders() const { return &element_readers_; } @@ -69,7 +68,7 @@ int ElementsUploadDataStream::InitElements(size_t start_index) { // Call Init() for all elements. for (size_t i = start_index; i < element_readers_.size(); ++i) { - UploadElementReader* reader = element_readers_[i]; + UploadElementReader* reader = element_readers_[i].get(); // When new_result is ERR_IO_PENDING, InitInternal() will be called // with start_index == i + 1 when reader->Init() finishes. int result = reader->Init( @@ -83,8 +82,8 @@ } uint64_t total_size = 0; - for (size_t i = 0; i < element_readers_.size(); ++i) { - total_size += element_readers_[i]->GetContentLength(); + for (const scoped_ptr<UploadElementReader>& it : element_readers_) { + total_size += it->GetContentLength(); } SetSize(total_size); return OK; @@ -105,7 +104,7 @@ int ElementsUploadDataStream::ReadElements( const scoped_refptr<DrainableIOBuffer>& buf) { while (!read_failed_ && element_index_ < element_readers_.size()) { - UploadElementReader* reader = element_readers_[element_index_]; + UploadElementReader* reader = element_readers_[element_index_].get(); if (reader->BytesRemaining() == 0) { ++element_index_;
diff --git a/net/base/elements_upload_data_stream.h b/net/base/elements_upload_data_stream.h index c65c3c61..e4773298 100644 --- a/net/base/elements_upload_data_stream.h +++ b/net/base/elements_upload_data_stream.h
@@ -5,11 +5,12 @@ #ifndef NET_BASE_ELEMENTS_UPLOAD_DATA_STREAM_H_ #define NET_BASE_ELEMENTS_UPLOAD_DATA_STREAM_H_ +#include <vector> + #include "base/basictypes.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "net/base/net_export.h" #include "net/base/upload_data_stream.h" @@ -23,8 +24,9 @@ // A non-chunked UploadDataStream consisting of one or more UploadElements. class NET_EXPORT ElementsUploadDataStream : public UploadDataStream { public: - ElementsUploadDataStream(ScopedVector<UploadElementReader> element_readers, - int64_t identifier); + ElementsUploadDataStream( + std::vector<scoped_ptr<UploadElementReader>> element_readers, + int64_t identifier); ~ElementsUploadDataStream() override; @@ -37,7 +39,8 @@ private: // UploadDataStream implementation. bool IsInMemory() const override; - const ScopedVector<UploadElementReader>* GetElementReaders() const override; + const std::vector<scoped_ptr<UploadElementReader>>* GetElementReaders() + const override; int InitInternal() override; int ReadInternal(IOBuffer* buf, int buf_len) override; void ResetInternal() override; @@ -65,7 +68,7 @@ void ProcessReadResult(const scoped_refptr<DrainableIOBuffer>& buf, int result); - ScopedVector<UploadElementReader> element_readers_; + std::vector<scoped_ptr<UploadElementReader>> element_readers_; // Index of the current upload element (i.e. the element currently being // read). The index is used as a cursor to iterate over elements in
diff --git a/net/base/elements_upload_data_stream_unittest.cc b/net/base/elements_upload_data_stream_unittest.cc index 8c72054..a395c83 100644 --- a/net/base/elements_upload_data_stream_unittest.cc +++ b/net/base/elements_upload_data_stream_unittest.cc
@@ -142,12 +142,12 @@ bool error_expected); base::ScopedTempDir temp_dir_; - ScopedVector<UploadElementReader> element_readers_; + std::vector<scoped_ptr<UploadElementReader>> element_readers_; }; TEST_F(ElementsUploadDataStreamTest, EmptyUploadData) { scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); ASSERT_EQ(OK, stream->Init(CompletionCallback())); EXPECT_TRUE(stream->IsInMemory()); EXPECT_EQ(0U, stream->size()); @@ -156,10 +156,10 @@ } TEST_F(ElementsUploadDataStreamTest, ConsumeAllBytes) { - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); + element_readers_.push_back( + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); ASSERT_EQ(OK, stream->Init(CompletionCallback())); EXPECT_TRUE(stream->IsInMemory()); EXPECT_EQ(kTestDataSize, stream->size()); @@ -182,13 +182,13 @@ ASSERT_EQ(static_cast<int>(kTestDataSize), base::WriteFile(temp_file_path, kTestData, kTestDataSize)); - element_readers_.push_back( - new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, kuint64max, base::Time())); + element_readers_.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max, + base::Time()))); TestCompletionCallback init_callback; scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); EXPECT_FALSE(stream->IsInMemory()); @@ -218,13 +218,13 @@ UploadFileElementReader::ScopedOverridingContentLengthForTests overriding_content_length(kFakeSize); - element_readers_.push_back( - new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, kuint64max, base::Time())); + element_readers_.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max, + base::Time()))); TestCompletionCallback init_callback; scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); EXPECT_FALSE(stream->IsInMemory()); @@ -251,18 +251,18 @@ TEST_F(ElementsUploadDataStreamTest, ReadErrorSync) { // This element cannot be read. - MockUploadElementReader* reader = - new MockUploadElementReader(kTestDataSize, true); + scoped_ptr<MockUploadElementReader> reader( + new MockUploadElementReader(kTestDataSize, true)); EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK)); reader->SetReadExpectation(ERR_FAILED); - element_readers_.push_back(reader); + element_readers_.push_back(std::move(reader)); // This element is ignored because of the error from the previous reader. - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); + element_readers_.push_back( + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); // Run Init(). ASSERT_EQ(OK, stream->Init(CompletionCallback())); @@ -287,18 +287,18 @@ TEST_F(ElementsUploadDataStreamTest, ReadErrorAsync) { // This element cannot be read. - MockUploadElementReader* reader = - new MockUploadElementReader(kTestDataSize, false); + scoped_ptr<MockUploadElementReader> reader( + new MockUploadElementReader(kTestDataSize, false)); reader->SetAsyncInitExpectation(OK); reader->SetReadExpectation(ERR_FAILED); - element_readers_.push_back(reader); + element_readers_.push_back(std::move(reader)); // This element is ignored because of the error from the previous reader. - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); + element_readers_.push_back( + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); // Run Init(). TestCompletionCallback init_callback; @@ -334,17 +334,17 @@ const uint64_t kFileRangeOffset = 1; const uint64_t kFileRangeLength = 4; - element_readers_.push_back(new UploadFileElementReader( + element_readers_.push_back(make_scoped_ptr(new UploadFileElementReader( base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, - kFileRangeOffset, kFileRangeLength, base::Time())); + kFileRangeOffset, kFileRangeLength, base::Time()))); - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); + element_readers_.push_back( + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); const uint64_t kStreamSize = kTestDataSize + kFileRangeLength; TestCompletionCallback init_callback; scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); EXPECT_FALSE(stream->IsInMemory()); @@ -367,30 +367,33 @@ // Init() with on-memory and not-on-memory readers. TEST_F(ElementsUploadDataStreamTest, InitAsync) { // Create UploadDataStream with mock readers. - MockUploadElementReader* reader = NULL; - - reader = new MockUploadElementReader(kTestDataSize, true); + scoped_ptr<MockUploadElementReader> reader( + new MockUploadElementReader(kTestDataSize, true)); EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK)); - element_readers_.push_back(reader); + element_readers_.push_back(std::move(reader)); - reader = new MockUploadElementReader(kTestDataSize, true); - EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK)); - element_readers_.push_back(reader); + scoped_ptr<MockUploadElementReader> reader2( + new MockUploadElementReader(kTestDataSize, true)); + EXPECT_CALL(*reader2, Init(_)).WillOnce(Return(OK)); + element_readers_.push_back(std::move(reader2)); - reader = new MockUploadElementReader(kTestDataSize, false); - reader->SetAsyncInitExpectation(OK); - element_readers_.push_back(reader); + scoped_ptr<MockUploadElementReader> reader3( + new MockUploadElementReader(kTestDataSize, false)); + reader3->SetAsyncInitExpectation(OK); + element_readers_.push_back(std::move(reader3)); - reader = new MockUploadElementReader(kTestDataSize, false); - reader->SetAsyncInitExpectation(OK); - element_readers_.push_back(reader); + scoped_ptr<MockUploadElementReader> reader4( + new MockUploadElementReader(kTestDataSize, false)); + reader4->SetAsyncInitExpectation(OK); + element_readers_.push_back(std::move(reader4)); - reader = new MockUploadElementReader(kTestDataSize, true); - EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK)); - element_readers_.push_back(reader); + scoped_ptr<MockUploadElementReader> reader5( + new MockUploadElementReader(kTestDataSize, true)); + EXPECT_CALL(*reader5, Init(_)).WillOnce(Return(OK)); + element_readers_.push_back(std::move(reader5)); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); // Run Init(). TestCompletionCallback callback; @@ -401,14 +404,13 @@ // Init() of a reader fails asynchronously. TEST_F(ElementsUploadDataStreamTest, InitAsyncFailureAsync) { // Create UploadDataStream with a mock reader. - MockUploadElementReader* reader = NULL; - - reader = new MockUploadElementReader(kTestDataSize, false); + scoped_ptr<MockUploadElementReader> reader( + new MockUploadElementReader(kTestDataSize, false)); reader->SetAsyncInitExpectation(ERR_FAILED); - element_readers_.push_back(reader); + element_readers_.push_back(std::move(reader)); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); // Run Init(). TestCompletionCallback callback; @@ -419,18 +421,18 @@ // Init() of a reader fails synchronously. TEST_F(ElementsUploadDataStreamTest, InitAsyncFailureSync) { // Create UploadDataStream with mock readers. - MockUploadElementReader* reader = NULL; - - reader = new MockUploadElementReader(kTestDataSize, false); + scoped_ptr<MockUploadElementReader> reader( + new MockUploadElementReader(kTestDataSize, false)); reader->SetAsyncInitExpectation(OK); - element_readers_.push_back(reader); + element_readers_.push_back(std::move(reader)); - reader = new MockUploadElementReader(kTestDataSize, true); - EXPECT_CALL(*reader, Init(_)).WillOnce(Return(ERR_FAILED)); - element_readers_.push_back(reader); + scoped_ptr<MockUploadElementReader> reader2( + new MockUploadElementReader(kTestDataSize, true)); + EXPECT_CALL(*reader2, Init(_)).WillOnce(Return(ERR_FAILED)); + element_readers_.push_back(std::move(reader2)); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); // Run Init(). TestCompletionCallback callback; @@ -440,10 +442,10 @@ // Read with a buffer whose size is same as the data. TEST_F(ElementsUploadDataStreamTest, ReadAsyncWithExactSizeBuffer) { - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); + element_readers_.push_back( + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); ASSERT_EQ(OK, stream->Init(CompletionCallback())); EXPECT_TRUE(stream->IsInMemory()); @@ -460,30 +462,32 @@ // Async Read() with on-memory and not-on-memory readers. TEST_F(ElementsUploadDataStreamTest, ReadAsync) { // Create UploadDataStream with mock readers. - MockUploadElementReader* reader = NULL; - - reader = new MockUploadElementReader(kTestDataSize, true); + scoped_ptr<MockUploadElementReader> reader( + new MockUploadElementReader(kTestDataSize, true)); EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK)); reader->SetReadExpectation(kTestDataSize); - element_readers_.push_back(reader); + element_readers_.push_back(std::move(reader)); - reader = new MockUploadElementReader(kTestDataSize, false); - reader->SetAsyncInitExpectation(OK); - reader->SetReadExpectation(kTestDataSize); - element_readers_.push_back(reader); + scoped_ptr<MockUploadElementReader> reader2( + new MockUploadElementReader(kTestDataSize, false)); + reader2->SetAsyncInitExpectation(OK); + reader2->SetReadExpectation(kTestDataSize); + element_readers_.push_back(std::move(reader2)); - reader = new MockUploadElementReader(kTestDataSize, true); - EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK)); - reader->SetReadExpectation(kTestDataSize); - element_readers_.push_back(reader); + scoped_ptr<MockUploadElementReader> reader3( + new MockUploadElementReader(kTestDataSize, true)); + EXPECT_CALL(*reader3, Init(_)).WillOnce(Return(OK)); + reader3->SetReadExpectation(kTestDataSize); + element_readers_.push_back(std::move(reader3)); - reader = new MockUploadElementReader(kTestDataSize, false); - reader->SetAsyncInitExpectation(OK); - reader->SetReadExpectation(kTestDataSize); - element_readers_.push_back(reader); + scoped_ptr<MockUploadElementReader> reader4( + new MockUploadElementReader(kTestDataSize, false)); + reader4->SetAsyncInitExpectation(OK); + reader4->SetReadExpectation(kTestDataSize); + element_readers_.push_back(std::move(reader4)); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); // Run Init(). TestCompletionCallback init_callback; @@ -520,13 +524,13 @@ bool error_expected) { // Don't use element_readers_ here, as this function is called twice, and // reusing element_readers_ is wrong. - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadFileElementReader( - base::ThreadTaskRunnerHandle::Get().get(), file_path, 1, 2, time)); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), file_path, 1, 2, time))); TestCompletionCallback init_callback; scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); int error_code = init_callback.WaitForResult(); if (error_expected) @@ -562,13 +566,13 @@ base::WriteFile(temp_file_path, kTestData, kTestDataSize)); // Prepare data. - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); element_readers_.push_back( - new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, kuint64max, base::Time())); + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); + element_readers_.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max, + base::Time()))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); std::string expected_data(kTestData, kTestData + kTestDataSize); expected_data += expected_data; @@ -605,13 +609,13 @@ TestCompletionCallback test_callback; // Prepare data. - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); element_readers_.push_back( - new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, kuint64max, base::Time())); + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); + element_readers_.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max, + base::Time()))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); std::string expected_data(kTestData, kTestData + kTestDataSize); expected_data += expected_data; @@ -645,13 +649,13 @@ base::WriteFile(temp_file_path, kTestData, kTestDataSize)); // Prepare data. - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); element_readers_.push_back( - new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, kuint64max, base::Time())); + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); + element_readers_.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max, + base::Time()))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), kTestData, @@ -701,13 +705,13 @@ base::WriteFile(temp_file_path, kTestData, kTestDataSize)); // Prepare data. - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); element_readers_.push_back( - new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, kuint64max, base::Time())); + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); + element_readers_.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max, + base::Time()))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), kTestData, @@ -747,13 +751,13 @@ base::WriteFile(temp_file_path, kTestData, kTestDataSize)); // Prepare data. - element_readers_.push_back(new UploadBytesElementReader( - kTestData, kTestDataSize)); element_readers_.push_back( - new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, kuint64max, base::Time())); + make_scoped_ptr(new UploadBytesElementReader(kTestData, kTestDataSize))); + element_readers_.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max, + base::Time()))); scoped_ptr<UploadDataStream> stream( - new ElementsUploadDataStream(element_readers_.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers_), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), kTestData,
diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc index c2d88f9..23c760ea 100644 --- a/net/base/upload_data_stream.cc +++ b/net/base/upload_data_stream.cc
@@ -88,7 +88,7 @@ return false; } -const ScopedVector<UploadElementReader>* +const std::vector<scoped_ptr<UploadElementReader>>* UploadDataStream::GetElementReaders() const { return NULL; }
diff --git a/net/base/upload_data_stream.h b/net/base/upload_data_stream.h index a4573ea..ebb20af 100644 --- a/net/base/upload_data_stream.h +++ b/net/base/upload_data_stream.h
@@ -5,9 +5,11 @@ #ifndef NET_BASE_UPLOAD_DATA_STREAM_H_ #define NET_BASE_UPLOAD_DATA_STREAM_H_ +#include <vector> + #include "base/basictypes.h" #include "base/macros.h" -#include "base/memory/scoped_vector.h" +#include "base/memory/scoped_ptr.h" #include "net/base/completion_callback.h" #include "net/base/net_export.h" @@ -86,8 +88,8 @@ virtual bool IsInMemory() const; // Returns a list of element readers owned by |this|, if it has any. - virtual const ScopedVector<UploadElementReader>* - GetElementReaders() const; + virtual const std::vector<scoped_ptr<UploadElementReader>>* + GetElementReaders() const; protected: // Must be called by subclasses when InitInternal and ReadInternal complete
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 84dec61..76deac3f 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -7,10 +7,11 @@ #include <stdint.h> #include <algorithm> +#include <vector> #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/memory/scoped_vector.h" +#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_util.h" @@ -1414,12 +1415,12 @@ MockHttpRequest writer_request(kSimpleGET_Transaction); writer_request.load_flags = LOAD_BYPASS_CACHE; - ScopedVector<Context> context_list; + std::vector<scoped_ptr<Context>> context_list; const int kNumTransactions = 4; for (int i = 0; i < kNumTransactions; ++i) { - context_list.push_back(new Context()); - Context* c = context_list[i]; + context_list.push_back(make_scoped_ptr(new Context())); + Context* c = context_list[i].get(); c->result = cache.CreateTransaction(&c->trans); ASSERT_EQ(OK, c->result); @@ -1438,13 +1439,12 @@ EXPECT_EQ(2, cache.network_layer()->transaction_count()); // Cancel the first queued transaction. - delete context_list[1]; - context_list.get()[1] = NULL; + context_list[1].reset(); for (int i = 0; i < kNumTransactions; ++i) { if (i == 1) continue; - Context* c = context_list[i]; + Context* c = context_list[i].get(); ASSERT_EQ(ERR_IO_PENDING, c->result); c->result = c->callback.WaitForResult(); ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); @@ -2926,9 +2926,10 @@ const int64 kUploadId = 1; // Just a dummy value. - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), kUploadId); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -2958,9 +2959,10 @@ const int64 kUploadId = 1; // Just a dummy value. - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), kUploadId); MockHttpRequest request(transaction); @@ -2978,9 +2980,10 @@ TEST(HttpCache, SimplePOST_SeparateCache) { MockHttpCache cache; - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1); MockTransaction transaction(kSimplePOST_Transaction); MockHttpRequest req1(transaction); @@ -3017,9 +3020,10 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1); transaction.method = "POST"; transaction.status = "HTTP/1.1 205 No Content"; @@ -3056,9 +3060,10 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); transaction.method = "POST"; transaction.status = "HTTP/1.1 205 No Content"; @@ -3088,9 +3093,10 @@ factory->FinishCreation(); MockHttpCache cache(factory.Pass()); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); MockTransaction transaction(kSimplePOST_Transaction); AddMockTransaction(&transaction); @@ -3117,9 +3123,10 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1); transaction.method = "POST"; transaction.status = "HTTP/1.1 100 Continue"; @@ -3428,9 +3435,10 @@ MockTransaction transaction(kSimplePOST_Transaction); transaction.method = "PUT"; - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3457,9 +3465,10 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); transaction.method = "PUT"; MockHttpRequest req2(transaction); @@ -3493,9 +3502,10 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); transaction.method = "PUT"; transaction.status = "HTTP/1.1 305 Use Proxy"; @@ -3531,9 +3541,10 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); transaction.method = "PUT"; transaction.status = "HTTP/1.1 404 Not Found"; @@ -3561,9 +3572,10 @@ MockTransaction transaction(kSimplePOST_Transaction); transaction.method = "DELETE"; - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3590,9 +3602,10 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello", 5)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello", 5))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); transaction.method = "DELETE"; MockHttpRequest req2(transaction);
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 5c58bb606..f310d575 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -1180,9 +1180,10 @@ } TEST_P(HttpNetworkTransactionTest, Ignores100) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -6012,9 +6013,10 @@ } TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request[2]; // Transaction 1: a GET request that succeeds. The socket is recycled @@ -9107,11 +9109,11 @@ UploadFileElementReader::ScopedOverridingContentLengthForTests overriding_content_length(kFakeSize); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back( - new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, kuint64max, base::Time())); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr(new UploadFileElementReader( + base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0, kuint64max, + base::Time()))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -9161,11 +9163,11 @@ temp_file_content.length())); ASSERT_TRUE(base::MakeFileUnreadable(temp_file)); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back( + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr( new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file, 0, kuint64max, base::Time())); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + temp_file, 0, kuint64max, base::Time()))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -9218,9 +9220,9 @@ }; FakeUploadElementReader* fake_reader = new FakeUploadElementReader; - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(fake_reader); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr(fake_reader)); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -14673,9 +14675,10 @@ } TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -14780,9 +14783,10 @@ // Delete the transaction to release the socket back into the socket pool. trans1.reset(); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request2; request2.method = "POST"; @@ -14812,9 +14816,10 @@ TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetPartialBodySent) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -14867,8 +14872,6 @@ // This tests the more common case than the previous test, where headers and // body are not merged into a single request. TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); ChunkedUploadDataStream upload_data_stream(0); HttpRequestInfo request; @@ -14926,9 +14929,10 @@ } TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -14979,9 +14983,10 @@ } TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -15021,9 +15026,10 @@ TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterResetAnd100) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -15064,9 +15070,10 @@ } TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -15104,9 +15111,10 @@ } TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -15326,9 +15334,10 @@ } TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -15370,9 +15379,10 @@ } TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("foo", 3))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -15415,8 +15425,6 @@ } TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("foo", 3)); ChunkedUploadDataStream upload_data_stream(0); HttpRequestInfo request;
diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc index b431549f..fbe964d 100644 --- a/net/http/http_stream_parser_unittest.cc +++ b/net/http/http_stream_parser_unittest.cc
@@ -14,6 +14,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" @@ -126,9 +127,9 @@ } TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) { - ScopedVector<UploadElementReader> element_readers; - scoped_ptr<UploadDataStream> body( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + scoped_ptr<UploadDataStream> body(make_scoped_ptr( + new ElementsUploadDataStream(std::move(element_readers), 0))); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Shouldn't be merged if upload data is empty. ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -153,14 +154,14 @@ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file_path)); { - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; - element_readers.push_back( + element_readers.push_back(make_scoped_ptr( new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - temp_file_path, 0, 0, base::Time())); + temp_file_path, 0, 0, base::Time()))); scoped_ptr<UploadDataStream> body( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); TestCompletionCallback callback; ASSERT_EQ(ERR_IO_PENDING, body->Init(callback.callback())); ASSERT_EQ(OK, callback.WaitForResult()); @@ -174,13 +175,13 @@ } TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_SmallBodyInMemory) { - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; const std::string payload = "123"; - element_readers.push_back(new UploadBytesElementReader( - payload.data(), payload.size())); + element_readers.push_back(make_scoped_ptr( + new UploadBytesElementReader(payload.data(), payload.size()))); scoped_ptr<UploadDataStream> body( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Yes, should be merged if the in-memory body is small here. ASSERT_TRUE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -188,13 +189,13 @@ } TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) { - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; const std::string payload(10000, 'a'); // 'a' x 10000. - element_readers.push_back(new UploadBytesElementReader( - payload.data(), payload.size())); + element_readers.push_back(make_scoped_ptr( + new UploadBytesElementReader(payload.data(), payload.size()))); scoped_ptr<UploadDataStream> body( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Shouldn't be merged if the in-memory body is large here. ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -333,9 +334,10 @@ scoped_ptr<ClientSocketHandle> socket_handle = CreateConnectedSocketHandle(&data); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadBytesElementReader("hello world!", 12)); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back( + make_scoped_ptr(new UploadBytesElementReader("hello world!", 12))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); HttpRequestInfo request;
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc index 39173d67..e2515ee 100644 --- a/net/quic/quic_end_to_end_unittest.cc +++ b/net/quic/quic_end_to_end_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <vector> + #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" @@ -199,12 +201,11 @@ // Initializes |request_| for a post of |length| bytes. void InitializePostRequest(size_t length) { GenerateBody(length); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back( - new UploadBytesElementReader(request_body_.data(), - request_body_.length())); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader( + request_body_.data(), request_body_.length()))); upload_data_stream_.reset( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); request_.method = "POST"; request_.url = GURL("https://test.example.com/"); request_.upload_data_stream = upload_data_stream_.get();
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc index 838f105d..6bc1af2 100644 --- a/net/quic/quic_http_stream_test.cc +++ b/net/quic/quic_http_stream_test.cc
@@ -8,6 +8,7 @@ #include <vector> +#include "base/memory/scoped_ptr.h" #include "base/thread_task_runner_handle.h" #include "net/base/chunked_upload_data_stream.h" #include "net/base/elements_upload_data_stream.h" @@ -518,10 +519,10 @@ Initialize(); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back( - new UploadBytesElementReader(kUploadData, strlen(kUploadData))); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr( + new UploadBytesElementReader(kUploadData, strlen(kUploadData)))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); request_.method = "POST"; request_.url = GURL("http://www.google.com/"); request_.upload_data_stream = &upload_data_stream;
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index deebd64..0add3ff 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -9,7 +9,7 @@ #include "base/bind_helpers.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/memory/scoped_vector.h" +#include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/test/test_file_util.h" @@ -459,11 +459,11 @@ const HttpRequestInfo& CreatePostRequest() { if (!post_request_initialized_) { - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back( - new UploadBytesElementReader(kUploadData, kUploadDataSize)); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr( + new UploadBytesElementReader(kUploadData, kUploadDataSize))); upload_data_stream_.reset( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); post_request_.method = "POST"; post_request_.url = GURL(GetDefaultUrl()); @@ -480,12 +480,12 @@ CHECK_EQ(static_cast<int>(kUploadDataSize), base::WriteFile(file_path, kUploadData, kUploadDataSize)); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadFileElementReader( + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr(new UploadFileElementReader( base::ThreadTaskRunnerHandle::Get().get(), file_path, 0, - kUploadDataSize, base::Time())); + kUploadDataSize, base::Time()))); upload_data_stream_.reset( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); post_request_.method = "POST"; post_request_.url = GURL(GetDefaultUrl()); @@ -505,12 +505,12 @@ base::WriteFile(file_path, kUploadData, kUploadDataSize)); CHECK(base::MakeFileUnreadable(file_path)); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back(new UploadFileElementReader( + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr(new UploadFileElementReader( base::ThreadTaskRunnerHandle::Get().get(), file_path, 0, - kUploadDataSize, base::Time())); + kUploadDataSize, base::Time()))); upload_data_stream_.reset( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); post_request_.method = "POST"; post_request_.url = GURL(GetDefaultUrl()); @@ -530,17 +530,17 @@ CHECK_EQ(static_cast<int>(kUploadDataSize), base::WriteFile(file_path, kUploadData, kUploadDataSize)); - ScopedVector<UploadElementReader> element_readers; - element_readers.push_back( - new UploadBytesElementReader(kUploadData, kFileRangeOffset)); - element_readers.push_back(new UploadFileElementReader( + std::vector<scoped_ptr<UploadElementReader>> element_readers; + element_readers.push_back(make_scoped_ptr( + new UploadBytesElementReader(kUploadData, kFileRangeOffset))); + element_readers.push_back(make_scoped_ptr(new UploadFileElementReader( base::ThreadTaskRunnerHandle::Get().get(), file_path, - kFileRangeOffset, kFileRangeLength, base::Time())); - element_readers.push_back(new UploadBytesElementReader( + kFileRangeOffset, kFileRangeLength, base::Time()))); + element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader( kUploadData + kFileRangeOffset + kFileRangeLength, - kUploadDataSize - (kFileRangeOffset + kFileRangeLength))); + kUploadDataSize - (kFileRangeOffset + kFileRangeLength)))); upload_data_stream_.reset( - new ElementsUploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(std::move(element_readers), 0)); post_request_.method = "POST"; post_request_.url = GURL(GetDefaultUrl()); @@ -1947,8 +1947,8 @@ TEST_P(SpdyNetworkTransactionTest, EmptyPost) { BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); // Create an empty UploadDataStream. - ScopedVector<UploadElementReader> element_readers; - ElementsUploadDataStream stream(element_readers.Pass(), 0); + std::vector<scoped_ptr<UploadElementReader>> element_readers; + ElementsUploadDataStream stream(std::move(element_readers), 0); // Setup the request HttpRequestInfo request; @@ -5844,12 +5844,12 @@ DeterministicSocketData data(reads, arraysize(reads), writes, arraysize(writes)); - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; for (int i = 0; i < kFrameCount; ++i) { - element_readers.push_back( - new UploadBytesElementReader(content->c_str(), content->size())); + element_readers.push_back(make_scoped_ptr( + new UploadBytesElementReader(content->c_str(), content->size()))); } - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); // Setup the request HttpRequestInfo request; @@ -6058,12 +6058,12 @@ DeterministicSocketData data(reads, arraysize(reads), writes, arraysize(writes)); - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; for (int i = 0; i < kFrameCount; ++i) { - element_readers.push_back( - new UploadBytesElementReader(content->c_str(), content->size())); + element_readers.push_back(make_scoped_ptr( + new UploadBytesElementReader(content->c_str(), content->size()))); } - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); // Setup the request HttpRequestInfo request; @@ -6166,12 +6166,12 @@ SequencedSocketData data(reads, arraysize(reads), writes.get(), num_writes); - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; std::string upload_data_string(initial_window_size, 'a'); upload_data_string.append(kUploadData, kUploadDataSize); - element_readers.push_back(new UploadBytesElementReader( - upload_data_string.c_str(), upload_data_string.size())); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader( + upload_data_string.c_str(), upload_data_string.size()))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -6281,12 +6281,12 @@ DeterministicSocketData data(reads.data(), reads.size(), writes.data(), writes.size()); - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; std::string upload_data_string(initial_window_size, 'a'); upload_data_string.append(kUploadData, kUploadDataSize); - element_readers.push_back(new UploadBytesElementReader( - upload_data_string.c_str(), upload_data_string.size())); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader( + upload_data_string.c_str(), upload_data_string.size()))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST"; @@ -6402,12 +6402,12 @@ DeterministicSocketData data(reads.data(), reads.size(), writes.data(), writes.size()); - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; std::string upload_data_string(initial_window_size, 'a'); upload_data_string.append(kUploadData, kUploadDataSize); - element_readers.push_back(new UploadBytesElementReader( - upload_data_string.c_str(), upload_data_string.size())); - ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + element_readers.push_back(make_scoped_ptr(new UploadBytesElementReader( + upload_data_string.c_str(), upload_data_string.size()))); + ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0); HttpRequestInfo request; request.method = "POST";
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 5ffe31c..c72d5c2 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -5459,17 +5459,17 @@ PathService::Get(base::DIR_EXE, &dir); base::SetCurrentDirectory(dir); - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; base::FilePath path; PathService::Get(base::DIR_SOURCE_ROOT, &path); path = path.Append(kTestFilePath); path = path.Append(FILE_PATH_LITERAL("with-headers.html")); - element_readers.push_back( + element_readers.push_back(make_scoped_ptr( new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(), - path, 0, kuint64max, base::Time())); + path, 0, kuint64max, base::Time()))); r->set_upload(make_scoped_ptr<UploadDataStream>( - new ElementsUploadDataStream(element_readers.Pass(), 0))); + new ElementsUploadDataStream(std::move(element_readers), 0))); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -5504,15 +5504,15 @@ http_test_server()->GetURL("/echo"), DEFAULT_PRIORITY, &d)); r->set_method("POST"); - ScopedVector<UploadElementReader> element_readers; + std::vector<scoped_ptr<UploadElementReader>> element_readers; - element_readers.push_back(new UploadFileElementReader( + element_readers.push_back(make_scoped_ptr(new UploadFileElementReader( base::ThreadTaskRunnerHandle::Get().get(), base::FilePath(FILE_PATH_LITERAL( "c:\\path\\to\\non\\existant\\file.randomness.12345")), - 0, kuint64max, base::Time())); + 0, kuint64max, base::Time()))); r->set_upload(make_scoped_ptr<UploadDataStream>( - new ElementsUploadDataStream(element_readers.Pass(), 0))); + new ElementsUploadDataStream(std::move(element_readers), 0))); r->Start(); EXPECT_TRUE(r->is_pending());
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 7e1272b8..f2d9d33 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -747,8 +747,8 @@ crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/row-progression-007.xht [ Failure ] crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/row-progression-008.xht [ Failure ] crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/row-progression-009.xht [ Failure ] -crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/text-baseline-006.xht [ Failure ] -crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/text-baseline-007.xht [ Failure ] +crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/text-baseline-vrl-006.xht [ Failure ] +crbug.com/492664 [ Mac ] imported/csswg-test/css-writing-modes-3/text-baseline-vlr-007.xht [ Failure ] crbug.com/498845 [ Win ] fast/multicol/vertical-rl/float-content-break.html [ Failure ] @@ -1295,9 +1295,6 @@ crbug.com/550285 [ XP ] virtual/syncpaint/inspector/tracing/decode-resize.html [ Slow Pass Failure ] -crbug.com/560652 [ Mac ] editing/selection/vertical-rl-rtl-extend-line-forward-p.html [ Failure ] -crbug.com/560652 [ Mac ] editing/selection/vertical-rl-rtl-extend-line-forward-br.html [ Failure ] - crbug.com/474759 fast/writing-mode/vertical-rl-replaced-selection.html [ Failure ] crbug.com/474759 fast/block/line-layout/selection-highlight-overlap.html [ Failure ] crbug.com/502927 [ XP ] paint/frames/frameset-with-stacking-context-and-not-stacking-context-children.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations index b95bde14..2ec4624 100644 --- a/third_party/WebKit/LayoutTests/W3CImportExpectations +++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -501,6 +501,12 @@ imported/csswg-test/css-writing-modes-3/line-box-direction-058.xht [ Skip ] imported/csswg-test/css-writing-modes-3/line-box-direction-059.xht [ Skip ] imported/csswg-test/css-writing-modes-3/line-box-direction-060.xht [ Skip ] +imported/csswg-test/css-writing-modes-3/text-baseline-slr-009.xht [ Skip ] +imported/csswg-test/css-writing-modes-3/text-baseline-slr-011.xht [ Skip ] +imported/csswg-test/css-writing-modes-3/text-baseline-slr-013.xht [ Skip ] +imported/csswg-test/css-writing-modes-3/text-baseline-srl-008.xht [ Skip ] +imported/csswg-test/css-writing-modes-3/text-baseline-srl-010.xht [ Skip ] +imported/csswg-test/css-writing-modes-3/text-baseline-srl-012.xht [ Skip ] # CSS Writing Modes Level 3: Following tests require applying writing-mode to table-cell, which we do not support today. crbug.com/409155 imported/csswg-test/css-writing-modes-3/block-flow-direction-017.xht [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-factor-less-than-one.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-factor-less-than-one.html new file mode 100644 index 0000000..dbeb0056 --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-factor-less-than-one.html
@@ -0,0 +1,158 @@ +<!DOCTYPE html> +<link href="resources/flexbox.css" rel="stylesheet"> +<style> +.container { + height: 100px; + width: 100px; + border: 1px solid black; +} + +.child-flex-grow-0-75 { + background-color: lime; + flex-grow: 0.75; +} + +.child-flex-grow-0-5 { + background-color: green; + flex-grow: 0.5; +} + +.child-flex-grow-0-25 { + background-color: red; + flex-grow: 0.25; +} + +.child-flex-shrink-0-5 { + background-color: green; + flex-shrink: 0.5; + width: 200px; + height: 200px; +} + +.child-flex-shrink-0-25 { + background-color: red; + flex-shrink: 0.25; + width: 200px; + height: 200px; +} + +.basis-0 { + flex-basis: 0; +} + +.basis { + flex-basis: 30px; +} + +.basis-big { + flex-basis: 100px; +} + +.vertical { + writing-mode: vertical-rl; +} +</style> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../../resources/check-layout-th.js"></script> +<body onload="checkLayout('.flexbox');"> +<div id=log></div> + +<div class="flexbox container"> + <div class="child-flex-grow-0-5" data-expected-width="50"></div> +</div> + +<div class="flexbox container"> + <div class="child-flex-grow-0-5" data-expected-width="50"></div> + <div class="child-flex-grow-0-25" data-expected-width="25"></div> +</div> + +<div class="flexbox container column"> + <div class="child-flex-grow-0-5" data-expected-height="50"></div> + <div class="child-flex-grow-0-25" data-expected-height="25"></div> +</div> + +<div class="flexbox container column vertical"> + <div class="child-flex-grow-0-5 " data-expected-width="50"></div> + <div class="child-flex-grow-0-25 " data-expected-width="25"></div> +</div> + +<div class="flexbox container vertical"> + <div class="child-flex-grow-0-5 " data-expected-height="50"></div> + <div class="child-flex-grow-0-25 " data-expected-height="25"></div> +</div> + +<div class="flexbox container"> + <div class="child-flex-grow-0-5 basis" data-expected-width="50"></div> + <div class="child-flex-grow-0-25 basis" data-expected-width="40"></div> + </div> + +<div class="flexbox container column"> + <div class="child-flex-grow-0-5 basis" data-expected-height="50"></div> + <div class="child-flex-grow-0-25 basis" data-expected-height="40"></div> +</div> + +<div class="flexbox container vertical"> + <div class="child-flex-grow-0-5 basis" data-expected-height="50"></div> + <div class="child-flex-grow-0-25 basis" data-expected-height="40"></div> +</div> + +<div class="flexbox container column vertical"> + <div class="child-flex-grow-0-5 basis" data-expected-width="50"></div> + <div class="child-flex-grow-0-25 basis" data-expected-width="40"></div> +</div> + +<!-- And now, the shrink cases --> +<div class="flexbox container"> + <div class="child-flex-shrink-0-5" data-expected-width="150"></div> +</div> + +<div class="flexbox container"> + <div class="child-flex-shrink-0-5" data-expected-width="50"></div> + <div class="child-flex-shrink-0-25" data-expected-width="125"></div> +</div> + +<div class="flexbox container column"> + <div class="child-flex-shrink-0-5" data-expected-height="50"></div> + <div class="child-flex-shrink-0-25" data-expected-height="125"></div> +</div> + +<div class="flexbox container column vertical"> + <div class="child-flex-shrink-0-5 " data-expected-width="50"></div> + <div class="child-flex-shrink-0-25 " data-expected-width="125"></div> +</div> + +<div class="flexbox container vertical"> + <div class="child-flex-shrink-0-5 " data-expected-height="50"></div> + <div class="child-flex-shrink-0-25 " data-expected-height="125"></div> +</div> + +<div class="flexbox container"> + <div class="child-flex-shrink-0-5 basis-big" data-expected-width="50"></div> + <div class="child-flex-shrink-0-25 basis-big" data-expected-width="75"></div> + </div> + +<div class="flexbox container column"> + <div class="child-flex-shrink-0-5 basis-big" data-expected-height="50"></div> + <div class="child-flex-shrink-0-25 basis-big" data-expected-height="75"></div> +</div> + +<div class="flexbox container vertical"> + <div class="child-flex-shrink-0-5 basis-big" data-expected-height="50"></div> + <div class="child-flex-shrink-0-25 basis-big" data-expected-height="75"></div> +</div> + +<div class="flexbox container column vertical"> + <div class="child-flex-shrink-0-5 basis-big" data-expected-width="50"></div> + <div class="child-flex-shrink-0-25 basis-big" data-expected-width="75"></div> +</div> + +<!-- Interaction of min-width: auto with fractional flex basis --> +<div class="flexbox container" style="background-color: red;"> + <div class="child-flex-grow-0-25 basis-0" style="background-color: green;" data-expected-width="10"></div> + <div class="child-flex-grow-0-75 basis-0" data-expected-width="90"> + <div style="width: 90px;"></div> + </div> +</div> + +</body>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one.html deleted file mode 100644 index 1f2b856..0000000 --- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one.html +++ /dev/null
@@ -1,77 +0,0 @@ -<!DOCTYPE html> -<link href="resources/flexbox.css" rel="stylesheet"> -<style> -.container { - height: 100px; - width: 100px; - border: 1px solid black; -} - -.child-flex-grow-0-5 { - background-color: green; - flex-grow: 0.5; -} - -.child-flex-grow-0-25 { - background-color: red; - flex-grow: 0.25; -} - -.basis { - flex-basis: 30px; -} - -.vertical { - -webkit-writing-mode: vertical-rl; -} -</style> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="../../resources/check-layout-th.js"></script> -<body onload="checkLayout('.flexbox');"> -<div id=log></div> - -<div class="flexbox container"> - <div class="child-flex-grow-0-5" data-expected-width="50"></div> -</div> - -<div class="flexbox container"> - <div class="child-flex-grow-0-5" data-expected-width="50"></div> - <div class="child-flex-grow-0-25" data-expected-width="25"></div> -</div> - -<div class="flexbox container column"> - <div class="child-flex-grow-0-5" data-expected-height="50"></div> - <div class="child-flex-grow-0-25" data-expected-height="25"></div> -</div> - -<div class="flexbox container column vertical"> - <div class="child-flex-grow-0-5 " data-expected-width="50"></div> - <div class="child-flex-grow-0-25 " data-expected-width="25"></div> -</div> - -<div class="flexbox container vertical"> - <div class="child-flex-grow-0-5 " data-expected-height="50"></div> - <div class="child-flex-grow-0-25 " data-expected-height="25"></div> -</div> - -<div class="flexbox container"> - <div class="child-flex-grow-0-5 basis" data-expected-width="50"></div> - <div class="child-flex-grow-0-25 basis" data-expected-width="40"></div> - </div> - -<div class="flexbox container column"> - <div class="child-flex-grow-0-5 basis" data-expected-height="50"></div> - <div class="child-flex-grow-0-25 basis" data-expected-height="40"></div> -</div> - -<div class="flexbox container vertical"> - <div class="child-flex-grow-0-5 basis" data-expected-height="50"></div> - <div class="child-flex-grow-0-25 basis" data-expected-height="40"></div> -</div> - -<div class="flexbox container column vertical"> - <div class="child-flex-grow-0-5 basis" data-expected-width="50"></div> - <div class="child-flex-grow-0-25 basis" data-expected-width="40"></div> -</div> -</body>
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-001.html b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-001.html index 9b8adc1..3c77c81b 100644 --- a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-001.html +++ b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-001.html
@@ -1,60 +1,31 @@ -<html> -<head> - -<style> -.editing { - border: 2px solid red; - font-size: 24px; -} -.explanation { - border: 2px solid blue; - padding: 12px; - font-size: 24px; - margin-bottom: 24px; -} -.scenario { margin-bottom: 16px;} -.scenario:first-line { font-weight: bold; margin-bottom: 16px;} -.expected-results:first-line { font-weight: bold } -</style> -<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script> - -<script> - -function editingTest() { - doubleClickAtSelectionStart(); - deleteCommand(); -} - -</script> - -<title>Editing Test</title> -</head> -<body> - -<div class="explanation"> -<div class="scenario"> -Tests: -<br> -Smart delete when deleting the first word on a line. -</div> -<div class="expected-results"> -Expected Results: -<br> +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<div> The first word and the space following the first word should be deleted. It should like this this: -<BR> +<br> bar baz </div> -</div> - <div contenteditable id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;"> -<div id="test" class="editing"> -foo bar baz +<div id="sample" contenteditable>foo bar baz</div> </div> -</div> - +<div id="log"></div> <script> -runEditingTest(); +test(function() { + if (window.internals) + internals.settings.setEditingBehavior('win'); + var selection = window.getSelection(); + var sample = document.getElementById('sample'); + selection.collapse(sample.firstChild, 0); + var rect = selection.getRangeAt(0).getClientRects()[0]; + if (!window.eventSender) + return; + eventSender.mouseMoveTo(rect.left, rect.top); + eventSender.mouseDown(); + eventSender.mouseUp(); + eventSender.mouseDown(); + eventSender.mouseUp(); + document.execCommand('delete'); + assert_equals(sample.textContent, 'bar baz'); +}); </script> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-002.html b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-002.html index 9430ee2..1471051 100644 --- a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-002.html +++ b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-002.html
@@ -1,64 +1,31 @@ -<html> -<head> - -<style> -.editing { - border: 2px solid red; - font-size: 24px; -} -.explanation { - border: 2px solid blue; - padding: 12px; - font-size: 24px; - margin-bottom: 24px; -} -.scenario { margin-bottom: 16px;} -.scenario:first-line { font-weight: bold; margin-bottom: 16px;} -.expected-results:first-line { font-weight: bold } -</style> -<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script> - -<script> - -function editingTest() { - if (window.internals) - internals.settings.setEditingBehavior('mac'); - moveSelectionForwardByWordCommand(); - moveSelectionForwardByCharacterCommand(); - doubleClickAtSelectionStart(); - deleteCommand(); -} - -</script> - -<title>Editing Test</title> -</head> -<body> - -<div class="explanation"> -<div class="scenario"> -Tests: -<br> -Smart delete when deleting the second word of a line. -</div> -<div class="expected-results"> -Expected Results: -<br> +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<div> The second word and the space before the second word should be deleted. It should like this this: -<BR> -foo baz +<br> +foo bar </div> -</div> - <div contenteditable id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;"> -<div id="test" class="editing"> -foo bar baz +<div id="sample" contenteditable>foo bar baz</div> </div> -</div> - +<div id="log"></div> <script> -runEditingTest(); +test(function() { + if (window.internals) + internals.settings.setEditingBehavior('win'); + var selection = window.getSelection(); + var sample = document.getElementById('sample'); + selection.collapse(sample.firstChild, 4); + var rect = selection.getRangeAt(0).getClientRects()[0]; + if (!window.eventSender) + return; + eventSender.mouseMoveTo(rect.left, rect.top); + eventSender.mouseDown(); + eventSender.mouseUp(); + eventSender.mouseDown(); + eventSender.mouseUp(); + document.execCommand('delete'); + assert_equals(sample.textContent, 'foo baz'); +}); </script> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-003-expected.txt b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-003-expected.txt deleted file mode 100644 index fd8ccd58..0000000 --- a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-003-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -Test for smart delete backward on double click selected word. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -includeSpace -PASS sample.innerText is "foo baz" -PASS getSelection().rangeCount is 1 -PASS getSelection().focusNode is sample.firstChild -PASS getSelection().focusOffset is 4 -notIncludeSpace -PASS sample.innerText is "foo baz" -PASS getSelection().rangeCount is 1 -PASS getSelection().focusNode is sample.firstChild -PASS getSelection().focusOffset is 3 -PASS successfullyParsed is true - -TEST COMPLETE -Please tun this test with DRT. - -To run it manually, double click on 'bar' and hit delete. You should see 'foo baz'. - -foo baz -foo baz
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-003.html b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-003.html index 87647da..da9573f 100644 --- a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-003.html +++ b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-003.html
@@ -1,16 +1,18 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> -<p>Please tun this test with DRT.</p> -<p>To run it manually, double click on 'bar' and hit delete. You should see 'foo baz'.</p> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<h1>Test for smart delete backward on double click selected word.</h1> +<p>Please tun this test with layout test runner</p> +<p>To run it manually, double click on 'bar' and hit backspace. You should see 'foo baz'.</p> <div id="includeSpace" contenteditable="true">foo b<span id="target">a</span>r baz</div> <div id="notIncludeSpace" contenteditable="true">foo b<span id="target">a</span>r baz</div> +<div id="log"></div> <script> -description('Test for smart delete backward on double click selected word.'); -var sample; function testIt(sampleId, expectedString, expectedOffset) { - if (!window.testRunner) + if (!window.eventSender || !window.internals || window.testRunner) return; - sample = document.getElementById(sampleId); + var selection = window.getSelection(); + var sample = document.getElementById(sampleId); var target = sample.querySelector('#target'); internals.settings.setSelectTrailingWhitespaceEnabled(sampleId == 'includeSpace'); eventSender.mouseMoveTo(target.offsetLeft, target.offsetTop); @@ -18,13 +20,12 @@ eventSender.mouseUp(); eventSender.mouseDown(); eventSender.mouseUp(); - debug(sampleId); testRunner.execCommand('DeleteBackward'); - shouldBeEqualToString('sample.innerText', expectedString); - shouldBe('getSelection().rangeCount', '1'); - shouldBe('getSelection().focusNode', 'sample.firstChild'); - shouldBe('getSelection().focusOffset', expectedOffset.toString()); + assert_equals(sample.innerText, expectedString, sampleId); + assert_true(selection.isCollapsed); + assert_equals(selection.focusNode, sample.firstChild, sampleId + ' focusNode'); + assert_equals(selection.focusOffset, expectedOffset, sample.firstChild, sampleId + ' focusOffset'); } -testIt('includeSpace', 'foo baz', 4); -testIt('notIncludeSpace', 'foo\u00A0baz', 3); +test(testIt.bind(this, 'includeSpace', 'foo baz', 4), 'includeSpace'); +test(testIt.bind(this, 'notIncludeSpace', 'foo\u00A0baz', 3), 'notIncludeSpace'); </script>
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-004-expected.txt b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-004-expected.txt deleted file mode 100644 index 25732ca2..0000000 --- a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-004-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -Test for smart delete forward on double click selected word. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -includeSpace -PASS sample.innerText is "foo baz" -PASS getSelection().rangeCount is 1 -PASS getSelection().focusNode is sample.firstChild -PASS getSelection().focusOffset is 4 -notIncludeSpace -PASS sample.innerText is "foo baz" -PASS getSelection().rangeCount is 1 -PASS getSelection().focusNode is sample.firstChild -PASS getSelection().focusOffset is 3 -PASS successfullyParsed is true - -TEST COMPLETE -Please tun this test with DRT. - -To run it manually, double click on 'bar' and hit delete. You should see 'foo baz'. - -foo baz -foo baz
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-004.html b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-004.html index 7ebfcb9..d74a079 100644 --- a/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-004.html +++ b/third_party/WebKit/LayoutTests/editing/deleting/smart-delete-004.html
@@ -1,16 +1,18 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> -<p>Please tun this test with DRT.</p> -<p>To run it manually, double click on 'bar' and hit delete. You should see 'foo baz'.</p> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<h1>Test for smart delete backward on double click selected word.</h1> +<p>Please tun this test with layout test runner</p> +<p>To run it manually, double click on 'bar' and hit backspace. You should see 'foo baz'.</p> <div id="includeSpace" contenteditable="true">foo b<span id="target">a</span>r baz</div> <div id="notIncludeSpace" contenteditable="true">foo b<span id="target">a</span>r baz</div> +<div id="log"></div> <script> -description('Test for smart delete forward on double click selected word.'); -var sample; function testIt(sampleId, expectedString, expectedOffset) { - if (!window.testRunner) + if (!window.eventSender || !window.internals || window.testRunner) return; - sample = document.getElementById(sampleId); + var selection = window.getSelection(); + var sample = document.getElementById(sampleId); var target = sample.querySelector('#target'); internals.settings.setSelectTrailingWhitespaceEnabled(sampleId == 'includeSpace'); eventSender.mouseMoveTo(target.offsetLeft, target.offsetTop); @@ -18,13 +20,12 @@ eventSender.mouseUp(); eventSender.mouseDown(); eventSender.mouseUp(); - debug(sampleId); testRunner.execCommand('DeleteForward'); - shouldBeEqualToString('sample.innerText', expectedString); - shouldBe('getSelection().rangeCount', '1'); - shouldBe('getSelection().focusNode', 'sample.firstChild'); - shouldBe('getSelection().focusOffset', expectedOffset.toString()); + assert_equals(sample.innerText, expectedString, sampleId); + assert_true(selection.isCollapsed); + assert_equals(selection.focusNode, sample.firstChild, sampleId + ' focusNode'); + assert_equals(selection.focusOffset, expectedOffset, sample.firstChild, sampleId + ' focusOffset'); } -testIt('includeSpace', 'foo baz', 4); -testIt('notIncludeSpace', 'foo\u00A0baz', 3); +test(testIt.bind(this, 'includeSpace', 'foo baz', 4), 'includeSpace'); +test(testIt.bind(this, 'notIncludeSpace', 'foo\u00A0baz', 3), 'notIncludeSpace'); </script>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-br.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-br.html index 3830f4a..082442d8 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-br.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-br.html
@@ -3,7 +3,7 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode.</p> -<div id="test" style="font-family: monospace; font-size: 20px; height: 15ex; -webkit-writing-mode: vertical-rl; -webkit-text-orientation: sideways-right; outline: none;" contenteditable> +<div id="test" style="font-family: Courier New; font-size: 20px; height: 15ex; -webkit-writing-mode: vertical-rl; -webkit-text-orientation: sideways-right; outline: none;" contenteditable> <p id="p1" dir="rtl">אני חתול.<br>אין לי שם.</p> </div> <div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-p.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-p.html index 494366b..5ac8958 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-p.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-p.html
@@ -3,7 +3,7 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode.</p> -<div id="test" style="font-family: monospace; font-size: 20px; height: 15ex; -webkit-writing-mode: vertical-rl;-webkit-text-orientation:sideways-right;text-rendering:optimizeLegibility; outline: none;" contenteditable> +<div id="test" style="font-family: Courier New; font-size: 20px; height: 15ex; -webkit-writing-mode: vertical-rl;-webkit-text-orientation:sideways-right;text-rendering:optimizeLegibility; outline: none;" contenteditable> <p id="p1" dir="rtl">אני חתול.</p><p id="p2" dir="rtl">אין לי שם.</p> </div> <div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/fast/html/link-clear-sheet-crash-expected.txt b/third_party/WebKit/LayoutTests/fast/html/link-clear-sheet-crash-expected.txt new file mode 100644 index 0000000..0724b25 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/html/link-clear-sheet-crash-expected.txt
@@ -0,0 +1 @@ +PASS if not crashed
diff --git a/third_party/WebKit/LayoutTests/fast/html/link-clear-sheet-crash.html b/third_party/WebKit/LayoutTests/fast/html/link-clear-sheet-crash.html new file mode 100644 index 0000000..48061e6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/html/link-clear-sheet-crash.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<link href="notexist.css" id="link" rel="stylesheet"> +<script> +if (window.testRunner) { + testRunner.dumpAsText(); + testRunner.waitUntilDone(); +} + +onload = function(){ + setTimeout(function(){ + document.body.offsetTop; + link.setAttribute("sizes", ""); + link.setAttribute("disabled", ""); + requestAnimationFrame(function(){ + if (window.testRunner) + testRunner.notifyDone(); + }); + }, 0); +}; +</script> +<p>PASS if not crashed</p>
diff --git a/third_party/WebKit/LayoutTests/fast/text/bidi-embedding-pop-and-push-same.html b/third_party/WebKit/LayoutTests/fast/text/bidi-embedding-pop-and-push-same.html index 3515f3b..ae521d1b 100644 --- a/third_party/WebKit/LayoutTests/fast/text/bidi-embedding-pop-and-push-same.html +++ b/third_party/WebKit/LayoutTests/fast/text/bidi-embedding-pop-and-push-same.html Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js index 541713bc5..c5c7998c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
@@ -169,7 +169,7 @@ if (typeof status === "string") caption = status; else - caption = status.textContent; + caption = status.deepTextContent(); if (callFrames) step1(); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js index a79d9c67d..a0dbaf1c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
@@ -969,14 +969,10 @@ InspectorTest.dumpAnimationTimeline = function(timeline) { - for (var nodeUI of timeline._nodesMap.values()) { - for (nodeRow of nodeUI._rows) { - for (var ui of nodeRow.animations) { - InspectorTest.addResult(ui.animation().type()); - InspectorTest.addResult(ui._nameElement.innerHTML); - InspectorTest.addResult(ui._svg.innerHTML); - } - } + for (var ui of timeline._uiAnimations) { + InspectorTest.addResult(ui.animation().type()); + InspectorTest.addResult(ui._nameElement.innerHTML); + InspectorTest.addResult(ui._svg.innerHTML); } }
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-003-expected.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-003-expected.xht similarity index 100% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-003-expected.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-003-expected.xht
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-003.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-003.xht similarity index 95% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-003.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-003.xht index cdb630a..37fe116 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-003.xht +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-003.xht
@@ -5,7 +5,7 @@ <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-09-26 --> <link rel="help" title="4.2. Text Baseline" href="http://www.w3.org/TR/css-writing-modes-3/#text-baselines" /> - <link rel="match" href="text-baseline-002-ref.xht" /> + <link rel="match" href="text-baseline-vrl-002-ref.xht" /> <meta name="assert" content="This test checks the generation of text baseline. When 'writing-mode' is 'vertical-lr' and when 'text-orientation' is 'mixed', then the central baseline is used as the dominant baseline." /> <meta name="flags" content="ahem" /> <style type="text/css"><![CDATA[
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-005-expected.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-005-expected.xht similarity index 100% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-005-expected.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-005-expected.xht
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-005.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-005.xht similarity index 95% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-005.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-005.xht index 1f2f304..4a10b43f 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-005.xht +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-005.xht
@@ -5,7 +5,7 @@ <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-09-26 --> <link rel="help" title="4.2. Text Baseline" href="http://www.w3.org/TR/css-writing-modes-3/#text-baselines" /> - <link rel="match" href="text-baseline-002-ref.xht" /> + <link rel="match" href="text-baseline-vrl-002-ref.xht" /> <meta name="assert" content="This test checks the generation of text baseline. When 'writing-mode' is 'vertical-lr' and when 'text-orientation' is 'upright', then the central baseline is used as the dominant baseline." /> <meta name="flags" content="ahem" /> <style type="text/css"><![CDATA[
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-007-expected.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-007-expected.xht similarity index 100% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-007-expected.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-007-expected.xht
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-007.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-007.xht similarity index 95% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-007.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-007.xht index 8e7007f..6ade11f16 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-007.xht +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vlr-007.xht
@@ -5,7 +5,7 @@ <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-09-26 --> <link rel="help" title="4.2. Text Baseline" href="http://www.w3.org/TR/css-writing-modes-3/#text-baselines" /> - <link rel="match" href="text-baseline-006-ref.xht" /> + <link rel="match" href="text-baseline-vrl-006-ref.xht" /> <meta name="assert" content="This test checks the generation of text baseline. When 'writing-mode' is 'vertical-lr' and when 'text-orientation' is 'sideways', then the alphabetical baseline is used as the dominant baseline." /> <meta name="flags" content="ahem" /> <style type="text/css"><![CDATA[
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-002-expected.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-002-expected.xht similarity index 100% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-002-expected.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-002-expected.xht
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-002.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-002.xht similarity index 95% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-002.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-002.xht index 571d22e..a4202575 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-002.xht +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-002.xht
@@ -5,7 +5,7 @@ <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-09-26 --> <link rel="help" title="4.2. Text Baseline" href="http://www.w3.org/TR/css-writing-modes-3/#text-baselines" /> - <link rel="match" href="text-baseline-002-ref.xht" /> + <link rel="match" href="text-baseline-vrl-002-ref.xht" /> <meta name="assert" content="This test checks the generation of text baseline. When 'writing-mode' is 'vertical-rl' and when 'text-orientation' is 'mixed', then the central baseline is used as the dominant baseline." /> <meta name="flags" content="ahem" /> <style type="text/css"><![CDATA[
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-004-expected.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-004-expected.xht similarity index 100% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-004-expected.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-004-expected.xht
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-004.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-004.xht similarity index 95% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-004.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-004.xht index ed60f37..e54e2d7 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-004.xht +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-004.xht
@@ -5,7 +5,7 @@ <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-09-26 --> <link rel="help" title="4.2. Text Baseline" href="http://www.w3.org/TR/css-writing-modes-3/#text-baselines" /> - <link rel="match" href="text-baseline-002-ref.xht" /> + <link rel="match" href="text-baseline-vrl-002-ref.xht" /> <meta name="assert" content="This test checks the generation of text baseline. When 'writing-mode' is 'vertical-rl' and when 'text-orientation' is 'upright', then the central baseline is used as the dominant baseline." /> <meta name="flags" content="ahem" /> <style type="text/css"><![CDATA[
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-006-expected.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-006-expected.xht similarity index 100% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-006-expected.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-006-expected.xht
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-006.xht b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-006.xht similarity index 95% rename from third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-006.xht rename to third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-006.xht index 83e374cc..c9f2897 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-006.xht +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/text-baseline-vrl-006.xht
@@ -5,7 +5,7 @@ <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-09-26 --> <link rel="help" title="4.2. Text Baseline" href="http://www.w3.org/TR/css-writing-modes-3/#text-baselines" /> - <link rel="match" href="text-baseline-006-ref.xht" /> + <link rel="match" href="text-baseline-vrl-006-ref.xht" /> <meta name="assert" content="This test checks the generation of text baseline. When 'writing-mode' is 'vertical-rl' and when 'text-orientation' is 'sideways', then the alphabetical baseline is used as the dominant baseline." /> <meta name="flags" content="ahem" /> <style type="text/css"><![CDATA[
diff --git a/third_party/WebKit/LayoutTests/inspector/animation/animation-timeline-expected.txt b/third_party/WebKit/LayoutTests/inspector/animation/animation-timeline-expected.txt index d52a226..3facea2 100644 --- a/third_party/WebKit/LayoutTests/inspector/animation/animation-timeline-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/animation/animation-timeline-expected.txt
@@ -3,21 +3,51 @@ >>>> Animation with start delay only WebAnimation -<g style="transform: translateX(222.22px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="451.44" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.94 10.85 L 3.51 10.85 L 7.66 10.85 L 13.28 10.85 L 20.28 10.85 L 28.59 10.85 L 38.10 10.85 L 48.73 10.85 L 60.39 10.85 L 72.99 10.85 L 86.44 10.85 L 100.65 10.85 L 115.54 10.85 L 131.00 10.85 L 146.95 10.85 L 163.31 10.85 L 179.98 10.85 L 196.87 10.85 L 213.90 10.85 L 230.96 10.85 L 247.99 10.85 L 264.88 10.85 L 281.54 10.85 L 297.89 10.85 L 313.83 10.85 L 329.28 10.85 L 344.15 10.85 L 358.34 10.85 L 371.77 10.85 L 384.35 10.85 L 395.99 10.85 L 406.60 10.85 L 416.08 10.85 L 424.36 10.85 L 431.33 10.85 L 436.92 10.85 L 441.03 10.85 L 443.56 10.85 L 444.44 10.85 L 444.44 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="451.44" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="229.22" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line> +<g style="transform: translateX(200px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.85 10.85 L 3.16 10.85 L 6.89 10.85 L 11.95 10.85 L 18.25 10.85 L 25.73 10.85 L 34.29 10.85 L 43.86 10.85 L 54.35 10.85 L 65.69 10.85 L 77.80 10.85 L 90.59 10.85 L 103.98 10.85 L 117.90 10.85 L 132.26 10.85 L 146.98 10.85 L 161.98 10.85 L 177.18 10.85 L 192.51 10.85 L 207.87 10.85 L 223.19 10.85 L 238.39 10.85 L 253.39 10.85 L 268.10 10.85 L 282.45 10.85 L 296.35 10.85 L 309.73 10.85 L 322.51 10.85 L 334.60 10.85 L 345.92 10.85 L 356.39 10.85 L 365.94 10.85 L 374.48 10.85 L 381.92 10.85 L 388.20 10.85 L 393.23 10.85 L 396.92 10.85 L 399.21 10.85 L 400.00 10.85 L 400.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="407.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="207.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(600px);"></line> >>>> Animation with start and end delay WebAnimation -<g style="transform: translateX(3.28px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="663.81" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.03 10.85 L 1.39 10.85 L 5.19 10.85 L 11.32 10.85 L 19.62 10.85 L 29.97 10.85 L 42.25 10.85 L 56.31 10.85 L 72.02 10.85 L 89.25 10.85 L 107.87 10.85 L 127.75 10.85 L 148.75 10.85 L 170.74 10.85 L 193.59 10.85 L 217.17 10.85 L 241.34 10.85 L 265.98 10.85 L 290.94 10.85 L 316.10 10.85 L 341.33 10.85 L 366.49 10.85 L 391.44 10.85 L 416.07 10.85 L 440.23 10.85 L 463.79 10.85 L 486.62 10.85 L 508.59 10.85 L 529.57 10.85 L 549.42 10.85 L 568.01 10.85 L 585.21 10.85 L 600.88 10.85 L 614.90 10.85 L 627.13 10.85 L 637.44 10.85 L 645.70 10.85 L 651.76 10.85 L 655.51 10.85 L 656.81 10.85 L 656.81 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="663.81" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="10.28" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="13.57" style="stroke: black; transform: translateX(660.1px);"></line> +<g style="transform: translateX(4.95px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="16.90" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.00 10.85 L 0.02 10.85 L 0.08 10.85 L 0.17 10.85 L 0.30 10.85 L 0.45 10.85 L 0.64 10.85 L 0.85 10.85 L 1.09 10.85 L 1.35 10.85 L 1.63 10.85 L 1.93 10.85 L 2.24 10.85 L 2.57 10.85 L 2.92 10.85 L 3.27 10.85 L 3.64 10.85 L 4.01 10.85 L 4.39 10.85 L 4.77 10.85 L 5.15 10.85 L 5.52 10.85 L 5.90 10.85 L 6.27 10.85 L 6.64 10.85 L 6.99 10.85 L 7.34 10.85 L 7.67 10.85 L 7.98 10.85 L 8.28 10.85 L 8.56 10.85 L 8.82 10.85 L 9.06 10.85 L 9.27 10.85 L 9.45 10.85 L 9.61 10.85 L 9.73 10.85 L 9.82 10.85 L 9.88 10.85 L 9.90 10.85 L 9.90 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="16.90" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="11.95" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(14.85px);"></line> +WebAnimation + +<g style="transform: translateX(4.95px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="997.10" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.05 10.85 L 2.09 10.85 L 7.83 10.85 L 17.06 10.85 L 29.58 10.85 L 45.18 10.85 L 63.68 10.85 L 84.88 10.85 L 108.56 10.85 L 134.54 10.85 L 162.61 10.85 L 192.57 10.85 L 224.23 10.85 L 257.38 10.85 L 291.83 10.85 L 327.37 10.85 L 363.81 10.85 L 400.94 10.85 L 438.57 10.85 L 476.50 10.85 L 514.53 10.85 L 552.45 10.85 L 590.07 10.85 L 627.19 10.85 L 663.61 10.85 L 699.13 10.85 L 733.55 10.85 L 766.67 10.85 L 798.29 10.85 L 828.21 10.85 L 856.23 10.85 L 882.16 10.85 L 905.79 10.85 L 926.92 10.85 L 945.36 10.85 L 960.89 10.85 L 973.34 10.85 L 982.49 10.85 L 988.14 10.85 L 990.10 10.85 L 990.10 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="997.10" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="11.95" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="16.90" style="stroke: black; transform: translateX(995.05px);"></line> >>>> Animation with step timing function WebAnimation -<g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.03 10.85 L 1.41 10.85 L 5.27 10.85 L 11.49 10.85 L 19.91 10.85 L 30.42 10.85 L 42.88 10.85 L 57.15 10.85 L 73.10 10.85 L 90.59 10.85 L 109.49 10.85 L 129.66 10.85 L 150.98 10.85 L 173.30 10.85 L 196.50 10.85 L 220.43 10.85 L 244.96 10.85 L 269.97 10.85 L 295.31 10.85 L 320.84 10.85 L 346.45 10.85 L 371.98 10.85 L 397.31 10.85 L 422.31 10.85 L 446.83 10.85 L 470.75 10.85 L 493.92 10.85 L 516.22 10.85 L 537.51 10.85 L 557.66 10.85 L 576.53 10.85 L 593.99 10.85 L 609.90 10.85 L 624.13 10.85 L 636.54 10.85 L 647.00 10.85 L 655.38 10.85 L 661.54 10.85 L 665.35 10.85 L 666.67 10.85 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line> +<g style="transform: translateX(200px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.85 10.85 L 3.16 10.85 L 6.89 10.85 L 11.95 10.85 L 18.25 10.85 L 25.73 10.85 L 34.29 10.85 L 43.86 10.85 L 54.35 10.85 L 65.69 10.85 L 77.80 10.85 L 90.59 10.85 L 103.98 10.85 L 117.90 10.85 L 132.26 10.85 L 146.98 10.85 L 161.98 10.85 L 177.18 10.85 L 192.51 10.85 L 207.87 10.85 L 223.19 10.85 L 238.39 10.85 L 253.39 10.85 L 268.10 10.85 L 282.45 10.85 L 296.35 10.85 L 309.73 10.85 L 322.51 10.85 L 334.60 10.85 L 345.92 10.85 L 356.39 10.85 L 365.94 10.85 L 374.48 10.85 L 381.92 10.85 L 388.20 10.85 L 393.23 10.85 L 396.92 10.85 L 399.21 10.85 L 400.00 10.85 L 400.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="407.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="207.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(600px);"></line> +WebAnimation + +<g style="transform: translateX(200px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="40007.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 1.84 10.85 L 84.56 10.85 L 316.34 10.85 L 689.13 10.85 L 1194.84 10.85 L 1825.44 10.85 L 2572.84 10.85 L 3429.00 10.85 L 4385.84 10.85 L 5435.31 10.85 L 6569.34 10.85 L 7779.87 10.85 L 9058.84 10.85 L 10398.19 10.85 L 11789.84 10.85 L 13225.75 10.85 L 14697.84 10.85 L 16198.06 10.85 L 17718.34 10.85 L 19250.63 10.85 L 20786.84 10.85 L 22318.94 10.85 L 23838.84 10.85 L 25338.50 10.85 L 26809.84 10.85 L 28244.81 10.85 L 29635.34 10.85 L 30973.38 10.85 L 32250.84 10.85 L 33459.69 10.85 L 34591.84 10.85 L 35639.25 10.85 L 36593.84 10.85 L 37447.56 10.85 L 38192.34 10.85 L 38820.13 10.85 L 39322.84 10.85 L 39692.44 10.85 L 39920.84 10.85 L 40000.00 10.85 L 40000.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="40007.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="207.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black; transform: translateX(1000px);"></line> +WebAnimation + +<g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.85 10.85 L 3.16 10.85 L 6.89 10.85 L 11.95 10.85 L 18.25 10.85 L 25.73 10.85 L 34.29 10.85 L 43.86 10.85 L 54.35 10.85 L 65.69 10.85 L 77.80 10.85 L 90.59 10.85 L 103.98 10.85 L 117.90 10.85 L 132.26 10.85 L 146.98 10.85 L 161.98 10.85 L 177.18 10.85 L 192.51 10.85 L 207.87 10.85 L 223.19 10.85 L 238.39 10.85 L 253.39 10.85 L 268.10 10.85 L 282.45 10.85 L 296.35 10.85 L 309.73 10.85 L 322.51 10.85 L 334.60 10.85 L 345.92 10.85 L 356.39 10.85 L 365.94 10.85 L 374.48 10.85 L 381.92 10.85 L 388.20 10.85 L 393.23 10.85 L 396.92 10.85 L 399.21 10.85 L 400.00 10.85 L 400.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="407.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(400px);"></line> >>>> CSS animation started +WebAnimation + +<g style="transform: translateX(200px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.85 10.85 L 3.16 10.85 L 6.89 10.85 L 11.95 10.85 L 18.25 10.85 L 25.73 10.85 L 34.29 10.85 L 43.86 10.85 L 54.35 10.85 L 65.69 10.85 L 77.80 10.85 L 90.59 10.85 L 103.98 10.85 L 117.90 10.85 L 132.26 10.85 L 146.98 10.85 L 161.98 10.85 L 177.18 10.85 L 192.51 10.85 L 207.87 10.85 L 223.19 10.85 L 238.39 10.85 L 253.39 10.85 L 268.10 10.85 L 282.45 10.85 L 296.35 10.85 L 309.73 10.85 L 322.51 10.85 L 334.60 10.85 L 345.92 10.85 L 356.39 10.85 L 365.94 10.85 L 374.48 10.85 L 381.92 10.85 L 388.20 10.85 L 393.23 10.85 L 396.92 10.85 L 399.21 10.85 L 400.00 10.85 L 400.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="407.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="207.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(600px);"></line> +WebAnimation + +<g style="transform: translateX(200px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="40007.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 1.84 10.85 L 84.56 10.85 L 316.34 10.85 L 689.13 10.85 L 1194.84 10.85 L 1825.44 10.85 L 2572.84 10.85 L 3429.00 10.85 L 4385.84 10.85 L 5435.31 10.85 L 6569.34 10.85 L 7779.87 10.85 L 9058.84 10.85 L 10398.19 10.85 L 11789.84 10.85 L 13225.75 10.85 L 14697.84 10.85 L 16198.06 10.85 L 17718.34 10.85 L 19250.63 10.85 L 20786.84 10.85 L 22318.94 10.85 L 23838.84 10.85 L 25338.50 10.85 L 26809.84 10.85 L 28244.81 10.85 L 29635.34 10.85 L 30973.38 10.85 L 32250.84 10.85 L 33459.69 10.85 L 34591.84 10.85 L 35639.25 10.85 L 36593.84 10.85 L 37447.56 10.85 L 38192.34 10.85 L 38820.13 10.85 L 39322.84 10.85 L 39692.44 10.85 L 39920.84 10.85 L 40000.00 10.85 L 40000.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="40007.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="207.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black; transform: translateX(1000px);"></line> +WebAnimation + +<g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.85 10.85 L 3.16 10.85 L 6.89 10.85 L 11.95 10.85 L 18.25 10.85 L 25.73 10.85 L 34.29 10.85 L 43.86 10.85 L 54.35 10.85 L 65.69 10.85 L 77.80 10.85 L 90.59 10.85 L 103.98 10.85 L 117.90 10.85 L 132.26 10.85 L 146.98 10.85 L 161.98 10.85 L 177.18 10.85 L 192.51 10.85 L 207.87 10.85 L 223.19 10.85 L 238.39 10.85 L 253.39 10.85 L 268.10 10.85 L 282.45 10.85 L 296.35 10.85 L 309.73 10.85 L 322.51 10.85 L 334.60 10.85 L 345.92 10.85 L 356.39 10.85 L 365.94 10.85 L 374.48 10.85 L 381.92 10.85 L 388.20 10.85 L 393.23 10.85 L 396.92 10.85 L 399.21 10.85 L 400.00 10.85 L 400.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="407.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(400px);"></line> CSSAnimation anim -<g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.52 24.97 L 21.68 22.90 L 42.20 20.86 L 62.11 18.88 L 81.45 16.99 L 100.24 15.22 L 118.53 13.59 L 136.34 12.11 L 153.72 10.79 L 170.70 9.63 L 187.31 8.62 L 203.59 7.75 L 219.57 7.02 L 235.29 6.41 L 250.79 5.91 L 266.09 5.51 L 281.23 5.20 L 296.26 4.97 L 311.20 4.83 L 326.08 4.76 L 340.95 4.76 L 355.83 4.83 L 370.77 4.97 L 385.80 5.20 L 400.95 5.51 L 416.26 5.91 L 431.76 6.41 L 447.48 7.02 L 463.47 7.75 L 479.76 8.62 L 496.38 9.63 L 513.36 10.79 L 530.75 12.11 L 548.58 13.59 L 566.87 15.22 L 585.68 16.99 L 605.03 18.88 L 624.95 20.86 L 645.48 22.90 L 666.67 24.97 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line> +<g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="607.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.47 24.97 L 19.52 22.90 L 37.98 20.86 L 55.90 18.88 L 73.30 16.99 L 90.22 15.22 L 106.67 13.59 L 122.71 12.11 L 138.35 10.79 L 153.63 9.63 L 168.58 8.62 L 183.23 7.75 L 197.61 7.02 L 211.76 6.41 L 225.71 5.91 L 239.48 5.51 L 253.11 5.20 L 266.63 4.97 L 280.08 4.83 L 293.47 4.76 L 306.85 4.76 L 320.25 4.83 L 333.70 4.97 L 347.22 5.20 L 360.85 5.51 L 374.63 5.91 L 388.58 6.41 L 402.73 7.02 L 417.12 7.75 L 431.78 8.62 L 446.74 9.63 L 462.03 10.79 L 477.68 12.11 L 493.72 13.59 L 510.19 15.22 L 527.11 16.99 L 544.52 18.88 L 562.45 20.86 L 580.94 22.90 L 600.00 24.97 L 600.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="607.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(600px);"></line> >>>> CSS transition started +WebAnimation + +<g style="transform: translateX(200px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.85 10.85 L 3.16 10.85 L 6.89 10.85 L 11.95 10.85 L 18.25 10.85 L 25.73 10.85 L 34.29 10.85 L 43.86 10.85 L 54.35 10.85 L 65.69 10.85 L 77.80 10.85 L 90.59 10.85 L 103.98 10.85 L 117.90 10.85 L 132.26 10.85 L 146.98 10.85 L 161.98 10.85 L 177.18 10.85 L 192.51 10.85 L 207.87 10.85 L 223.19 10.85 L 238.39 10.85 L 253.39 10.85 L 268.10 10.85 L 282.45 10.85 L 296.35 10.85 L 309.73 10.85 L 322.51 10.85 L 334.60 10.85 L 345.92 10.85 L 356.39 10.85 L 365.94 10.85 L 374.48 10.85 L 381.92 10.85 L 388.20 10.85 L 393.23 10.85 L 396.92 10.85 L 399.21 10.85 L 400.00 10.85 L 400.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="407.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="207.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(600px);"></line> +WebAnimation + +<g style="transform: translateX(200px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="40007.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 1.84 10.85 L 84.56 10.85 L 316.34 10.85 L 689.13 10.85 L 1194.84 10.85 L 1825.44 10.85 L 2572.84 10.85 L 3429.00 10.85 L 4385.84 10.85 L 5435.31 10.85 L 6569.34 10.85 L 7779.87 10.85 L 9058.84 10.85 L 10398.19 10.85 L 11789.84 10.85 L 13225.75 10.85 L 14697.84 10.85 L 16198.06 10.85 L 17718.34 10.85 L 19250.63 10.85 L 20786.84 10.85 L 22318.94 10.85 L 23838.84 10.85 L 25338.50 10.85 L 26809.84 10.85 L 28244.81 10.85 L 29635.34 10.85 L 30973.38 10.85 L 32250.84 10.85 L 33459.69 10.85 L 34591.84 10.85 L 35639.25 10.85 L 36593.84 10.85 L 37447.56 10.85 L 38192.34 10.85 L 38820.13 10.85 L 39322.84 10.85 L 39692.44 10.85 L 39920.84 10.85 L 40000.00 10.85 L 40000.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="40007.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="207.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black; transform: translateX(1000px);"></line> +WebAnimation + +<g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="407.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 10.85 L 0.85 10.85 L 3.16 10.85 L 6.89 10.85 L 11.95 10.85 L 18.25 10.85 L 25.73 10.85 L 34.29 10.85 L 43.86 10.85 L 54.35 10.85 L 65.69 10.85 L 77.80 10.85 L 90.59 10.85 L 103.98 10.85 L 117.90 10.85 L 132.26 10.85 L 146.98 10.85 L 161.98 10.85 L 177.18 10.85 L 192.51 10.85 L 207.87 10.85 L 223.19 10.85 L 238.39 10.85 L 253.39 10.85 L 268.10 10.85 L 282.45 10.85 L 296.35 10.85 L 309.73 10.85 L 322.51 10.85 L 334.60 10.85 L 345.92 10.85 L 356.39 10.85 L 365.94 10.85 L 374.48 10.85 L 381.92 10.85 L 388.20 10.85 L 393.23 10.85 L 396.92 10.85 L 399.21 10.85 L 400.00 10.85 L 400.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="407.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(400px);"></line> +CSSAnimation +anim +<g style="transform: translateX(0px);"><g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="607.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.47 24.97 L 19.52 22.90 L 37.98 20.86 L 55.90 18.88 L 73.30 16.99 L 90.22 15.22 L 106.67 13.59 L 122.71 12.11 L 138.35 10.79 L 153.63 9.63 L 168.58 8.62 L 183.23 7.75 L 197.61 7.02 L 211.76 6.41 L 225.71 5.91 L 239.48 5.51 L 253.11 5.20 L 266.63 4.97 L 280.08 4.83 L 293.47 4.76 L 306.85 4.76 L 320.25 4.83 L 333.70 4.97 L 347.22 5.20 L 360.85 5.51 L 374.63 5.91 L 388.58 6.41 L 402.73 7.02 L 417.12 7.75 L 431.78 8.62 L 446.74 9.63 L 462.03 10.79 L 477.68 12.11 L 493.72 13.59 L 510.19 15.22 L 527.11 16.99 L 544.52 18.88 L 562.45 20.86 L 580.94 22.90 L 600.00 24.97 L 600.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="607.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><g class="animation-tail-iterations"></g></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(600px);"></line> CSSTransition background-color -<g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="673.67" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.02 0.00 L 0.71 0.00 L 2.69 0.00 L 5.90 0.02 L 10.33 0.11 L 15.93 0.31 L 22.68 0.66 L 30.54 1.15 L 39.47 1.76 L 49.44 2.45 L 60.43 3.21 L 72.38 4.00 L 85.28 4.82 L 99.09 5.64 L 113.77 6.47 L 129.29 7.29 L 145.62 8.10 L 162.73 8.90 L 180.57 9.69 L 199.12 10.46 L 218.34 11.23 L 238.20 11.98 L 258.66 12.72 L 279.70 13.46 L 301.28 14.19 L 323.36 14.91 L 345.91 15.63 L 368.90 16.35 L 392.29 17.08 L 416.06 17.80 L 440.16 18.53 L 464.56 19.26 L 489.23 20.01 L 514.14 20.76 L 539.25 21.52 L 564.53 22.30 L 589.95 23.09 L 615.46 23.90 L 641.05 24.72 L 666.67 25.57 L 666.67 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="673.67" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(666.67px);"></line> +<g style="transform: translateX(0px);"><line class="animation-line" x1="7" y1="26" y2="26" x2="307.00" style="stroke: black;"></line><path class="animation-keyframe" d="M 0 26 L 0.01 0.00 L 0.32 0.00 L 1.21 0.00 L 2.66 0.02 L 4.65 0.11 L 7.17 0.31 L 10.21 0.66 L 13.74 1.15 L 17.76 1.76 L 22.25 2.45 L 27.19 3.21 L 32.57 4.00 L 38.38 4.82 L 44.59 5.64 L 51.20 6.47 L 58.18 7.29 L 65.53 8.10 L 73.23 8.90 L 81.26 9.69 L 89.60 10.46 L 98.25 11.23 L 107.19 11.98 L 116.40 12.72 L 125.87 13.46 L 135.58 14.19 L 145.51 14.91 L 155.66 15.63 L 166.00 16.35 L 176.53 17.08 L 187.23 17.80 L 198.07 18.53 L 209.05 19.26 L 220.15 20.01 L 231.36 20.76 L 242.66 21.52 L 254.04 22.30 L 265.48 23.09 L 276.96 23.90 L 288.47 24.72 L 300.00 25.57 L 300.00 26 Z" style="transform: translateX(7px); fill: black;"></path><circle class="animation-endpoint" cx="7.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle><circle class="animation-endpoint" cx="307.00" cy="26" r="3.5" style="stroke: black; fill: black;"></circle></g><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black;"></line><line class="animation-delay-line" x1="7" y1="26" y2="26" x2="7.00" style="stroke: black; transform: translateX(300px);"></line>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-001-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-001-expected.png deleted file mode 100644 index 2484a83..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-001-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-001-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-001-expected.txt deleted file mode 100644 index 2f7b355..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-001-expected.txt +++ /dev/null
@@ -1,32 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {DIV} at (0,0) size 784x210 [border: (2px solid #0000FF)] - LayoutBlockFlow {DIV} at (14,14) size 756x55 - LayoutText {#text} at (0,0) size 64x26 - text run at (0,0) width 64: "Tests: " - LayoutBR {BR} at (0,0) size 0x0 - LayoutText {#text} at (0,27) size 489x27 - text run at (0,27) width 489: "Smart delete when deleting the first word on a line." - LayoutBlockFlow {DIV} at (14,85) size 756x111 - LayoutText {#text} at (0,0) size 189x26 - text run at (0,0) width 189: "Expected Results: " - LayoutBR {BR} at (189,21) size 0x0 - LayoutText {#text} at (0,27) size 705x55 - text run at (0,27) width 705: "The first word and the space following the first word should be deleted. It" - text run at (0,55) width 196: "should like this this: " - LayoutBR {BR} at (196,76) size 0x0 - LayoutText {#text} at (0,83) size 70x27 - text run at (0,83) width 70: "bar baz" - LayoutBlockFlow {DIV} at (0,234) size 784x32 - LayoutBlockFlow {DIV} at (0,0) size 784x32 [border: (2px solid #FF0000)] - LayoutText {#text} at (2,2) size 70x27 - text run at (2,2) width 70: "bar baz" -caret: position 0 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-002-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-002-expected.png deleted file mode 100644 index 51987bf5..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-002-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-002-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-002-expected.txt deleted file mode 100644 index fd16889a..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/deleting/smart-delete-002-expected.txt +++ /dev/null
@@ -1,34 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {DIV} at (0,0) size 784x210 [border: (2px solid #0000FF)] - LayoutBlockFlow {DIV} at (14,14) size 756x55 - LayoutText {#text} at (0,0) size 64x26 - text run at (0,0) width 64: "Tests: " - LayoutBR {BR} at (0,0) size 0x0 - LayoutText {#text} at (0,27) size 514x27 - text run at (0,27) width 514: "Smart delete when deleting the second word of a line." - LayoutBlockFlow {DIV} at (14,85) size 756x111 - LayoutText {#text} at (0,0) size 189x26 - text run at (0,0) width 189: "Expected Results: " - LayoutBR {BR} at (189,21) size 0x0 - LayoutText {#text} at (0,27) size 735x55 - text run at (0,27) width 735: "The second word and the space before the second word should be deleted. It" - text run at (0,55) width 196: "should like this this: " - LayoutBR {BR} at (196,76) size 0x0 - LayoutText {#text} at (0,83) size 71x27 - text run at (0,83) width 71: "foo baz" - LayoutBlockFlow {DIV} at (0,234) size 784x32 - LayoutBlockFlow {DIV} at (0,0) size 784x32 [border: (2px solid #FF0000)] - LayoutText {#text} at (2,2) size 71x27 - text run at (2,2) width 71: "foo baz" -caret: position 4 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-001-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-001-expected.png deleted file mode 100644 index ca2bb3a..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-001-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-001-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-001-expected.txt deleted file mode 100644 index c014053..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-001-expected.txt +++ /dev/null
@@ -1,32 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {DIV} at (0,0) size 784x212 [border: (2px solid #0000FF)] - LayoutBlockFlow {DIV} at (14,14) size 756x56 - LayoutText {#text} at (0,0) size 66x28 - text run at (0,0) width 66: "Tests: " - LayoutBR {BR} at (0,0) size 0x0 - LayoutText {#text} at (0,28) size 491x28 - text run at (0,28) width 491: "Smart delete when deleting the first word on a line." - LayoutBlockFlow {DIV} at (14,86) size 756x112 - LayoutText {#text} at (0,0) size 190x28 - text run at (0,0) width 190: "Expected Results: " - LayoutBR {BR} at (189,22) size 1x0 - LayoutText {#text} at (0,28) size 706x56 - text run at (0,28) width 706: "The first word and the space following the first word should be deleted. It" - text run at (0,56) width 201: "should like this this: " - LayoutBR {BR} at (200,78) size 1x0 - LayoutText {#text} at (0,84) size 70x28 - text run at (0,84) width 70: "bar baz" - LayoutBlockFlow {DIV} at (0,236) size 784x32 - LayoutBlockFlow {DIV} at (0,0) size 784x32 [border: (2px solid #FF0000)] - LayoutText {#text} at (2,2) size 70x28 - text run at (2,2) width 70: "bar baz" -caret: position 0 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-002-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-002-expected.png deleted file mode 100644 index d812b8a..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-002-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-002-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-002-expected.txt deleted file mode 100644 index 79054d9a..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/deleting/smart-delete-002-expected.txt +++ /dev/null
@@ -1,34 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {DIV} at (0,0) size 784x212 [border: (2px solid #0000FF)] - LayoutBlockFlow {DIV} at (14,14) size 756x56 - LayoutText {#text} at (0,0) size 66x28 - text run at (0,0) width 66: "Tests: " - LayoutBR {BR} at (0,0) size 0x0 - LayoutText {#text} at (0,28) size 516x28 - text run at (0,28) width 516: "Smart delete when deleting the second word of a line." - LayoutBlockFlow {DIV} at (14,86) size 756x112 - LayoutText {#text} at (0,0) size 190x28 - text run at (0,0) width 190: "Expected Results: " - LayoutBR {BR} at (189,22) size 1x0 - LayoutText {#text} at (0,28) size 732x56 - text run at (0,28) width 732: "The second word and the space before the second word should be deleted. It" - text run at (0,56) width 201: "should like this this: " - LayoutBR {BR} at (200,78) size 1x0 - LayoutText {#text} at (0,84) size 72x28 - text run at (0,84) width 72: "foo baz" - LayoutBlockFlow {DIV} at (0,236) size 784x32 - LayoutBlockFlow {DIV} at (0,0) size 784x32 [border: (2px solid #FF0000)] - LayoutText {#text} at (2,2) size 72x28 - text run at (2,2) width 72: "foo baz" -caret: position 4 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-001-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-001-expected.png deleted file mode 100644 index a7cc9a56f..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-001-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-001-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-001-expected.txt deleted file mode 100644 index c5d5216..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-001-expected.txt +++ /dev/null
@@ -1,32 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {DIV} at (0,0) size 784x210 [border: (2px solid #0000FF)] - LayoutBlockFlow {DIV} at (14,14) size 756x55 - LayoutText {#text} at (0,0) size 66x26 - text run at (0,0) width 66: "Tests: " - LayoutBR {BR} at (0,0) size 0x0 - LayoutText {#text} at (0,27) size 489x27 - text run at (0,27) width 489: "Smart delete when deleting the first word on a line." - LayoutBlockFlow {DIV} at (14,85) size 756x111 - LayoutText {#text} at (0,0) size 189x26 - text run at (0,0) width 189: "Expected Results: " - LayoutBR {BR} at (189,21) size 0x0 - LayoutText {#text} at (0,27) size 705x55 - text run at (0,27) width 705: "The first word and the space following the first word should be deleted. It" - text run at (0,55) width 196: "should like this this: " - LayoutBR {BR} at (196,76) size 0x0 - LayoutText {#text} at (0,83) size 70x27 - text run at (0,83) width 70: "bar baz" - LayoutBlockFlow {DIV} at (0,234) size 784x32 - LayoutBlockFlow {DIV} at (0,0) size 784x32 [border: (2px solid #FF0000)] - LayoutText {#text} at (2,2) size 70x27 - text run at (2,2) width 70: "bar baz" -caret: position 0 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-002-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-002-expected.png deleted file mode 100644 index e0c9fce..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-002-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-002-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-002-expected.txt deleted file mode 100644 index a2842f0e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/deleting/smart-delete-002-expected.txt +++ /dev/null
@@ -1,34 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {DIV} at (0,0) size 784x210 [border: (2px solid #0000FF)] - LayoutBlockFlow {DIV} at (14,14) size 756x55 - LayoutText {#text} at (0,0) size 66x26 - text run at (0,0) width 66: "Tests: " - LayoutBR {BR} at (0,0) size 0x0 - LayoutText {#text} at (0,27) size 514x27 - text run at (0,27) width 514: "Smart delete when deleting the second word of a line." - LayoutBlockFlow {DIV} at (14,85) size 756x111 - LayoutText {#text} at (0,0) size 189x26 - text run at (0,0) width 189: "Expected Results: " - LayoutBR {BR} at (189,21) size 0x0 - LayoutText {#text} at (0,27) size 735x55 - text run at (0,27) width 735: "The second word and the space before the second word should be deleted. It" - text run at (0,55) width 196: "should like this this: " - LayoutBR {BR} at (196,76) size 0x0 - LayoutText {#text} at (0,83) size 71x27 - text run at (0,83) width 71: "foo baz" - LayoutBlockFlow {DIV} at (0,234) size 784x32 - LayoutBlockFlow {DIV} at (0,0) size 784x32 [border: (2px solid #FF0000)] - LayoutText {#text} at (2,2) size 71x27 - text run at (2,2) width 71: "foo baz" -caret: position 5 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-001-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-001-expected.png deleted file mode 100644 index 1f1f53e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-001-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-001-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-001-expected.txt deleted file mode 100644 index 4ec15cf..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-001-expected.txt +++ /dev/null
@@ -1,32 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {DIV} at (0,0) size 784x206 [border: (2px solid #0000FF)] - LayoutBlockFlow {DIV} at (14,14) size 756x54 - LayoutText {#text} at (0,0) size 66x26 - text run at (0,0) width 66: "Tests: " - LayoutBR {BR} at (0,0) size 0x0 - LayoutText {#text} at (0,27) size 492x26 - text run at (0,27) width 492: "Smart delete when deleting the first word on a line." - LayoutBlockFlow {DIV} at (14,84) size 756x108 - LayoutText {#text} at (0,0) size 190x26 - text run at (0,0) width 190: "Expected Results: " - LayoutBR {BR} at (189,21) size 1x0 - LayoutText {#text} at (0,27) size 708x53 - text run at (0,27) width 708: "The first word and the space following the first word should be deleted. It" - text run at (0,54) width 201: "should like this this: " - LayoutBR {BR} at (200,75) size 1x0 - LayoutText {#text} at (0,81) size 70x26 - text run at (0,81) width 70: "bar baz" - LayoutBlockFlow {DIV} at (0,230) size 784x31 - LayoutBlockFlow {DIV} at (0,0) size 784x31 [border: (2px solid #FF0000)] - LayoutText {#text} at (2,2) size 70x26 - text run at (2,2) width 70: "bar baz" -caret: position 0 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-002-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-002-expected.png deleted file mode 100644 index 263cd867..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-002-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-002-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-002-expected.txt deleted file mode 100644 index e80bd68..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/deleting/smart-delete-002-expected.txt +++ /dev/null
@@ -1,34 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {DIV} at (0,0) size 784x206 [border: (2px solid #0000FF)] - LayoutBlockFlow {DIV} at (14,14) size 756x54 - LayoutText {#text} at (0,0) size 66x26 - text run at (0,0) width 66: "Tests: " - LayoutBR {BR} at (0,0) size 0x0 - LayoutText {#text} at (0,27) size 516x26 - text run at (0,27) width 516: "Smart delete when deleting the second word of a line." - LayoutBlockFlow {DIV} at (14,84) size 756x108 - LayoutText {#text} at (0,0) size 190x26 - text run at (0,0) width 190: "Expected Results: " - LayoutBR {BR} at (189,21) size 1x0 - LayoutText {#text} at (0,27) size 732x53 - text run at (0,27) width 732: "The second word and the space before the second word should be deleted. It" - text run at (0,54) width 201: "should like this this: " - LayoutBR {BR} at (200,75) size 1x0 - LayoutText {#text} at (0,81) size 72x26 - text run at (0,81) width 72: "foo baz" - LayoutBlockFlow {DIV} at (0,230) size 784x31 - LayoutBlockFlow {DIV} at (0,0) size 784x31 [border: (2px solid #FF0000)] - LayoutText {#text} at (2,2) size 72x26 - text run at (2,2) width 72: "foo baz" -caret: position 5 of child 0 {#text} of child 1 {DIV} of child 3 {DIV} of body
diff --git a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt index 3d44613..81f6967 100644 --- a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt +++ b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt
@@ -36,7 +36,7 @@ ActiveDOMObject CachedAttribute=* CallWith=ExecutionContext|ScriptState|ScriptArguments|ActiveWindow|FirstWindow|ThisValue -CheckSecurity=Frame|Node|Window +CheckSecurity=Receiver|ReturnValue Clamp Conditional=* Constructor
diff --git a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp index 9654ddf..bbbace5b 100644 --- a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp
@@ -41,13 +41,15 @@ namespace blink { -static bool isOriginAccessibleFromDOMWindow(SecurityOrigin* targetOrigin, LocalDOMWindow* accessingWindow) +static bool isOriginAccessibleFromDOMWindow(const SecurityOrigin* targetOrigin, const LocalDOMWindow* accessingWindow) { return accessingWindow && accessingWindow->document()->securityOrigin()->canAccessCheckSuborigins(targetOrigin); } -static bool canAccessFrame(v8::Isolate* isolate, LocalDOMWindow* accessingWindow, SecurityOrigin* targetFrameOrigin, DOMWindow* targetWindow, ExceptionState& exceptionState) +static bool canAccessFrame(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const SecurityOrigin* targetFrameOrigin, const DOMWindow* targetWindow, ExceptionState& exceptionState) { + ASSERT_WITH_SECURITY_IMPLICATION(!(targetWindow && targetWindow->frame()) || targetWindow == targetWindow->frame()->domWindow()); + if (isOriginAccessibleFromDOMWindow(targetFrameOrigin, accessingWindow)) return true; @@ -56,8 +58,10 @@ return false; } -static bool canAccessFrame(v8::Isolate* isolate, LocalDOMWindow* accessingWindow, SecurityOrigin* targetFrameOrigin, DOMWindow* targetWindow, SecurityReportingOption reportingOption = ReportSecurityError) +static bool canAccessFrame(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, SecurityOrigin* targetFrameOrigin, const DOMWindow* targetWindow, SecurityReportingOption reportingOption = ReportSecurityError) { + ASSERT_WITH_SECURITY_IMPLICATION(!(targetWindow && targetWindow->frame()) || targetWindow == targetWindow->frame()->domWindow()); + if (isOriginAccessibleFromDOMWindow(targetFrameOrigin, accessingWindow)) return true; @@ -66,28 +70,77 @@ return false; } -bool BindingSecurity::shouldAllowAccessToFrame(v8::Isolate* isolate, LocalDOMWindow* accessingWindow, Frame* target, SecurityReportingOption reportingOption) +bool BindingSecurity::shouldAllowAccessTo(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const DOMWindow* target, ExceptionState& exceptionState) +{ + ASSERT(target); + const Frame* frame = target->frame(); + if (!frame || !frame->securityContext()) + return false; + return canAccessFrame(isolate, accessingWindow, frame->securityContext()->securityOrigin(), target, exceptionState); +} + +bool BindingSecurity::shouldAllowAccessTo(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const DOMWindow* target, SecurityReportingOption reportingOption) +{ + ASSERT(target); + const Frame* frame = target->frame(); + if (!frame || !frame->securityContext()) + return false; + return canAccessFrame(isolate, accessingWindow, frame->securityContext()->securityOrigin(), target, reportingOption); +} + +bool BindingSecurity::shouldAllowAccessTo(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const EventTarget* target, ExceptionState& exceptionState) +{ + ASSERT(target); + const DOMWindow* window = target->toDOMWindow(); + if (!window) { + // We only need to check the access to Window objects which are + // cross-origin accessible. If it's not a Window, the object's + // origin must always be the same origin (or it already leaked). + return true; + } + const Frame* frame = window->frame(); + if (!frame || !frame->securityContext()) + return false; + return canAccessFrame(isolate, accessingWindow, frame->securityContext()->securityOrigin(), window, exceptionState); +} + +bool BindingSecurity::shouldAllowAccessTo(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const Location* target, ExceptionState& exceptionState) +{ + ASSERT(target); + const Frame* frame = target->frame(); + if (!frame || !frame->securityContext()) + return false; + return canAccessFrame(isolate, accessingWindow, frame->securityContext()->securityOrigin(), frame->domWindow(), exceptionState); +} + +bool BindingSecurity::shouldAllowAccessTo(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const Location* target, SecurityReportingOption reportingOption) +{ + ASSERT(target); + const Frame* frame = target->frame(); + if (!frame || !frame->securityContext()) + return false; + return canAccessFrame(isolate, accessingWindow, frame->securityContext()->securityOrigin(), frame->domWindow(), reportingOption); +} + +bool BindingSecurity::shouldAllowAccessTo(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const Node* target, ExceptionState& exceptionState) +{ + if (!target) + return false; + return canAccessFrame(isolate, accessingWindow, target->document().securityOrigin(), target->document().domWindow(), exceptionState); +} + +bool BindingSecurity::shouldAllowAccessTo(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const Node* target, SecurityReportingOption reportingOption) +{ + if (!target) + return false; + return canAccessFrame(isolate, accessingWindow, target->document().securityOrigin(), target->document().domWindow(), reportingOption); +} + +bool BindingSecurity::shouldAllowAccessToFrame(v8::Isolate* isolate, const LocalDOMWindow* accessingWindow, const Frame* target, SecurityReportingOption reportingOption) { if (!target || !target->securityContext()) return false; return canAccessFrame(isolate, accessingWindow, target->securityContext()->securityOrigin(), target->domWindow(), reportingOption); } -bool BindingSecurity::shouldAllowAccessToFrame(v8::Isolate* isolate, LocalDOMWindow* accessingWindow, Frame* target, ExceptionState& exceptionState) -{ - if (!target || !target->securityContext()) - return false; - return canAccessFrame(isolate, accessingWindow, target->securityContext()->securityOrigin(), target->domWindow(), exceptionState); -} - -bool BindingSecurity::shouldAllowAccessToNode(v8::Isolate* isolate, LocalDOMWindow* accessingWindow, Node* target, SecurityReportingOption reportingOption) -{ - return target && canAccessFrame(isolate, accessingWindow, target->document().securityOrigin(), target->document().domWindow(), reportingOption); -} - -bool BindingSecurity::shouldAllowAccessToNode(v8::Isolate* isolate, LocalDOMWindow* accessingWindow, Node* target, ExceptionState& exceptionState) -{ - return target && canAccessFrame(isolate, accessingWindow, target->document().securityOrigin(), target->document().domWindow(), exceptionState); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.h b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.h index f8fbe35..85205f6 100644 --- a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.h +++ b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.h
@@ -31,16 +31,18 @@ #ifndef BindingSecurity_h #define BindingSecurity_h -// FIXME: The LocalFrame include should not be necessary, clients should be including it where they use it. #include "core/CoreExport.h" -#include "core/frame/LocalFrame.h" #include "wtf/Allocator.h" #include <v8.h> namespace blink { -class LocalDOMWindow; +class DOMWindow; +class EventTarget; class ExceptionState; +class Frame; +class LocalDOMWindow; +class Location; class Node; enum SecurityReportingOption { @@ -48,18 +50,45 @@ ReportSecurityError, }; -class BindingSecurity { +class CORE_EXPORT BindingSecurity { STATIC_ONLY(BindingSecurity); public: - // Check the access to the return value. - static bool shouldAllowAccessToNode(v8::Isolate*, LocalDOMWindow* accessingWindow, Node*, SecurityReportingOption); - static bool shouldAllowAccessToNode(v8::Isolate*, LocalDOMWindow* accessingWindow, Node*, ExceptionState&); + // Check if the caller (|accessingWindow|) is allowed to access the JS + // receiver object (|target|), where the receiver object is the JS object + // for which the DOM attribute or DOM operation is being invoked (in the + // form of receiver.domAttr or receiver.domOp()). + // Note that only Window and Location objects are cross-origin accessible + // and that EventTarget interface is the parent interface of Window + // interface. So the receiver object must be of type DOMWindow, + // EventTarget, or Location. + // + // DOMWindow + static bool shouldAllowAccessTo(v8::Isolate*, const LocalDOMWindow* accessingWindow, const DOMWindow* target, ExceptionState&); + static bool shouldAllowAccessTo(v8::Isolate*, const LocalDOMWindow* accessingWindow, const DOMWindow* target, SecurityReportingOption); + // EventTarget (as the parent of DOMWindow) + static bool shouldAllowAccessTo(v8::Isolate*, const LocalDOMWindow* accessingWindow, const EventTarget* target, ExceptionState&); // NOLINT(readability/parameter_name) + // Location + static bool shouldAllowAccessTo(v8::Isolate*, const LocalDOMWindow* accessingWindow, const Location* target, ExceptionState&); + static bool shouldAllowAccessTo(v8::Isolate*, const LocalDOMWindow* accessingWindow, const Location* target, SecurityReportingOption); + // Prefer to use the previous overloads instead of falling back to using + // Frame*. + static bool shouldAllowAccessToFrame(v8::Isolate*, const LocalDOMWindow* accessingWindow, const Frame* target, SecurityReportingOption); // OBSOLETE - // Check the access to the receiver. - CORE_EXPORT static bool shouldAllowAccessToFrame(v8::Isolate*, LocalDOMWindow* accessingWindow, Frame*, SecurityReportingOption = ReportSecurityError); - CORE_EXPORT static bool shouldAllowAccessToFrame(v8::Isolate*, LocalDOMWindow* accessingWindow, Frame*, ExceptionState&); + // Check if the caller (|accessingWindow|) is allowed to access the JS + // returned object (|target|), where the returned object is the JS object + // which is returned as a result of invoking a DOM attribute or DOM + // operation (in the form of + // var x = receiver.domAttr // or receiver.domOp() + // where |x| is the returned object). + // See window.frameElement for example, which may return a frame object. + // The object returned from window.frameElement must be the same origin if + // it's not null. + // + // Node + static bool shouldAllowAccessTo(v8::Isolate*, const LocalDOMWindow* accessingWindow, const Node* target, ExceptionState&); + static bool shouldAllowAccessTo(v8::Isolate*, const LocalDOMWindow* accessingWindow, const Node* target, SecurityReportingOption); }; -} +} // namespace blink #endif
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp index 4a354bc7..c39597d 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
@@ -89,7 +89,7 @@ if (!frame) return false; v8::Isolate* isolate = toIsolate(frame); - return !isolate->InContext() || BindingSecurity::shouldAllowAccessToFrame(isolate, callingDOMWindow(isolate), frame); + return !isolate->InContext() || BindingSecurity::shouldAllowAccessToFrame(isolate, callingDOMWindow(isolate), frame, ReportSecurityError); } ScriptController::ScriptController(LocalFrame* frame)
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp index 58528e58..2f0b950 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp
@@ -78,13 +78,9 @@ return; } EventTarget* impl = V8EventTarget::toImpl(info.Holder()); - if (LocalDOMWindow* window = impl->toDOMWindow()) { - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window->frame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } - if (!window->document()) - return; + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { + exceptionState.throwIfNeeded(); + return; } V8StringResource<> type; RefPtrWillBeRawPtr<EventListener> listener; @@ -121,13 +117,9 @@ return; } EventTarget* impl = V8EventTarget::toImpl(info.Holder()); - if (LocalDOMWindow* window = impl->toDOMWindow()) { - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window->frame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } - if (!window->document()) - return; + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { + exceptionState.throwIfNeeded(); + return; } V8StringResource<> type; RefPtrWillBeRawPtr<EventListener> listener;
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8InjectedScriptManager.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8InjectedScriptManager.cpp index c5d2934f..bb56576 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8InjectedScriptManager.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8InjectedScriptManager.cpp
@@ -83,15 +83,8 @@ if (!scriptState->contextIsValid()) return false; ScriptState::Scope scope(scriptState); - v8::Local<v8::Object> global = scriptState->context()->Global(); - if (global.IsEmpty()) - return false; - v8::Local<v8::Object> holder = V8Window::findInstanceInPrototypeChain(global, scriptState->isolate()); - if (holder.IsEmpty()) - return false; - LocalFrame* frame = toLocalDOMWindow(V8Window::toImpl(holder))->frame(); - - return BindingSecurity::shouldAllowAccessToFrame(scriptState->isolate(), callingDOMWindow(scriptState->isolate()), frame, DoNotReportSecurityError); + DOMWindow* window = toDOMWindow(scriptState->isolate(), scriptState->context()->Global()); + return window && BindingSecurity::shouldAllowAccessTo(scriptState->isolate(), callingDOMWindow(scriptState->isolate()), window, DoNotReportSecurityError); } } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp index d6a5292..794d2672 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
@@ -68,13 +68,14 @@ void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - LocalFrame* frame = toLocalDOMWindow(V8Window::toImpl(info.Holder()))->frame(); + LocalDOMWindow* impl = toLocalDOMWindow(V8Window::toImpl(info.Holder())); ExceptionState exceptionState(ExceptionState::GetterContext, "event", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), frame, exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return; } + LocalFrame* frame = impl->frame(); ASSERT(frame); // This is a fast path to retrieve info.Holder()->CreationContext(). v8::Local<v8::Context> context = toV8Context(frame, DOMWrapperWorld::current(info.GetIsolate())); @@ -89,13 +90,14 @@ void V8Window::eventAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { - LocalFrame* frame = toLocalDOMWindow(V8Window::toImpl(info.Holder()))->frame(); + LocalDOMWindow* impl = toLocalDOMWindow(V8Window::toImpl(info.Holder())); ExceptionState exceptionState(ExceptionState::SetterContext, "event", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), frame, exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return; } + LocalFrame* frame = impl->frame(); ASSERT(frame); // This is a fast path to retrieve info.Holder()->CreationContext(). v8::Local<v8::Context> context = toV8Context(frame, DOMWrapperWorld::current(info.GetIsolate())); @@ -109,7 +111,7 @@ { LocalDOMWindow* impl = toLocalDOMWindow(V8Window::toImpl(info.Holder())); - if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frameElement(), DoNotReportSecurityError)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frameElement(), DoNotReportSecurityError)) { v8SetReturnValueNull(info); return; } @@ -127,7 +129,7 @@ v8::Isolate* isolate = info.GetIsolate(); DOMWindow* impl = V8Window::toImpl(info.Holder()); ExceptionState exceptionState(ExceptionState::SetterContext, "opener", "Window", info.Holder(), isolate); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return; } @@ -233,7 +235,7 @@ { DOMWindow* impl = V8Window::toImpl(info.Holder()); ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return; } @@ -330,7 +332,7 @@ return; // This is an AllCanRead interceptor. Check that the caller has access to the named results. - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), frame, DoNotReportSecurityError)) + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window, DoNotReportSecurityError)) return; bool hasNamedItem = toHTMLDocument(doc)->hasNamedItem(propName); @@ -378,7 +380,7 @@ if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument()) target->loader().didAccessInitialDocument(); - return BindingSecurity::shouldAllowAccessToFrame(isolate, callingDOMWindow(isolate), target, DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessTo(isolate, callingDOMWindow(isolate), targetWindow, DoNotReportSecurityError); } bool V8Window::securityCheckCustom(v8::Local<v8::Context> accessingContext, v8::Local<v8::Object> accessedObject)
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_attributes.py b/third_party/WebKit/Source/bindings/scripts/v8_attributes.py index 850fb54b..6535851 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_attributes.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_attributes.py
@@ -55,15 +55,12 @@ # [CheckSecurity] is_do_not_check_security = 'DoNotCheckSecurity' in extended_attributes - is_check_security_for_frame = ( - has_extended_attribute_value(interface, 'CheckSecurity', 'Frame') and + is_check_security_for_receiver = ( + has_extended_attribute_value(interface, 'CheckSecurity', 'Receiver') and not is_do_not_check_security) - is_check_security_for_node = ( - has_extended_attribute_value(attribute, 'CheckSecurity', 'Node')) - is_check_security_for_window = ( - has_extended_attribute_value(interface, 'CheckSecurity', 'Window') and - not is_do_not_check_security) - if is_check_security_for_frame or is_check_security_for_node or is_check_security_for_window: + is_check_security_for_return_value = ( + has_extended_attribute_value(attribute, 'CheckSecurity', 'ReturnValue')) + if is_check_security_for_receiver or is_check_security_for_return_value: includes.add('bindings/core/v8/BindingSecurity.h') # [Constructor] # TODO(yukishiino): Constructors are much like methods although constructors @@ -119,9 +116,8 @@ 'idl_type': str(idl_type), # need trailing [] on array for Dictionary::ConversionContext::setConversionType 'is_call_with_execution_context': has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'), 'is_call_with_script_state': has_extended_attribute_value(attribute, 'CallWith', 'ScriptState'), - 'is_check_security_for_frame': is_check_security_for_frame, - 'is_check_security_for_node': is_check_security_for_node, - 'is_check_security_for_window': is_check_security_for_window, + 'is_check_security_for_receiver': is_check_security_for_receiver, + 'is_check_security_for_return_value': is_check_security_for_return_value, 'is_custom_element_callbacks': is_custom_element_callbacks, # TODO(yukishiino): Make all DOM attributes accessor-type properties. 'is_data_type_property': constructor_type or interface.name == 'Window' or interface.name == 'Location',
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py index fbb57bb..2ae2d22 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -564,8 +564,8 @@ context.update({ 'conditionally_enabled_methods': conditionally_enabled_methods, 'custom_registration_methods': custom_registration_methods, - 'has_origin_safe_method_setter': any( - method['is_check_security_for_frame'] and not method['is_read_only'] + 'has_origin_safe_method_setter': is_global and any( + method['is_check_security_for_receiver'] and not method['is_unforgeable'] for method in methods), 'has_private_script': any(attribute['is_implemented_in_private_script'] for attribute in attributes) or any(method['is_implemented_in_private_script'] for method in methods),
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_methods.py b/third_party/WebKit/Source/bindings/scripts/v8_methods.py index 3ac9276e..8d37950 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_methods.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_methods.py
@@ -90,23 +90,21 @@ is_call_with_this_value = has_extended_attribute_value(method, 'CallWith', 'ThisValue') if is_call_with_script_state or is_call_with_this_value: includes.add('bindings/core/v8/ScriptState.h') - is_check_security_for_node = 'CheckSecurity' in extended_attributes - if is_check_security_for_node: + + # [CheckSecurity] + is_do_not_check_security = 'DoNotCheckSecurity' in extended_attributes + is_check_security_for_receiver = ( + has_extended_attribute_value(interface, 'CheckSecurity', 'Receiver') and + not is_do_not_check_security) + is_check_security_for_return_value = ( + has_extended_attribute_value(method, 'CheckSecurity', 'ReturnValue')) + if is_check_security_for_receiver or is_check_security_for_return_value: includes.add('bindings/core/v8/BindingSecurity.h') + is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes if is_custom_element_callbacks: includes.add('core/dom/custom/CustomElementProcessingStack.h') - is_do_not_check_security = 'DoNotCheckSecurity' in extended_attributes - - is_check_security_for_frame = ( - has_extended_attribute_value(interface, 'CheckSecurity', 'Frame') and - not is_do_not_check_security) - - is_check_security_for_window = ( - has_extended_attribute_value(interface, 'CheckSecurity', 'Window') and - not is_do_not_check_security) - is_raises_exception = 'RaisesException' in extended_attributes is_custom_call_prologue = has_extended_attribute_value(method, 'Custom', 'CallPrologue') is_custom_call_epilogue = has_extended_attribute_value(method, 'Custom', 'CallEpilogue') @@ -143,8 +141,7 @@ method, CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES), 'has_exception_state': is_raises_exception or - is_check_security_for_frame or - is_check_security_for_window or + is_check_security_for_receiver or any(argument for argument in arguments if (argument.idl_type.name == 'SerializedScriptValue' or argument_conversion_needs_exception_state(method, argument))), @@ -153,9 +150,8 @@ 'is_call_with_script_arguments': is_call_with_script_arguments, 'is_call_with_script_state': is_call_with_script_state, 'is_call_with_this_value': is_call_with_this_value, - 'is_check_security_for_frame': is_check_security_for_frame, - 'is_check_security_for_node': is_check_security_for_node, - 'is_check_security_for_window': is_check_security_for_window, + 'is_check_security_for_receiver': is_check_security_for_receiver, + 'is_check_security_for_return_value': is_check_security_for_return_value, 'is_custom': 'Custom' in extended_attributes and not (is_custom_call_prologue or is_custom_call_epilogue), 'is_custom_call_prologue': is_custom_call_prologue, @@ -170,8 +166,8 @@ 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes, 'is_post_message': is_post_message, 'is_raises_exception': is_raises_exception, - 'is_read_only': is_unforgeable(interface, method), 'is_static': is_static, + 'is_unforgeable': is_unforgeable(interface, method), 'is_variadic': arguments and arguments[-1].is_variadic, 'measure_as': v8_utilities.measure_as(method, interface), # [MeasureAs] 'name': name,
diff --git a/third_party/WebKit/Source/bindings/templates/attributes.cpp b/third_party/WebKit/Source/bindings/templates/attributes.cpp index e7a68af..89604a19 100644 --- a/third_party/WebKit/Source/bindings/templates/attributes.cpp +++ b/third_party/WebKit/Source/bindings/templates/attributes.cpp
@@ -53,10 +53,9 @@ {% if attribute.is_call_with_script_state %} ScriptState* scriptState = ScriptState::current(info.GetIsolate()); {% endif %} - {% if ((attribute.is_check_security_for_frame or - attribute.is_check_security_for_window) and + {% if (attribute.is_check_security_for_receiver and not attribute.is_data_type_property) or - attribute.is_check_security_for_node or + attribute.is_check_security_for_return_value or attribute.is_getter_raises_exception %} ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate()); {% endif %} @@ -77,26 +76,16 @@ {% endif %} {# Security checks #} {% if not attribute.is_data_type_property %} - {% if attribute.is_check_security_for_window %} - if (LocalDOMWindow* window = impl->toDOMWindow()) { - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window->frame(), exceptionState)) { - v8SetReturnValueNull(info); - exceptionState.throwIfNeeded(); - return; - } - if (!window->document()) - return; - } - {% elif attribute.is_check_security_for_frame %} - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + {% if attribute.is_check_security_for_receiver %} + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return; } {% endif %} {% endif %} - {% if attribute.is_check_security_for_node %} - if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), {{attribute.cpp_value}}, exceptionState)) { + {% if attribute.is_check_security_for_return_value %} + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), {{attribute.cpp_value}}, exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return; @@ -250,9 +239,8 @@ ((not attribute.is_replaceable and not attribute.constructor_type and not attribute.is_data_type_property) and - (attribute.is_check_security_for_frame or - attribute.is_check_security_for_node or - attribute.is_check_security_for_window)) %} + (attribute.is_check_security_for_receiver or + attribute.is_check_security_for_return_value)) %} {% set raise_exception = 1 %} {% else %} {% set raise_exception = 0 %} @@ -298,30 +286,16 @@ {% if not attribute.is_replaceable and not attribute.constructor_type %} {% if not attribute.is_data_type_property %} - {% if attribute.is_check_security_for_window %} - if (LocalDOMWindow* window = impl->toDOMWindow()) { - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window->frame(), exceptionState)) { - v8SetReturnValue(info, v8Value); - exceptionState.throwIfNeeded(); - return; - } - if (!window->document()) - return; - } - {% elif attribute.is_check_security_for_frame %} - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + {% if attribute.is_check_security_for_receiver %} + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { v8SetReturnValue(info, v8Value); exceptionState.throwIfNeeded(); return; } {% endif %} {% endif %} - {% if attribute.is_check_security_for_node %} - if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), {{attribute.cpp_value}}, exceptionState)) { - v8SetReturnValue(info, v8Value); - exceptionState.throwIfNeeded(); - return; - } + {% if attribute.is_check_security_for_return_value %} +#error Attribute setter with the security check for the return value is not supported. {% endif %} {% endif %}{# not attribute.is_replaceable and not attribute.constructor_type #}
diff --git a/third_party/WebKit/Source/bindings/templates/interface.cpp b/third_party/WebKit/Source/bindings/templates/interface.cpp index 9616b9a2..a44d2d1 100644 --- a/third_party/WebKit/Source/bindings/templates/interface.cpp +++ b/third_party/WebKit/Source/bindings/templates/interface.cpp
@@ -450,7 +450,7 @@ {{cpp_class}}* impl = {{v8_class}}::toImpl(holder); v8::String::Utf8Value attributeName(name); ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "{{interface_name}}", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return; } @@ -624,11 +624,11 @@ (cpp_class, method.name, world_suffix) %} {% set setter_callback = '{0}V8Internal::{0}OriginSafeMethodSetterCallback'.format(cpp_class) - if not method.is_read_only else '0' %} + if not method.is_unforgeable else '0' %} {% if method.is_per_world_bindings %} {% set getter_callback_for_main_world = '%sForMainWorld' % getter_callback %} {% set setter_callback_for_main_world = '%sForMainWorld' % setter_callback - if not method.is_read_only else '0' %} + if not method.is_unforgeable else '0' %} {% else %} {% set getter_callback_for_main_world = '0' %} {% set setter_callback_for_main_world = '0' %}
diff --git a/third_party/WebKit/Source/bindings/templates/interface_base.cpp b/third_party/WebKit/Source/bindings/templates/interface_base.cpp index 0e365a6..3ac4590 100644 --- a/third_party/WebKit/Source/bindings/templates/interface_base.cpp +++ b/third_party/WebKit/Source/bindings/templates/interface_base.cpp
@@ -63,7 +63,7 @@ {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); v8::String::Utf8Value attributeName(name); ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "{{interface_name}}", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return false; } @@ -132,7 +132,7 @@ { // TODO(jochen): Take accessingContext into account. {{cpp_class}}* impl = {{v8_class}}::toImpl(accessedObject); - return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(), callingDOMWindow(v8::Isolate::GetCurrent()), impl->frame(), DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessTo(v8::Isolate::GetCurrent(), callingDOMWindow(v8::Isolate::GetCurrent()), impl, DoNotReportSecurityError); } {% endif %}
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp b/third_party/WebKit/Source/bindings/templates/methods.cpp index 0a18d9b..5f8285bd 100644 --- a/third_party/WebKit/Source/bindings/templates/methods.cpp +++ b/third_party/WebKit/Source/bindings/templates/methods.cpp
@@ -27,23 +27,21 @@ CustomElementProcessingStack::CallbackDeliveryScope deliveryScope; {% endif %} {# Security checks #} - {% if method.is_check_security_for_window %} - if (LocalDOMWindow* window = impl->toDOMWindow()) { - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window->frame(), exceptionState)) { - {{propagate_error_with_exception_state(method) | indent(12)}} - } - if (!window->document()) - return; - } - {% elif method.is_check_security_for_frame %} - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { - {{propagate_error_with_exception_state(method) | indent(8)}} + {% if method.is_check_security_for_receiver %} + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { + {% if not method.returns_promise %} + exceptionState.throwIfNeeded(); + {% endif %} + return; } {% endif %} - {% if method.is_check_security_for_node %} - if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->{{method.name}}(exceptionState), exceptionState)) { + {% if method.is_check_security_for_return_value %} + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), {{method.cpp_value}}, exceptionState)) { v8SetReturnValueNull(info); - {{propagate_error_with_exception_state(method) | indent(8)}} + {% if not method.returns_promise %} + exceptionState.throwIfNeeded(); + {% endif %} + return; } {% endif %} {# Call method #} @@ -536,7 +534,7 @@ return; } {{cpp_class}}* impl = {{v8_class}}::toImpl(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), DoNotReportSecurityError)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, DoNotReportSecurityError)) { v8SetReturnValue(info, domTemplate->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked()); return; }
diff --git a/third_party/WebKit/Source/bindings/tests/idls/core/TestInterfaceCheckSecurity.idl b/third_party/WebKit/Source/bindings/tests/idls/core/TestInterfaceCheckSecurity.idl index a29dd81..5aaf41d1 100644 --- a/third_party/WebKit/Source/bindings/tests/idls/core/TestInterfaceCheckSecurity.idl +++ b/third_party/WebKit/Source/bindings/tests/idls/core/TestInterfaceCheckSecurity.idl
@@ -27,7 +27,8 @@ */ [ - CheckSecurity=Frame, + CheckSecurity=Receiver, + Global, ] interface TestInterfaceCheckSecurity { readonly attribute long readonlyLongAttribute; attribute long longAttribute;
diff --git a/third_party/WebKit/Source/bindings/tests/idls/core/TestObject.idl b/third_party/WebKit/Source/bindings/tests/idls/core/TestObject.idl index 8258bce..ec0fe4e 100644 --- a/third_party/WebKit/Source/bindings/tests/idls/core/TestObject.idl +++ b/third_party/WebKit/Source/bindings/tests/idls/core/TestObject.idl
@@ -177,7 +177,7 @@ [CallWith=ExecutionContext] attribute any callWithExecutionContextAnyAttribute; [CallWith=ScriptState] attribute any callWithScriptStateAnyAttribute; [CallWith=(ExecutionContext,ScriptState)] attribute any callWithExecutionContextAndScriptStateAnyAttribute; - [CheckSecurity=Node] readonly attribute Document checkSecurityForNodeReadonlyDocumentAttribute; // All uses are read only + [CheckSecurity=ReturnValue] readonly attribute Document checkSecurityForNodeReadonlyDocumentAttribute; // All uses are read only [Conditional=CONDITION] attribute long conditionalLongAttribute; // Constructors: FIXME: replace suffix with [ConstructorAttribute] attribute TestInterfaceEmptyConstructor testInterfaceEmptyConstructorAttribute; @@ -518,7 +518,7 @@ [CallWith=ActiveWindow] void callWithActiveWindow(); [CallWith=(ActiveWindow,FirstWindow)] void callWithActiveWindowScriptWindow(); [CallWith=ThisValue] void callWithThisValue(); - [CheckSecurity=Node] void checkSecurityForNodeVoidMethod(); + [CheckSecurity=ReturnValue] void checkSecurityForNodeVoidMethod(); [Conditional=CONDITION] void conditionalConditionVoidMethod(); [Conditional=CONDITION] static void conditionalConditionStaticVoidMethod(); [Custom] void customVoidMethod();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp index 2293a54..36045240 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
@@ -44,7 +44,7 @@ TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(info.Holder()); v8::String::Utf8Value attributeName(name); ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "TestInterfaceCheckSecurity", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return false; } @@ -57,7 +57,7 @@ v8::Local<v8::Object> holder = info.Holder(); TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); ExceptionState exceptionState(ExceptionState::GetterContext, "readonlyLongAttribute", "TestInterfaceCheckSecurity", holder, info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return; @@ -77,7 +77,7 @@ v8::Local<v8::Object> holder = info.Holder(); TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); ExceptionState exceptionState(ExceptionState::GetterContext, "longAttribute", "TestInterfaceCheckSecurity", holder, info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return; @@ -97,7 +97,7 @@ v8::Local<v8::Object> holder = info.Holder(); ExceptionState exceptionState(ExceptionState::SetterContext, "longAttribute", "TestInterfaceCheckSecurity", holder, info.GetIsolate()); TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { v8SetReturnValue(info, v8Value); exceptionState.throwIfNeeded(); return; @@ -228,14 +228,14 @@ { // TODO(jochen): Take accessingContext into account. TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(accessedObject); - return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(), callingDOMWindow(v8::Isolate::GetCurrent()), impl->frame(), DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessTo(v8::Isolate::GetCurrent(), callingDOMWindow(v8::Isolate::GetCurrent()), impl, DoNotReportSecurityError); } static void voidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "voidMethod", "TestInterfaceCheckSecurity", info.Holder(), info.GetIsolate()); TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(info.Holder()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return; } @@ -276,7 +276,7 @@ return; } TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), DoNotReportSecurityError)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, DoNotReportSecurityError)) { v8SetReturnValue(info, domTemplate->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked()); return; } @@ -324,7 +324,7 @@ return; } TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), DoNotReportSecurityError)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, DoNotReportSecurityError)) { v8SetReturnValue(info, domTemplate->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked()); return; } @@ -372,7 +372,7 @@ return; } TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), DoNotReportSecurityError)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, DoNotReportSecurityError)) { v8SetReturnValue(info, domTemplate->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked()); return; } @@ -420,7 +420,7 @@ return; } TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), DoNotReportSecurityError)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, DoNotReportSecurityError)) { v8SetReturnValue(info, domTemplate->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked()); return; } @@ -468,7 +468,7 @@ return; } TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), DoNotReportSecurityError)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, DoNotReportSecurityError)) { v8SetReturnValue(info, domTemplate->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked()); return; } @@ -497,7 +497,7 @@ TestInterfaceCheckSecurity* impl = V8TestInterfaceCheckSecurity::toImpl(holder); v8::String::Utf8Value attributeName(name); ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "TestInterfaceCheckSecurity", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl, exceptionState)) { exceptionState.throwIfNeeded(); return; } @@ -515,16 +515,16 @@ } // namespace TestInterfaceCheckSecurityV8Internal const V8DOMConfiguration::AccessorConfiguration V8TestInterfaceCheckSecurityAccessors[] = { - {"readonlyLongAttribute", TestInterfaceCheckSecurityV8Internal::readonlyLongAttributeAttributeGetterCallback, 0, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder}, - {"longAttribute", TestInterfaceCheckSecurityV8Internal::longAttributeAttributeGetterCallback, TestInterfaceCheckSecurityV8Internal::longAttributeAttributeSetterCallback, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder}, - {"doNotCheckSecurityLongAttribute", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityLongAttributeAttributeGetterCallback, TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityLongAttributeAttributeSetterCallback, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder}, - {"doNotCheckSecurityReadonlyLongAttribute", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityReadonlyLongAttributeAttributeGetterCallback, 0, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder}, - {"doNotCheckSecurityOnSetterLongAttribute", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityOnSetterLongAttributeAttributeGetterCallback, TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityOnSetterLongAttributeAttributeSetterCallback, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder}, - {"doNotCheckSecurityReplaceableReadonlyLongAttribute", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityReplaceableReadonlyLongAttributeAttributeGetterCallback, TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityReplaceableReadonlyLongAttributeAttributeSetterCallback, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder}, + {"readonlyLongAttribute", TestInterfaceCheckSecurityV8Internal::readonlyLongAttributeAttributeGetterCallback, 0, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder}, + {"longAttribute", TestInterfaceCheckSecurityV8Internal::longAttributeAttributeGetterCallback, TestInterfaceCheckSecurityV8Internal::longAttributeAttributeSetterCallback, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder}, + {"doNotCheckSecurityLongAttribute", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityLongAttributeAttributeGetterCallback, TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityLongAttributeAttributeSetterCallback, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder}, + {"doNotCheckSecurityReadonlyLongAttribute", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityReadonlyLongAttributeAttributeGetterCallback, 0, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder}, + {"doNotCheckSecurityOnSetterLongAttribute", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityOnSetterLongAttributeAttributeGetterCallback, TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityOnSetterLongAttributeAttributeSetterCallback, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder}, + {"doNotCheckSecurityReplaceableReadonlyLongAttribute", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityReplaceableReadonlyLongAttributeAttributeGetterCallback, TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityReplaceableReadonlyLongAttributeAttributeSetterCallback, 0, 0, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder}, }; const V8DOMConfiguration::MethodConfiguration V8TestInterfaceCheckSecurityMethods[] = { - {"voidMethod", TestInterfaceCheckSecurityV8Internal::voidMethodMethodCallback, 0, 0, v8::None, V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype}, + {"voidMethod", TestInterfaceCheckSecurityV8Internal::voidMethodMethodCallback, 0, 0, v8::None, V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance}, }; static void installV8TestInterfaceCheckSecurityTemplate(v8::Local<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate) @@ -544,21 +544,22 @@ ALLOW_UNUSED_LOCAL(context); instanceTemplate->SetAccessCheckCallback(TestInterfaceCheckSecurityV8Internal::securityCheck, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&V8TestInterfaceCheckSecurity::wrapperTypeInfo))); const V8DOMConfiguration::AttributeConfiguration doNotCheckSecurityVoidMethodOriginSafeAttributeConfiguration = { - "doNotCheckSecurityVoidMethod", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityVoidMethodOriginSafeMethodGetterCallback, TestInterfaceCheckSecurityV8Internal::TestInterfaceCheckSecurityOriginSafeMethodSetterCallback, 0, 0, &V8TestInterfaceCheckSecurity::wrapperTypeInfo, v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder, + "doNotCheckSecurityVoidMethod", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityVoidMethodOriginSafeMethodGetterCallback, TestInterfaceCheckSecurityV8Internal::TestInterfaceCheckSecurityOriginSafeMethodSetterCallback, 0, 0, &V8TestInterfaceCheckSecurity::wrapperTypeInfo, v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder, }; V8DOMConfiguration::installAttribute(isolate, instanceTemplate, prototypeTemplate, doNotCheckSecurityVoidMethodOriginSafeAttributeConfiguration); const V8DOMConfiguration::AttributeConfiguration doNotCheckSecurityDoNotCheckSignatureVoidMethodOriginSafeAttributeConfiguration = { - "doNotCheckSecurityDoNotCheckSignatureVoidMethod", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityDoNotCheckSignatureVoidMethodOriginSafeMethodGetterCallback, TestInterfaceCheckSecurityV8Internal::TestInterfaceCheckSecurityOriginSafeMethodSetterCallback, 0, 0, &V8TestInterfaceCheckSecurity::wrapperTypeInfo, v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::DoNotCheckHolder, + "doNotCheckSecurityDoNotCheckSignatureVoidMethod", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityDoNotCheckSignatureVoidMethodOriginSafeMethodGetterCallback, TestInterfaceCheckSecurityV8Internal::TestInterfaceCheckSecurityOriginSafeMethodSetterCallback, 0, 0, &V8TestInterfaceCheckSecurity::wrapperTypeInfo, v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::DoNotCheckHolder, }; V8DOMConfiguration::installAttribute(isolate, instanceTemplate, prototypeTemplate, doNotCheckSecurityDoNotCheckSignatureVoidMethodOriginSafeAttributeConfiguration); const V8DOMConfiguration::AttributeConfiguration doNotCheckSecurityPerWorldBindingsVoidMethodOriginSafeAttributeConfiguration = { - "doNotCheckSecurityPerWorldBindingsVoidMethod", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityPerWorldBindingsVoidMethodOriginSafeMethodGetterCallback, TestInterfaceCheckSecurityV8Internal::TestInterfaceCheckSecurityOriginSafeMethodSetterCallback, TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityPerWorldBindingsVoidMethodOriginSafeMethodGetterCallbackForMainWorld, TestInterfaceCheckSecurityV8Internal::TestInterfaceCheckSecurityOriginSafeMethodSetterCallbackForMainWorld, &V8TestInterfaceCheckSecurity::wrapperTypeInfo, v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder, + "doNotCheckSecurityPerWorldBindingsVoidMethod", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityPerWorldBindingsVoidMethodOriginSafeMethodGetterCallback, TestInterfaceCheckSecurityV8Internal::TestInterfaceCheckSecurityOriginSafeMethodSetterCallback, TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityPerWorldBindingsVoidMethodOriginSafeMethodGetterCallbackForMainWorld, TestInterfaceCheckSecurityV8Internal::TestInterfaceCheckSecurityOriginSafeMethodSetterCallbackForMainWorld, &V8TestInterfaceCheckSecurity::wrapperTypeInfo, v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder, }; V8DOMConfiguration::installAttribute(isolate, instanceTemplate, prototypeTemplate, doNotCheckSecurityPerWorldBindingsVoidMethodOriginSafeAttributeConfiguration); const V8DOMConfiguration::AttributeConfiguration doNotCheckSecurityUnforgeableVoidMethodOriginSafeAttributeConfiguration = { "doNotCheckSecurityUnforgeableVoidMethod", TestInterfaceCheckSecurityV8Internal::doNotCheckSecurityUnforgeableVoidMethodOriginSafeMethodGetterCallback, 0, 0, 0, &V8TestInterfaceCheckSecurity::wrapperTypeInfo, v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance, V8DOMConfiguration::CheckHolder, }; V8DOMConfiguration::installAttribute(isolate, instanceTemplate, prototypeTemplate, doNotCheckSecurityUnforgeableVoidMethodOriginSafeAttributeConfiguration); + functionTemplate->SetHiddenPrototype(true); // Custom toString template functionTemplate->Set(v8AtomicString(isolate, "toString"), V8PerIsolateData::from(isolate)->toStringTemplate());
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp index f6c7d93c..08835a4 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -2586,7 +2586,7 @@ v8::Local<v8::Object> holder = info.Holder(); TestObject* impl = V8TestObject::toImpl(holder); ExceptionState exceptionState(ExceptionState::GetterContext, "checkSecurityForNodeReadonlyDocumentAttribute", "TestObject", holder, info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->checkSecurityForNodeReadonlyDocumentAttribute(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->checkSecurityForNodeReadonlyDocumentAttribute(), exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return; @@ -10492,7 +10492,7 @@ static void checkSecurityForNodeVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { TestObject* impl = V8TestObject::toImpl(info.Holder()); - if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->checkSecurityForNodeVoidMethod(exceptionState), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessTo(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), impl->checkSecurityForNodeVoidMethod(), exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return;
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in index 3555ea1..062ef004 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.in +++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -225,9 +225,9 @@ min-height interpolable, initial=initialMinSize, converter=convertLengthSizing min-width interpolable, initial=initialMinSize, converter=convertLengthSizing mix-blend-mode runtime_flag=CSSCompositing, type_name=blink::WebBlendMode, name_for_methods=BlendMode -motion-offset runtime_flag=CSSMotionPath, interpolable, converter=convertLength -motion-path runtime_flag=CSSMotionPath, custom_all -motion-rotation runtime_flag=CSSMotionPath, interpolable, custom_all +motion-offset interpolable, converter=convertLength +motion-path custom_all +motion-rotation interpolable, custom_all object-fit type_name=ObjectFit object-position interpolable, converter=convertPosition opacity interpolable, type_name=float @@ -470,7 +470,7 @@ list-style longhands=list-style-type;list-style-position;list-style-image margin longhands=margin-top;margin-right;margin-bottom;margin-left marker longhands=marker-start;marker-mid;marker-end -motion runtime_flag=CSSMotionPath, longhands=motion-path;motion-offset;motion-rotation +motion longhands=motion-path;motion-offset;motion-rotation outline longhands=outline-color;outline-style;outline-width overflow longhands=overflow-x;overflow-y padding longhands=padding-top;padding-right;padding-bottom;padding-left
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp index 8f17a4de..2b4ff3a 100644 --- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp +++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -2419,11 +2419,9 @@ return nullptr; case CSSPropertyMotion: - ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled()); return valuesForShorthandProperty(motionShorthand(), style, layoutObject, styledNode, allowVisitedStyle); case CSSPropertyMotionPath: { - ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled()); const StyleMotionPath* styleMotionPath = style.motionPath(); if (!styleMotionPath) return cssValuePool().createIdentifierValue(CSSValueNone); @@ -2433,11 +2431,9 @@ } case CSSPropertyMotionOffset: - ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled()); return zoomAdjustedPixelValueForLength(style.motionOffset(), style); case CSSPropertyMotionRotation: { - ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled()); RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (style.motionRotationType() == MotionRotationAuto) list->append(cssValuePool().createIdentifierValue(CSSValueAuto));
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index 260d1a9..6d18201 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -2099,13 +2099,10 @@ case CSSPropertyTextDecorationLine: return consumeTextDecorationLine(m_range); case CSSPropertyMotionPath: - ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled()); return consumeMotionPath(m_range); case CSSPropertyMotionOffset: - ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled()); return consumeLengthOrPercent(m_range, m_context.mode(), ValueRangeAll); case CSSPropertyMotionRotation: - ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled()); return consumeMotionRotation(m_range, m_context.mode()); case CSSPropertyWebkitTextEmphasisStyle: return consumeTextEmphasisStyle(m_range); @@ -2692,7 +2689,6 @@ case CSSPropertyPadding: return consume4Values(paddingShorthand(), important); case CSSPropertyMotion: - ASSERT(RuntimeEnabledFeatures::cssMotionPathEnabled()); return consumeShorthandGreedily(motionShorthand(), important); case CSSPropertyWebkitTextEmphasis: return consumeShorthandGreedily(webkitTextEmphasisShorthand(), important);
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp index 2a63bf0e..e9695df 100644 --- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
@@ -21,61 +21,25 @@ namespace blink { -// TODO(leviw): This should take a CSSParserTokenRange -static void findEndIndexOfVariableReference(const Vector<CSSParserToken>& resolvedTokens, unsigned startIndex, unsigned& endIndex, unsigned& commaIndex, bool& hasClosingBracket) +bool CSSVariableResolver::resolveVariableTokensRecursive(CSSParserTokenRange range, + Vector<CSSParserToken>& result) { - endIndex = 0; - commaIndex = 0; - unsigned bracketCount = 1; - for (unsigned i = startIndex; i < resolvedTokens.size(); ++i) { - CSSParserTokenType type = resolvedTokens[i].type(); - - if (type == CommaToken && !commaIndex) { - commaIndex = i; - } else if (type == LeftParenthesisToken || type == FunctionToken) { - bracketCount++; - } else if (type == RightParenthesisToken) { - if (bracketCount == 1) { - hasClosingBracket = true; - endIndex = i; - return; - } - bracketCount--; - } - } - hasClosingBracket = false; - endIndex = resolvedTokens.size() - 1; -} - -unsigned CSSVariableResolver::resolveVariableTokensRecursive(Vector<CSSParserToken>& resolvedTokens, unsigned startIndex) -{ - unsigned variableLocation = startIndex; - while (resolvedTokens[variableLocation].type() != IdentToken) - variableLocation++; - - unsigned commaIndex; - unsigned endIndex; - bool hasClosingBracket; - // Find default value and match braces - findEndIndexOfVariableReference(resolvedTokens, variableLocation + 1, endIndex, commaIndex, hasClosingBracket); - - unsigned length = endIndex - startIndex + 1; - unsigned varFunctionPosition = startIndex; - - AtomicString variableName = resolvedTokens[variableLocation].value(); + range.consumeWhitespace(); + ASSERT(range.peek().type() == IdentToken); + AtomicString variableName = range.consumeIncludingWhitespace().value(); + ASSERT(range.atEnd() || (range.peek().type() == CommaToken)); if (m_variablesSeen.contains(variableName)) { m_cycleDetected = true; - resolvedTokens.clear(); - return 0; + return false; } CSSVariableData* variableData = m_styleVariableData ? m_styleVariableData->getVariable(variableName) : nullptr; if (variableData) { - Vector<CSSParserToken> tokens(variableData->tokens()); + Vector<CSSParserToken> tokens; if (variableData->needsVariableResolution()) { m_variablesSeen.add(variableName); - resolveVariableReferencesFromTokens(tokens); + resolveVariableReferencesFromTokens(variableData->tokens(), tokens); m_variablesSeen.remove(variableName); // The old variable data holds onto the backing string the new resolved CSSVariableData @@ -83,56 +47,46 @@ ASSERT(variableData->refCount() > 1); m_styleVariableData->setVariable(variableName, CSSVariableData::createResolved(tokens)); + } else { + tokens = variableData->tokens(); } - if (tokens.size()) { - resolvedTokens.remove(startIndex, length); - resolvedTokens.insert(startIndex, tokens); - return tokens.size(); + if (!tokens.isEmpty()) { + result.appendVector(tokens); + return true; } } - // Fallback on default value if present - if (!commaIndex || m_cycleDetected) { - resolvedTokens.clear(); - return 0; - } + if (range.atEnd()) + return false; - // Move the tokens to the beginning of the variable reference - unsigned defaultValueStart = commaIndex + 1; - unsigned defaultValueLength = endIndex - commaIndex - (hasClosingBracket ? 1 : 0); - for (unsigned i = 0; i < defaultValueLength; ++i) - resolvedTokens[varFunctionPosition + i] = resolvedTokens[defaultValueStart + i]; - resolvedTokens.remove(varFunctionPosition + defaultValueLength, length - defaultValueLength); + // Comma Token, as asserted above. + range.consume(); - resolveVariableReferencesFromTokens(resolvedTokens); - - return resolvedTokens.size(); + resolveVariableReferencesFromTokens(range, result); + return true; } -void CSSVariableResolver::resolveVariableReferencesFromTokens(Vector<CSSParserToken>& tokens) +bool CSSVariableResolver::resolveVariableReferencesFromTokens(CSSParserTokenRange range, + Vector<CSSParserToken>& result) { - for (unsigned i = 0; i < tokens.size(); ++i) { - if (tokens[i].functionId() == CSSValueVar) { - unsigned validTokens = resolveVariableTokensRecursive(tokens, i); - if (validTokens < 1 || m_cycleDetected) { - tokens.clear(); - break; - } - i += validTokens - 1; + while (!range.atEnd()) { + if (range.peek().functionId() != CSSValueVar) { + result.append(range.consume()); + } else if (!resolveVariableTokensRecursive(range.consumeBlock(), result) || m_cycleDetected) { + result.clear(); + return false; } } + return true; } void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value) { // TODO(leviw): This should be a stack - Vector<CSSParserToken> tokens = value.variableDataValue()->tokens(); - CSSVariableResolver resolver(state.style()->variables()); - resolver.resolveVariableReferencesFromTokens(tokens); - - if (!tokens.size()) + Vector<CSSParserToken> tokens; + if (!resolver.resolveVariableReferencesFromTokens(value.variableDataValue()->tokens(), tokens)) return; CSSParserContext context(HTMLStandardMode, 0); @@ -154,10 +108,10 @@ for (auto& variable : variables->m_data) { if (!variable.value->needsVariableResolution()) continue; - Vector<CSSParserToken> resolvedTokens(variable.value->tokens()); + Vector<CSSParserToken> resolvedTokens; CSSVariableResolver resolver(variables, variable.key); - resolver.resolveVariableReferencesFromTokens(resolvedTokens); + resolver.resolveVariableReferencesFromTokens(variable.value->tokens(), resolvedTokens); variable.value = CSSVariableData::createResolved(resolvedTokens); }
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h index fb832cce..6b542fc 100644 --- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h +++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h
@@ -13,6 +13,7 @@ namespace blink { +class CSSParserTokenRange; class CSSVariableReferenceValue; class StyleResolverState; class StyleVariableData; @@ -26,8 +27,8 @@ CSSVariableResolver(StyleVariableData*); CSSVariableResolver(StyleVariableData*, AtomicString& variable); - unsigned resolveVariableTokensRecursive(Vector<CSSParserToken>&, unsigned startOffset); - void resolveVariableReferencesFromTokens(Vector<CSSParserToken>& tokens); + bool resolveVariableTokensRecursive(CSSParserTokenRange, Vector<CSSParserToken>& result); + bool resolveVariableReferencesFromTokens(CSSParserTokenRange tokens, Vector<CSSParserToken>& result); StyleVariableData* m_styleVariableData; HashSet<AtomicString> m_variablesSeen;
diff --git a/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.cpp b/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.cpp index e93e8b3..624b4818 100644 --- a/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.cpp +++ b/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.cpp
@@ -107,6 +107,12 @@ void MatchedPropertiesCache::clear() { + // MatchedPropertiesCache must be cleared promptly because some + // destructors in the properties (e.g., ~FontFallbackList) expect that + // the destructors are called promptly without relying on a GC timing. + for (auto& cacheEntry : m_cache) { + cacheEntry.value->clear(); + } m_cache.clear(); }
diff --git a/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.h b/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.h index ebfc882..d1887cf 100644 --- a/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.h +++ b/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.h
@@ -94,6 +94,10 @@ WTF_MAKE_NONCOPYABLE(MatchedPropertiesCache); public: MatchedPropertiesCache(); + ~MatchedPropertiesCache() + { + ASSERT(m_cache.isEmpty()); + } const CachedMatchedProperties* find(unsigned hash, const StyleResolverState&, const MatchedPropertiesVector&); void add(const ComputedStyle&, const ComputedStyle& parentStyle, unsigned hash, const MatchedPropertiesVector&);
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp index 35ab44b..4d343cda 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -165,6 +165,11 @@ { } +void StyleResolver::dispose() +{ + m_matchedPropertiesCache.clear(); +} + void StyleResolver::initWatchedSelectorRules() { CSSSelectorWatch* watch = CSSSelectorWatch::fromIfExists(*m_document);
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h index 59e73e1..2e3c58a9 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
@@ -86,6 +86,7 @@ return adoptPtrWillBeNoop(new StyleResolver(document)); } ~StyleResolver(); + void dispose(); // FIXME: StyleResolver should not be keeping tree-walk state. // These should move to some global tree-walk state, or should be contained in a
diff --git a/third_party/WebKit/Source/core/dom/Attr.h b/third_party/WebKit/Source/core/dom/Attr.h index 359a588..9bfd829 100644 --- a/third_party/WebKit/Source/core/dom/Attr.h +++ b/third_party/WebKit/Source/core/dom/Attr.h
@@ -70,7 +70,7 @@ String nodeValue() const override { return value(); } void setNodeValue(const String&) override; - PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = true) override; + PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) override; bool isAttributeNode() const override { return true; }
diff --git a/third_party/WebKit/Source/core/dom/Comment.h b/third_party/WebKit/Source/core/dom/Comment.h index bdc5ebe..45a0444 100644 --- a/third_party/WebKit/Source/core/dom/Comment.h +++ b/third_party/WebKit/Source/core/dom/Comment.h
@@ -37,7 +37,7 @@ String nodeName() const override; NodeType nodeType() const override; - PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = true) override; + PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) override; }; DEFINE_NODE_TYPE_CASTS(Comment, nodeType() == Node::COMMENT_NODE);
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index 56c7aa9..22555f4 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -1103,7 +1103,7 @@ String nodeName() const final; NodeType nodeType() const final; bool childTypeAllowed(NodeType) const final; - PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = true) final; + PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) final; void cloneDataFromDocument(const Document&); #if !ENABLE(OILPAN)
diff --git a/third_party/WebKit/Source/core/dom/DocumentFragment.h b/third_party/WebKit/Source/core/dom/DocumentFragment.h index de58ffc..74788f62 100644 --- a/third_party/WebKit/Source/core/dom/DocumentFragment.h +++ b/third_party/WebKit/Source/core/dom/DocumentFragment.h
@@ -47,7 +47,7 @@ private: NodeType nodeType() const final; - PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = true) override; + PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) override; bool childTypeAllowed(NodeType) const override; bool isDocumentFragment() const = delete; // This will catch anyone doing an unnecessary check.
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h index e7ab471e..18ea2ae 100644 --- a/third_party/WebKit/Source/core/dom/Node.h +++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -228,7 +228,7 @@ PassRefPtrWillBeRawPtr<Node> appendChild(PassRefPtrWillBeRawPtr<Node> newChild, ExceptionState& = ASSERT_NO_EXCEPTION); bool hasChildren() const { return firstChild(); } - virtual PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = false) = 0; + virtual PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) = 0; void normalize(); bool isSameNode(Node* other) const { return this == other; }
diff --git a/third_party/WebKit/Source/core/dom/Node.idl b/third_party/WebKit/Source/core/dom/Node.idl index 5423489..3507934 100644 --- a/third_party/WebKit/Source/core/dom/Node.idl +++ b/third_party/WebKit/Source/core/dom/Node.idl
@@ -57,8 +57,7 @@ [TreatUndefinedAs=NullString, CustomElementCallbacks] attribute DOMString? textContent; [CustomElementCallbacks] void normalize(); - // FIXME: The deep argument should have a default value false. - [NewObject, CustomElementCallbacks] Node cloneNode(optional boolean deep); + [NewObject, CustomElementCallbacks] Node cloneNode(optional boolean deep = false); boolean isEqualNode(Node? node); const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
diff --git a/third_party/WebKit/Source/core/dom/ProcessingInstruction.h b/third_party/WebKit/Source/core/dom/ProcessingInstruction.h index 2d97897..48c3c64 100644 --- a/third_party/WebKit/Source/core/dom/ProcessingInstruction.h +++ b/third_party/WebKit/Source/core/dom/ProcessingInstruction.h
@@ -82,7 +82,7 @@ String nodeName() const override; NodeType nodeType() const override; - PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = true) override; + PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) override; InsertionNotificationRequest insertedInto(ContainerNode*) override; void removedFrom(ContainerNode*) override;
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp index 4fde5b99..a926715 100644 --- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp +++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -429,6 +429,7 @@ if (m_resolver) { TRACE_EVENT1("blink", "StyleEngine::clearResolver", "frame", document().frame()); + m_resolver->dispose(); m_resolver.clear(); } }
diff --git a/third_party/WebKit/Source/core/dom/Text.h b/third_party/WebKit/Source/core/dom/Text.h index 08178b7..fa8435d 100644 --- a/third_party/WebKit/Source/core/dom/Text.h +++ b/third_party/WebKit/Source/core/dom/Text.h
@@ -70,7 +70,7 @@ private: String nodeName() const override; - PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = true) final; + PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) final; bool isTextNode() const = delete; // This will catch anyone doing an unnecessary check.
diff --git a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.idl b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.idl index cfb06f2..f783a41e 100644 --- a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.idl +++ b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.idl
@@ -42,5 +42,5 @@ // interface. Here, it's used to implement "Invoking the cloneNode() method // on a ShadowRoot instance must always throw a DATA_CLONE_ERR exception" as // Node.cloneNode() does not have [RaisesException]. - [RaisesException] Node cloneNode([Default=Undefined] optional boolean deep); + [RaisesException] Node cloneNode(optional boolean deep = false); };
diff --git a/third_party/WebKit/Source/core/events/EventTarget.cpp b/third_party/WebKit/Source/core/events/EventTarget.cpp index 85ebd98a..8ced267 100644 --- a/third_party/WebKit/Source/core/events/EventTarget.cpp +++ b/third_party/WebKit/Source/core/events/EventTarget.cpp
@@ -94,6 +94,11 @@ return nullptr; } +const LocalDOMWindow* EventTarget::toDOMWindow() const +{ + return nullptr; +} + LocalDOMWindow* EventTarget::toDOMWindow() { return nullptr;
diff --git a/third_party/WebKit/Source/core/events/EventTarget.h b/third_party/WebKit/Source/core/events/EventTarget.h index acd8940..5f56ecb0 100644 --- a/third_party/WebKit/Source/core/events/EventTarget.h +++ b/third_party/WebKit/Source/core/events/EventTarget.h
@@ -125,6 +125,7 @@ virtual ExecutionContext* executionContext() const = 0; virtual Node* toNode(); + virtual const LocalDOMWindow* toDOMWindow() const; virtual LocalDOMWindow* toDOMWindow(); virtual MessagePort* toMessagePort();
diff --git a/third_party/WebKit/Source/core/events/EventTarget.idl b/third_party/WebKit/Source/core/events/EventTarget.idl index e4bcd44..b38ff757 100644 --- a/third_party/WebKit/Source/core/events/EventTarget.idl +++ b/third_party/WebKit/Source/core/events/EventTarget.idl
@@ -21,7 +21,7 @@ // https://dom.spec.whatwg.org/#interface-eventtarget [ - CheckSecurity=Window, + CheckSecurity=Receiver, WillBeGarbageCollected, Exposed=(Window,Worker) ] interface EventTarget {
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/third_party/WebKit/Source/core/frame/DOMWindow.cpp index 442a2d7..d48031c 100644 --- a/third_party/WebKit/Source/core/frame/DOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
@@ -230,7 +230,7 @@ // exactly which details may be exposed to JavaScript. // // http://crbug.com/17325 -String DOMWindow::sanitizedCrossDomainAccessErrorMessage(LocalDOMWindow* callingWindow) +String DOMWindow::sanitizedCrossDomainAccessErrorMessage(const LocalDOMWindow* callingWindow) const { if (!callingWindow || !callingWindow->document() || !frame()) return String(); @@ -241,7 +241,7 @@ ASSERT(!callingWindow->document()->securityOrigin()->canAccessCheckSuborigins(frame()->securityContext()->securityOrigin())); - SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin(); + const SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin(); String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a cross-origin frame."; // FIXME: Evaluate which details from 'crossDomainAccessErrorMessage' may safely be reported to JavaScript. @@ -249,7 +249,7 @@ return message; } -String DOMWindow::crossDomainAccessErrorMessage(LocalDOMWindow* callingWindow) +String DOMWindow::crossDomainAccessErrorMessage(const LocalDOMWindow* callingWindow) const { if (!callingWindow || !callingWindow->document() || !frame()) return String(); @@ -259,8 +259,8 @@ return String(); // FIXME: This message, and other console messages, have extra newlines. Should remove them. - SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin(); - SecurityOrigin* targetOrigin = frame()->securityContext()->securityOrigin(); + const SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin(); + const SecurityOrigin* targetOrigin = frame()->securityContext()->securityOrigin(); ASSERT(!activeOrigin->canAccessCheckSuborigins(targetOrigin)); String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a frame with origin \"" + targetOrigin->toString() + "\". ";
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.h b/third_party/WebKit/Source/core/frame/DOMWindow.h index f8bedc4..7c2a6e4c 100644 --- a/third_party/WebKit/Source/core/frame/DOMWindow.h +++ b/third_party/WebKit/Source/core/frame/DOMWindow.h
@@ -184,8 +184,8 @@ void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, const String& targetOrigin, LocalDOMWindow* source, ExceptionState&); - String sanitizedCrossDomainAccessErrorMessage(LocalDOMWindow* callingWindow); - String crossDomainAccessErrorMessage(LocalDOMWindow* callingWindow); + String sanitizedCrossDomainAccessErrorMessage(const LocalDOMWindow* callingWindow) const; + String crossDomainAccessErrorMessage(const LocalDOMWindow* callingWindow) const; bool isInsecureScriptAccess(LocalDOMWindow& callingWindow, const String& urlString); // FIXME: When this DOMWindow is no longer the active DOMWindow (i.e.,
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp index 652db630..34fa2a0 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -474,6 +474,11 @@ return m_document.get(); } +const LocalDOMWindow* LocalDOMWindow::toDOMWindow() const +{ + return this; +} + LocalDOMWindow* LocalDOMWindow::toDOMWindow() { return this; @@ -1434,7 +1439,7 @@ } } -void LocalDOMWindow::printErrorMessage(const String& message) +void LocalDOMWindow::printErrorMessage(const String& message) const { if (!isCurrentlyDisplayedInFrame()) return;
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h index 318e84d0..4cbd839 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
@@ -82,6 +82,7 @@ // EventTarget overrides: ExecutionContext* executionContext() const override; + const LocalDOMWindow* toDOMWindow() const override; LocalDOMWindow* toDOMWindow() override; // DOMWindow overrides: @@ -165,7 +166,7 @@ FrameConsole* frameConsole() const; - void printErrorMessage(const String&); + void printErrorMessage(const String&) const; void postMessageTimerFired(PostMessageTimer*); void removePostMessageTimer(PostMessageTimer*);
diff --git a/third_party/WebKit/Source/core/frame/Location.idl b/third_party/WebKit/Source/core/frame/Location.idl index d68eaf7..592474d 100644 --- a/third_party/WebKit/Source/core/frame/Location.idl +++ b/third_party/WebKit/Source/core/frame/Location.idl
@@ -29,7 +29,7 @@ // https://html.spec.whatwg.org/#the-location-interface [ - CheckSecurity=Frame, + CheckSecurity=Receiver, Unforgeable, WillBeGarbageCollected, ] interface Location {
diff --git a/third_party/WebKit/Source/core/frame/Window.idl b/third_party/WebKit/Source/core/frame/Window.idl index 8a3292d9..6691a833 100644 --- a/third_party/WebKit/Source/core/frame/Window.idl +++ b/third_party/WebKit/Source/core/frame/Window.idl
@@ -28,7 +28,7 @@ // FIXME: explain all uses of [DoNotCheckSecurity] [ - CheckSecurity=Frame, + CheckSecurity=Receiver, ImplementedAs=DOMWindow, PrimaryGlobal, ] interface Window : EventTarget { @@ -60,7 +60,7 @@ // FIXME: opener should be of type any. [DoNotCheckSecurity, Custom=Setter] attribute Window opener; [Replaceable, DoNotCheckSecurity] readonly attribute Window parent; - [CheckSecurity=Node, Custom=Getter] readonly attribute Element? frameElement; + [CheckSecurity=ReturnValue, Custom=Getter] readonly attribute Element? frameElement; // FIXME: open() should have 4 optional arguments with defaults. [Custom] Window? open(DOMString url, DOMString target, optional DOMString features); // FIXME: These getters should not have [NotEnumerable].
diff --git a/third_party/WebKit/Source/core/html/HTMLEmbedElement.idl b/third_party/WebKit/Source/core/html/HTMLEmbedElement.idl index 5759506..5def601 100644 --- a/third_party/WebKit/Source/core/html/HTMLEmbedElement.idl +++ b/third_party/WebKit/Source/core/html/HTMLEmbedElement.idl
@@ -29,7 +29,7 @@ [Reflect] attribute DOMString type; [Reflect] attribute DOMString width; [Reflect] attribute DOMString height; - [CheckSecurity=Node, RaisesException] Document? getSVGDocument(); + [CheckSecurity=ReturnValue, RaisesException] Document? getSVGDocument(); // FIXME: The spec has a legacycaller any (any... arguments); crbug.com/465009 // obsolete members
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameElement.idl b/third_party/WebKit/Source/core/html/HTMLFrameElement.idl index bd50b0ce..54e2901 100644 --- a/third_party/WebKit/Source/core/html/HTMLFrameElement.idl +++ b/third_party/WebKit/Source/core/html/HTMLFrameElement.idl
@@ -27,7 +27,7 @@ [Reflect] attribute DOMString frameBorder; [Reflect, URL] attribute DOMString longDesc; [Reflect] attribute boolean noResize; - [CheckSecurity=Node] readonly attribute Document? contentDocument; + [CheckSecurity=ReturnValue] readonly attribute Document? contentDocument; readonly attribute Window? contentWindow; [Reflect, TreatNullAs=EmptyString] attribute DOMString marginHeight;
diff --git a/third_party/WebKit/Source/core/html/HTMLIFrameElement.idl b/third_party/WebKit/Source/core/html/HTMLIFrameElement.idl index 247a3902..2b834dd 100644 --- a/third_party/WebKit/Source/core/html/HTMLIFrameElement.idl +++ b/third_party/WebKit/Source/core/html/HTMLIFrameElement.idl
@@ -29,9 +29,9 @@ [Reflect] attribute boolean allowFullscreen; [Reflect] attribute DOMString width; [Reflect] attribute DOMString height; - [CheckSecurity=Node] readonly attribute Document? contentDocument; + [CheckSecurity=ReturnValue] readonly attribute Document? contentDocument; readonly attribute Window? contentWindow; - [CheckSecurity=Node, RaisesException] Document? getSVGDocument(); + [CheckSecurity=ReturnValue, RaisesException] Document? getSVGDocument(); [RuntimeEnabled=ReferrerPolicyAttribute, Reflect, ReflectOnly=("","no-referrer","origin","no-referrer-when-downgrade","origin-when-cross-origin","unsafe-url"), ReflectMissing="", ReflectInvalid=""] attribute DOMString referrerpolicy;
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp index 76eab4d..de182035 100644 --- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -603,8 +603,7 @@ { ASSERT(m_sheet); ASSERT(m_sheet->ownerNode() == m_owner); - m_sheet->clearOwnerNode(); - m_sheet = nullptr; + m_sheet.release()->clearOwnerNode(); } bool LinkStyle::styleSheetIsLoading() const
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.idl b/third_party/WebKit/Source/core/html/HTMLObjectElement.idl index a936771..d0f62615 100644 --- a/third_party/WebKit/Source/core/html/HTMLObjectElement.idl +++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.idl
@@ -33,9 +33,9 @@ [ImplementedAs=formOwner] readonly attribute HTMLFormElement? form; [Reflect] attribute DOMString width; [Reflect] attribute DOMString height; - [CheckSecurity=Node] readonly attribute Document? contentDocument; + [CheckSecurity=ReturnValue] readonly attribute Document? contentDocument; // TODO(philipj): readonly attribute WindowProxy? contentWindow; - [CheckSecurity=Node, RaisesException] Document? getSVGDocument(); + [CheckSecurity=ReturnValue, RaisesException] Document? getSVGDocument(); readonly attribute boolean willValidate; readonly attribute ValidityState validity;
diff --git a/third_party/WebKit/Source/core/html/HTMLTemplateElement.h b/third_party/WebKit/Source/core/html/HTMLTemplateElement.h index 2185690..2574ec1 100644 --- a/third_party/WebKit/Source/core/html/HTMLTemplateElement.h +++ b/third_party/WebKit/Source/core/html/HTMLTemplateElement.h
@@ -48,7 +48,7 @@ DocumentFragment* content() const; private: - PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = true) override; + PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) override; void didMoveToNewDocument(Document& oldDocument) override; explicit HTMLTemplateElement(Document&);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp index 9309d9f..926fc41 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -160,7 +160,7 @@ ScriptState::Scope scope(scriptState); v8::Isolate* isolate = scriptState->isolate(); ExceptionState exceptionState(ExceptionState::ExecutionContext, "nodeAsScriptValue", "InjectedScriptHost", scriptState->context()->Global(), isolate); - if (!BindingSecurity::shouldAllowAccessToNode(isolate, callingDOMWindow(isolate), node, exceptionState)) + if (!BindingSecurity::shouldAllowAccessTo(isolate, callingDOMWindow(isolate), node, exceptionState)) return ScriptValue(scriptState, v8::Null(isolate)); return ScriptValue(scriptState, toV8(node, scriptState->context()->Global(), isolate)); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp index 2ce5335c..755fb36 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -691,6 +691,7 @@ OrderedFlexItemList orderedChildren; LayoutUnit sumFlexBaseSize; double totalFlexGrow; + double totalFlexShrink; double totalWeightedFlexShrink; LayoutUnit sumHypotheticalMainSize; @@ -698,18 +699,22 @@ m_orderIterator.first(); LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore(); - while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalWeightedFlexShrink, sumHypotheticalMainSize, relayoutChildren)) { + while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, sumHypotheticalMainSize, relayoutChildren)) { LayoutUnit containerMainInnerSize = mainAxisContentExtent(sumHypotheticalMainSize); + // availableFreeSpace is the initial amount of free space in this flexbox. + // remainingFreeSpace starts out at the same value but as we place and lay out + // flex items we subtract from it. Note that both values can be negative. LayoutUnit availableFreeSpace = containerMainInnerSize - sumFlexBaseSize; + LayoutUnit remainingFreeSpace = availableFreeSpace; FlexSign flexSign = (sumHypotheticalMainSize < containerMainInnerSize) ? PositiveFlexibility : NegativeFlexibility; InflexibleFlexItemSize inflexibleItems; childSizes.reserveCapacity(orderedChildren.size()); - while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems, childSizes)) { + while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, remainingFreeSpace, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, inflexibleItems, childSizes)) { ASSERT(totalFlexGrow >= 0 && totalWeightedFlexShrink >= 0); ASSERT(inflexibleItems.size() > 0); } - layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace, relayoutChildren, layoutScope, lineContexts); + layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, remainingFreeSpace, relayoutChildren, layoutScope, lineContexts); } if (hasLineIfEmpty()) { // Even if computeNextFlexLine returns true, the flexbox might not have @@ -927,11 +932,11 @@ return std::max(childSize, minExtent); } -bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayoutChildren) +bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayoutChildren) { orderedChildren.clear(); sumFlexBaseSize = 0; - totalFlexGrow = totalWeightedFlexShrink = 0; + totalFlexGrow = totalFlexShrink = totalWeightedFlexShrink = 0; sumHypotheticalMainSize = 0; if (!m_orderIterator.currentChild()) @@ -971,19 +976,21 @@ lineHasInFlowItem = true; sumFlexBaseSize += childOuterFlexBaseSize; totalFlexGrow += child->style()->flexGrow(); + totalFlexShrink += child->style()->flexShrink(); totalWeightedFlexShrink += child->style()->flexShrink() * childInnerFlexBaseSize; sumHypotheticalMainSize += childHypotheticalMainSize; } return true; } -void LayoutFlexibleBox::freezeViolations(const Vector<Violation>& violations, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems) +void LayoutFlexibleBox::freezeViolations(const Vector<Violation>& violations, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems) { for (size_t i = 0; i < violations.size(); ++i) { LayoutBox* child = violations[i].child; LayoutUnit childSize = violations[i].childSize; availableFreeSpace -= childSize - violations[i].childInnerFlexBaseSize; totalFlexGrow -= child->style()->flexGrow(); + totalFlexShrink -= child->style()->flexShrink(); totalWeightedFlexShrink -= child->style()->flexShrink() * violations[i].childInnerFlexBaseSize; // totalWeightedFlexShrink can be negative when we exceed the precision of a double when we initially // calcuate totalWeightedFlexShrink. We then subtract each child's weighted flex shrink with full precision, @@ -994,13 +1001,21 @@ } // Returns true if we successfully ran the algorithm and sized the flex items. -bool LayoutFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit, 16>& childSizes) +bool LayoutFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit availableFreeSpace, LayoutUnit& remainingFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit, 16>& childSizes) { childSizes.resize(0); LayoutUnit totalViolation = 0; LayoutUnit usedFreeSpace = 0; Vector<Violation> minViolations; Vector<Violation> maxViolations; + + double sumFlexFactors = (flexSign == PositiveFlexibility) ? totalFlexGrow : totalFlexShrink; + if (sumFlexFactors > 0 && sumFlexFactors < 1) { + LayoutUnit fractional = availableFreeSpace * sumFlexFactors; + if (fractional.abs() < remainingFreeSpace.abs()) + remainingFreeSpace = fractional; + } + for (size_t i = 0; i < children.size(); ++i) { LayoutBox* child = children[i]; if (child->isOutOfFlowPositioned()) { @@ -1014,13 +1029,10 @@ LayoutUnit childInnerFlexBaseSize = computeInnerFlexBaseSizeForChild(*child); LayoutUnit childSize = childInnerFlexBaseSize; double extraSpace = 0; - if (availableFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && std::isfinite(totalFlexGrow)) { - if (totalFlexGrow < 1) - extraSpace = availableFreeSpace * child->style()->flexGrow(); - else - extraSpace = availableFreeSpace * child->style()->flexGrow() / totalFlexGrow; - } else if (availableFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink) && child->style()->flexShrink()) { - extraSpace = availableFreeSpace * child->style()->flexShrink() * childInnerFlexBaseSize / totalWeightedFlexShrink; + if (remainingFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && std::isfinite(totalFlexGrow)) { + extraSpace = remainingFreeSpace * child->style()->flexGrow() / totalFlexGrow; + } else if (remainingFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink) && child->style()->flexShrink()) { + extraSpace = remainingFreeSpace * child->style()->flexShrink() * childInnerFlexBaseSize / totalWeightedFlexShrink; } if (std::isfinite(extraSpace)) childSize += LayoutUnit::fromFloatRound(extraSpace); @@ -1040,9 +1052,9 @@ } if (totalViolation) - freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems); + freezeViolations(totalViolation < 0 ? maxViolations : minViolations, remainingFreeSpace, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, inflexibleItems); else - availableFreeSpace -= usedFreeSpace; + remainingFreeSpace -= usedFreeSpace; return !totalViolation; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h index e404192..a4948ca8 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
@@ -155,10 +155,10 @@ void prepareOrderIteratorAndMargins(); LayoutUnit adjustChildSizeForMinAndMax(const LayoutBox& child, LayoutUnit childSize); // The hypothetical main size of an item is the flex base size clamped according to its min and max main size properties - bool computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayoutChildren); + bool computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayoutChildren); - bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, Vector<LayoutUnit, 16>& childSizes); - void freezeViolations(const Vector<Violation>&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&); + bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit availableFreeSpace, LayoutUnit& remainingFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, Vector<LayoutUnit, 16>& childSizes); + void freezeViolations(const Vector<Violation>&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, InflexibleFlexItemSize&); void resetAutoMarginsAndLogicalTopInCrossAxis(LayoutBox& child); void setOverrideMainAxisSizeForChild(LayoutBox& child, LayoutUnit childPreferredSize);
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp index 3b32e5d..5a654f7 100644 --- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -1105,15 +1105,13 @@ void LayoutGrid::insertItemIntoGrid(LayoutBox& child, const GridCoordinate& coordinate) { + RELEASE_ASSERT(coordinate.rows.isDefinite() && coordinate.columns.isDefinite()); ensureGridSize(coordinate.rows.resolvedFinalPosition().toInt(), coordinate.columns.resolvedFinalPosition().toInt()); for (GridSpan::iterator row = coordinate.rows.begin(); row != coordinate.rows.end(); ++row) { for (GridSpan::iterator column = coordinate.columns.begin(); column != coordinate.columns.end(); ++column) m_grid[row.toInt()][column.toInt()].append(&child); } - - RELEASE_ASSERT(!m_gridItemCoordinate.contains(&child)); - m_gridItemCoordinate.set(&child, coordinate); } void LayoutGrid::placeItemsOnGrid() @@ -1134,17 +1132,16 @@ if (child->isOutOfFlowPositioned()) continue; - GridSpan rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForRows); - GridSpan columnPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForColumns); - if (!rowPositions.isDefinite() || !columnPositions.isDefinite()) { - GridSpan majorAxisPositions = (autoPlacementMajorAxisDirection() == ForColumns) ? columnPositions : rowPositions; + GridCoordinate coordinate = cachedGridCoordinate(*child); + if (!coordinate.rows.isDefinite() || !coordinate.columns.isDefinite()) { + GridSpan majorAxisPositions = (autoPlacementMajorAxisDirection() == ForColumns) ? coordinate.columns : coordinate.rows; if (!majorAxisPositions.isDefinite()) autoMajorAxisAutoGridItems.append(child); else specifiedMajorAxisAutoGridItems.append(child); continue; } - insertItemIntoGrid(*child, GridCoordinate(rowPositions, columnPositions)); + insertItemIntoGrid(*child, coordinate); } ASSERT(gridRowCount() >= GridResolvedPosition::explicitGridRowCount(*style())); @@ -1154,6 +1151,16 @@ placeAutoMajorAxisItemsOnGrid(autoMajorAxisAutoGridItems); m_grid.shrinkToFit(); + +#if ENABLE(ASSERT) + for (LayoutBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) { + if (child->isOutOfFlowPositioned()) + continue; + + GridCoordinate coordinate = cachedGridCoordinate(*child); + ASSERT(coordinate.rows.isDefinite() && coordinate.columns.isDefinite()); + } +#endif } void LayoutGrid::populateExplicitGridAndOrderIterator() @@ -1175,6 +1182,7 @@ // This function bypasses the cache (cachedGridCoordinate()) as it is used to build it. GridSpan rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForRows); GridSpan columnPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForColumns); + m_gridItemCoordinate.set(child, GridCoordinate(rowPositions, columnPositions)); // |positions| is 0 if we need to run the auto-placement algorithm. if (rowPositions.isDefinite()) { @@ -1218,7 +1226,9 @@ HashMap<unsigned, unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> minorAxisCursors; for (const auto& autoGridItem : autoGridItems) { - GridSpan majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *autoGridItem, autoPlacementMajorAxisDirection()); + GridSpan majorAxisPositions = cachedGridSpan(*autoGridItem, autoPlacementMajorAxisDirection()); + ASSERT(majorAxisPositions.isDefinite()); + ASSERT(!cachedGridSpan(*autoGridItem, autoPlacementMinorAxisDirection()).isDefinite()); GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *autoGridItem, autoPlacementMinorAxisDirection(), GridResolvedPosition(0)); unsigned majorAxisInitialPosition = majorAxisPositions.resolvedInitialPosition().toInt(); @@ -1226,6 +1236,8 @@ OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea(majorAxisPositions.integerSpan(), minorAxisPositions.integerSpan()); if (!emptyGridArea) emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(*autoGridItem, autoPlacementMajorAxisDirection(), majorAxisPositions); + + m_gridItemCoordinate.set(autoGridItem, *emptyGridArea); insertItemIntoGrid(*autoGridItem, *emptyGridArea); if (!isGridAutoFlowDense) @@ -1251,8 +1263,8 @@ void LayoutGrid::placeAutoMajorAxisItemOnGrid(LayoutBox& gridItem, std::pair<size_t, size_t>& autoPlacementCursor) { - GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), gridItem, autoPlacementMinorAxisDirection()); - ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(*style(), gridItem, autoPlacementMajorAxisDirection()).isDefinite()); + GridSpan minorAxisPositions = cachedGridSpan(gridItem, autoPlacementMinorAxisDirection()); + ASSERT(!cachedGridSpan(gridItem, autoPlacementMajorAxisDirection()).isDefinite()); GridSpan majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), gridItem, autoPlacementMajorAxisDirection(), GridResolvedPosition(0)); const size_t endOfMajorAxis = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : gridRowCount(); @@ -1299,6 +1311,7 @@ emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), minorAxisPositions); } + m_gridItemCoordinate.set(&gridItem, *emptyGridArea); insertItemIntoGrid(gridItem, *emptyGridArea); // Move auto-placement cursor to the new position. autoPlacementCursor.first = emptyGridArea->rows.resolvedInitialPosition().toInt();
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationGroupPreviewUI.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationGroupPreviewUI.js index 432501a4..f9b4d12 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationGroupPreviewUI.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationGroupPreviewUI.js
@@ -61,7 +61,7 @@ this._svg.removeChildren(); var maxToShow = 10; var numberOfAnimations = Math.min(this._model.animations().length, maxToShow); - var timeToPixelRatio = 100 / Math.max(this._groupDuration(), 300); + var timeToPixelRatio = 100 / Math.max(this._groupDuration(), 750); for (var i = 0; i < numberOfAnimations; i++) { var effect = this._model.animations()[i].source(); var line = this._svg.createSVGChild("line");
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js index 03253a3..0db79cd3 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
@@ -102,7 +102,7 @@ if (!matchedGroup) { this._animationGroups.set(incomingGroup.id(), incomingGroup); - this._screenshotCapture.captureScreenshots(incomingGroup._finiteDuration(), incomingGroup._screenshots); + this._screenshotCapture.captureScreenshots(incomingGroup.finiteDuration(), incomingGroup._screenshots); } this.dispatchEventToListeners(WebInspector.AnimationModel.Events.AnimationGroupStarted, matchedGroup || incomingGroup); return !!matchedGroup; @@ -314,7 +314,7 @@ */ _finiteDuration: function() { - var iterations = this.source().iterations() ? this.source().iterations() : 3; + var iterations = Math.min(this.source().iterations(), 3); return this.source().delay() + this.source().duration() * iterations; }, @@ -714,7 +714,7 @@ /** * @return {number} */ - _finiteDuration: function() + finiteDuration: function() { var maxDuration = 0; for (var i = 0; i < this._animations.length; ++i)
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js index 3102f8e..3dc4cbef 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
@@ -25,6 +25,7 @@ this._timelineControlsWidth = 150; /** @type {!Map.<!DOMAgent.BackendNodeId, !WebInspector.AnimationTimeline.NodeUI>} */ this._nodesMap = new Map(); + this._uiAnimations = []; this._groupBuffer = []; this._groupBufferSize = 8; /** @type {!Map.<!WebInspector.AnimationModel.AnimationGroup, !WebInspector.AnimationGroupPreviewUI>} */ @@ -34,6 +35,7 @@ this._animationsMap = new Map(); WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._nodeChanged, this); } WebInspector.AnimationTimeline.GlobalPlaybackRates = [1, 0.25, 0.1]; @@ -312,23 +314,13 @@ this.scheduleRedraw(); }, - /** - * @return {number|undefined} - */ - startTime: function() - { - return this._startTime; - }, - _clearTimeline: function() { this._nodesMap.clear(); this._animationsMap.clear(); this._animationsContainer.removeChildren(); this._duration = this._defaultDuration(); - delete this._startTime; this._timelineScrubber.classList.add("hidden"); - }, _reset: function() @@ -435,6 +427,7 @@ this._selectedGroup = group; this._previewMap.forEach(applySelectionClass, this); this._clearTimeline(); + this.setDuration(Math.max(500, group.finiteDuration() + 100)); for (var anim of group.animations()) this._addAnimation(anim); this.scheduleRedraw(); @@ -454,24 +447,22 @@ */ function nodeResolved(node) { - if (!node) - return; + nodeUI.nodeResolved(node); uiAnimation.setNode(node); - node[this._symbol] = nodeUI; + if (node) + node[this._symbol] = nodeUI; } - this._resizeWindow(animation); - var nodeUI = this._nodesMap.get(animation.source().backendNodeId()); if (!nodeUI) { nodeUI = new WebInspector.AnimationTimeline.NodeUI(animation.source()); this._animationsContainer.appendChild(nodeUI.element); this._nodesMap.set(animation.source().backendNodeId(), nodeUI); } - var nodeRow = nodeUI.findRow(animation); - var uiAnimation = new WebInspector.AnimationUI(animation, this, nodeRow.element); + var nodeRow = nodeUI.createNewRow(); + var uiAnimation = new WebInspector.AnimationUI(animation, this, nodeRow); animation.source().deferredNode().resolve(nodeResolved.bind(this)); - nodeRow.animations.push(uiAnimation); + this._uiAnimations.push(uiAnimation); this._animationsMap.set(animation.id(), animation); }, @@ -525,8 +516,8 @@ _redraw: function(timestamp) { delete this._redrawing; - for (var nodeUI of this._nodesMap.values()) - nodeUI.redraw(); + for (var ui of this._uiAnimations) + ui.redraw(); this._renderGrid(); }, @@ -553,15 +544,13 @@ _resizeWindow: function(animation) { var resized = false; - if (!this._startTime) - this._startTime = animation.startTime(); // This shows at most 3 iterations - var duration = animation.source().duration() * Math.min(3, animation.source().iterations()); - var requiredDuration = animation.startTime() + animation.source().delay() + duration + animation.source().endDelay() - this.startTime(); - if (requiredDuration > this._duration * 0.8) { + var duration = animation.source().duration() * Math.min(2, animation.source().iterations()); + var requiredDuration = animation.source().delay() + duration + animation.source().endDelay(); + if (requiredDuration > this._duration) { resized = true; - this._duration = requiredDuration * 1.5; + this._duration = requiredDuration + 200; } return resized; }, @@ -689,72 +678,32 @@ */ WebInspector.AnimationTimeline.NodeUI = function(animationEffect) { - /** - * @param {?WebInspector.DOMNode} node - * @this {WebInspector.AnimationTimeline.NodeUI} - */ - function nodeResolved(node) - { - if (!node) - return; - this._node = node; - this._nodeChanged(); - this._description.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node)); - } - - this._rows = []; this.element = createElementWithClass("div", "animation-node-row"); this._description = this.element.createChild("div", "animation-node-description"); - animationEffect.deferredNode().resolve(nodeResolved.bind(this)); this._timelineElement = this.element.createChild("div", "animation-node-timeline"); } -/** @typedef {{element: !Element, animations: !Array<!WebInspector.AnimationUI>}} */ -WebInspector.AnimationTimeline.NodeRow; - WebInspector.AnimationTimeline.NodeUI.prototype = { /** - * @param {!WebInspector.AnimationModel.Animation} animation - * @return {!WebInspector.AnimationTimeline.NodeRow} + * @param {?WebInspector.DOMNode} node */ - findRow: function(animation) + nodeResolved: function(node) { - // Check if it can fit into an existing row - var existingRow = this._collapsibleIntoRow(animation); - if (existingRow) - return existingRow; - - // Create new row - var container = this._timelineElement.createChild("div", "animation-timeline-row"); - var nodeRow = {element: container, animations: []}; - this._rows.push(nodeRow); - return nodeRow; - }, - - redraw: function() - { - for (var nodeRow of this._rows) { - for (var ui of nodeRow.animations) - ui.redraw(); + if (!node) { + this._description.createTextChild(WebInspector.UIString("<node>")); + return; } + this._node = node; + this._nodeChanged(); + this._description.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node)); }, /** - * @param {!WebInspector.AnimationModel.Animation} animation - * @return {?WebInspector.AnimationTimeline.NodeRow} + * @return {!Element} */ - _collapsibleIntoRow: function(animation) + createNewRow: function() { - if (animation.endTime() === Infinity) - return null; - for (var nodeRow of this._rows) { - var overlap = false; - for (var ui of nodeRow.animations) - overlap |= animation.overlaps(ui.animation()); - if (!overlap) - return nodeRow; - } - return null; + return this._timelineElement.createChild("div", "animation-timeline-row"); }, nodeRemoved: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js index 1e587d3..68010e0 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js
@@ -195,15 +195,13 @@ redraw: function() { var durationWithDelay = this._delay() + this._duration() * this._animation.source().iterations() + this._animation.source().endDelay(); - var leftMargin = ((this._animation.startTime() - this._timeline.startTime()) * this._timeline.pixelMsRatio()); - var maxWidth = this._timeline.width() - WebInspector.AnimationUI.Options.AnimationMargin - leftMargin; + var maxWidth = this._timeline.width() - WebInspector.AnimationUI.Options.AnimationMargin; this._svg.classList.toggle("animation-ui-canceled", this._animation.playState() === "idle"); this._svg.setAttribute("width", (maxWidth + 2 * WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2)); - this._svg.style.transform = "translateX(" + leftMargin.toFixed(2) + "px)"; this._activeIntervalGroup.style.transform = "translateX(" + (this._delay() * this._timeline.pixelMsRatio()).toFixed(2) + "px)"; - this._nameElement.style.transform = "translateX(" + (leftMargin + this._delay() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2) + "px)"; + this._nameElement.style.transform = "translateX(" + (this._delay() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2) + "px)"; this._nameElement.style.width = (this._duration() * this._timeline.pixelMsRatio()).toFixed(2) + "px"; this._drawDelayLine(this._svg); @@ -327,7 +325,7 @@ _mouseMove: function (event) { this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pixelMsRatio(); - if (this._animation.startTime() + this._delay() + this._duration() - this._timeline.startTime() > this._timeline.duration() * 0.8) + if (this._delay() + this._duration() > this._timeline.duration() * 0.8) this._timeline.setDuration(this._timeline.duration() * 1.2); this.redraw(); },
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/animationTimeline.css b/third_party/WebKit/Source/devtools/front_end/animation/animationTimeline.css index fb207f64..9a02b3d1 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/animationTimeline.css +++ b/third_party/WebKit/Source/devtools/front_end/animation/animationTimeline.css
@@ -86,7 +86,6 @@ text-align: center; margin-left: -8px; white-space: nowrap; - min-width: 50px; } .animation-timeline-toolbar-container {
diff --git a/third_party/WebKit/Source/devtools/front_end/components/domUtils.css b/third_party/WebKit/Source/devtools/front_end/components/domUtils.css index 79e2544..09397a03 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/domUtils.css +++ b/third_party/WebKit/Source/devtools/front_end/components/domUtils.css
@@ -11,6 +11,7 @@ .node-link { cursor: pointer; display: inline; + pointer-events: auto; } .stack-preview-async-description {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index 1b99a6d..3927cbc 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -618,8 +618,6 @@ { if (typeof b === "string") b = createTextNode(b); - else if (b.shadowRoot) - b = createTextNode(b.shadowRoot.lastChild.textContent); element.appendChild(b); } String.format(WebInspector.UIString(format), substitutions, formatters, initialValue, append);
diff --git a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp index 41bf1f2fb..9a9acdb0 100644 --- a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp +++ b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp
@@ -46,7 +46,7 @@ { } -PassRefPtr<EncodedFormData> PasswordCredential::encodeFormData() const +PassRefPtr<EncodedFormData> PasswordCredential::encodeFormData(String& contentType) const { if (m_additionalData.isURLSearchParams()) { // If |additionalData| is a 'URLSearchParams' object, build a urlencoded response. @@ -57,6 +57,8 @@ params->append(idName(), id()); params->append(passwordName(), password()); + contentType = AtomicString("application/x-www-form-urlencoded;charset=UTF-8", AtomicString::ConstructFromLiteral); + return params->encodeFormData(); } @@ -74,7 +76,9 @@ formData->append(idName(), id()); formData->append(passwordName(), password()); - return formData->encodeMultiPartFormData(); + RefPtr<EncodedFormData> encodedData = formData->encodeMultiPartFormData(); + contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + encodedData->boundary().data(); + return encodedData.release(); } const String& PasswordCredential::password() const
diff --git a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.h b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.h index 38ac8d7..c34b11a 100644 --- a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.h +++ b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.h
@@ -39,7 +39,7 @@ void additionalData(CredentialPostBodyType& out) const { out = m_additionalData; } // Internal methods - PassRefPtr<EncodedFormData> encodeFormData() const; + PassRefPtr<EncodedFormData> encodeFormData(String& contentType) const; const String& password() const; DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp b/third_party/WebKit/Source/modules/fetch/RequestInit.cpp index a356d26..dd14ee8c 100644 --- a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp +++ b/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
@@ -92,11 +92,7 @@ isCredentialRequest = true; PasswordCredential* credential = V8PasswordCredential::toImpl(v8::Local<v8::Object>::Cast(v8Body)); - RefPtr<EncodedFormData> encodedData = credential->encodeFormData(); - if (encodedData->boundary().isEmpty()) - contentType = AtomicString("application/x-www-form-urlencoded;charset=UTF-8", AtomicString::ConstructFromLiteral); - else - contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + encodedData->boundary().data(); + RefPtr<EncodedFormData> encodedData = credential->encodeFormData(contentType); body = FetchFormDataConsumerHandle::create(context, encodedData.release()); } else if (v8Body->IsString()) { contentType = "text/plain;charset=UTF-8";
diff --git a/third_party/WebKit/Source/modules/vr/PositionSensorVRDevice.cpp b/third_party/WebKit/Source/modules/vr/PositionSensorVRDevice.cpp index d36b1fa..083f162e 100644 --- a/third_party/WebKit/Source/modules/vr/PositionSensorVRDevice.cpp +++ b/third_party/WebKit/Source/modules/vr/PositionSensorVRDevice.cpp
@@ -17,13 +17,12 @@ VRPositionState* PositionSensorVRDevice::getState() { - // FIXME: This value should be stable for the duration of a requestAnimationFrame callback return hardwareUnit()->getSensorState(); } VRPositionState* PositionSensorVRDevice::getImmediateState() { - return hardwareUnit()->getSensorState(); + return hardwareUnit()->getImmediateSensorState(false); } void PositionSensorVRDevice::resetSensor()
diff --git a/third_party/WebKit/Source/modules/vr/VREyeParameters.cpp b/third_party/WebKit/Source/modules/vr/VREyeParameters.cpp index ce9a42e..8c39e87d 100644 --- a/third_party/WebKit/Source/modules/vr/VREyeParameters.cpp +++ b/third_party/WebKit/Source/modules/vr/VREyeParameters.cpp
@@ -14,7 +14,7 @@ point->setX(vec.x); point->setY(vec.y); point->setZ(vec.z); - point->setW(0.0); + point->setW(1.0); } } // namespace
diff --git a/third_party/WebKit/Source/modules/vr/VRHardwareUnit.cpp b/third_party/WebKit/Source/modules/vr/VRHardwareUnit.cpp index f463332..c01614f 100644 --- a/third_party/WebKit/Source/modules/vr/VRHardwareUnit.cpp +++ b/third_party/WebKit/Source/modules/vr/VRHardwareUnit.cpp
@@ -18,12 +18,15 @@ : m_nextDeviceId(1) , m_frameIndex(0) , m_navigatorVRDevice(navigatorVRDevice) + , m_canUpdatePositionState(true) { m_positionState = VRPositionState::create(); } VRHardwareUnit::~VRHardwareUnit() { + if (!m_canUpdatePositionState) + Platform::current()->currentThread()->removeTaskObserver(this); } void VRHardwareUnit::updateFromWebVRDevice(const WebVRDevice& device) @@ -64,11 +67,35 @@ VRPositionState* VRHardwareUnit::getSensorState() { + if (m_canUpdatePositionState) { + m_positionState = getImmediateSensorState(true); + Platform::current()->currentThread()->addTaskObserver(this); + m_canUpdatePositionState = false; + } + + return m_positionState; +} + +VRPositionState* VRHardwareUnit::getImmediateSensorState(bool updateFrameIndex) +{ WebHMDSensorState state; controller()->getSensorState(m_index, state); - m_positionState->setState(state); - m_frameIndex = state.frameIndex; - return m_positionState; + if (updateFrameIndex) + m_frameIndex = state.frameIndex; + + VRPositionState* immediatePositionState = VRPositionState::create(); + immediatePositionState->setState(state); + return immediatePositionState; +} + + +void VRHardwareUnit::didProcessTask() +{ + // State should be stable until control is returned to the user agent. + if (!m_canUpdatePositionState) { + Platform::current()->currentThread()->removeTaskObserver(this); + m_canUpdatePositionState = true; + } } DEFINE_TRACE(VRHardwareUnit)
diff --git a/third_party/WebKit/Source/modules/vr/VRHardwareUnit.h b/third_party/WebKit/Source/modules/vr/VRHardwareUnit.h index 62a4cbee..996513d 100644 --- a/third_party/WebKit/Source/modules/vr/VRHardwareUnit.h +++ b/third_party/WebKit/Source/modules/vr/VRHardwareUnit.h
@@ -8,6 +8,7 @@ #include "modules/vr/VRFieldOfView.h" #include "modules/vr/VRPositionState.h" #include "platform/heap/Handle.h" +#include "public/platform/WebThread.h" #include "wtf/text/WTFString.h" namespace blink { @@ -24,7 +25,7 @@ VREyeNone, }; -class VRHardwareUnit : public GarbageCollectedFinalized<VRHardwareUnit> { +class VRHardwareUnit : public GarbageCollectedFinalized<VRHardwareUnit>, public WebThread::TaskObserver { public: explicit VRHardwareUnit(NavigatorVRDevice*); virtual ~VRHardwareUnit(); @@ -42,6 +43,7 @@ // VRController queries VRPositionState* getSensorState(); + VRPositionState* getImmediateSensorState(bool updateFrameIndex); HMDVRDevice* hmd() const { return m_hmd; } PositionSensorVRDevice* positionSensor() const { return m_positionSensor; } @@ -49,6 +51,10 @@ DECLARE_VIRTUAL_TRACE(); private: + // TaskObserver implementation. + void didProcessTask() override; + void willProcessTask() override { } + unsigned m_index; String m_hardwareUnitId; unsigned m_nextDeviceId; @@ -57,6 +63,7 @@ Member<NavigatorVRDevice> m_navigatorVRDevice; Member<VRPositionState> m_positionState; + bool m_canUpdatePositionState; // Device types Member<HMDVRDevice> m_hmd;
diff --git a/third_party/WebKit/Source/modules/vr/VRPositionState.cpp b/third_party/WebKit/Source/modules/vr/VRPositionState.cpp index 0a1738b8..8c7a956 100644 --- a/third_party/WebKit/Source/modules/vr/VRPositionState.cpp +++ b/third_party/WebKit/Source/modules/vr/VRPositionState.cpp
@@ -18,7 +18,7 @@ DOMPoint* vecToDomPoint(const WebVRVector3& vec, bool valid) { if (valid) - return DOMPoint::create(vec.x, vec.y, vec.z, 0.0); + return DOMPoint::create(vec.x, vec.y, vec.z, 1.0); return nullptr; }
diff --git a/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystemPosix.cpp b/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystemPosix.cpp index a1921a0..fda7d6c 100644 --- a/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystemPosix.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystemPosix.cpp
@@ -143,17 +143,10 @@ int chromiumOpenInternal(sqlite3_vfs* vfs, const char* fileName, sqlite3_file* id, int desiredFlags, int* usedFlags) { chromium_sqlite3_initialize_unix_sqlite3_file(id); - int fd = -1; - int result = chromium_sqlite3_get_reusable_file_handle(id, fileName, desiredFlags, &fd); - if (result != SQLITE_OK) - return result; - - if (fd < 0) { - fd = Platform::current()->databaseOpenFile(String(fileName), desiredFlags); - if ((fd < 0) && (desiredFlags & SQLITE_OPEN_READWRITE)) { - int newFlags = (desiredFlags & ~(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)) | SQLITE_OPEN_READONLY; - fd = Platform::current()->databaseOpenFile(String(fileName), newFlags); - } + int fd = Platform::current()->databaseOpenFile(String(fileName), desiredFlags); + if ((fd < 0) && (desiredFlags & SQLITE_OPEN_READWRITE)) { + int newFlags = (desiredFlags & ~(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)) | SQLITE_OPEN_READONLY; + fd = Platform::current()->databaseOpenFile(String(fileName), newFlags); } if (fd < 0) { chromium_sqlite3_destroy_reusable_file_handle(id); @@ -170,7 +163,7 @@ int fileType = desiredFlags & 0x00007F00; int noLock = (fileType != SQLITE_OPEN_MAIN_DB); sqlite3_vfs* wrappedVfs = static_cast<sqlite3_vfs*>(vfs->pAppData); - result = chromium_sqlite3_fill_in_unix_sqlite3_file(wrappedVfs, fd, -1, id, fileName, noLock); + int result = chromium_sqlite3_fill_in_unix_sqlite3_file(wrappedVfs, fd, -1, id, fileName, noLock); if (result != SQLITE_OK) chromium_sqlite3_destroy_reusable_file_handle(id); return result;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index 0a5053b3..2e4b21ed 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -49,7 +49,6 @@ CSSGridLayout status=experimental CSSIndependentTransformProperties status=experimental CSSMaskSourceType status=experimental -CSSMotionPath status=stable CSSOMSmoothScroll status=experimental CSSStickyPosition CSSTouchActionPanDirections status=experimental
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm index 666c28e..39e1e14 100644 --- a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm +++ b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
@@ -35,15 +35,15 @@ #include "platform/RuntimeEnabledFeatures.h" #include "platform/fonts/FontDescription.h" #include "platform/fonts/FontFaceCreationParams.h" -#include "platform/fonts/FontPlatformData.h" +#include "platform/fonts/FontPlatformData.h" #include "platform/fonts/SimpleFontData.h" #include "platform/fonts/mac/FontFamilyMatcherMac.h" #include "public/platform/Platform.h" #include "public/platform/WebTaskRunner.h" #include "public/platform/WebTraceLocation.h" -#include <wtf/Functional.h> -#include <wtf/MainThread.h> -#include <wtf/StdLibExtras.h> +#include "wtf/Functional.h" +#include "wtf/MainThread.h" +#include "wtf/StdLibExtras.h" // Forward declare Mac SPIs. // Request for public API: rdar://13803570
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.mm b/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.mm index d71d4b2..8a0bb29 100644 --- a/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.mm +++ b/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.mm
@@ -33,12 +33,11 @@ #import <AppKit/AppKit.h> #import <Foundation/Foundation.h> #import <math.h> -#import <wtf/HashSet.h> -#import <wtf/text/AtomicStringHash.h> - #include "platform/fonts/FontTraits.h" #include "platform/LayoutTestSupport.h" #include "platform/mac/VersionUtilMac.h" +#import "wtf/HashSet.h" +#import "wtf/text/AtomicStringHash.h" @interface NSFont (YosemiteAdditions) + (NSFont*)systemFontOfSize:(CGFloat)size weight:(CGFloat)weight;
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp index 5cf79cc4..256190d7 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -116,7 +116,7 @@ , m_paintCount(0) , m_contentsLayer(0) , m_contentsLayerId(0) - , m_scrollableArea(0) + , m_scrollableArea(nullptr) , m_3dRenderingContext(0) { #if ENABLE(ASSERT)
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h index de584cc..371b1f1 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -368,8 +368,7 @@ OwnPtr<ContentLayerDelegate> m_contentLayerDelegate; - GC_PLUGIN_IGNORE("509911") - ScrollableArea* m_scrollableArea; + RawPtrWillBeWeakPersistent<ScrollableArea> m_scrollableArea; GraphicsLayerDebugInfo m_debugInfo; int m_3dRenderingContext;
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.cpp b/third_party/WebKit/Source/platform/heap/HeapPage.cpp index 10b30f8..1364135 100644 --- a/third_party/WebKit/Source/platform/heap/HeapPage.cpp +++ b/third_party/WebKit/Source/platform/heap/HeapPage.cpp
@@ -177,8 +177,10 @@ { clearFreeLists(); ASSERT(isConsistentForGC()); - for (BasePage* page = m_firstPage; page; page = page->next()) + for (BasePage* page = m_firstPage; page; page = page->next()) { page->markAsUnswept(); + page->invalidateObjectStartBitmap(); + } // If a new GC is requested before this thread got around to sweep, // ie. due to the thread doing a long running operation, we clear @@ -191,6 +193,7 @@ for (BasePage* page = m_firstUnsweptPage; page; previousPage = page, page = page->next()) { page->makeConsistentForGC(); ASSERT(!page->hasBeenSwept()); + page->invalidateObjectStartBitmap(); } if (previousPage) { ASSERT(m_firstUnsweptPage); @@ -213,6 +216,7 @@ for (BasePage* page = m_firstUnsweptPage; page; previousPage = page, page = page->next()) { page->makeConsistentForMutator(); page->markAsSwept(); + page->invalidateObjectStartBitmap(); } if (previousPage) { ASSERT(m_firstUnsweptPage); @@ -508,7 +512,6 @@ m_freeList.clear(); size_t freedSize = 0; for (NormalPage* page = static_cast<NormalPage*>(m_firstPage); page; page = static_cast<NormalPage*>(page->next())) { - page->clearObjectStartBitMap(); Address startOfGap = page->payload(); for (Address headerAddress = startOfGap; headerAddress < page->payloadEnd(); ) { HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAddress); @@ -1073,8 +1076,8 @@ NormalPage::NormalPage(PageMemory* storage, BaseHeap* heap) : BasePage(storage, heap) + , m_objectStartBitMapComputed(false) { - m_objectStartBitMapComputed = false; ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); } @@ -1110,8 +1113,6 @@ void NormalPage::sweep() { - clearObjectStartBitMap(); - size_t markedObjectSize = 0; Address startOfGap = payload(); for (Address headerAddress = startOfGap; headerAddress < payloadEnd(); ) { @@ -1266,11 +1267,6 @@ m_objectStartBitMapComputed = true; } -void NormalPage::clearObjectStartBitMap() -{ - m_objectStartBitMapComputed = false; -} - static int numberOfLeadingZeroes(uint8_t byte) { if (!byte) @@ -1293,7 +1289,7 @@ { if (address < payload()) return nullptr; - if (!isObjectStartBitMapComputed()) + if (!m_objectStartBitMapComputed) populateObjectStartBitMap(); size_t objectOffset = address - payload(); size_t objectStartNumber = objectOffset / allocationGranularity;
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.h b/third_party/WebKit/Source/platform/heap/HeapPage.h index 7dc892e..b35988a 100644 --- a/third_party/WebKit/Source/platform/heap/HeapPage.h +++ b/third_party/WebKit/Source/platform/heap/HeapPage.h
@@ -235,14 +235,14 @@ #endif // In 64 bit architectures, we intentionally add 4 byte padding immediately - // after the HeapHeaderObject. This is because: + // after the HeapObjectHeader. This is because: // - // | HeapHeaderObject (4 byte) | padding (4 byte) | object payload (8 * n byte) | + // | HeapObjectHeader (4 byte) | padding (4 byte) | object payload (8 * n byte) | // ^8 byte aligned ^8 byte aligned // // is better than: // - // | HeapHeaderObject (4 byte) | object payload (8 * n byte) | padding (4 byte) | + // | HeapObjectHeader (4 byte) | object payload (8 * n byte) | padding (4 byte) | // ^4 byte aligned ^8 byte aligned ^4 byte aligned // // since the former layout aligns both header and payload to 8 byte. @@ -373,6 +373,7 @@ virtual void sweep() = 0; virtual void makeConsistentForGC() = 0; virtual void makeConsistentForMutator() = 0; + virtual void invalidateObjectStartBitmap() = 0; #if defined(ADDRESS_SANITIZER) virtual void poisonObjects(BlinkGC::ObjectsToPoison, BlinkGC::Poisoning) = 0; @@ -457,6 +458,7 @@ void sweep() override; void makeConsistentForGC() override; void makeConsistentForMutator() override; + void invalidateObjectStartBitmap() override { m_objectStartBitMapComputed = false; } #if defined(ADDRESS_SANITIZER) void poisonObjects(BlinkGC::ObjectsToPoison, BlinkGC::Poisoning) override; #endif @@ -481,12 +483,10 @@ NormalPageHeap* heapForNormalPage(); - void clearObjectStartBitMap(); private: HeapObjectHeader* findHeaderFromAddress(Address); void populateObjectStartBitMap(); - bool isObjectStartBitMapComputed() { return m_objectStartBitMapComputed; } bool m_objectStartBitMapComputed; uint8_t m_objectStartBitMap[reservedForObjectBitMap]; @@ -515,6 +515,7 @@ void sweep() override; void makeConsistentForGC() override; void makeConsistentForMutator() override; + void invalidateObjectStartBitmap() override { } #if defined(ADDRESS_SANITIZER) void poisonObjects(BlinkGC::ObjectsToPoison, BlinkGC::Poisoning) override; #endif
diff --git a/third_party/WebKit/Source/platform/mac/BlockExceptions.h b/third_party/WebKit/Source/platform/mac/BlockExceptions.h index 10f80b2..6882ac85f 100644 --- a/third_party/WebKit/Source/platform/mac/BlockExceptions.h +++ b/third_party/WebKit/Source/platform/mac/BlockExceptions.h
@@ -23,9 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import <platform/PlatformExport.h> #import <Foundation/NSException.h> -#import <wtf/Assertions.h> +#import "platform/PlatformExport.h" +#import "wtf/Assertions.h" PLATFORM_EXPORT NO_RETURN_DUE_TO_ASSERT void ReportBlockedObjCException(NSException *);
diff --git a/third_party/WebKit/Source/platform/mac/BlockExceptions.mm b/third_party/WebKit/Source/platform/mac/BlockExceptions.mm index af3b879c..bb8d32ce 100644 --- a/third_party/WebKit/Source/platform/mac/BlockExceptions.mm +++ b/third_party/WebKit/Source/platform/mac/BlockExceptions.mm
@@ -26,7 +26,7 @@ #import "config.h" #import "platform/mac/BlockExceptions.h" -#import <wtf/Assertions.h> +#import "wtf/Assertions.h" void ReportBlockedObjCException(NSException *exception) {
diff --git a/third_party/WebKit/Source/platform/mac/ColorMac.mm b/third_party/WebKit/Source/platform/mac/ColorMac.mm index 7a1eef6..2265b45 100644 --- a/third_party/WebKit/Source/platform/mac/ColorMac.mm +++ b/third_party/WebKit/Source/platform/mac/ColorMac.mm
@@ -26,8 +26,8 @@ #import "config.h" #import "platform/mac/ColorMac.h" -#import <wtf/RetainPtr.h> -#import <wtf/StdLibExtras.h> +#import "wtf/RetainPtr.h" +#import "wtf/StdLibExtras.h" namespace blink {
diff --git a/third_party/WebKit/Source/web/WebDevToolsFrontendImpl.h b/third_party/WebKit/Source/web/WebDevToolsFrontendImpl.h index 2825ab4f..4d9e770f 100644 --- a/third_party/WebKit/Source/web/WebDevToolsFrontendImpl.h +++ b/third_party/WebKit/Source/web/WebDevToolsFrontendImpl.h
@@ -60,9 +60,7 @@ void setInjectedScriptForOrigin(const String& origin, const String& source) override; private: - // TODO(Oilpan): Make the lifetime of m_webFrame clear to remove this GC_PLUGIN_IGNORE. - GC_PLUGIN_IGNORE("http://crbug.com/509911") - WebLocalFrameImpl* m_webFrame; + RefPtrWillBePersistent<WebLocalFrameImpl> m_webFrame; WebDevToolsFrontendClient* m_client; RefPtrWillBePersistent<DevToolsHost> m_devtoolsHost; typedef HashMap<String, String> InjectedScriptForOriginMap;
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp index 95730bd..f6a78101 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1631,6 +1631,11 @@ return WebLocalFrameImpl::create(scope, client); } +WebLocalFrame* WebLocalFrame::createProvisional(WebFrameClient* client, WebRemoteFrame* oldWebFrame, WebSandboxFlags flags, const WebFrameOwnerProperties& frameOwnerProperties) +{ + return WebLocalFrameImpl::createProvisional(client, oldWebFrame, flags, frameOwnerProperties); +} + WebLocalFrameImpl* WebLocalFrameImpl::create(WebTreeScopeType scope, WebFrameClient* client) { WebLocalFrameImpl* frame = new WebLocalFrameImpl(scope, client); @@ -1641,6 +1646,45 @@ #endif } +WebLocalFrameImpl* WebLocalFrameImpl::createProvisional(WebFrameClient* client, WebRemoteFrame* oldWebFrame, WebSandboxFlags flags, const WebFrameOwnerProperties& frameOwnerProperties) +{ + RefPtrWillBeRawPtr<WebLocalFrameImpl> webFrame = adoptRefWillBeNoop(new WebLocalFrameImpl(oldWebFrame, client)); + Frame* oldFrame = oldWebFrame->toImplBase()->frame(); + webFrame->setParent(oldWebFrame->parent()); + webFrame->setOpener(oldWebFrame->opener()); + // Note: this *always* temporarily sets a frame owner, even for main frames! + // When a core Frame is created with no owner, it attempts to set itself as + // the main frame of the Page. However, this is a provisional frame, and may + // disappear, so Page::m_mainFrame can't be updated just yet. + OwnPtrWillBeRawPtr<FrameOwner> tempOwner = RemoteBridgeFrameOwner::create(nullptr, SandboxNone, WebFrameOwnerProperties()); + // TODO(dcheng): This block is very similar to initializeCoreFrame. Try to reuse it here. + RefPtrWillBeRawPtr<LocalFrame> frame = LocalFrame::create(webFrame->m_frameLoaderClientImpl.get(), oldFrame->host(), tempOwner.get()); + // Set the name and unique name directly, bypassing any of the normal logic + // to calculate unique name. + frame->tree().setNameForReplacementFrame(toWebRemoteFrameImpl(oldWebFrame)->frame()->tree().name(), toWebRemoteFrameImpl(oldWebFrame)->frame()->tree().uniqueName()); + webFrame->setCoreFrame(frame); + + frame->setOwner(oldFrame->owner()); + + if (frame->owner() && !frame->owner()->isLocal()) { + toRemoteBridgeFrameOwner(frame->owner())->setSandboxFlags(static_cast<SandboxFlags>(flags)); + // Since a remote frame doesn't get the notifications about frame owner + // property modifications, we need to sync up those properties here. + webFrame->setFrameOwnerProperties(frameOwnerProperties); + } + + // We must call init() after m_frame is assigned because it is referenced + // during init(). Note that this may dispatch JS events; the frame may be + // detached after init() returns. + frame->init(); +#if ENABLE(OILPAN) + return webFrame.get(); +#else + return webFrame.release().leakRef(); +#endif +} + + WebLocalFrameImpl::WebLocalFrameImpl(WebTreeScopeType scope, WebFrameClient* client) : WebLocalFrame(scope) , m_frameLoaderClientImpl(FrameLoaderClientImpl::create(this)) @@ -1660,6 +1704,11 @@ frameCount++; } +WebLocalFrameImpl::WebLocalFrameImpl(WebRemoteFrame* oldWebFrame, WebFrameClient* client) + : WebLocalFrameImpl(oldWebFrame->inShadowTree() ? WebTreeScopeType::Shadow : WebTreeScopeType::Document, client) +{ +} + WebLocalFrameImpl::~WebLocalFrameImpl() { // The widget for the frame, if any, must have already been closed. @@ -1982,38 +2031,6 @@ frameLoader.stateMachine()->advanceTo(FrameLoaderStateMachine::CommittedMultipleRealLoads); } -void WebLocalFrameImpl::initializeToReplaceRemoteFrame(WebRemoteFrame* oldWebFrame, const WebString& name, WebSandboxFlags flags, const WebFrameOwnerProperties& frameOwnerProperties) -{ - Frame* oldFrame = oldWebFrame->toImplBase()->frame(); - // Note: this *always* temporarily sets a frame owner, even for main frames! - // When a core Frame is created with no owner, it attempts to set itself as - // the main frame of the Page. However, this is a provisional frame, and may - // disappear, so Page::m_mainFrame can't be updated just yet. - OwnPtrWillBeRawPtr<FrameOwner> tempOwner = RemoteBridgeFrameOwner::create(nullptr, SandboxNone, WebFrameOwnerProperties()); - RefPtrWillBeRawPtr<LocalFrame> frame = LocalFrame::create(m_frameLoaderClientImpl.get(), oldFrame->host(), tempOwner.get()); - frame->setOwner(oldFrame->owner()); - setParent(oldWebFrame->parent()); - setOpener(oldWebFrame->opener()); - - // Set the name and unique name directly. - // TODO(creis): Remove |name| and use the oldWebFrame's name. - frame->tree().setNameForReplacementFrame(name, toWebRemoteFrameImpl(oldWebFrame)->frame()->tree().uniqueName()); - - setCoreFrame(frame); - - if (frame->owner() && !frame->owner()->isLocal()) { - toRemoteBridgeFrameOwner(frame->owner())->setSandboxFlags(static_cast<SandboxFlags>(flags)); - // Since a remote frame doesn't get the notifications about frame owner - // property modifications, we need to sync up those properties here. - WebLocalFrameImpl::fromFrame(frame.get())->setFrameOwnerProperties(frameOwnerProperties); - } - - // We must call init() after m_frame is assigned because it is referenced - // during init(). Note that this may dispatch JS events; the frame may be - // detached after init() returns. - frame->init(); -} - void WebLocalFrameImpl::setAutofillClient(WebAutofillClient* autofillClient) { m_autofillClient = autofillClient;
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h index ecc3356..c2618b72 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -235,7 +235,6 @@ v8::Local<v8::Value> createTestInterface(const AtomicString& name); // WebLocalFrame methods: - void initializeToReplaceRemoteFrame(WebRemoteFrame*, const WebString& name, WebSandboxFlags, const WebFrameOwnerProperties&) override; void setAutofillClient(WebAutofillClient*) override; WebAutofillClient* autofillClient() override; void setDevToolsAgentClient(WebDevToolsAgentClient*) override; @@ -267,6 +266,7 @@ void willDetachParent(); static WebLocalFrameImpl* create(WebTreeScopeType, WebFrameClient*); + static WebLocalFrameImpl* createProvisional(WebFrameClient*, WebRemoteFrame*, WebSandboxFlags, const WebFrameOwnerProperties&); ~WebLocalFrameImpl() override; PassRefPtrWillBeRawPtr<LocalFrame> createChildFrame(const FrameLoadRequest&, const AtomicString& name, HTMLFrameOwnerElement*); @@ -355,6 +355,7 @@ friend class FrameLoaderClientImpl; WebLocalFrameImpl(WebTreeScopeType, WebFrameClient*); + WebLocalFrameImpl(WebRemoteFrame*, WebFrameClient*); // Sets the local core frame and registers destruction observers. void setCoreFrame(PassRefPtrWillBeRawPtr<LocalFrame>);
diff --git a/third_party/WebKit/Source/web/tests/FrameTestHelpers.h b/third_party/WebKit/Source/web/tests/FrameTestHelpers.h index dc110ad..74be950 100644 --- a/third_party/WebKit/Source/web/tests/FrameTestHelpers.h +++ b/third_party/WebKit/Source/web/tests/FrameTestHelpers.h
@@ -163,7 +163,7 @@ WebDOMMessageEvent) override { } private: - WebRemoteFrameImpl* const m_frame; + RawPtrWillBePersistent<WebRemoteFrameImpl> const m_frame; }; class TestWebViewClient : public WebViewClient {
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp index e31d13e..5bb8dd90 100644 --- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -7015,8 +7015,7 @@ mainFrame()->swap(remoteFrame); FrameTestHelpers::TestWebFrameClient client; - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); remoteFrame->swap(localFrame); // Finally, make sure an embedder triggered load in the local frame swapped @@ -7091,8 +7090,7 @@ swapAndVerifyFirstChildConsistency("local->remote", mainFrame(), remoteFrame); FrameTestHelpers::TestWebFrameClient client; - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); swapAndVerifyFirstChildConsistency("remote->local", mainFrame(), localFrame); // FIXME: This almost certainly fires more load events on the iframe element @@ -7130,8 +7128,7 @@ swapAndVerifyMiddleChildConsistency("local->remote", mainFrame(), remoteFrame); FrameTestHelpers::TestWebFrameClient client; - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); swapAndVerifyMiddleChildConsistency("remote->local", mainFrame(), localFrame); // FIXME: This almost certainly fires more load events on the iframe element @@ -7166,8 +7163,7 @@ swapAndVerifyLastChildConsistency("local->remote", mainFrame(), remoteFrame); FrameTestHelpers::TestWebFrameClient client; - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); swapAndVerifyLastChildConsistency("remote->local", mainFrame(), localFrame); // FIXME: This almost certainly fires more load events on the iframe element @@ -7211,8 +7207,7 @@ WebRemoteFrame* childRemoteFrame = remoteFrame->createRemoteChild(WebTreeScopeType::Document, "", WebSandboxFlags::None, &remoteFrameClient2); FrameTestHelpers::TestWebFrameClient client; - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); swapAndVerifySubframeConsistency("remote->local", targetFrame, localFrame); // FIXME: This almost certainly fires more load events on the iframe element @@ -7255,8 +7250,7 @@ // Now check that remote -> local works too, since it goes through a different code path. FrameTestHelpers::TestWebFrameClient client; - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); remoteFrame->swap(localFrame); v8::Local<v8::Value> localWindow = mainFrame()->executeScriptAndReturnValue(WebScriptSource( "document.querySelector('#frame2').contentWindow;")); @@ -7289,8 +7283,7 @@ EXPECT_TRUE(windowTop->StrictEquals(remoteWindowTop)); FrameTestHelpers::TestWebFrameClient client; - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); remoteFrame->swap(localFrame); v8::Local<v8::Value> localWindowTop = mainFrame()->executeScriptAndReturnValue(WebScriptSource("saved.top")); EXPECT_TRUE(localWindowTop->IsObject()); @@ -7435,8 +7428,7 @@ ASSERT_EQ(mainFrame()->firstChild(), remoteFrame); RemoteToLocalSwapWebFrameClient client(remoteFrame); - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html"); EXPECT_EQ(WebInitialCommitInChildFrame, client.historyCommitType()); @@ -7460,8 +7452,7 @@ ASSERT_EQ(mainFrame()->firstChild(), remoteFrame); RemoteToLocalSwapWebFrameClient client(remoteFrame); - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); localFrame->setCommittedFirstRealLoad(); FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html"); EXPECT_EQ(WebStandardCommit, client.historyCommitType()); @@ -7492,8 +7483,7 @@ // Swap back to a LocalFrame. RemoteToLocalSwapWebFrameClient client(remoteFrame); - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &client); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "frame1", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&client, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); FrameTestHelpers::loadFrame(localFrame, m_baseURL + "subframe-hello.html"); EXPECT_EQ(uniqueName.utf8(), localFrame->uniqueName().utf8()); EXPECT_EQ(uniqueName.utf8(), WebString(toWebLocalFrameImpl(localFrame)->frame()->loader().currentItem()->target()).utf8()); @@ -7511,8 +7501,7 @@ EXPECT_EQ(uniqueName2.utf8(), WebString(toWebRemoteFrameImpl(remoteFrame2)->frame()->tree().uniqueName()).utf8()); RemoteToLocalSwapWebFrameClient client2(remoteFrame2); - WebLocalFrame* localFrame2 = WebLocalFrame::create(WebTreeScopeType::Document, &client2); - localFrame2->initializeToReplaceRemoteFrame(remoteFrame2, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame2 = WebLocalFrame::createProvisional(&client2, remoteFrame2, WebSandboxFlags::None, WebFrameOwnerProperties()); FrameTestHelpers::loadFrame(localFrame2, m_baseURL + "subframe-hello.html"); EXPECT_EQ(uniqueName2.utf8(), localFrame2->uniqueName().utf8()); EXPECT_EQ(uniqueName2.utf8(), WebString(toWebLocalFrameImpl(localFrame2)->frame()->loader().currentItem()->target()).utf8()); @@ -7650,8 +7639,7 @@ // Do a remote-to-local swap in the popup. FrameTestHelpers::TestWebFrameClient popupLocalClient; - WebLocalFrame* popupLocalFrame = WebLocalFrame::create(WebTreeScopeType::Document, &popupLocalClient); - popupLocalFrame->initializeToReplaceRemoteFrame(popupRemoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* popupLocalFrame = WebLocalFrame::createProvisional(&popupLocalClient, popupRemoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); popupRemoteFrame->swap(popupLocalFrame); // The initial document created during the remote-to-local swap should have @@ -7673,8 +7661,7 @@ // Now swap in a local frame. It shouldn't crash. FrameTestHelpers::TestWebFrameClient localClient; - WebLocalFrame* localFrame = WebLocalFrame::create(WebTreeScopeType::Document, &localClient); - localFrame->initializeToReplaceRemoteFrame(remoteFrame, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localFrame = WebLocalFrame::createProvisional(&localClient, remoteFrame, WebSandboxFlags::None, WebFrameOwnerProperties()); remoteFrame->swap(localFrame); // And the opener cycle should still be preserved. @@ -8021,8 +8008,7 @@ // Do a remote-to-local swap of the top frame. FrameTestHelpers::TestWebFrameClient localClient; - WebLocalFrame* localRoot = WebLocalFrame::create(WebTreeScopeType::Document, &localClient); - localRoot->initializeToReplaceRemoteFrame(remoteRoot, "", WebSandboxFlags::None, WebFrameOwnerProperties()); + WebLocalFrame* localRoot = WebLocalFrame::createProvisional(&localClient, remoteRoot, WebSandboxFlags::None, WebFrameOwnerProperties()); remoteRoot->swap(localRoot); // Load a page with a child frame in the new root to make sure this doesn't
diff --git a/third_party/WebKit/Tools/Scripts/display-profiler-output b/third_party/WebKit/Tools/Scripts/display-profiler-output deleted file mode 100755 index 0a8c15e9c..0000000 --- a/third_party/WebKit/Tools/Scripts/display-profiler-output +++ /dev/null
@@ -1,938 +0,0 @@ -#!/usr/bin/env ruby - -# Copyright (C) 2012, 2013 Apple Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. - -require 'rubygems' - -require 'readline' - -begin - require 'json' - require 'highline' -rescue LoadError - $stderr.puts "Error: some required gems are not installed!" - $stderr.puts - $stderr.puts "Try running:" - $stderr.puts - $stderr.puts "sudo gem install json" - $stderr.puts "sudo gem install highline" - exit 1 -end - -class Bytecode - attr_accessor :bytecodes, :bytecodeIndex, :opcode, :description, :topCounts, :bottomCounts, :machineInlinees, :osrExits - - def initialize(bytecodes, bytecodeIndex, opcode, description) - @bytecodes = bytecodes - @bytecodeIndex = bytecodeIndex - @opcode = opcode - @description = description - @topCounts = [] # "source" counts - @bottomCounts = {} # "machine" counts, maps compilations to counts - @machineInlinees = {} # maps my compilation to a set of inlinees - @osrExits = [] - end - - def shouldHaveCounts? - @opcode != "op_call_put_result" - end - - def addTopCount(count) - @topCounts << count - end - - def addBottomCountForCompilation(count, compilation) - @bottomCounts[compilation] = [] unless @bottomCounts[compilation] - @bottomCounts[compilation] << count - end - - def addMachineInlinee(compilation, inlinee) - @machineInlinees[compilation] = {} unless @machineInlinees[compilation] - @machineInlinees[compilation][inlinee] = true - end - - def totalTopExecutionCount - sum = 0 - @topCounts.each { - | value | - sum += value.count - } - sum - end - - def topExecutionCount(engine) - sum = 0 - @topCounts.each { - | value | - if value.engine == engine - sum += value.count - end - } - sum - end - - def totalBottomExecutionCount - sum = 0 - @bottomCounts.each_value { - | counts | - max = 0 - counts.each { - | value | - max = [max, value.count].max - } - sum += max - } - sum - end - - def bottomExecutionCount(engine) - sum = 0 - @bottomCounts.each_pair { - | compilation, counts | - if compilation.engine == engine - max = 0 - counts.each { - | value | - max = [max, value.count].max - } - sum += max - end - } - sum - end - - def totalExitCount - sum = 0 - @osrExits.each { - | exit | - sum += exit.count - } - sum - end -end - -class Bytecodes - attr_accessor :codeHash, :inferredName, :source, :instructionCount, :machineInlineSites, :compilations - - def initialize(json) - @codeHash = json["hash"].to_s - @inferredName = json["inferredName"].to_s - @source = json["sourceCode"].to_s - @instructionCount = json["instructionCount"].to_i - @bytecode = {} - json["bytecode"].each { - | subJson | - index = subJson["bytecodeIndex"].to_i - @bytecode[index] = Bytecode.new(self, index, subJson["opcode"].to_s, subJson["description"].to_s) - } - @machineInlineSites = {} # maps compilation to a set of origins - @compilations = [] - end - - def name(limit) - if to_s.size > limit - "\##{@codeHash}" - else - to_s - end - end - - def to_s - "#{@inferredName}\##{@codeHash}" - end - - def matches(pattern) - if pattern =~ /^#/ - $~.post_match == @codeHash - elsif pattern =~ /#/ - pattern == to_s - else - pattern == @inferredName or pattern == @codeHash - end - end - - def each - @bytecode.values.sort{|a, b| a.bytecodeIndex <=> b.bytecodeIndex}.each { - | value | - yield value - } - end - - def bytecode(bytecodeIndex) - @bytecode[bytecodeIndex] - end - - def addMachineInlineSite(compilation, origin) - @machineInlineSites[compilation] = {} unless @machineInlineSites[compilation] - @machineInlineSites[compilation][origin] = true - end - - def totalMachineInlineSites - sum = 0 - @machineInlineSites.each_value { - | set | - sum += set.size - } - sum - end - - def sourceMachineInlineSites - set = {} - @machineInlineSites.each_value { - | mySet | - set.merge!(mySet) - } - set.size - end - - def totalMaxTopExecutionCount - max = 0 - @bytecode.each_value { - | bytecode | - max = [max, bytecode.totalTopExecutionCount].max - } - max - end - - def maxTopExecutionCount(engine) - max = 0 - @bytecode.each_value { - | bytecode | - max = [max, bytecode.topExecutionCount(engine)].max - } - max - end - - def totalMaxBottomExecutionCount - max = 0 - @bytecode.each_value { - | bytecode | - max = [max, bytecode.totalBottomExecutionCount].max - } - max - end - - def maxBottomExecutionCount(engine) - max = 0 - @bytecode.each_value { - | bytecode | - max = [max, bytecode.bottomExecutionCount(engine)].max - } - max - end - - def totalExitCount - sum = 0 - each { - | bytecode | - sum += bytecode.totalExitCount - } - sum - end -end - -class ProfiledBytecode - attr_reader :bytecodeIndex, :description - - def initialize(json) - @bytecodeIndex = json["bytecodeIndex"].to_i - @description = json["description"].to_s - end -end - -class ProfiledBytecodes - attr_reader :header, :bytecodes - - def initialize(json) - @header = json["header"] - @bytecodes = $bytecodes[json["bytecodesID"].to_i] - @sequence = json["bytecode"].map { - | subJson | - ProfiledBytecode.new(subJson) - } - end - - def each - @sequence.each { - | description | - yield description - } - end -end - -def originStackFromJSON(json) - json.map { - | subJson | - $bytecodes[subJson["bytecodesID"].to_i].bytecode(subJson["bytecodeIndex"].to_i) - } -end - -class CompiledBytecode - attr_accessor :origin, :description - - def initialize(json) - @origin = originStackFromJSON(json["origin"]) - @description = json["description"].to_s - end -end - -class ExecutionCounter - attr_accessor :origin, :engine, :count - - def initialize(origin, engine, count) - @origin = origin - @engine = engine - @count = count - end -end - -class OSRExit - attr_reader :compilation, :origin, :codeAddresses, :exitKind, :isWatchpoint, :count - - def initialize(compilation, origin, codeAddresses, exitKind, isWatchpoint, count) - @compilation = compilation - @origin = origin - @codeAddresses = codeAddresses - @exitKind = exitKind - @isWatchpoint = isWatchpoint - @count = count - end - - def dumpForDisplay(prefix) - puts(prefix + "EXIT: due to #{@exitKind}, #{@count} times") - end -end - -class Compilation - attr_accessor :bytecode, :engine, :descriptions, :counters, :compilationIndex - attr_accessor :osrExits, :profiledBytecodes, :numInlinedGetByIds, :numInlinedPutByIds - attr_accessor :numInlinedCalls - - def initialize(json) - @bytecode = $bytecodes[json["bytecodesID"].to_i] - @bytecode.compilations << self - @compilationIndex = @bytecode.compilations.size - @engine = json["compilationKind"] - @descriptions = json["descriptions"].map { - | subJson | - CompiledBytecode.new(subJson) - } - @descriptions.each { - | description | - next if description.origin.empty? - description.origin[1..-1].each_with_index { - | inlinee, index | - description.origin[0].addMachineInlinee(self, inlinee.bytecodes) - inlinee.bytecodes.addMachineInlineSite(self, description.origin[0...index]) - } - } - @counters = {} - json["counters"].each { - | subJson | - origin = originStackFromJSON(subJson["origin"]) - counter = ExecutionCounter.new(origin, @engine, subJson["executionCount"].to_i) - @counters[origin] = counter - origin[-1].addTopCount(counter) - origin[0].addBottomCountForCompilation(counter, self) - } - @osrExits = {} - json["osrExits"].each { - | subJson | - osrExit = OSRExit.new(self, originStackFromJSON(subJson["origin"]), - json["osrExitSites"][subJson["id"]].map { - | value | - value.hex - }, subJson["exitKind"], subJson["isWatchpoint"], - subJson["count"]) - osrExit.codeAddresses.each { - | codeAddress | - osrExits[codeAddress] = [] unless osrExits[codeAddress] - osrExits[codeAddress] << osrExit - } - osrExit.origin[-1].osrExits << osrExit - } - @profiledBytecodes = [] - json["profiledBytecodes"].each { - | subJson | - @profiledBytecodes << ProfiledBytecodes.new(subJson) - } - @numInlinedGetByIds = json["numInlinedGetByIds"] - @numInlinedPutByIds = json["numInlinedPutByIds"] - @numInlinedCalls = json["numInlinedCalls"] - end - - def counter(origin) - @counters[origin] - end - - def to_s - "#{bytecode}-#{compilationIndex}-#{engine}" - end -end - -class DescriptionLine - attr_reader :actualCountsString, :sourceCountsString, :disassembly, :shouldShow - - def initialize(actualCountsString, sourceCountsString, disassembly, shouldShow) - @actualCountsString = actualCountsString - @sourceCountsString = sourceCountsString - @disassembly = disassembly - @shouldShow = shouldShow - end - - def codeAddress - if @disassembly =~ /^\s*(0x[0-9a-fA-F]+):/ - $1.hex - else - nil - end - end -end - -if ARGV.length != 1 - $stderr.puts "Usage: display-profiler-output <path to profiler output file>" - $stderr.puts - $stderr.puts "The typical usage pattern for the profiler currently looks something like:" - $stderr.puts - $stderr.puts "Path/To/jsc -p profile.json myprogram.js" - $stderr.puts "display-profiler-output profile.json" - exit 1 -end - -$json = JSON::parse(IO::read(ARGV[0])) -$bytecodes = $json["bytecodes"].map { - | subJson | - Bytecodes.new(subJson) -} -$compilations = $json["compilations"].map { - | subJson | - Compilation.new(subJson) -} -$engines = ["Baseline", "DFG"] - -def lpad(str,chars) - if str.length>chars - str - else - "%#{chars}s"%(str) - end -end - -def rpad(str, chars) - while str.length < chars - str += " " - end - str -end - -def center(str, chars) - while str.length < chars - str += " " - if str.length < chars - str = " " + str - end - end - str -end - -def mayBeHash(hash) - hash =~ /#/ or hash.size == 6 -end - -def sourceOnOneLine(source, limit) - source.gsub(/\s+/, ' ')[0...limit] -end - -def screenWidth - if $stdin.tty? - HighLine::SystemExtensions.terminal_size[0] - else - 200 - end -end - -def summary(mode) - remaining = screenWidth - - # Figure out how many columns we need for the code block names, and for counts - maxCount = 0 - maxName = 0 - $bytecodes.each { - | bytecodes | - maxCount = ([maxCount] + $engines.map { - | engine | - bytecodes.maxTopExecutionCount(engine) - } + $engines.map { - | engine | - bytecodes.maxBottomExecutionCount(engine) - }).max - maxName = [bytecodes.to_s.size, maxName].max - } - maxCountDigits = maxCount.to_s.size - - hashCols = [[maxName, 30].min, "CodeBlock".size].max - remaining -= hashCols + 1 - - countCols = [maxCountDigits * $engines.size, "Source Counts".size].max - remaining -= countCols + 1 - - if mode == :full - instructionCountCols = 6 - remaining -= instructionCountCols + 1 - - machineCountCols = [maxCountDigits * $engines.size, "Machine Counts".size].max - remaining -= machineCountCols + 1 - - compilationsCols = 7 - remaining -= compilationsCols + 1 - - inlinesCols = 9 - remaining -= inlinesCols + 1 - - exitCountCols = 7 - remaining -= exitCountCols + 1 - - recentOptsCols = 12 - remaining -= recentOptsCols + 1 - end - - if remaining > 0 - sourceCols = remaining - else - sourceCols = nil - end - - print(center("CodeBlock", hashCols)) - if mode == :full - print(" " + center("#Instr", instructionCountCols)) - end - print(" " + center("Source Counts", countCols)) - if mode == :full - print(" " + center("Machine Counts", machineCountCols)) - print(" " + center("#Compil", compilationsCols)) - print(" " + center("Inlines", inlinesCols)) - print(" " + center("#Exits", exitCountCols)) - print(" " + center("Last Opts", recentOptsCols)) - end - if sourceCols - print(" " + center("Source", sourceCols)) - end - puts - - print(center("", hashCols)) - if mode == :full - print(" " + (" " * instructionCountCols)) - end - print(" " + center("Base/DFG", countCols)) - if mode == :full - print(" " + center("Base/DFG", machineCountCols)) - print(" " + (" " * compilationsCols)) - print(" " + center("Src/Total", inlinesCols)) - print(" " + (" " * exitCountCols)) - print(" " + center("Get/Put/Call", recentOptsCols)) - end - puts - $bytecodes.sort { - | a, b | - b.totalMaxTopExecutionCount <=> a.totalMaxTopExecutionCount - }.each { - | bytecode | - print(center(bytecode.name(hashCols), hashCols)) - if mode == :full - print(" " + center(bytecode.instructionCount.to_s, instructionCountCols)) - end - print(" " + - center($engines.map { - | engine | - bytecode.maxTopExecutionCount(engine).to_s - }.join("/"), countCols)) - if mode == :full - print(" " + center($engines.map { - | engine | - bytecode.maxBottomExecutionCount(engine).to_s - }.join("/"), machineCountCols)) - print(" " + center(bytecode.compilations.size.to_s, compilationsCols)) - print(" " + center(bytecode.sourceMachineInlineSites.to_s + "/" + bytecode.totalMachineInlineSites.to_s, inlinesCols)) - print(" " + center(bytecode.totalExitCount.to_s, exitCountCols)) - lastCompilation = bytecode.compilations[-1] - if lastCompilation - optData = [lastCompilation.numInlinedGetByIds, - lastCompilation.numInlinedPutByIds, - lastCompilation.numInlinedCalls] - else - optData = ["N/A"] - end - print(" " + center(optData.join('/'), recentOptsCols)) - end - if sourceCols - print(" " + sourceOnOneLine(bytecode.source, sourceCols)) - end - puts - } -end - -def executeCommand(*commandArray) - command = commandArray[0] - args = commandArray[1..-1] - case command - when "help", "h", "?" - puts "summary (s) Print a summary of code block execution rates." - puts "full (f) Same as summary, but prints more information." - puts "source Show the source for a code block." - puts "bytecode (b) Show the bytecode for a code block, with counts." - puts "profiling (p) Show the (internal) profiling data for a code block." - puts "display (d) Display details for a code block." - puts "inlines Show all inlining stacks that the code block was on." - puts "help (h) Print this message." - puts "quit (q) Quit." - when "quit", "q", "exit" - exit 0 - when "summary", "s" - summary(:summary) - when "full", "f" - summary(:full) - when "source" - if args.length != 1 - puts "Usage: source <code block hash>" - return - end - $bytecodes.each { - | bytecode | - if bytecode.matches(args[0]) - puts bytecode.source - end - } - when "bytecode", "b" - if args.length != 1 - puts "Usage: source <code block hash>" - return - end - - hash = args[0] - - countCols = 10 * $engines.size - machineCols = 10 * $engines.size - pad = 1 - while (countCols + 1 + machineCols + pad) % 8 != 0 - pad += 1 - end - - $bytecodes.each { - | bytecodes | - next unless bytecodes.matches(hash) - puts(center("Source Counts", countCols) + " " + center("Machine Counts", machineCols) + - (" " * pad) + center("Bytecode for #{bytecodes}", screenWidth - pad - countCols - 1 - machineCols)) - puts(center("Base/DFG", countCols) + " " + center("Base/DFG", countCols)) - bytecodes.each { - | bytecode | - if bytecode.shouldHaveCounts? - countsString = $engines.map { - | myEngine | - bytecode.topExecutionCount(myEngine) - }.join("/") - machineString = $engines.map { - | myEngine | - bytecode.bottomExecutionCount(myEngine) - }.join("/") - else - countsString = "" - machineString = "" - end - puts(center(countsString, countCols) + " " + center(machineString, machineCols) + (" " * pad) + bytecode.description.chomp) - bytecode.osrExits.each { - | exit | - puts(center("!!!!!", countCols) + " " + center("!!!!!", machineCols) + (" " * (pad + 10)) + - "EXIT: in #{exit.compilation} due to #{exit.exitKind}, #{exit.count} times") - } - } - } - when "profiling", "p" - if args.length != 1 - puts "Usage: profiling <code block hash>" - return - end - - hash = args[0] - - first = true - $compilations.each { - | compilation | - - compilation.profiledBytecodes.each { - | profiledBytecodes | - if profiledBytecodes.bytecodes.matches(hash) - if first - first = false - else - puts - end - - puts "Compilation #{compilation}:" - profiledBytecodes.header.each { - | header | - puts(" " * 6 + header) - } - profiledBytecodes.each { - | bytecode | - puts(" " * 8 + bytecode.description) - profiledBytecodes.bytecodes.bytecode(bytecode.bytecodeIndex).osrExits.each { - | exit | - if exit.compilation == compilation - puts(" !!!!! EXIT: due to #{exit.exitKind}, #{exit.count} times") - end - } - } - end - } - } - when "inlines" - if args.length != 1 - puts "Usage: inlines <code block hash>" - return - end - - hash = args[0] - - $bytecodes.each { - | bytecodes | - next unless bytecodes.matches(hash) - - # FIXME: print something useful to say more about which code block this is. - - $compilations.each { - | compilation | - myOrigins = [] - compilation.descriptions.each { - | description | - if description.origin.index { - | myBytecode | - bytecodes == myBytecode.bytecodes - } - myOrigins << description.origin - end - } - myOrigins.uniq! - myOrigins.sort! { - | a, b | - result = 0 - [a.size, b.size].min.times { - | index | - result = a[index].bytecodeIndex <=> b[index].bytecodeIndex - break if result != 0 - } - result - } - - next if myOrigins.empty? - - printArray = [] - lastPrintStack = [] - - def originToPrintStack(origin) - (0...(origin.size - 1)).map { - | index | - "bc\##{origin[index].bytecodeIndex} --> #{origin[index + 1].bytecodes}" - } - end - - def printStack(printArray, stack, lastStack) - stillCommon = true - stack.each_with_index { - | entry, index | - next if stillCommon and entry == lastStack[index] - printArray << (" " * (index + 1) + entry) - stillCommon = false - } - end - - myOrigins.each { - | origin | - currentPrintStack = originToPrintStack(origin) - printStack(printArray, currentPrintStack, lastPrintStack) - lastPrintStack = currentPrintStack - } - - next if printArray.empty? - - puts "Compilation #{compilation}:" - printArray.each { - | entry | - puts entry - } - } - } - when "display", "d" - compilationIndex = nil - - case args.length - when 1 - if args[0] == "*" - hash = nil - else - hash = args[0] - end - engine = nil - when 2 - if mayBeHash(args[0]) - hash = args[0] - engine = args[1] - else - engine = args[0] - hash = args[1] - end - else - puts "Usage: summary <code block hash> <engine>" - return - end - - if hash and hash =~ /-([0-9]+)-/ - hash = $~.pre_match - engine = $~.post_match - compilationIndex = $1.to_i - end - - if engine and not $engines.index(engine) - pattern = Regexp.new(Regexp.escape(engine), "i") - trueEngine = nil - $engines.each { - | myEngine | - if myEngine =~ pattern - trueEngine = myEngine - break - end - } - unless trueEngine - puts "#{engine} is not a valid engine, try #{$engines.join(' or ')}." - return - end - engine = trueEngine - end - - actualCountCols = 13 - sourceCountCols = 10 * $engines.size - - first = true - $compilations.each { - | compilation | - next if hash and not compilation.bytecode.matches(hash) - next if engine and compilation.engine != engine - next if compilationIndex and compilation.compilationIndex != compilationIndex - - if first - first = false - else - puts - end - - puts("Compilation #{compilation}:") - puts(" Num inlined: GetByIds: #{compilation.numInlinedGetByIds} PutByIds: #{compilation.numInlinedPutByIds} Calls: #{compilation.numInlinedCalls}") - puts(center("Actual Counts", actualCountCols) + " " + center("Source Counts", sourceCountCols) + " " + center("Disassembly in #{compilation.engine}", screenWidth - 1 - sourceCountCols - 1 - actualCountCols)) - puts((" " * actualCountCols) + " " + center("Base/DFG", sourceCountCols)) - - lines = [] - - compilation.descriptions.each { - | description | - # FIXME: We should have a better way of detecting things like CountExecution nodes - # and slow path entries in the baseline JIT. - if description.description =~ /CountExecution\(/ and compilation.engine == "DFG" - shouldShow = false - else - shouldShow = true - end - if description.origin.empty? or not description.origin[-1].shouldHaveCounts? or (compilation.engine == "Baseline" and description.description =~ /^\s*\(S\)/) - actualCountsString = "" - sourceCountsString = "" - else - actualCountsString = compilation.counter(description.origin).count.to_s - sourceCountsString = $engines.map { - | myEngine | - description.origin[-1].topExecutionCount(myEngine) - }.join("/") - end - description.description.split("\n").each { - | line | - lines << DescriptionLine.new(actualCountsString, sourceCountsString, line.chomp, shouldShow) - } - } - - exitPrefix = center("!!!!!", actualCountCols) + " " + center("!!!!!", sourceCountCols) + (" " * 25) - - lines.each_with_index { - | line, index | - codeAddress = line.codeAddress - if codeAddress - list = compilation.osrExits[codeAddress] - if list - list.each { - | exit | - if exit.isWatchpoint - exit.dumpForDisplay(exitPrefix) - end - } - end - end - if line.shouldShow - puts(center(line.actualCountsString, actualCountCols) + " " + center(line.sourceCountsString, sourceCountCols) + " " + line.disassembly) - end - if codeAddress - # Find the next disassembly address. - endIndex = index + 1 - endAddress = nil - while endIndex < lines.size - myAddress = lines[endIndex].codeAddress - if myAddress - endAddress = myAddress - break - end - endIndex += 1 - end - - if endAddress - list = compilation.osrExits[endAddress] - if list - list.each { - | exit | - unless exit.isWatchpoint - exit.dumpForDisplay(exitPrefix) - end - } - end - end - end - } - } - else - puts "Invalid command: #{command}" - end -end - -if $stdin.tty? - executeCommand("full") -end - -while commandLine = Readline.readline("> ", true) - executeCommand(*commandLine.split) -end -
diff --git a/third_party/WebKit/Tools/Scripts/find-included-framework-headers b/third_party/WebKit/Tools/Scripts/find-included-framework-headers deleted file mode 100755 index 759a60b5..0000000 --- a/third_party/WebKit/Tools/Scripts/find-included-framework-headers +++ /dev/null
@@ -1,30 +0,0 @@ -#!/bin/sh -# Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# A script to find headers included from the given frameworks by files in the -# current directory (and subdirectories). - -for framework in $*; do - echo -e "\n$framework\n==================" - find . \( -name '*.cpp' -o -name '*.h' -o -name '*.m' -o -name '*.mm' \) -exec grep "<$framework/" {} ';' | sed -e 's|.*/\(.*\.h\).*|\1|' | sort -u -done
diff --git a/third_party/WebKit/Tools/Scripts/test-webkitpy b/third_party/WebKit/Tools/Scripts/test-webkitpy index d7b5d996..4e2c7bd 100755 --- a/third_party/WebKit/Tools/Scripts/test-webkitpy +++ b/third_party/WebKit/Tools/Scripts/test-webkitpy
@@ -41,6 +41,7 @@ import typ +skip = [] if sys.platform == 'win32': # These test fail on win32. We could annotate some of these in # class-level skips, but we don't support package/module-level skips. @@ -52,12 +53,6 @@ 'webkitpy.w3c.*', 'webkitpy.layout_tests.layout_package.bot_test_expectations_unittest.*', ] -else: - # The scm tests are really slow, so we skip them by default. - # bugs.webkit.org/show_bug.cgi?id=31818 . - skip = [ - 'webkitpy.common.checkout.scm.scm_unittest.*', - ] sys.exit(typ.main(top_level_dir=scripts_dir, skip=skip,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py index 9314eb5..0cdf0ce 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py
@@ -32,6 +32,7 @@ import os import re +import webkitpy.common.config from webkitpy.common.checkout.scm.scm import SCM from webkitpy.common.memoized import memoized from webkitpy.common.system.executive import Executive, ScriptError
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py index 48635da..9c609e0 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Pull latest revisions of the W3C test repos and update our DEPS entries.""" +"""Pull latest revisions of a W3C test repo and make a local commit.""" import argparse import re @@ -30,17 +30,21 @@ self.print_('## noting the current Blink commitish') blink_commitish = self.run(['git', 'show-ref', 'HEAD'])[1].split()[0] - wpt_import_text = self.update('web-platform-tests', - 'https://chromium.googlesource.com/external/w3c/web-platform-tests.git') + wpt_import_text = '' + if self.target == 'wpt': + wpt_import_text = self.update('web-platform-tests', + 'https://chromium.googlesource.com/external/w3c/web-platform-tests.git') - for resource in ['testharnessreport.js', 'vendor-prefix.js']: - source = self.path_from_webkit_base('LayoutTests', 'resources', resource) - destination = self.path_from_webkit_base('LayoutTests', 'imported', 'web-platform-tests', 'resources', resource) - self.copyfile(source, destination) - self.run(['git', 'add', destination]) + for resource in ['testharnessreport.js', 'vendor-prefix.js']: + source = self.path_from_webkit_base('LayoutTests', 'resources', resource) + destination = self.path_from_webkit_base('LayoutTests', 'imported', 'web-platform-tests', 'resources', resource) + self.copyfile(source, destination) + self.run(['git', 'add', destination]) - css_import_text = self.update('csswg-test', - 'https://chromium.googlesource.com/external/w3c/csswg-test.git') + css_import_text = '' + if self.target == 'css': + css_import_text = self.update('csswg-test', + 'https://chromium.googlesource.com/external/w3c/csswg-test.git') self.commit_changes_if_needed(blink_commitish, css_import_text, wpt_import_text) @@ -55,11 +59,14 @@ help='allow script to run even if we have local blink commits') parser.add_argument('--keep-w3c-repos-around', action='store_true', help='leave the w3c repos around that were imported previously.') + parser.add_argument('target', choices=['css', 'wpt'], + help='Target repository. "css" for csswg-test, "wpt" for web-platform-tests.') args = parser.parse_args(argv) self.allow_local_blink_commits = args.allow_local_blink_commits self.keep_w3c_repos_around = args.keep_w3c_repos_around self.verbose = args.verbose + self.target = args.target def checkout_is_okay(self): if self.run(['git', 'diff', '--quiet', 'HEAD'], exit_on_failure=False)[0]:
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h index c412834..d561de9 100644 --- a/third_party/WebKit/public/web/WebLocalFrame.h +++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -33,6 +33,13 @@ // It is valid to pass a null client pointer. BLINK_EXPORT static WebLocalFrame* create(WebTreeScopeType, WebFrameClient*); + // Used to create a provisional local frame in prepration for replacing a + // remote frame if the load commits. The returned frame is only partially + // attached to the frame tree: it has the same parent as its potential + // replacee but is invisible to the rest of the frames in the frame tree. + // If the load commits, call swap() to fully attach this frame. + BLINK_EXPORT static WebLocalFrame* createProvisional(WebFrameClient*, WebRemoteFrame*, WebSandboxFlags, const WebFrameOwnerProperties&); + // Returns the WebFrame associated with the current V8 context. This // function can return 0 if the context is associated with a Document that // is not currently being displayed in a Frame. @@ -49,11 +56,6 @@ // Initialization --------------------------------------------------------- - // Used when we might swap from a remote frame to a local frame. - // Creates a provisional, semi-attached frame that will be fully - // swapped into the frame tree if it commits. - virtual void initializeToReplaceRemoteFrame(WebRemoteFrame*, const WebString& name, WebSandboxFlags, const WebFrameOwnerProperties&) = 0; - virtual void setAutofillClient(WebAutofillClient*) = 0; virtual WebAutofillClient* autofillClient() = 0; virtual void setDevToolsAgentClient(WebDevToolsAgentClient*) = 0;
diff --git a/third_party/accessibility-audit/OWNERS b/third_party/accessibility-audit/OWNERS deleted file mode 100644 index cd795ab..0000000 --- a/third_party/accessibility-audit/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -aboxhall@chromium.org \ No newline at end of file
diff --git a/third_party/accessibility-audit/README.chromium b/third_party/accessibility-audit/README.chromium index 6cf4986..8df33898 100644 --- a/third_party/accessibility-audit/README.chromium +++ b/third_party/accessibility-audit/README.chromium
@@ -2,7 +2,7 @@ Short Name: accessibility-audit URL: https://raw.githubusercontent.com/GoogleChrome/accessibility-developer-tools/master/dist/js/axs_testing.js Version: 0 -Revision: 404ede0f2186682fbbef624141e76ec2b601317d +Revision: 3d4893b4ecd0eb8f4765e04479213d04b240f3e0 License: Apache 2.0 License File: LICENSE Security Critical: no
diff --git a/third_party/accessibility-audit/axs_testing.js b/third_party/accessibility-audit/axs_testing.js index f075a05..f0e6f4a3 100644 --- a/third_party/accessibility-audit/axs_testing.js +++ b/third_party/accessibility-audit/axs_testing.js
@@ -1,5 +1,5 @@ /* - * Copyright 2015 Google Inc. + * Copyright 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Generated from http://github.com/GoogleChrome/accessibility-developer-tools/tree/404ede0f2186682fbbef624141e76ec2b601317d + * Generated from http://github.com/GoogleChrome/accessibility-developer-tools/tree/3d4893b4ecd0eb8f4765e04479213d04b240f3e0 * * See project README for build steps. */ - + // AUTO-GENERATED CONTENT BELOW: DO NOT EDIT! See above for details. -var fn = (function() { - var COMPILED = !0, goog = goog || {}; +var COMPILED = !0, goog = goog || {}; goog.global = this; goog.isDef = function(a) { return void 0 !== a; @@ -63,7 +62,7 @@ goog.forwardDeclare = function(a) { }; COMPILED || (goog.isProvided_ = function(a) { - return !goog.implicitNamespaces_[a] && goog.isDefAndNotNull(goog.getObjectByName(a)); + return!goog.implicitNamespaces_[a] && goog.isDefAndNotNull(goog.getObjectByName(a)); }, goog.implicitNamespaces_ = {}); goog.getObjectByName = function(a, b) { for (var c = a.split("."), d = b || goog.global, e;e = c.shift();) { @@ -154,14 +153,14 @@ var b = goog.global.document; if ("complete" == b.readyState) { if (/\bdeps.js$/.test(a)) { - return !1; + return!1; } throw Error('Cannot write "' + a + '" after document load'); } b.write('<script type="text/javascript" src="' + a + '">\x3c/script>'); - return !0; + return!0; } - return !1; + return!1; }, goog.writeScripts_ = function() { function a(e) { if (!(e in d.written)) { @@ -259,7 +258,7 @@ return a[goog.UID_PROPERTY_] || (a[goog.UID_PROPERTY_] = ++goog.uidCounter_); }; goog.hasUid = function(a) { - return !!a[goog.UID_PROPERTY_]; + return!!a[goog.UID_PROPERTY_]; }; goog.removeUid = function(a) { "removeAttribute" in a && a.removeAttribute(goog.UID_PROPERTY_); @@ -323,7 +322,7 @@ } }; goog.now = goog.TRUSTED_SITE && Date.now || function() { - return +new Date; + return+new Date; }; goog.globalEval = function(a) { if (goog.global.execScript) { @@ -422,24 +421,24 @@ var axs = {}; axs.browserUtils = {}; axs.browserUtils.matchSelector = function(a, b) { - return a.matches ? a.matches(b) : a.webkitMatchesSelector ? a.webkitMatchesSelector(b) : a.mozMatchesSelector ? a.mozMatchesSelector(b) : a.msMatchesSelector ? a.msMatchesSelector(b) : !1; + return a.webkitMatchesSelector ? a.webkitMatchesSelector(b) : a.mozMatchesSelector ? a.mozMatchesSelector(b) : !1; }; axs.constants = {}; axs.constants.ARIA_ROLES = {alert:{namefrom:["author"], parent:["region"]}, alertdialog:{namefrom:["author"], namerequired:!0, parent:["alert", "dialog"]}, application:{namefrom:["author"], namerequired:!0, parent:["landmark"]}, article:{namefrom:["author"], parent:["document", "region"]}, banner:{namefrom:["author"], parent:["landmark"]}, button:{childpresentational:!0, namefrom:["contents", "author"], namerequired:!0, parent:["command"], properties:["aria-expanded", "aria-pressed"]}, checkbox:{namefrom:["contents", -"author"], namerequired:!0, parent:["input"], requiredProperties:["aria-checked"], properties:["aria-checked"]}, columnheader:{namefrom:["contents", "author"], namerequired:!0, parent:["gridcell", "sectionhead", "widget"], properties:["aria-sort"], scope:["row"]}, combobox:{mustcontain:["listbox", "textbox"], namefrom:["author"], namerequired:!0, parent:["select"], requiredProperties:["aria-expanded"], properties:["aria-expanded", "aria-autocomplete", "aria-required"]}, command:{"abstract":!0, namefrom:["author"], +"author"], namerequired:!0, parent:["input"], requiredProperties:["aria-checked"], properties:["aria-checked"]}, columnheader:{namefrom:["contents", "author"], namerequired:!0, parent:["gridcell", "sectionhead", "widget"], properties:["aria-sort"]}, combobox:{mustcontain:["listbox", "textbox"], namefrom:["author"], namerequired:!0, parent:["select"], requiredProperties:["aria-expanded"], properties:["aria-expanded", "aria-autocomplete", "aria-required"]}, command:{"abstract":!0, namefrom:["author"], parent:["widget"]}, complementary:{namefrom:["author"], parent:["landmark"]}, composite:{"abstract":!0, childpresentational:!1, namefrom:["author"], parent:["widget"], properties:["aria-activedescendant"]}, contentinfo:{namefrom:["author"], parent:["landmark"]}, definition:{namefrom:["author"], parent:["section"]}, dialog:{namefrom:["author"], namerequired:!0, parent:["window"]}, directory:{namefrom:["contents", "author"], parent:["list"]}, document:{namefrom:[" author"], namerequired:!0, parent:["structure"], -properties:["aria-expanded"]}, form:{namefrom:["author"], parent:["landmark"]}, grid:{mustcontain:["row", "rowgroup"], namefrom:["author"], namerequired:!0, parent:["composite", "region"], properties:["aria-level", "aria-multiselectable", "aria-readonly"]}, gridcell:{namefrom:["contents", "author"], namerequired:!0, parent:["section", "widget"], properties:["aria-readonly", "aria-required", "aria-selected"], scope:["row"]}, group:{namefrom:[" author"], parent:["section"], properties:["aria-activedescendant"]}, +properties:["aria-expanded"]}, form:{namefrom:["author"], parent:["landmark"]}, grid:{mustcontain:["row", "rowgroup"], namefrom:["author"], namerequired:!0, parent:["composite", "region"], properties:["aria-level", "aria-multiselectable", "aria-readonly"]}, gridcell:{namefrom:["contents", "author"], namerequired:!0, parent:["section", "widget"], properties:["aria-readonly", "aria-required", "aria-selected"]}, group:{namefrom:[" author"], parent:["section"], properties:["aria-activedescendant"]}, heading:{namerequired:!0, parent:["sectionhead"], properties:["aria-level"]}, img:{childpresentational:!0, namefrom:["author"], namerequired:!0, parent:["section"]}, input:{"abstract":!0, namefrom:["author"], parent:["widget"]}, landmark:{"abstract":!0, namefrom:["contents", "author"], namerequired:!1, parent:["region"]}, link:{namefrom:["contents", "author"], namerequired:!0, parent:["command"], properties:["aria-expanded"]}, list:{mustcontain:["group", "listitem"], namefrom:["author"], parent:["region"]}, -listbox:{mustcontain:["option"], namefrom:["author"], namerequired:!0, parent:["list", "select"], properties:["aria-multiselectable", "aria-required"]}, listitem:{namefrom:["contents", "author"], namerequired:!0, parent:["section"], properties:["aria-level", "aria-posinset", "aria-setsize"], scope:["list"]}, log:{namefrom:[" author"], namerequired:!0, parent:["region"]}, main:{namefrom:["author"], parent:["landmark"]}, marquee:{namerequired:!0, parent:["section"]}, math:{childpresentational:!0, namefrom:["author"], -parent:["section"]}, menu:{mustcontain:["group", "menuitemradio", "menuitem", "menuitemcheckbox"], namefrom:["author"], namerequired:!0, parent:["list", "select"]}, menubar:{namefrom:["author"], parent:["menu"]}, menuitem:{namefrom:["contents", "author"], namerequired:!0, parent:["command"], scope:["menu", "menubar"]}, menuitemcheckbox:{namefrom:["contents", "author"], namerequired:!0, parent:["checkbox", "menuitem"], scope:["menu", "menubar"]}, menuitemradio:{namefrom:["contents", "author"], namerequired:!0, -parent:["menuitemcheckbox", "radio"], scope:["menu", "menubar"]}, navigation:{namefrom:["author"], parent:["landmark"]}, note:{namefrom:["author"], parent:["section"]}, option:{namefrom:["contents", "author"], namerequired:!0, parent:["input"], properties:["aria-checked", "aria-posinset", "aria-selected", "aria-setsize"]}, presentation:{parent:["structure"]}, progressbar:{childpresentational:!0, namefrom:["author"], namerequired:!0, parent:["range"]}, radio:{namefrom:["contents", "author"], namerequired:!0, -parent:["checkbox", "option"]}, radiogroup:{mustcontain:["radio"], namefrom:["author"], namerequired:!0, parent:["select"], properties:["aria-required"]}, range:{"abstract":!0, namefrom:["author"], parent:["widget"], properties:["aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-valuetext"]}, region:{namefrom:[" author"], parent:["section"]}, roletype:{"abstract":!0, properties:"aria-atomic aria-busy aria-controls aria-describedby aria-disabled aria-dropeffect aria-flowto aria-grabbed aria-haspopup aria-hidden aria-invalid aria-label aria-labelledby aria-live aria-owns aria-relevant".split(" ")}, -row:{mustcontain:["columnheader", "gridcell", "rowheader"], namefrom:["contents", "author"], parent:["group", "widget"], properties:["aria-level", "aria-selected"], scope:["grid", "rowgroup", "treegrid"]}, rowgroup:{mustcontain:["row"], namefrom:["contents", "author"], parent:["group"], scope:["grid"]}, rowheader:{namefrom:["contents", "author"], namerequired:!0, parent:["gridcell", "sectionhead", "widget"], properties:["aria-sort"], scope:["row"]}, search:{namefrom:["author"], parent:["landmark"]}, -section:{"abstract":!0, namefrom:["contents", "author"], parent:["structure"], properties:["aria-expanded"]}, sectionhead:{"abstract":!0, namefrom:["contents", "author"], parent:["structure"], properties:["aria-expanded"]}, select:{"abstract":!0, namefrom:["author"], parent:["composite", "group", "input"]}, separator:{childpresentational:!0, namefrom:["author"], parent:["structure"], properties:["aria-expanded", "aria-orientation"]}, scrollbar:{childpresentational:!0, namefrom:["author"], namerequired:!1, -parent:["input", "range"], requiredProperties:["aria-controls", "aria-orientation", "aria-valuemax", "aria-valuemin", "aria-valuenow"], properties:["aria-controls", "aria-orientation", "aria-valuemax", "aria-valuemin", "aria-valuenow"]}, slider:{childpresentational:!0, namefrom:["author"], namerequired:!0, parent:["input", "range"], requiredProperties:["aria-valuemax", "aria-valuemin", "aria-valuenow"], properties:["aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-orientation"]}, spinbutton:{namefrom:["author"], -namerequired:!0, parent:["input", "range"], requiredProperties:["aria-valuemax", "aria-valuemin", "aria-valuenow"], properties:["aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-required"]}, status:{parent:["region"]}, structure:{"abstract":!0, parent:["roletype"]}, tab:{namefrom:["contents", "author"], parent:["sectionhead", "widget"], properties:["aria-selected"], scope:["tablist"]}, tablist:{mustcontain:["tab"], namefrom:["author"], parent:["composite", "directory"], properties:["aria-level"]}, -tabpanel:{namefrom:["author"], namerequired:!0, parent:["region"]}, textbox:{namefrom:["author"], namerequired:!0, parent:["input"], properties:["aria-activedescendant", "aria-autocomplete", "aria-multiline", "aria-readonly", "aria-required"]}, timer:{namefrom:["author"], namerequired:!0, parent:["status"]}, toolbar:{namefrom:["author"], parent:["group"]}, tooltip:{namerequired:!0, parent:["section"]}, tree:{mustcontain:["group", "treeitem"], namefrom:["author"], namerequired:!0, parent:["select"], -properties:["aria-multiselectable", "aria-required"]}, treegrid:{mustcontain:["row"], namefrom:["author"], namerequired:!0, parent:["grid", "tree"]}, treeitem:{namefrom:["contents", "author"], namerequired:!0, parent:["listitem", "option"], scope:["group", "tree"]}, widget:{"abstract":!0, parent:["roletype"]}, window:{"abstract":!0, namefrom:[" author"], parent:["roletype"], properties:["aria-expanded"]}}; +listbox:{mustcontain:["option"], namefrom:["author"], namerequired:!0, parent:["list", "select"], properties:["aria-multiselectable", "aria-required"]}, listitem:{namefrom:["contents", "author"], namerequired:!0, parent:["section"], properties:["aria-level", "aria-posinset", "aria-setsize"]}, log:{namefrom:[" author"], namerequired:!0, parent:["region"]}, main:{namefrom:["author"], parent:["landmark"]}, marquee:{namerequired:!0, parent:["section"]}, math:{childpresentational:!0, namefrom:["author"], +parent:["section"]}, menu:{mustcontain:["group", "menuitemradio", "menuitem", "menuitemcheckbox"], namefrom:["author"], namerequired:!0, parent:["list", "select"]}, menubar:{namefrom:["author"], parent:["menu"]}, menuitem:{namefrom:["contents", "author"], namerequired:!0, parent:["command"]}, menuitemcheckbox:{namefrom:["contents", "author"], namerequired:!0, parent:["checkbox", "menuitem"]}, menuitemradio:{namefrom:["contents", "author"], namerequired:!0, parent:["menuitemcheckbox", "radio"]}, navigation:{namefrom:["author"], +parent:["landmark"]}, note:{namefrom:["author"], parent:["section"]}, option:{namefrom:["contents", "author"], namerequired:!0, parent:["input"], properties:["aria-checked", "aria-posinset", "aria-selected", "aria-setsize"]}, presentation:{parent:["structure"]}, progressbar:{childpresentational:!0, namefrom:["author"], namerequired:!0, parent:["range"]}, radio:{namefrom:["contents", "author"], namerequired:!0, parent:["checkbox", "option"]}, radiogroup:{mustcontain:["radio"], namefrom:["author"], +namerequired:!0, parent:["select"], properties:["aria-required"]}, range:{"abstract":!0, namefrom:["author"], parent:["widget"], properties:["aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-valuetext"]}, region:{namefrom:[" author"], parent:["section"]}, roletype:{"abstract":!0, properties:"aria-atomic aria-busy aria-controls aria-describedby aria-disabled aria-dropeffect aria-flowto aria-grabbed aria-haspopup aria-hidden aria-invalid aria-label aria-labelledby aria-live aria-owns aria-relevant".split(" ")}, +row:{mustcontain:["columnheader", "gridcell", "rowheader"], namefrom:["contents", "author"], parent:["group", "widget"], properties:["aria-level", "aria-selected"]}, rowgroup:{mustcontain:["row"], namefrom:["contents", "author"], parent:["group"]}, rowheader:{namefrom:["contents", "author"], namerequired:!0, parent:["gridcell", "sectionhead", "widget"], properties:["aria-sort"]}, search:{namefrom:["author"], parent:["landmark"]}, section:{"abstract":!0, namefrom:["contents", "author"], parent:["structure"], +properties:["aria-expanded"]}, sectionhead:{"abstract":!0, namefrom:["contents", "author"], parent:["structure"], properties:["aria-expanded"]}, select:{"abstract":!0, namefrom:["author"], parent:["composite", "group", "input"]}, separator:{childpresentational:!0, namefrom:["author"], parent:["structure"], properties:["aria-expanded", "aria-orientation"]}, scrollbar:{childpresentational:!0, namefrom:["author"], namerequired:!1, parent:["input", "range"], requiredProperties:["aria-controls", "aria-orientation", +"aria-valuemax", "aria-valuemin", "aria-valuenow"], properties:["aria-controls", "aria-orientation", "aria-valuemax", "aria-valuemin", "aria-valuenow"]}, slider:{childpresentational:!0, namefrom:["author"], namerequired:!0, parent:["input", "range"], requiredProperties:["aria-valuemax", "aria-valuemin", "aria-valuenow"], properties:["aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-orientation"]}, spinbutton:{namefrom:["author"], namerequired:!0, parent:["input", "range"], requiredProperties:["aria-valuemax", +"aria-valuemin", "aria-valuenow"], properties:["aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-required"]}, status:{parent:["region"]}, structure:{"abstract":!0, parent:["roletype"]}, tab:{namefrom:["contents", "author"], parent:["sectionhead", "widget"], properties:["aria-selected"]}, tablist:{mustcontain:["tab"], namefrom:["author"], parent:["composite", "directory"], properties:["aria-level"]}, tabpanel:{namefrom:["author"], namerequired:!0, parent:["region"]}, textbox:{namefrom:["author"], +namerequired:!0, parent:["input"], properties:["aria-activedescendant", "aria-autocomplete", "aria-multiline", "aria-readonly", "aria-required"]}, timer:{namefrom:["author"], namerequired:!0, parent:["status"]}, toolbar:{namefrom:["author"], parent:["group"]}, tooltip:{namerequired:!0, parent:["section"]}, tree:{mustcontain:["group", "treeitem"], namefrom:["author"], namerequired:!0, parent:["select"], properties:["aria-multiselectable", "aria-required"]}, treegrid:{mustcontain:["row"], namefrom:["author"], +namerequired:!0, parent:["grid", "tree"]}, treeitem:{namefrom:["contents", "author"], namerequired:!0, parent:["listitem", "option"]}, widget:{"abstract":!0, parent:["roletype"]}, window:{"abstract":!0, namefrom:[" author"], parent:["roletype"], properties:["aria-expanded"]}}; axs.constants.WIDGET_ROLES = {}; axs.constants.addAllParentRolesToSet_ = function(a, b) { if (a.parent) { @@ -481,18 +480,7 @@ multiline:{defaultValue:"false", type:"property", valueType:"boolean"}, multiselectable:{defaultValue:"false", type:"property", valueType:"boolean"}, orientation:{defaultValue:"vertical", type:"property", valueType:"token", values:["horizontal", "vertical"]}, owns:{type:"property", valueType:"idref_list"}, posinset:{type:"property", valueType:"integer"}, pressed:{defaultValue:"undefined", type:"state", valueType:"token", values:["true", "false", "mixed", "undefined"]}, readonly:{defaultValue:"false", type:"property", valueType:"boolean"}, relevant:{defaultValue:"additions text", type:"property", valueType:"token_list", values:["additions", "removals", "text", "all"]}, required:{defaultValue:"false", type:"property", valueType:"boolean"}, selected:{defaultValue:"undefined", type:"state", valueType:"token", values:["true", "false", "undefined"]}, setsize:{type:"property", valueType:"integer"}, sort:{defaultValue:"none", type:"property", valueType:"token", values:["ascending", "descending", "none", "other"]}, valuemax:{type:"property", valueType:"decimal"}, valuemin:{type:"property", valueType:"decimal"}, valuenow:{type:"property", valueType:"decimal"}, valuetext:{type:"property", valueType:"string"}}; -(function() { - for (var a in axs.constants.ARIA_PROPERTIES) { - var b = axs.constants.ARIA_PROPERTIES[a]; - if (b.values) { - for (var c = {}, d = 0;d < b.values.length;d++) { - c[b.values[d]] = !0; - } - b.valuesSet = c; - } - } -})(); -axs.constants.GLOBAL_PROPERTIES = axs.constants.ARIA_ROLES.roletype.propertiesSet; +axs.constants.GLOBAL_PROPERTIES = "aria-atomic aria-busy aria-controls aria-describedby aria-disabled aria-dropeffect aria-flowto aria-grabbed aria-haspopup aria-hidden aria-invalid aria-label aria-labelledby aria-live aria-owns aria-relevant".split(" "); axs.constants.NO_ROLE_NAME = " "; axs.constants.WIDGET_ROLE_TO_NAME = {alert:"aria_role_alert", alertdialog:"aria_role_alertdialog", button:"aria_role_button", checkbox:"aria_role_checkbox", columnheader:"aria_role_columnheader", combobox:"aria_role_combobox", dialog:"aria_role_dialog", grid:"aria_role_grid", gridcell:"aria_role_gridcell", link:"aria_role_link", listbox:"aria_role_listbox", log:"aria_role_log", marquee:"aria_role_marquee", menu:"aria_role_menu", menubar:"aria_role_menubar", menuitem:"aria_role_menuitem", menuitemcheckbox:"aria_role_menuitemcheckbox", menuitemradio:"aria_role_menuitemradio", option:axs.constants.NO_ROLE_NAME, progressbar:"aria_role_progressbar", radio:"aria_role_radio", radiogroup:"aria_role_radiogroup", rowheader:"aria_role_rowheader", scrollbar:"aria_role_scrollbar", slider:"aria_role_slider", spinbutton:"aria_role_spinbutton", status:"aria_role_status", tab:"aria_role_tab", tabpanel:"aria_role_tabpanel", textbox:"aria_role_textbox", timer:"aria_role_timer", toolbar:"aria_role_toolbar", tooltip:"aria_role_tooltip", treeitem:"aria_role_treeitem"}; @@ -506,277 +494,80 @@ axs.constants.TAG_TO_INFORMATION_TABLE_VERBOSE_MSG = {A:"tag_link", BUTTON:"tag_button", H1:"tag_h1", H2:"tag_h2", H3:"tag_h3", H4:"tag_h4", H5:"tag_h5", H6:"tag_h6", LI:"tag_li", OL:"tag_ol", SELECT:"tag_select", TEXTAREA:"tag_textarea", UL:"tag_ul", SECTION:"tag_section", NAV:"tag_nav", ARTICLE:"tag_article", ASIDE:"tag_aside", HGROUP:"tag_hgroup", HEADER:"tag_header", FOOTER:"tag_footer", TIME:"tag_time", MARK:"tag_mark"}; axs.constants.TAG_TO_INFORMATION_TABLE_BRIEF_MSG = {BUTTON:"tag_button", SELECT:"tag_select", TEXTAREA:"tag_textarea"}; axs.constants.MIXED_VALUES = {"true":!0, "false":!0, mixed:!0}; +(function() { + for (var a in axs.constants.ARIA_PROPERTIES) { + var b = axs.constants.ARIA_PROPERTIES[a]; + if (b.values) { + for (var c = {}, d = 0;d < b.values.length;d++) { + c[b.values[d]] = !0; + } + b.valuesSet = c; + } + } +})(); axs.constants.Severity = {INFO:"Info", WARNING:"Warning", SEVERE:"Severe"}; axs.constants.AuditResult = {PASS:"PASS", FAIL:"FAIL", NA:"NA"}; axs.constants.InlineElements = {TT:!0, I:!0, B:!0, BIG:!0, SMALL:!0, EM:!0, STRONG:!0, DFN:!0, CODE:!0, SAMP:!0, KBD:!0, VAR:!0, CITE:!0, ABBR:!0, ACRONYM:!0, A:!0, IMG:!0, OBJECT:!0, BR:!0, SCRIPT:!0, MAP:!0, Q:!0, SUB:!0, SUP:!0, SPAN:!0, BDO:!0, INPUT:!0, SELECT:!0, TEXTAREA:!0, LABEL:!0, BUTTON:!0}; -axs.constants.NATIVELY_DISABLEABLE = {BUTTON:!0, INPUT:!0, SELECT:!0, TEXTAREA:!0, FIELDSET:!0, OPTGROUP:!0, OPTION:!0}; -axs.constants.ARIA_TO_HTML_ATTRIBUTE = {"aria-checked":"checked", "aria-disabled":"disabled", "aria-hidden":"hidden", "aria-expanded":"open", "aria-valuemax":"max", "aria-valuemin":"min", "aria-readonly":"readonly", "aria-required":"required", "aria-selected":"selected", "aria-valuenow":"value"}; -axs.constants.TAG_TO_IMPLICIT_SEMANTIC_INFO = {A:[{role:"link", allowed:"button checkbox menuitem menuitemcheckbox menuitemradio tab treeitem".split(" "), selector:"a[href]"}], ADDRESS:[{role:"", allowed:["contentinfo", "presentation"]}], AREA:[{role:"link", selector:"area[href]"}], ARTICLE:[{role:"article", allowed:["presentation", "article", "document", "application", "main"]}], ASIDE:[{role:"complementary", allowed:["note", "complementary", "search", "presentation"]}], AUDIO:[{role:"", allowed:["application", -"presentation"]}], BASE:[{role:"", reserved:!0}], BODY:[{role:"document", allowed:["presentation"]}], BUTTON:[{role:"button", allowed:["link", "menuitem", "menuitemcheckbox", "menuitemradio", "radio"], selector:'button:not([aria-pressed]):not([type="menu"])'}, {role:"button", allowed:["button"], selector:"button[aria-pressed]"}, {role:"button", attributes:{"aria-haspopup":!0}, allowed:["link", "menuitem", "menuitemcheckbox", "menuitemradio", "radio"], selector:'button[type="menu"]'}], CAPTION:[{role:"", -allowed:["presentation"]}], COL:[{role:"", reserved:!0}], COLGROUP:[{role:"", reserved:!0}], DATALIST:[{role:"listbox", attributes:{"aria-multiselectable":!1}, allowed:["presentation"]}], DEL:[{role:"", allowed:["*"]}], DD:[{role:"", allowed:["presentation"]}], DT:[{role:"", allowed:["presentation"]}], DETAILS:[{role:"group", allowed:["group", "presentation"]}], DIALOG:[{role:"dialog", allowed:"dialog alert alertdialog application log marquee status".split(" "), selector:"dialog[open]"}, {role:"dialog", -attributes:{"aria-hidden":!0}, allowed:"dialog alert alertdialog application log marquee status".split(" "), selector:"dialog:not([open])"}], DIV:[{role:"", allowed:["*"]}], DL:[{role:"list", allowed:["presentation"]}], EMBED:[{role:"", allowed:["application", "document", "img", "presentation"]}], FIGURE:[{role:"", allowed:["*"]}], FOOTER:[{role:"", allowed:["contentinfo", "presentation"]}], FORM:[{role:"form", allowed:["presentation"]}], P:[{role:"", allowed:["*"]}], PRE:[{role:"", allowed:["*"]}], -BLOCKQUOTE:[{role:"", allowed:["*"]}], H1:[{role:"heading"}], H2:[{role:"heading"}], H3:[{role:"heading"}], H4:[{role:"heading"}], H5:[{role:"heading"}], H6:[{role:"heading"}], HEAD:[{role:"", reserved:!0}], HEADER:[{role:"", allowed:["banner", "presentation"]}], HR:[{role:"separator", allowed:["presentation"]}], HTML:[{role:"", reserved:!0}], IFRAME:[{role:"", allowed:["application", "document", "img", "presentation"], selector:"iframe:not([seamless])"}, {role:"", allowed:["application", "document", -"img", "presentation", "group"], selector:"iframe[seamless]"}], IMG:[{role:"presentation", reserved:!0, selector:'img[alt=""]'}, {role:"img", allowed:["*"], selector:'img[alt]:not([alt=""])'}], INPUT:[{role:"button", allowed:["link", "menuitem", "menuitemcheckbox", "menuitemradio", "radio"], selector:'input[type="button"]:not([aria-pressed])'}, {role:"button", allowed:["button"], selector:'input[type="button"][aria-pressed]'}, {role:"checkbox", allowed:["checkbox"], selector:'input[type="checkbox"]'}, -{role:"", selector:'input[type="color"]'}, {role:"", selector:'input[type="date"]'}, {role:"", selector:'input[type="datetime"]'}, {role:"textbox", selector:'input[type="email"]:not([list])'}, {role:"", selector:'input[type="file"]'}, {role:"", reserved:!0, selector:'input[type="hidden"]'}, {role:"button", allowed:["button"], selector:'input[type="image"][aria-pressed]'}, {role:"button", allowed:["link", "menuitem", "menuitemcheckbox", "menuitemradio", "radio"], selector:'input[type="image"]:not([aria-pressed])'}, -{role:"", selector:'input[type="month"]'}, {role:"", selector:'input[type="number"]'}, {role:"textbox", selector:'input[type="password"]'}, {role:"radio", allowed:["menuitemradio"], selector:'input[type="radio"]'}, {role:"slider", selector:'input[type="range"]'}, {role:"button", selector:'input[type="reset"]'}, {role:"combobox", selector:'input[type="search"][list]'}, {role:"textbox", selector:'input[type="search"]:not([list])'}, {role:"button", selector:'input[type="submit"]'}, {role:"combobox", -selector:'input[type="tel"][list]'}, {role:"textbox", selector:'input[type="tel"]:not([list])'}, {role:"combobox", selector:'input[type="text"][list]'}, {role:"textbox", selector:'input[type="text"]:not([list])'}, {role:"textbox", selector:"input:not([type])"}, {role:"", selector:'input[type="time"]'}, {role:"combobox", selector:'input[type="url"][list]'}, {role:"textbox", selector:'input[type="url"]:not([list])'}, {role:"", selector:'input[type="week"]'}], INS:[{role:"", allowed:["*"]}], KEYGEN:[{role:""}], -LABEL:[{role:"", allowed:["presentation"]}], LI:[{role:"listitem", allowed:"menuitem menuitemcheckbox menuitemradio option tab treeitem presentation".split(" "), selector:'ol:not([role="presentation"])>li, ul:not([role="presentation"])>li'}, {role:"listitem", allowed:"listitem menuitem menuitemcheckbox menuitemradio option tab treeitem presentation".split(" "), selector:'ol[role="presentation"]>li, ul[role="presentation"]>li'}], LINK:[{role:"link", reserved:!0, selector:"link[href]"}], MAIN:[{role:"", -allowed:["main", "presentation"]}], MAP:[{role:"", reserved:!0}], MATH:[{role:"", allowed:["presentation"]}], MENU:[{role:"toolbar", selector:'menu[type="toolbar"]'}], MENUITEM:[{role:"menuitem", selector:'menuitem[type="command"]'}, {role:"menuitemcheckbox", selector:'menuitem[type="checkbox"]'}, {role:"menuitemradio", selector:'menuitem[type="radio"]'}], META:[{role:"", reserved:!0}], METER:[{role:"progressbar", allowed:["presentation"]}], NAV:[{role:"navigation", allowed:["navigation", "presentation"]}], -NOSCRIPT:[{role:"", reserved:!0}], OBJECT:[{role:"", allowed:["application", "document", "img", "presentation"]}], OL:[{role:"list", allowed:"directory group listbox menu menubar tablist toolbar tree presentation".split(" ")}], OPTGROUP:[{role:"", allowed:["presentation"]}], OPTION:[{role:"option"}], OUTPUT:[{role:"status", allowed:["*"]}], PARAM:[{role:"", reserved:!0}], PICTURE:[{role:"", reserved:!0}], PROGRESS:[{role:"progressbar", allowed:["presentation"]}], SCRIPT:[{role:"", reserved:!0}], -SECTION:[{role:"region", allowed:"alert alertdialog application contentinfo dialog document log marquee search status presentation".split(" ")}], SELECT:[{role:"listbox"}], SOURCE:[{role:"", reserved:!0}], SPAN:[{role:"", allowed:["*"]}], STYLE:[{role:"", reserved:!0}], SVG:[{role:"", allowed:["application", "document", "img", "presentation"]}], SUMMARY:[{role:"", allowed:["presentation"]}], TABLE:[{role:"", allowed:["*"]}], TEMPLATE:[{role:"", reserved:!0}], TEXTAREA:[{role:"textbox"}], TBODY:[{role:"rowgroup", -allowed:["*"]}], THEAD:[{role:"rowgroup", allowed:["*"]}], TFOOT:[{role:"rowgroup", allowed:["*"]}], TITLE:[{role:"", reserved:!0}], TD:[{role:"", allowed:["*"]}], TH:[{role:"", allowed:["*"]}], TR:[{role:"", allowed:["*"]}], TRACK:[{role:"", reserved:!0}], UL:[{role:"list", allowed:"directory group listbox menu menubar tablist toolbar tree presentation".split(" ")}], VIDEO:[{role:"", allowed:["application", "presentation"]}]}; -axs.color = {}; -axs.color.Color = function(a, b, c, d) { +axs.utils = {}; +axs.utils.FOCUSABLE_ELEMENTS_SELECTOR = "input:not([type=hidden]):not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled]),a[href],iframe,[tabindex]"; +axs.utils.Color = function(a, b, c, d) { this.red = a; this.green = b; this.blue = c; this.alpha = d; }; -axs.color.YCbCr = function(a) { - this.luma = this.z = a[0]; - this.Cb = this.x = a[1]; - this.Cr = this.y = a[2]; -}; -axs.color.YCbCr.prototype = {multiply:function(a) { - return new axs.color.YCbCr([this.luma * a, this.Cb * a, this.Cr * a]); -}, add:function(a) { - return new axs.color.YCbCr([this.luma + a.luma, this.Cb + a.Cb, this.Cr + a.Cr]); -}, subtract:function(a) { - return new axs.color.YCbCr([this.luma - a.luma, this.Cb - a.Cb, this.Cr - a.Cr]); -}}; -axs.color.calculateContrastRatio = function(a, b) { - 1 > a.alpha && (a = axs.color.flattenColors(a, b)); - var c = axs.color.calculateLuminance(a), d = axs.color.calculateLuminance(b); - return (Math.max(c, d) + .05) / (Math.min(c, d) + .05); -}; -axs.color.calculateLuminance = function(a) { - return axs.color.toYCbCr(a).luma; -}; -axs.color.luminanceRatio = function(a, b) { - return (Math.max(a, b) + .05) / (Math.min(a, b) + .05); -}; -axs.color.parseColor = function(a) { - if ("transparent" === a) { - return new axs.color.Color(0, 0, 0, 0); +axs.utils.calculateContrastRatio = function(a, b) { + if (!a || !b) { + return null; } - var b = a.match(/^rgb\((\d+), (\d+), (\d+)\)$/); + 1 > a.alpha && (a = axs.utils.flattenColors(a, b)); + var c = axs.utils.calculateLuminance(a), d = axs.utils.calculateLuminance(b); + return(Math.max(c, d) + .05) / (Math.min(c, d) + .05); +}; +axs.utils.luminanceRatio = function(a, b) { + return(Math.max(a, b) + .05) / (Math.min(a, b) + .05); +}; +axs.utils.parentElement = function(a) { + if (!a) { + return null; + } + if (a.nodeType == Node.DOCUMENT_FRAGMENT_NODE) { + return a.host; + } + var b = a.parentElement; if (b) { - a = parseInt(b[1], 10); - var c = parseInt(b[2], 10), d = parseInt(b[3], 10); - return new axs.color.Color(a, c, d, 1); - } - return (b = a.match(/^rgba\((\d+), (\d+), (\d+), (\d*(\.\d+)?)\)/)) ? (a = parseInt(b[1], 10), c = parseInt(b[2], 10), d = parseInt(b[3], 10), b = parseFloat(b[4]), new axs.color.Color(a, c, d, b)) : null; -}; -axs.color.colorChannelToString = function(a) { - a = Math.round(a); - return 15 >= a ? "0" + a.toString(16) : a.toString(16); -}; -axs.color.colorToString = function(a) { - return 1 == a.alpha ? "#" + axs.color.colorChannelToString(a.red) + axs.color.colorChannelToString(a.green) + axs.color.colorChannelToString(a.blue) : "rgba(" + [a.red, a.green, a.blue, a.alpha].join() + ")"; -}; -axs.color.luminanceFromContrastRatio = function(a, b, c) { - return c ? (a + .05) * b - .05 : (a + .05) / b - .05; -}; -axs.color.translateColor = function(a, b) { - for (var c = b > a.luma ? axs.color.WHITE_YCC : axs.color.BLACK_YCC, d = c == axs.color.WHITE_YCC ? axs.color.YCC_CUBE_FACES_WHITE : axs.color.YCC_CUBE_FACES_BLACK, e = new axs.color.YCbCr([0, a.Cb, a.Cr]), f = new axs.color.YCbCr([1, a.Cb, a.Cr]), f = {a:e, b:f}, e = null, g = 0;g < d.length && !(e = axs.color.findIntersection(f, d[g]), 0 <= e.z && 1 >= e.z);g++) { - } - if (!e) { - throw "Couldn't find intersection with YCbCr color cube for Cb=" + a.Cb + ", Cr=" + a.Cr + "."; - } - if (e.x != a.x || e.y != a.y) { - throw "Intersection has wrong Cb/Cr values."; - } - if (Math.abs(c.luma - e.luma) < Math.abs(c.luma - b)) { - return c = [b, a.Cb, a.Cr], axs.color.fromYCbCrArray(c); - } - c = (b - e.luma) / (c.luma - e.luma); - c = [b, e.Cb - e.Cb * c, e.Cr - e.Cr * c]; - return axs.color.fromYCbCrArray(c); -}; -axs.color.suggestColors = function(a, b, c) { - var d = {}, e = axs.color.calculateLuminance(a), f = axs.color.calculateLuminance(b), g = f > e, h = axs.color.toYCbCr(b), k = axs.color.toYCbCr(a), m; - for (m in c) { - var l = c[m], n = axs.color.luminanceFromContrastRatio(e, l + .02, g); - if (1 >= n && 0 <= n) { - var p = axs.color.translateColor(h, n), l = axs.color.calculateContrastRatio(p, a), n = {}; - n.fg = axs.color.colorToString(p); - n.bg = axs.color.colorToString(a); - n.contrast = l.toFixed(2); - d[m] = n; - } else { - l = axs.color.luminanceFromContrastRatio(f, l + .02, !g), 1 >= l && 0 <= l && (p = axs.color.translateColor(k, l), l = axs.color.calculateContrastRatio(b, p), n = {}, n.bg = axs.color.colorToString(p), n.fg = axs.color.colorToString(b), n.contrast = l.toFixed(2), d[m] = n); - } - } - return d; -}; -axs.color.flattenColors = function(a, b) { - var c = a.alpha; - return new axs.color.Color((1 - c) * b.red + c * a.red, (1 - c) * b.green + c * a.green, (1 - c) * b.blue + c * a.blue, a.alpha + b.alpha * (1 - a.alpha)); -}; -axs.color.multiplyMatrixVector = function(a, b) { - var c = b[0], d = b[1], e = b[2]; - return [a[0][0] * c + a[0][1] * d + a[0][2] * e, a[1][0] * c + a[1][1] * d + a[1][2] * e, a[2][0] * c + a[2][1] * d + a[2][2] * e]; -}; -axs.color.toYCbCr = function(a) { - var b = a.red / 255, c = a.green / 255; - a = a.blue / 255; - b = .03928 >= b ? b / 12.92 : Math.pow((b + .055) / 1.055, 2.4); - c = .03928 >= c ? c / 12.92 : Math.pow((c + .055) / 1.055, 2.4); - a = .03928 >= a ? a / 12.92 : Math.pow((a + .055) / 1.055, 2.4); - return new axs.color.YCbCr(axs.color.multiplyMatrixVector(axs.color.YCC_MATRIX, [b, c, a])); -}; -axs.color.fromYCbCr = function(a) { - return axs.color.fromYCbCrArray([a.luma, a.Cb, a.Cr]); -}; -axs.color.fromYCbCrArray = function(a) { - var b = axs.color.multiplyMatrixVector(axs.color.INVERTED_YCC_MATRIX, a), c = b[0]; - a = b[1]; - b = b[2]; - c = .00303949 >= c ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - .055; - a = .00303949 >= a ? 12.92 * a : 1.055 * Math.pow(a, 1 / 2.4) - .055; - b = .00303949 >= b ? 12.92 * b : 1.055 * Math.pow(b, 1 / 2.4) - .055; - c = Math.min(Math.max(Math.round(255 * c), 0), 255); - a = Math.min(Math.max(Math.round(255 * a), 0), 255); - b = Math.min(Math.max(Math.round(255 * b), 0), 255); - return new axs.color.Color(c, a, b, 1); -}; -axs.color.RGBToYCbCrMatrix = function(a, b) { - return [[a, 1 - a - b, b], [-a / (2 - 2 * b), (a + b - 1) / (2 - 2 * b), (1 - b) / (2 - 2 * b)], [(1 - a) / (2 - 2 * a), (a + b - 1) / (2 - 2 * a), -b / (2 - 2 * a)]]; -}; -axs.color.invert3x3Matrix = function(a) { - var b = a[0][0], c = a[0][1], d = a[0][2], e = a[1][0], f = a[1][1], g = a[1][2], h = a[2][0], k = a[2][1]; - a = a[2][2]; - return axs.color.scalarMultiplyMatrix([[f * a - g * k, d * k - c * a, c * g - d * f], [g * h - e * a, b * a - d * h, d * e - b * g], [e * k - f * h, h * c - b * k, b * f - c * e]], 1 / (b * (f * a - g * k) - c * (a * e - g * h) + d * (e * k - f * h))); -}; -axs.color.findIntersection = function(a, b) { - var c = [a.a.x - b.p0.x, a.a.y - b.p0.y, a.a.z - b.p0.z], d = axs.color.invert3x3Matrix([[a.a.x - a.b.x, b.p1.x - b.p0.x, b.p2.x - b.p0.x], [a.a.y - a.b.y, b.p1.y - b.p0.y, b.p2.y - b.p0.y], [a.a.z - a.b.z, b.p1.z - b.p0.z, b.p2.z - b.p0.z]]), c = axs.color.multiplyMatrixVector(d, c)[0]; - return a.a.add(a.b.subtract(a.a).multiply(c)); -}; -axs.color.scalarMultiplyMatrix = function(a, b) { - for (var c = [], d = 0;3 > d;d++) { - c[d] = axs.color.scalarMultiplyVector(a[d], b); - } - return c; -}; -axs.color.scalarMultiplyVector = function(a, b) { - for (var c = [], d = 0;d < a.length;d++) { - c[d] = a[d] * b; - } - return c; -}; -axs.color.kR = .2126; -axs.color.kB = .0722; -axs.color.YCC_MATRIX = axs.color.RGBToYCbCrMatrix(axs.color.kR, axs.color.kB); -axs.color.INVERTED_YCC_MATRIX = axs.color.invert3x3Matrix(axs.color.YCC_MATRIX); -axs.color.BLACK = new axs.color.Color(0, 0, 0, 1); -axs.color.BLACK_YCC = axs.color.toYCbCr(axs.color.BLACK); -axs.color.WHITE = new axs.color.Color(255, 255, 255, 1); -axs.color.WHITE_YCC = axs.color.toYCbCr(axs.color.WHITE); -axs.color.RED = new axs.color.Color(255, 0, 0, 1); -axs.color.RED_YCC = axs.color.toYCbCr(axs.color.RED); -axs.color.GREEN = new axs.color.Color(0, 255, 0, 1); -axs.color.GREEN_YCC = axs.color.toYCbCr(axs.color.GREEN); -axs.color.BLUE = new axs.color.Color(0, 0, 255, 1); -axs.color.BLUE_YCC = axs.color.toYCbCr(axs.color.BLUE); -axs.color.CYAN = new axs.color.Color(0, 255, 255, 1); -axs.color.CYAN_YCC = axs.color.toYCbCr(axs.color.CYAN); -axs.color.MAGENTA = new axs.color.Color(255, 0, 255, 1); -axs.color.MAGENTA_YCC = axs.color.toYCbCr(axs.color.MAGENTA); -axs.color.YELLOW = new axs.color.Color(255, 255, 0, 1); -axs.color.YELLOW_YCC = axs.color.toYCbCr(axs.color.YELLOW); -axs.color.YCC_CUBE_FACES_BLACK = [{p0:axs.color.BLACK_YCC, p1:axs.color.RED_YCC, p2:axs.color.GREEN_YCC}, {p0:axs.color.BLACK_YCC, p1:axs.color.GREEN_YCC, p2:axs.color.BLUE_YCC}, {p0:axs.color.BLACK_YCC, p1:axs.color.BLUE_YCC, p2:axs.color.RED_YCC}]; -axs.color.YCC_CUBE_FACES_WHITE = [{p0:axs.color.WHITE_YCC, p1:axs.color.CYAN_YCC, p2:axs.color.MAGENTA_YCC}, {p0:axs.color.WHITE_YCC, p1:axs.color.MAGENTA_YCC, p2:axs.color.YELLOW_YCC}, {p0:axs.color.WHITE_YCC, p1:axs.color.YELLOW_YCC, p2:axs.color.CYAN_YCC}]; -axs.dom = {}; -axs.dom.parentElement = function(a) { - if (!a) { - return null; - } - a = axs.dom.composedParentNode(a); - if (!a) { - return null; - } - switch(a.nodeType) { - case Node.ELEMENT_NODE: - return a; - default: - return axs.dom.parentElement(a); - } -}; -axs.dom.shadowHost = function(a) { - return "host" in a ? a.host : null; -}; -axs.dom.composedParentNode = function(a) { - if (!a) { - return null; - } - if (a.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { - return axs.dom.shadowHost(a); - } - var b = a.parentNode; - if (!b) { - return null; - } - if (b.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { - return axs.dom.shadowHost(b); - } - if (!b.shadowRoot) { return b; } - a = a.getDestinationInsertionPoints(); - return 0 < a.length ? axs.dom.composedParentNode(a[a.length - 1]) : null; -}; -axs.dom.asElement = function(a) { + a = a.parentNode; + if (!a) { + return null; + } switch(a.nodeType) { - case Node.COMMENT_NODE: - break; case Node.ELEMENT_NODE: - if ("script" == a.localName || "template" == a.localName) { - break; - } return a; case Node.DOCUMENT_FRAGMENT_NODE: return a.host; - case Node.TEXT_NODE: - return axs.dom.parentElement(a); default: - console.warn("Unhandled node type: ", a.nodeType); + return null; } - return null; }; -axs.dom.composedTreeSearch = function(a, b, c, d) { - if (a === b) { - return !0; +axs.utils.asElement = function(a) { + switch(a.nodeType) { + case Node.COMMENT_NODE: + return null; + case Node.ELEMENT_NODE: + if ("script" == a.tagName.toLowerCase()) { + return null; + } + break; + case Node.TEXT_NODE: + a = axs.utils.parentElement(a); + break; + default: + return console.warn("Unhandled node type: ", a.nodeType), null; } - if (a.nodeType == Node.ELEMENT_NODE) { - var e = a - } - var f = !1; - if (e && c.preorder && !c.preorder(e)) { - return f; - } - if (e) { - var g = e.shadowRoot || e.webkitShadowRoot; - if (g) { - return f = axs.dom.composedTreeSearch(g, b, c, g), e && c.postorder && !f && c.postorder(e), f; - } - } - if (e && "content" == e.localName) { - a = e.getDistributedNodes(); - for (g = 0;g < a.length && !f;g++) { - f = axs.dom.composedTreeSearch(a[g], b, c, d); - } - e && c.postorder && !f && c.postorder.call(null, e); - return f; - } - for (a = a.firstChild;null != a && !f;) { - f = axs.dom.composedTreeSearch(a, b, c, d), a = a.nextSibling; - } - e && c.postorder && !f && c.postorder.call(null, e); - return f; + return a; }; -axs.utils = {}; -axs.utils.FOCUSABLE_ELEMENTS_SELECTOR = "input:not([type=hidden]):not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled]),a[href],iframe,[tabindex]"; -axs.utils.LABELABLE_ELEMENTS_SELECTOR = "button,input:not([type=hidden]),keygen,meter,output,progress,select,textarea"; axs.utils.elementIsTransparent = function(a) { return "0" == a.style.opacity; }; @@ -786,45 +577,32 @@ return a.right - a.left && b ? !1 : !0; }; axs.utils.elementIsOutsideScrollArea = function(a) { - for (var b = axs.dom.parentElement(a), c = a.ownerDocument.defaultView;b != c.document.body;) { + for (var b = axs.utils.parentElement(a), c = a.ownerDocument.defaultView;b != c.document.body;) { if (axs.utils.isClippedBy(a, b)) { - return !0; + return!0; } if (axs.utils.canScrollTo(a, b) && !axs.utils.elementIsOutsideScrollArea(b)) { - return !1; + return!1; } - b = axs.dom.parentElement(b); + b = axs.utils.parentElement(b); } - return !axs.utils.canScrollTo(a, c.document.body); + return!axs.utils.canScrollTo(a, c.document.body); }; axs.utils.canScrollTo = function(a, b) { - var c = a.getBoundingClientRect(), d = b.getBoundingClientRect(); - if (b == b.ownerDocument.body) { - var e = d.top, f = d.left - } else { - e = d.top - b.scrollTop, f = d.left - b.scrollLeft; + var c = a.getBoundingClientRect(), d = b.getBoundingClientRect(), e = d.top, f = d.left, g = e - b.scrollTop, e = e - b.scrollTop + b.scrollHeight, h = f - b.scrollLeft + b.scrollWidth; + if (c.right < f - b.scrollLeft || c.bottom < g || c.left > h || c.top > e) { + return!1; } - var g = e + b.scrollHeight, h = f + b.scrollWidth; - if (c.right < f || c.bottom < e || c.left > h || c.top > g) { - return !1; - } - e = a.ownerDocument.defaultView; - f = e.getComputedStyle(b); - return c.left > d.right || c.top > d.bottom ? "scroll" == f.overflow || "auto" == f.overflow || b instanceof e.HTMLBodyElement : !0; + f = a.ownerDocument.defaultView; + g = f.getComputedStyle(b); + return c.left > d.right || c.top > d.bottom ? "scroll" == g.overflow || "auto" == g.overflow || b instanceof f.HTMLBodyElement : !0; }; axs.utils.isClippedBy = function(a, b) { var c = a.getBoundingClientRect(), d = b.getBoundingClientRect(), e = d.top - b.scrollTop, f = d.left - b.scrollLeft, g = a.ownerDocument.defaultView.getComputedStyle(b); - return (c.right < d.left || c.bottom < d.top || c.left > d.right || c.top > d.bottom) && "hidden" == g.overflow ? !0 : c.right < f || c.bottom < e ? "visible" != g.overflow : !1; + return(c.right < d.left || c.bottom < d.top || c.left > d.right || c.top > d.bottom) && "hidden" == g.overflow ? !0 : c.right < f || c.bottom < e ? "visible" != g.overflow : !1; }; axs.utils.isAncestor = function(a, b) { - if (null == b) { - return !1; - } - if (b === a) { - return !0; - } - var c = axs.dom.composedParentNode(b); - return axs.utils.isAncestor(a, c); + return null == b ? !1 : b === a ? !0 : axs.utils.isAncestor(a, b.parentNode); }; axs.utils.overlappingElements = function(a) { if (axs.utils.elementHasZeroArea(a)) { @@ -870,13 +648,13 @@ } if (c = b.match(/(\d+)pt/)) { if (b = parseInt(c[1], 10), a && 14 <= b || 18 <= b) { - return !0; + return!0; } } - return !1; + return!1; }; axs.utils.getBgColor = function(a, b) { - var c = axs.color.parseColor(a.backgroundColor); + var c = axs.utils.parseColor(a.backgroundColor); if (!c) { return null; } @@ -886,38 +664,158 @@ if (null == d) { return null; } - c = axs.color.flattenColors(c, d); + c = axs.utils.flattenColors(c, d); } return c; }; axs.utils.getParentBgColor = function(a) { var b = a; a = []; - for (var c = null;b = axs.dom.parentElement(b);) { + for (var c = null;b = axs.utils.parentElement(b);) { var d = window.getComputedStyle(b, null); if (d) { - var e = axs.color.parseColor(d.backgroundColor); + var e = axs.utils.parseColor(d.backgroundColor); if (e && (1 > d.opacity && (e.alpha *= d.opacity), 0 != e.alpha && (a.push(e), 1 == e.alpha))) { c = !0; break; } } } - c || a.push(new axs.color.Color(255, 255, 255, 1)); + c || a.push(new axs.utils.Color(255, 255, 255, 1)); for (b = a.pop();a.length;) { - c = a.pop(), b = axs.color.flattenColors(c, b); + c = a.pop(), b = axs.utils.flattenColors(c, b); } return b; }; axs.utils.getFgColor = function(a, b, c) { - var d = axs.color.parseColor(a.color); + var d = axs.utils.parseColor(a.color); if (!d) { return null; } - 1 > d.alpha && (d = axs.color.flattenColors(d, c)); - 1 > a.opacity && (b = axs.utils.getParentBgColor(b), d.alpha *= a.opacity, d = axs.color.flattenColors(d, b)); + 1 > d.alpha && (d = axs.utils.flattenColors(d, c)); + 1 > a.opacity && (b = axs.utils.getParentBgColor(b), d.alpha *= a.opacity, d = axs.utils.flattenColors(d, b)); return d; }; +axs.utils.parseColor = function(a) { + var b = a.match(/^rgb\((\d+), (\d+), (\d+)\)$/); + if (b) { + a = parseInt(b[1], 10); + var c = parseInt(b[2], 10), b = parseInt(b[3], 10), d; + return new axs.utils.Color(a, c, b, 1); + } + return(b = a.match(/^rgba\((\d+), (\d+), (\d+), (\d+(\.\d+)?)\)/)) ? (d = parseInt(b[4], 10), a = parseInt(b[1], 10), c = parseInt(b[2], 10), b = parseInt(b[3], 10), new axs.utils.Color(a, c, b, d)) : null; +}; +axs.utils.colorChannelToString = function(a) { + a = Math.round(a); + return 15 >= a ? "0" + a.toString(16) : a.toString(16); +}; +axs.utils.colorToString = function(a) { + return 1 == a.alpha ? "#" + axs.utils.colorChannelToString(a.red) + axs.utils.colorChannelToString(a.green) + axs.utils.colorChannelToString(a.blue) : "rgba(" + [a.red, a.green, a.blue, a.alpha].join() + ")"; +}; +axs.utils.luminanceFromContrastRatio = function(a, b, c) { + return c ? (a + .05) * b - .05 : (a + .05) / b - .05; +}; +axs.utils.translateColor = function(a, b) { + var c = a[0], c = (b - c) / ((c > b ? 0 : 1) - c); + return axs.utils.fromYCC([b, a[1] - a[1] * c, a[2] - a[2] * c]); +}; +axs.utils.suggestColors = function(a, b, c, d) { + if (!axs.utils.isLowContrast(c, d, !0)) { + return null; + } + var e = {}, f = axs.utils.calculateLuminance(a), g = axs.utils.calculateLuminance(b), h = axs.utils.isLargeFont(d) ? 3 : 4.5, k = axs.utils.isLargeFont(d) ? 4.5 : 7, m = g > f, l = axs.utils.luminanceFromContrastRatio(f, h + .02, m), n = axs.utils.luminanceFromContrastRatio(f, k + .02, m), q = axs.utils.toYCC(b); + if (axs.utils.isLowContrast(c, d, !1) && 1 >= l && 0 <= l) { + var p = axs.utils.translateColor(q, l), l = axs.utils.calculateContrastRatio(p, a); + axs.utils.calculateLuminance(p); + f = {}; + f.fg = axs.utils.colorToString(p); + f.bg = axs.utils.colorToString(a); + f.contrast = l.toFixed(2); + e.AA = f; + } + axs.utils.isLowContrast(c, d, !0) && 1 >= n && 0 <= n && (n = axs.utils.translateColor(q, n), l = axs.utils.calculateContrastRatio(n, a), f = {}, f.fg = axs.utils.colorToString(n), f.bg = axs.utils.colorToString(a), f.contrast = l.toFixed(2), e.AAA = f); + h = axs.utils.luminanceFromContrastRatio(g, h + .02, !m); + g = axs.utils.luminanceFromContrastRatio(g, k + .02, !m); + a = axs.utils.toYCC(a); + !("AA" in e) && axs.utils.isLowContrast(c, d, !1) && 1 >= h && 0 <= h && (k = axs.utils.translateColor(a, h), l = axs.utils.calculateContrastRatio(b, k), f = {}, f.bg = axs.utils.colorToString(k), f.fg = axs.utils.colorToString(b), f.contrast = l.toFixed(2), e.AA = f); + !("AAA" in e) && axs.utils.isLowContrast(c, d, !0) && 1 >= g && 0 <= g && (c = axs.utils.translateColor(a, g), l = axs.utils.calculateContrastRatio(b, c), f = {}, f.bg = axs.utils.colorToString(c), f.fg = axs.utils.colorToString(b), f.contrast = l.toFixed(2), e.AAA = f); + return e; +}; +axs.utils.flattenColors = function(a, b) { + var c = a.alpha; + return new axs.utils.Color((1 - c) * b.red + c * a.red, (1 - c) * b.green + c * a.green, (1 - c) * b.blue + c * a.blue, a.alpha + b.alpha * (1 - a.alpha)); +}; +axs.utils.calculateLuminance = function(a) { + return axs.utils.toYCC(a)[0]; +}; +axs.utils.RGBToYCCMatrix = function(a, b) { + return[[a, 1 - a - b, b], [-a / (2 - 2 * b), (a + b - 1) / (2 - 2 * b), (1 - b) / (2 - 2 * b)], [(1 - a) / (2 - 2 * a), (a + b - 1) / (2 - 2 * a), -b / (2 - 2 * a)]]; +}; +axs.utils.invert3x3Matrix = function(a) { + var b = a[0][0], c = a[0][1], d = a[0][2], e = a[1][0], f = a[1][1], g = a[1][2], h = a[2][0], k = a[2][1]; + a = a[2][2]; + return axs.utils.scalarMultiplyMatrix([[f * a - g * k, d * k - c * a, c * g - d * f], [g * h - e * a, b * a - d * h, d * e - b * g], [e * k - f * h, h * c - b * k, b * f - c * e]], 1 / (b * (f * a - g * k) - c * (a * e - g * h) + d * (e * k - f * h))); +}; +axs.utils.scalarMultiplyMatrix = function(a, b) { + for (var c = [[], [], []], d = 0;3 > d;d++) { + for (var e = 0;3 > e;e++) { + c[d][e] = a[d][e] * b; + } + } + return c; +}; +axs.utils.kR = .2126; +axs.utils.kB = .0722; +axs.utils.YCC_MATRIX = axs.utils.RGBToYCCMatrix(axs.utils.kR, axs.utils.kB); +axs.utils.INVERTED_YCC_MATRIX = axs.utils.invert3x3Matrix(axs.utils.YCC_MATRIX); +axs.utils.convertColor = function(a, b) { + var c = b[0], d = b[1], e = b[2]; + return[a[0][0] * c + a[0][1] * d + a[0][2] * e, a[1][0] * c + a[1][1] * d + a[1][2] * e, a[2][0] * c + a[2][1] * d + a[2][2] * e]; +}; +axs.utils.multiplyMatrices = function(a, b) { + for (var c = [[], [], []], d = 0;3 > d;d++) { + for (var e = 0;3 > e;e++) { + c[d][e] = a[d][0] * b[0][e] + a[d][1] * b[1][e] + a[d][2] * b[2][e]; + } + } + return c; +}; +axs.utils.toYCC = function(a) { + var b = a.red / 255, c = a.green / 255; + a = a.blue / 255; + b = .03928 >= b ? b / 12.92 : Math.pow((b + .055) / 1.055, 2.4); + c = .03928 >= c ? c / 12.92 : Math.pow((c + .055) / 1.055, 2.4); + a = .03928 >= a ? a / 12.92 : Math.pow((a + .055) / 1.055, 2.4); + return axs.utils.convertColor(axs.utils.YCC_MATRIX, [b, c, a]); +}; +axs.utils.fromYCC = function(a) { + var b = axs.utils.convertColor(axs.utils.INVERTED_YCC_MATRIX, a), c = b[0]; + a = b[1]; + b = b[2]; + c = .00303949 >= c ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - .055; + a = .00303949 >= a ? 12.92 * a : 1.055 * Math.pow(a, 1 / 2.4) - .055; + b = .00303949 >= b ? 12.92 * b : 1.055 * Math.pow(b, 1 / 2.4) - .055; + c = Math.min(Math.max(Math.round(255 * c), 0), 255); + a = Math.min(Math.max(Math.round(255 * a), 0), 255); + b = Math.min(Math.max(Math.round(255 * b), 0), 255); + return new axs.utils.Color(c, a, b, 1); +}; +axs.utils.scalarMultiplyMatrix = function(a, b) { + for (var c = [[], [], []], d = 0;3 > d;d++) { + for (var e = 0;3 > e;e++) { + c[d][e] = a[d][e] * b; + } + } + return c; +}; +axs.utils.multiplyMatrices = function(a, b) { + for (var c = [[], [], []], d = 0;3 > d;d++) { + for (var e = 0;3 > e;e++) { + c[d][e] = a[d][0] * b[0][e] + a[d][1] * b[1][e] + a[d][2] * b[2][e]; + } + } + return c; +}; axs.utils.getContrastRatioForElement = function(a) { var b = window.getComputedStyle(a, null); return axs.utils.getContrastRatioForElementWithComputedStyle(b, a); @@ -931,16 +829,16 @@ return null; } var d = axs.utils.getFgColor(a, b, c); - return d ? axs.color.calculateContrastRatio(d, c) : null; + return d ? axs.utils.calculateContrastRatio(d, c) : null; }; axs.utils.isNativeTextElement = function(a) { var b = a.tagName.toLowerCase(); a = a.type ? a.type.toLowerCase() : ""; if ("textarea" == b) { - return !0; + return!0; } if ("input" != b) { - return !1; + return!1; } switch(a) { case "email": @@ -958,9 +856,9 @@ case "url": ; case "": - return !0; + return!0; default: - return !1; + return!1; } }; axs.utils.isLowContrast = function(a, b, c) { @@ -969,37 +867,20 @@ }; axs.utils.hasLabel = function(a) { var b = a.tagName.toLowerCase(), c = a.type ? a.type.toLowerCase() : ""; - if (a.hasAttribute("aria-label") || a.hasAttribute("title") || "img" == b && a.hasAttribute("alt") || "input" == b && "image" == c && a.hasAttribute("alt") || "input" == b && ("submit" == c || "reset" == c) || a.hasAttribute("aria-labelledby") || a.hasAttribute("id") && 0 < document.querySelectorAll('label[for="' + a.id + '"]').length) { - return !0; + if (a.hasAttribute("aria-label") || a.hasAttribute("title") || "img" == b && a.hasAttribute("alt") || "input" == b && "image" == c && a.hasAttribute("alt") || "input" == b && ("submit" == c || "reset" == c) || a.hasAttribute("aria-labelledby") || axs.utils.isNativeTextElement(a) && a.hasAttribute("placeholder") || a.hasAttribute("id") && 0 < document.querySelectorAll('label[for="' + a.id + '"]').length) { + return!0; } - for (b = axs.dom.parentElement(a);b;) { + for (b = axs.utils.parentElement(a);b;) { if ("label" == b.tagName.toLowerCase() && b.control == a) { - return !0; + return!0; } - b = axs.dom.parentElement(b); + b = axs.utils.parentElement(b); } - return !1; -}; -axs.utils.isNativelyDisableable = function(a) { - return a.tagName.toUpperCase() in axs.constants.NATIVELY_DISABLEABLE; -}; -axs.utils.isElementDisabled = function(a) { - if (axs.browserUtils.matchSelector(a, "[aria-disabled=true], [aria-disabled=true] *")) { - return !0; - } - if (!axs.utils.isNativelyDisableable(a) || axs.browserUtils.matchSelector(a, "fieldset>legend:first-of-type *")) { - return !1; - } - for (;null !== a;a = axs.dom.parentElement(a)) { - if (axs.utils.isNativelyDisableable(a) && a.hasAttribute("disabled")) { - return !0; - } - } - return !1; + return!1; }; axs.utils.isElementHidden = function(a) { if (!(a instanceof a.ownerDocument.defaultView.HTMLElement)) { - return !1; + return!1; } if (a.hasAttribute("chromevoxignoreariahidden")) { var b = !0 @@ -1008,27 +889,22 @@ return "none" == c.display || "hidden" == c.visibility ? !0 : a.hasAttribute("aria-hidden") && "true" == a.getAttribute("aria-hidden").toLowerCase() ? !b : !1; }; axs.utils.isElementOrAncestorHidden = function(a) { - return axs.utils.isElementHidden(a) ? !0 : axs.dom.parentElement(a) ? axs.utils.isElementOrAncestorHidden(axs.dom.parentElement(a)) : !1; + return axs.utils.isElementHidden(a) ? !0 : axs.utils.parentElement(a) ? axs.utils.isElementOrAncestorHidden(axs.utils.parentElement(a)) : !1; }; axs.utils.isInlineElement = function(a) { a = a.tagName.toUpperCase(); return axs.constants.InlineElements[a]; }; -axs.utils.getRoles = function(a, b) { - if (!a || a.nodeType !== Node.ELEMENT_NODE || !a.hasAttribute("role") && !b) { - return null; +axs.utils.getRoles = function(a) { + if (!a.hasAttribute("role")) { + return!1; } - var c = a.getAttribute("role"); - !c && b && (c = axs.properties.getImplicitRole(a)); - if (!c) { - return null; + a = a.getAttribute("role").split(" "); + for (var b = [], c = !0, d = 0;d < a.length;d++) { + var e = a[d]; + axs.constants.ARIA_ROLES[e] ? b.push({name:e, details:axs.constants.ARIA_ROLES[e], valid:!0}) : (b.push({name:e, valid:!1}), c = !1); } - for (var c = c.split(" "), d = {roles:[], valid:!1}, e = 0;e < c.length;e++) { - var f = c[e], g = axs.constants.ARIA_ROLES[f], f = {name:f}; - g && !g.abstract ? (f.details = g, d.applied || (d.applied = f), f.valid = d.valid = !0) : f.valid = !1; - d.roles.push(f); - } - return d; + return{roles:b, valid:c}; }; axs.utils.getAriaPropertyValue = function(a, b, c) { var d = a.replace(/^aria-/, ""), e = axs.constants.ARIA_PROPERTIES[d], d = {name:a, rawValue:b}; @@ -1050,22 +926,16 @@ } return d; case "integer": + ; + case "decimal": c = axs.utils.isValidNumber(b); if (!c.valid) { return d.valid = !1, d.reason = c.reason, d; } - Math.floor(c.value) !== c.value ? (d.valid = !1, d.reason = "" + b + " is not a whole integer") : (d.valid = !0, d.value = c.value); + Math.floor(c.value) != c.value ? (d.valid = !1, d.reason = "" + b + " is not a whole integer") : (d.valid = !0, d.value = c.value); return d; - case "decimal": - ; case "number": - c = axs.utils.isValidNumber(b); - d.valid = c.valid; - if (!c.valid) { - return d.reason = c.reason, d; - } - d.value = c.value; - return d; + c = axs.utils.isValidNumber(b), c.valid && (d.valid = !0, d.value = c.value); case "string": return d.valid = !0, d.value = b, d; case "token": @@ -1105,15 +975,12 @@ return 0 == a.length ? {valid:!0, idref:a} : b.ownerDocument.getElementById(a) ? {valid:!0, idref:a} : {valid:!1, idref:a, reason:'No element with ID "' + a + '"'}; }; axs.utils.isValidNumber = function(a) { - var b = {valid:!1, value:a, reason:'"' + a + '" is not a number'}; - if (!a) { - return b; + try { + var b = JSON.parse(a); + } catch (c) { + return{valid:!1, value:a, reason:'"' + a + '" is not a number'}; } - if (/^0x/i.test(a)) { - return b.reason = '"' + a + '" is not a decimal number', b; - } - a *= 1; - return isFinite(a) ? {valid:!0, value:a} : b; + return "number" != typeof b ? {valid:!1, value:a, reason:'"' + a + '" is not a number'} : {valid:!0, value:b}; }; axs.utils.isElementImplicitlyFocusable = function(a) { var b = a.ownerDocument.defaultView; @@ -1160,9 +1027,7 @@ } else { d = 1; } - if (1 == d) { - return axs.utils.getQuerySelectorText(a.parentNode) + " > " + b; - } + return 1 == d ? axs.utils.getQuerySelectorText(a.parentNode) + " > " + b : axs.utils.getQuerySelectorText(a.parentNode) + " > " + b + ":nth-of-type(" + d + ")"; } if (a.parentNode) { b = a.parentNode.children; @@ -1181,103 +1046,6 @@ } return ""; }; -axs.utils.getAriaIdReferrers = function(a, b) { - var c = function(a) { - var b = axs.constants.ARIA_PROPERTIES[a]; - if (b) { - if ("idref" === b.valueType) { - return "[aria-" + a + "='" + d + "']"; - } - if ("idref_list" === b.valueType) { - return "[aria-" + a + "~='" + d + "']"; - } - } - return ""; - }; - if (!a) { - return null; - } - var d = a.id; - if (!d) { - return null; - } - d = d.replace(/'/g, "\\'"); - if (b) { - var e = b.replace(/^aria-/, ""), f = c(e); - if (f) { - return a.ownerDocument.querySelectorAll(f); - } - } else { - var g = []; - for (e in axs.constants.ARIA_PROPERTIES) { - (f = c(e)) && g.push(f); - } - return a.ownerDocument.querySelectorAll(g.join(",")); - } - return null; -}; -axs.utils.getHtmlIdReferrers = function(a) { - if (!a) { - return null; - } - var b = a.id; - if (!b) { - return null; - } - var b = b.replace(/'/g, "\\'"), c = "[contextmenu='{id}'] [itemref~='{id}'] button[form='{id}'] button[menu='{id}'] fieldset[form='{id}'] input[form='{id}'] input[list='{id}'] keygen[form='{id}'] label[for='{id}'] label[form='{id}'] menuitem[command='{id}'] object[form='{id}'] output[for~='{id}'] output[form='{id}'] select[form='{id}'] td[headers~='{id}'] textarea[form='{id}'] tr[headers~='{id}']".split(" ").map(function(a) { - return a.replace("{id}", b); - }); - return a.ownerDocument.querySelectorAll(c.join(",")); -}; -axs.utils.getIdReferrers = function(a) { - var b = [], c = axs.utils.getHtmlIdReferrers(a); - c && (b = b.concat(Array.prototype.slice.call(c))); - (c = axs.utils.getAriaIdReferrers(a)) && (b = b.concat(Array.prototype.slice.call(c))); - return b; -}; -axs.utils.getIdReferents = function(a, b) { - var c = [], d = a.replace(/^aria-/, ""), d = axs.constants.ARIA_PROPERTIES[d]; - if (!d || !b.hasAttribute(a)) { - return c; - } - d = d.valueType; - if ("idref_list" === d || "idref" === d) { - for (var d = b.ownerDocument, e = b.getAttribute(a), e = e.split(/\s+/), f = 0, g = e.length;f < g;f++) { - var h = d.getElementById(e[f]); - h && (c[c.length] = h); - } - } - return c; -}; -axs.utils.getAriaPropertiesByValueType = function(a) { - var b = {}, c; - for (c in axs.constants.ARIA_PROPERTIES) { - var d = axs.constants.ARIA_PROPERTIES[c]; - d && 0 <= a.indexOf(d.valueType) && (b[c] = d); - } - return b; -}; -axs.utils.getSelectorForAriaProperties = function(a) { - a = Object.keys(a).map(function(a) { - return "[aria-" + a + "]"; - }); - a.sort(); - return a.join(","); -}; -axs.utils.findDescendantsWithRole = function(a, b) { - if (!a || !b) { - return []; - } - var c = axs.properties.getSelectorForRole(b); - if (c && (c = a.querySelectorAll(c))) { - c = Array.prototype.map.call(c, function(a) { - return a; - }); - } else { - return []; - } - return c; -}; axs.properties = {}; axs.properties.TEXT_CONTENT_XPATH = './/text()[normalize-space(.)!=""]/parent::*[name()!="script"]'; axs.properties.getFocusProperties = function(a) { @@ -1310,7 +1078,7 @@ var b = !0 } var c = window.getComputedStyle(a, null); - return "none" == c.display ? {property:"display: none", on:a} : "hidden" == c.visibility ? {property:"visibility: hidden", on:a} : a.hasAttribute("aria-hidden") && "true" == a.getAttribute("aria-hidden").toLowerCase() && !b ? {property:"aria-hidden", on:a} : axs.properties.getHiddenReason(axs.dom.parentElement(a)); + return "none" == c.display ? {property:"display: none", on:a} : "hidden" == c.visibility ? {property:"visibility: hidden", on:a} : a.hasAttribute("aria-hidden") && "true" == a.getAttribute("aria-hidden").toLowerCase() && !b ? {property:"aria-hidden", on:a} : axs.properties.getHiddenReason(axs.utils.parentElement(a)); }; axs.properties.getColorProperties = function(a) { var b = {}; @@ -1318,25 +1086,13 @@ return 0 == Object.keys(b).length ? null : b; }; axs.properties.hasDirectTextDescendant = function(a) { - function b() { - for (var b = c.evaluate(axs.properties.TEXT_CONTENT_XPATH, a, null, XPathResult.ANY_TYPE, null), e = b.iterateNext();null != e;e = b.iterateNext()) { - if (e === a) { - return !0; - } + for (var b = (a.nodeType == Node.DOCUMENT_NODE ? a : a.ownerDocument).evaluate(axs.properties.TEXT_CONTENT_XPATH, a, null, XPathResult.ANY_TYPE, null), c = !1, d = b.iterateNext();null != d;d = b.iterateNext()) { + if (d === a) { + c = !0; + break; } - return !1; } - var c; - c = a.nodeType == Node.DOCUMENT_NODE ? a : a.ownerDocument; - return c.evaluate ? b() : function() { - for (var b = c.createTreeWalker(a, NodeFilter.SHOW_TEXT, null, !1);b.nextNode();) { - var e = b.currentNode, f = e.parentNode.tagName.toLowerCase(); - if (e.nodeValue.trim() && "script" !== f && a !== e) { - return !0; - } - } - return !1; - }(); + return c; }; axs.properties.getContrastRatioProperties = function(a) { if (!axs.properties.hasDirectTextDescendant(a)) { @@ -1346,28 +1102,22 @@ if (!d) { return null; } - b.backgroundColor = axs.color.colorToString(d); + b.backgroundColor = axs.utils.colorToString(d); var e = axs.utils.getFgColor(c, a, d); - b.foregroundColor = axs.color.colorToString(e); + b.foregroundColor = axs.utils.colorToString(e); a = axs.utils.getContrastRatioForElementWithComputedStyle(c, a); if (!a) { return null; } b.value = a.toFixed(2); axs.utils.isLowContrast(a, c) && (b.alert = !0); - var f = axs.utils.isLargeFont(c) ? 3 : 4.5, c = axs.utils.isLargeFont(c) ? 4.5 : 7, g = {}; - f > a && (g.AA = f); - c > a && (g.AAA = c); - if (!Object.keys(g).length) { - return b; - } - (d = axs.color.suggestColors(d, e, g)) && Object.keys(d).length && (b.suggestedColors = d); + (c = axs.utils.suggestColors(d, e, a, c)) && Object.keys(c).length && (b.suggestedColors = c); return b; }; axs.properties.findTextAlternatives = function(a, b, c, d) { var e = c || !1; - c = axs.dom.asElement(a); - if (!c || !d && axs.utils.isElementOrAncestorHidden(c)) { + c = axs.utils.asElement(a); + if (!c || !e && !d && axs.utils.isElementOrAncestorHidden(c)) { return null; } if (a.nodeType == Node.TEXT_NODE) { @@ -1375,23 +1125,17 @@ } a = null; e || (a = axs.properties.getTextFromAriaLabelledby(c, b)); - if (c.hasAttribute("aria-label")) { - var f = {type:"text"}; - f.text = c.getAttribute("aria-label"); - f.lastWord = axs.properties.getLastWord(f.text); - a ? f.unused = !0 : e && axs.utils.elementIsHtmlControl(c) || (a = f.text); - b.ariaLabel = f; - } + c.hasAttribute("aria-label") && (d = {type:"text"}, d.text = c.getAttribute("aria-label"), d.lastWord = axs.properties.getLastWord(d.text), a ? d.unused = !0 : e && axs.utils.elementIsHtmlControl(c) || (a = d.text), b.ariaLabel = d); c.hasAttribute("role") && "presentation" == c.getAttribute("role") || (a = axs.properties.getTextFromHostLanguageAttributes(c, b, a, e)); if (e && axs.utils.elementIsHtmlControl(c)) { - f = c.ownerDocument.defaultView; - if (c instanceof f.HTMLInputElement) { - var g = c; - "text" == g.type && g.value && 0 < g.value.length && (b.controlValue = {text:g.value}); - "range" == g.type && (b.controlValue = {text:g.value}); + d = c.ownerDocument.defaultView; + if (c instanceof d.HTMLInputElement) { + var f = c; + "text" == f.type && f.value && 0 < f.value.length && (b.controlValue = {text:f.value}); + "range" == f.type && (b.controlValue = {text:f.value}); } - c instanceof f.HTMLSelectElement && (b.controlValue = {text:c.value}); - b.controlValue && (f = b.controlValue, a ? f.unused = !0 : a = f.text); + c instanceof d.HTMLSelectElement && (b.controlValue = {text:c.value}); + b.controlValue && (d = b.controlValue, a ? d.unused = !0 : a = d.text); } if (e && axs.utils.elementIsAriaWidget(c)) { e = c.getAttribute("role"); @@ -1400,39 +1144,43 @@ c.hasAttribute("aria-valuetext") ? b.controlValue = {text:c.getAttribute("aria-valuetext")} : c.hasAttribute("aria-valuenow") && (b.controlValue = {value:c.getAttribute("aria-valuenow"), text:"" + c.getAttribute("aria-valuenow")}); } if ("menu" == e) { - for (var h = c.querySelectorAll("[role=menuitemcheckbox], [role=menuitemradio]"), f = [], g = 0;g < h.length;g++) { - "true" == h[g].getAttribute("aria-checked") && f.push(h[g]); + var g = c.querySelectorAll("[role=menuitemcheckbox], [role=menuitemradio]"); + d = []; + for (f = 0;f < g.length;f++) { + "true" == g[f].getAttribute("aria-checked") && d.push(g[f]); } - if (0 < f.length) { - h = ""; - for (g = 0;g < f.length;g++) { - h += axs.properties.findTextAlternatives(f[g], {}, !0), g < f.length - 1 && (h += ", "); + if (0 < d.length) { + g = ""; + for (f = 0;f < d.length;f++) { + g += axs.properties.findTextAlternatives(d[f], {}, !0), f < d.length - 1 && (g += ", "); } - b.controlValue = {text:h}; + b.controlValue = {text:g}; } } if ("combobox" == e || "select" == e) { b.controlValue = {text:"TODO"}; } - b.controlValue && (f = b.controlValue, a ? f.unused = !0 : a = f.text); + b.controlValue && (d = b.controlValue, a ? d.unused = !0 : a = d.text); } - f = !0; - c.hasAttribute("role") && (e = c.getAttribute("role"), (e = axs.constants.ARIA_ROLES[e]) && (!e.namefrom || 0 > e.namefrom.indexOf("contents")) && (f = !1)); - (d = axs.properties.getTextFromDescendantContent(c, d)) && f && (e = {type:"text"}, e.text = d, e.lastWord = axs.properties.getLastWord(e.text), a ? e.unused = !0 : a = d, b.content = e); - c.hasAttribute("title") && (d = {type:"string", valid:!0}, d.text = c.getAttribute("title"), d.lastWord = axs.properties.getLastWord(d.lastWord), a ? d.unused = !0 : a = d.text, b.title = d); + d = !0; + c.hasAttribute("role") && (e = c.getAttribute("role"), (e = axs.constants.ARIA_ROLES[e]) && (!e.namefrom || 0 > e.namefrom.indexOf("contents")) && (d = !1)); + (e = axs.properties.getTextFromDescendantContent(c)) && d && (d = {type:"text"}, d.text = e, d.lastWord = axs.properties.getLastWord(d.text), a ? d.unused = !0 : a = e, b.content = d); + c.hasAttribute("title") && (e = {type:"string", valid:!0}, e.text = c.getAttribute("title"), e.lastWord = axs.properties.getLastWord(e.lastWord), a ? e.unused = !0 : a = e.text, b.title = e); return 0 == Object.keys(b).length && null == a ? null : a; }; -axs.properties.getTextFromDescendantContent = function(a, b) { - for (var c = a.childNodes, d = [], e = 0;e < c.length;e++) { - var f = axs.properties.findTextAlternatives(c[e], {}, !0, b); - f && d.push(f.trim()); +axs.properties.getTextFromDescendantContent = function(a) { + var b = a.childNodes; + a = []; + for (var c = 0;c < b.length;c++) { + var d = axs.properties.findTextAlternatives(b[c], {}, !0); + d && a.push(d.trim()); } - if (d.length) { - c = ""; - for (e = 0;e < d.length;e++) { - c = [c, d[e]].join(" ").trim(); + if (a.length) { + b = ""; + for (c = 0;c < a.length;c++) { + b = [b, a[c]].join(" ").trim(); } - return c; + return b; } return null; }; @@ -1445,18 +1193,22 @@ var k = {type:"element"}, m = d[h]; k.value = m; var l = document.getElementById(m); - l ? (k.valid = !0, k.text = axs.properties.findTextAlternatives(l, {}, !0, !0), k.lastWord = axs.properties.getLastWord(k.text), f.push(k.text), k.element = l) : (k.valid = !1, e.valid = !1, k.errorMessage = {messageKey:"noElementWithId", args:[m]}); + l ? (k.valid = !0, k.text = axs.properties.findTextAlternatives(l, {}, !0), k.lastWord = axs.properties.getLastWord(k.text), f.push(l.textContent.trim()), k.element = l) : (k.valid = !1, e.valid = !1, k.errorMessage = {messageKey:"noElementWithId", args:[m]}); g.push(k); } 0 < g.length && (g[g.length - 1].last = !0, e.values = g, e.text = f.join(" "), e.lastWord = axs.properties.getLastWord(e.text), c = e.text, b.ariaLabelledby = e); return c; }; axs.properties.getTextFromHostLanguageAttributes = function(a, b, c, d) { - if (axs.browserUtils.matchSelector(a, "img") && a.hasAttribute("alt")) { - var e = {type:"string", valid:!0}; - e.text = a.getAttribute("alt"); - c ? e.unused = !0 : c = e.text; - b.alt = e; + if (axs.browserUtils.matchSelector(a, "img")) { + if (a.hasAttribute("alt")) { + var e = {type:"string", valid:!0}; + e.text = a.getAttribute("alt"); + c ? e.unused = !0 : c = e.text; + b.alt = e; + } else { + e = {valid:!1, errorMessage:"No alt value provided"}, b.alt = e, e = a.src, "string" == typeof e && (c = e.split("/").pop(), b.filename = {text:c}); + } } if (axs.browserUtils.matchSelector(a, 'input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), video:not([disabled])') && !d) { if (a.hasAttribute("id")) { @@ -1469,7 +1221,7 @@ } 0 < f.length && (f[f.length - 1].last = !0, e.values = f, e.text = g.join(" "), e.lastWord = axs.properties.getLastWord(e.text), c ? e.unused = !0 : c = e.text, b.labelFor = e); } - d = axs.dom.parentElement(a); + d = axs.utils.parentElement(a); for (e = {};d;) { if ("label" == d.tagName.toLowerCase() && (f = d, f.control == a)) { e.type = "element"; @@ -1478,10 +1230,9 @@ e.element = f; break; } - d = axs.dom.parentElement(d); + d = axs.utils.parentElement(d); } e.text && (c ? e.unused = !0 : c = e.text, b.labelWrapped = e); - axs.browserUtils.matchSelector(a, 'input[type="image"]') && a.hasAttribute("alt") && (e = {type:"string", valid:!0}, e.text = a.getAttribute("alt"), c ? e.unused = !0 : c = e.text, b.alt = e); Object.keys(b).length || (b.noLabel = !0); } return c; @@ -1494,13 +1245,18 @@ return a.substring(b > c ? b : c); }; axs.properties.getTextProperties = function(a) { - var b = {}, c = axs.properties.findTextAlternatives(a, b, !1, !0); - if (0 == Object.keys(b).length && ((a = axs.dom.asElement(a)) && axs.browserUtils.matchSelector(a, "img") && (b.alt = {valid:!1, errorMessage:"No alt value provided"}, a = a.src, "string" == typeof a && (c = a.split("/").pop(), b.filename = {text:c})), !c)) { - return null; + var b = {}; + a = axs.properties.findTextAlternatives(a, b, !1, !0); + if (0 == Object.keys(b).length) { + if (!a) { + return null; + } + b.hasProperties = !1; + } else { + b.hasProperties = !0; } - b.hasProperties = Boolean(Object.keys(b).length); - b.computedText = c; - b.lastWord = axs.properties.getLastWord(c); + b.computedText = a; + b.lastWord = axs.properties.getLastWord(a); return b; }; axs.properties.getAriaProperties = function(a) { @@ -1533,11 +1289,11 @@ return 0 < Object.keys(b).length ? b : null; }; axs.properties.getGlobalAriaProperties = function(a) { - var b = {}, c; - for (c in axs.constants.GLOBAL_PROPERTIES) { - if (a.hasAttribute(c)) { - var d = a.getAttribute(c); - b[c] = axs.utils.getAriaPropertyValue(c, d, a); + for (var b = {}, c = 0;c < axs.constants.GLOBAL_PROPERTIES.length;c++) { + var d = axs.constants.GLOBAL_PROPERTIES[c]; + if (a.hasAttribute(d)) { + var e = a.getAttribute(d); + b[d] = axs.utils.getAriaPropertyValue(d, e, a); } } return b; @@ -1572,9 +1328,9 @@ return d; }; axs.properties.getAllProperties = function(a) { - var b = axs.dom.asElement(a); + var b = axs.utils.asElement(a); if (!b) { - return {}; + return{}; } var c = {}; c.ariaProperties = axs.properties.getAriaProperties(b); @@ -1584,80 +1340,6 @@ c.videoProperties = axs.properties.getVideoProperties(b); return c; }; -(function() { - function a(a) { - if (!a) { - return null; - } - var c = a.tagName; - if (!c) { - return null; - } - c = c.toUpperCase(); - c = axs.constants.TAG_TO_IMPLICIT_SEMANTIC_INFO[c]; - if (!c || !c.length) { - return null; - } - for (var d = null, e = 0, f = c.length;e < f;e++) { - var g = c[e]; - if (g.selector) { - if (axs.browserUtils.matchSelector(a, g.selector)) { - return g; - } - } else { - d = g; - } - } - return d; - } - axs.properties.getImplicitRole = function(b) { - return (b = a(b)) ? b.role : ""; - }; - axs.properties.canTakeAriaAttributes = function(b) { - return (b = a(b)) ? !b.reserved : !0; - }; -})(); -axs.properties.getNativelySupportedAttributes = function(a) { - var b = []; - if (!a) { - return b; - } - a = a.cloneNode(!1); - for (var c = Object.keys(axs.constants.ARIA_TO_HTML_ATTRIBUTE), d = 0;d < c.length;d++) { - var e = c[d]; - axs.constants.ARIA_TO_HTML_ATTRIBUTE[e] in a && (b[b.length] = e); - } - return b; -}; -(function() { - var a = {}; - axs.properties.getSelectorForRole = function(b) { - if (!b) { - return ""; - } - if (a[b] && a.hasOwnProperty(b)) { - return a[b]; - } - var c = ['[role="' + b + '"]']; - Object.keys(axs.constants.TAG_TO_IMPLICIT_SEMANTIC_INFO).forEach(function(a) { - var e = axs.constants.TAG_TO_IMPLICIT_SEMANTIC_INFO[a]; - if (e && e.length) { - for (var f = 0;f < e.length;f++) { - var g = e[f]; - if (g.role === b) { - if (g.selector) { - c[c.length] = g.selector; - } else { - c[c.length] = a; - break; - } - } - } - } - }); - return a[b] = c.join(","); - }; -})(); axs.AuditRule = function(a) { for (var b = !0, c = [], d = 0;d < axs.AuditRule.requiredFields.length;d++) { var e = axs.AuditRule.requiredFields[d]; @@ -1681,59 +1363,69 @@ a.push(b); }; axs.AuditRule.collectMatchingElements = function(a, b, c, d) { - axs.dom.composedTreeSearch(a, null, {preorder:function(a) { - if (d) { - for (var f = 0;f < d.length;f++) { - if (axs.browserUtils.matchSelector(a, d[f])) { - return !1; - } + if (a.nodeType == Node.ELEMENT_NODE) { + var e = a + } + e && b.call(null, e) && c.push(e); + if (e) { + var f = e.shadowRoot || e.webkitShadowRoot; + if (f) { + axs.AuditRule.collectMatchingElements(f, b, c, f); + return; + } + } + if (e && "content" == e.localName) { + for (e = e.getDistributedNodes(), a = 0;a < e.length;a++) { + axs.AuditRule.collectMatchingElements(e[a], b, c, d); + } + } else { + if (e && "shadow" == e.localName) { + a = e, d ? (d = d.olderShadowRoot || a.olderShadowRoot) && axs.AuditRule.collectMatchingElements(d, b, c, d) : console.warn("ShadowRoot not provided for", e); + } else { + for (e = a.firstChild;null != e;) { + axs.AuditRule.collectMatchingElements(e, b, c, d), e = e.nextSibling; } } - b(a) && c.push(a); - return !0; - }}); + } }; axs.AuditRule.prototype.run = function(a) { a = a || {}; - var b = "maxResults" in a ? a.maxResults : null, c = []; - axs.AuditRule.collectMatchingElements("scope" in a ? a.scope : document, this.relevantElementMatcher_, c, a.ignoreSelectors); - var d = []; - if (!c.length) { - return {result:axs.constants.AuditResult.NA}; + var b = "ignoreSelectors" in a ? a.ignoreSelectors : [], c = "maxResults" in a ? a.maxResults : null, d = []; + axs.AuditRule.collectMatchingElements("scope" in a ? a.scope : document, this.relevantElementMatcher_, d); + var e = []; + if (!d.length) { + return{result:axs.constants.AuditResult.NA}; } - for (var e = 0;e < c.length && !(null != b && d.length >= b);e++) { - var f = c[e]; - this.test_(f, a.config) && this.addElement(d, f); + for (a = 0;a < d.length && !(null != c && e.length >= c);a++) { + var f = d[a], g; + a: { + g = f; + for (var h = 0;h < b.length;h++) { + if (axs.browserUtils.matchSelector(g, b[h])) { + g = !0; + break a; + } + } + g = !1; + } + !g && this.test_(f) && this.addElement(e, f); } - a = {result:d.length ? axs.constants.AuditResult.FAIL : axs.constants.AuditResult.PASS, elements:d}; - e < c.length && (a.resultsTruncated = !0); - return a; + b = {result:e.length ? axs.constants.AuditResult.FAIL : axs.constants.AuditResult.PASS, elements:e}; + a < d.length && (b.resultsTruncated = !0); + return b; }; +axs.AuditRule.specs = {}; axs.AuditRules = {}; -(function() { - var a = {}, b = {}; - axs.AuditRules.specs = {}; - axs.AuditRules.addRule = function(c) { - var d = new axs.AuditRule(c); - if (d.code in b) { - throw Error('Can not add audit rule with same code: "' + d.code + '"'); +axs.AuditRules.getRule = function(a) { + if (!axs.AuditRules.rules) { + axs.AuditRules.rules = {}; + for (var b in axs.AuditRule.specs) { + var c = axs.AuditRule.specs[b], d = new axs.AuditRule(c); + axs.AuditRules.rules[c.name] = d; } - if (d.name in a) { - throw Error('Can not add audit rule with same name: "' + d.name + '"'); - } - a[d.name] = b[d.code] = d; - axs.AuditRules.specs[c.name] = c; - }; - axs.AuditRules.getRule = function(c) { - return a[c] || b[c] || null; - }; - axs.AuditRules.getRules = function(b) { - var d = Object.keys(a); - return b ? d : d.map(function(a) { - return this.getRule(a); - }, axs.AuditRules); - }; -})(); + } + return axs.AuditRules.rules[a]; +}; axs.AuditResults = function() { this.errors_ = []; this.warnings_ = []; @@ -1775,15 +1467,11 @@ }; goog.exportProperty(axs.AuditResults.prototype, "toString", axs.AuditResults.prototype.toString); axs.Audit = {}; -axs.AuditConfiguration = function(a) { - null == a && (a = {}); +axs.AuditConfiguration = function() { this.rules_ = {}; this.maxResults = this.auditRulesToIgnore = this.auditRulesToRun = this.scope = null; this.withConsoleApi = !1; this.showUnsupportedRulesWarning = !0; - for (var b in this) { - this.hasOwnProperty(b) && b in a && (this[b] = a[b]); - } goog.exportProperty(this, "scope", this.scope); goog.exportProperty(this, "auditRulesToRun", this.auditRulesToRun); goog.exportProperty(this, "auditRulesToIgnore", this.auditRulesToIgnore); @@ -1802,26 +1490,21 @@ this.rules_[a].severity = b; }, getSeverity:function(a) { return a in this.rules_ && "severity" in this.rules_[a] ? this.rules_[a].severity : null; -}, setRuleConfig:function(a, b) { - a in this.rules_ || (this.rules_[a] = {}); - this.rules_[a].config = b; -}, getRuleConfig:function(a) { - return a in this.rules_ && "config" in this.rules_[a] ? this.rules_[a].config : null; }}; goog.exportProperty(axs.AuditConfiguration.prototype, "ignoreSelectors", axs.AuditConfiguration.prototype.ignoreSelectors); goog.exportProperty(axs.AuditConfiguration.prototype, "getIgnoreSelectors", axs.AuditConfiguration.prototype.getIgnoreSelectors); axs.Audit.unsupportedRulesWarningShown = !1; axs.Audit.getRulesCannotRun = function(a) { - return a.withConsoleApi ? [] : axs.AuditRules.getRules().filter(function(a) { - return a.requiresConsoleAPI; + return a.withConsoleApi ? [] : Object.keys(axs.AuditRule.specs).filter(function(a) { + return axs.AuditRules.getRule(a).requiresConsoleAPI; }).map(function(a) { - return a.code; + return axs.AuditRules.getRule(a).code; }); }; axs.Audit.run = function(a) { a = a || new axs.AuditConfiguration; var b = a.withConsoleApi, c = [], d; - d = a.auditRulesToRun && 0 < a.auditRulesToRun.length ? a.auditRulesToRun : axs.AuditRules.getRules(!0); + d = a.auditRulesToRun && 0 < a.auditRulesToRun.length ? a.auditRulesToRun : Object.keys(axs.AuditRule.specs); if (a.auditRulesToIgnore) { for (var e = 0;e < a.auditRulesToIgnore.length;e++) { var f = a.auditRulesToIgnore[e]; @@ -1836,8 +1519,6 @@ if (0 < k.length || a.scope) { h.ignoreSelectors = k; } - k = a.getRuleConfig(g.name); - null != k && (h.config = k); a.scope && (h.scope = a.scope); a.maxResults && (h.maxResults = a.maxResults); h = g.run.call(g, h); @@ -1878,72 +1559,17 @@ return b; }; goog.exportSymbol("axs.Audit.accessibilityErrorMessage", axs.Audit.accessibilityErrorMessage); -axs.AuditRules.addRule({name:"ariaOnReservedElement", heading:"This element does not support ARIA roles, states and properties", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_12", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return !axs.properties.canTakeAriaAttributes(a); -}, test:function(a) { - return null !== axs.properties.getAriaProperties(a); -}, code:"AX_ARIA_12"}); -axs.AuditRules.addRule({name:"ariaOwnsDescendant", heading:"aria-owns should not be used if ownership is implicit in the DOM", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_06", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, "[aria-owns]"); -}, test:function(a) { - return axs.utils.getIdReferents("aria-owns", a).some(function(b) { - return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_CONTAINED_BY; - }); -}, code:"AX_ARIA_06"}); -axs.AuditRules.addRule({name:"ariaRoleNotScoped", heading:"Elements with ARIA roles must be in the correct scope", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_09", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, "[role]"); -}, test:function(a) { - var b = axs.utils.getRoles(a); - if (!b || !b.applied) { - return !1; - } - b = b.applied.details.scope; - if (!b || 0 === b.length) { - return !1; - } - for (var c = a;c = axs.dom.parentElement(c);) { - var d = axs.utils.getRoles(c, !0); - if (d && d.applied && 0 <= b.indexOf(d.applied.name)) { - return !1; - } - } - if (a = axs.utils.getAriaIdReferrers(a, "aria-owns")) { - for (c = 0;c < a.length;c++) { - if ((d = axs.utils.getRoles(a[c], !0)) && d.applied && 0 <= b.indexOf(d.applied.name)) { - return !1; - } - } - } - return !0; -}, code:"AX_ARIA_09"}); -axs.AuditRules.addRule({name:"audioWithoutControls", heading:"Audio elements should have controls", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_audio_01", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { +axs.AuditRule.specs.audioWithoutControls = {name:"audioWithoutControls", heading:"Audio elements should have controls", url:"", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { return axs.browserUtils.matchSelector(a, "audio[autoplay]"); }, test:function(a) { - return !a.querySelectorAll("[controls]").length && 3 < a.duration; -}, code:"AX_AUDIO_01"}); -(function() { - var a = /^aria\-/; - axs.AuditRules.addRule({name:"badAriaAttribute", heading:"This element has an invalid ARIA attribute", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_11", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(b) { - b = b.attributes; - for (var c = 0, d = b.length;c < d;c++) { - if (a.test(b[c].name)) { - return !0; - } - } - return !1; - }, test:function(b) { - b = b.attributes; - for (var c = 0, d = b.length;c < d;c++) { - var e = b[c].name; - if (a.test(e) && (e = e.replace(a, ""), !axs.constants.ARIA_PROPERTIES.hasOwnProperty(e))) { - return !0; - } - } - return !1; - }, code:"AX_ARIA_11"}); -})(); -axs.AuditRules.addRule({name:"badAriaAttributeValue", heading:"ARIA state and property values must be valid", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_04", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - var b = axs.utils.getSelectorForAriaProperties(axs.constants.ARIA_PROPERTIES); + return!a.querySelectorAll("[controls]").length && 3 < a.duration; +}, code:"AX_AUDIO_01"}; +axs.AuditRule.specs.badAriaAttributeValue = {name:"badAriaAttributeValue", heading:"ARIA state and property values must be valid", url:"", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { + var b = "", c; + for (c in axs.constants.ARIA_PROPERTIES) { + b += "[aria-" + c + "],"; + } + b = b.substring(0, b.length - 1); return axs.browserUtils.matchSelector(a, b); }, test:function(a) { for (var b in axs.constants.ARIA_PROPERTIES) { @@ -1951,328 +1577,135 @@ if (a.hasAttribute(c)) { var d = a.getAttribute(c); if (!axs.utils.getAriaPropertyValue(c, d, a).valid) { - return !0; + return!0; } } } - return !1; -}, code:"AX_ARIA_04"}); -axs.AuditRules.addRule({name:"badAriaRole", heading:"Elements with ARIA roles must use a valid, non-abstract ARIA role", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_01", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { + return!1; +}, code:"AX_ARIA_04"}; +axs.AuditRule.specs.badAriaRole = {name:"badAriaRole", heading:"Elements with ARIA roles must use a valid, non-abstract ARIA role", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_aria_01--elements-with-aria-roles-must-use-a-valid-non-abstract-aria-role", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { return axs.browserUtils.matchSelector(a, "[role]"); }, test:function(a) { - return !axs.utils.getRoles(a).valid; -}, code:"AX_ARIA_01"}); -axs.AuditRules.addRule({name:"controlsWithoutLabel", heading:"Controls and media elements should have labels", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_text_01", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - if (!axs.browserUtils.matchSelector(a, 'input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), video:not([disabled])') || "presentation" == a.getAttribute("role")) { - return !1; + return!axs.utils.getRoles(a).valid; +}, code:"AX_ARIA_01"}; +axs.AuditRule.specs.controlsWithoutLabel = {name:"controlsWithoutLabel", heading:"Controls and media elements should have labels", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_text_01--controls-and-media-elements-should-have-labels", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { + if (!axs.browserUtils.matchSelector(a, 'input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), video:not([disabled])')) { + return!1; } if (0 <= a.tabIndex) { - return !0; + return!0; } - for (a = axs.dom.parentElement(a);null != a;a = axs.dom.parentElement(a)) { + for (a = axs.utils.parentElement(a);null != a;a = axs.utils.parentElement(a)) { if (axs.utils.elementIsAriaWidget(a)) { - return !1; + return!1; } } - return !0; + return!0; }, test:function(a) { - if (axs.utils.isElementOrAncestorHidden(a) || "input" == a.tagName.toLowerCase() && "button" == a.type && a.value.length || "button" == a.tagName.toLowerCase() && a.textContent.replace(/^\s+|\s+$/g, "").length || axs.utils.hasLabel(a)) { - return !1; - } - a = axs.properties.findTextAlternatives(a, {}); - return null === a || "" === a.trim() ? !0 : !1; -}, code:"AX_TEXT_01", ruleName:"Controls and media elements should have labels"}); -axs.AuditRules.addRule({name:"duplicateId", heading:"Any ID referred to via an IDREF must be unique in the DOM", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_html_02", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - return a.hasAttribute("id") ? axs.utils.getIdReferrers(a).some(function(a) { - return !axs.utils.isElementOrAncestorHidden(a); - }) : !1; -}, test:function(a) { - var b = "[id='" + a.id.replace(/'/g, "\\'") + "']"; - return 1 < a.ownerDocument.querySelectorAll(b).length; -}, code:"AX_HTML_02"}); -axs.AuditRules.addRule({name:"focusableElementNotVisibleAndNotAriaHidden", heading:"These elements are focusable but either invisible or obscured by another element", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_01", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return axs.utils.isElementOrAncestorHidden(a) || "input" == a.tagName.toLowerCase() && "button" == a.type && a.value.length || "button" == a.tagName.toLowerCase() && a.textContent.replace(/^\s+|\s+$/g, "").length ? !1 : axs.utils.hasLabel(a) ? !1 : !0; +}, code:"AX_TEXT_01", ruleName:"Controls and media elements should have labels"}; +axs.AuditRule.specs.focusableElementNotVisibleAndNotAriaHidden = {name:"focusableElementNotVisibleAndNotAriaHidden", heading:"These elements are focusable but either invisible or obscured by another element", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_focus_01--these-elements-are-focusable-but-either-invisible-or-obscured-by-another-element", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { if (!axs.browserUtils.matchSelector(a, axs.utils.FOCUSABLE_ELEMENTS_SELECTOR)) { - return !1; + return!1; } if (0 <= a.tabIndex) { - return !0; + return!0; } - for (var b = axs.dom.parentElement(a);null != b;b = axs.dom.parentElement(b)) { - if (axs.utils.elementIsAriaWidget(b)) { - return !1; + for (a = axs.utils.parentElement(a);null != a;a = axs.utils.parentElement(a)) { + if (axs.utils.elementIsAriaWidget(a)) { + return!1; } } - a = axs.properties.findTextAlternatives(a, {}); - return null === a || "" === a.trim() ? !1 : !0; + return!0; }, test:function(a) { if (axs.utils.isElementOrAncestorHidden(a)) { - return !1; + return!1; } a.focus(); - return !axs.utils.elementIsVisible(a); -}, code:"AX_FOCUS_01"}); -axs.AuditRules.addRule({name:"humanLangMissing", heading:"The web page should have the content's human language indicated in the markup", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_html_01", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return a instanceof a.ownerDocument.defaultView.HTMLHtmlElement; -}, test:function(a) { - return a.lang ? !1 : !0; -}, code:"AX_HTML_01"}); -axs.AuditRules.addRule({name:"imagesWithoutAltText", heading:"Images should have a text alternative or presentational role", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_text_02", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return!axs.utils.elementIsVisible(a); +}, code:"AX_FOCUS_01"}; +axs.AuditRule.specs.imagesWithoutAltText = {name:"imagesWithoutAltText", heading:"Images should have an alt attribute", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_text_02--images-should-have-an-alt-attribute-unless-they-have-an-aria-role-of-presentation", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { return axs.browserUtils.matchSelector(a, "img") && !axs.utils.isElementOrAncestorHidden(a); }, test:function(a) { - if (a.hasAttribute("alt") && "" == a.alt || "presentation" == a.getAttribute("role")) { - return !1; - } - var b = {}; - axs.properties.findTextAlternatives(a, b); - return 0 == Object.keys(b).length ? !0 : !1; -}, code:"AX_TEXT_02"}); -axs.AuditRules.addRule({name:"linkWithUnclearPurpose", heading:"The purpose of each link should be clear from the link text", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_text_04", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, "a[href]") && !axs.utils.isElementOrAncestorHidden(a); -}, test:function(a, b) { - for (var c = b || {}, d = c.blacklistPhrases || [], e = /\s+/, f = 0;f < d.length;f++) { - var g = "^\\s*" + d[f].trim().replace(e, "\\s*") + "s*[^a-z]$"; - if ((new RegExp(g, "i")).test(a.textContent)) { - return !0; - } - } - c = c.stopwords || "click tap go here learn more this page link about".split(" "); - d = axs.properties.findTextAlternatives(a, {}); - if (null === d || "" === d.trim()) { - return !0; - } - d = d.replace(/[^a-zA-Z ]/g, ""); - for (f = 0;f < c.length;f++) { - if (d = d.replace(new RegExp("\\b" + c[f] + "\\b", "ig"), ""), "" == d.trim()) { - return !0; - } - } - return !1; -}, code:"AX_TEXT_04"}); -axs.AuditRules.addRule({name:"lowContrastElements", heading:"Text elements should have a reasonable contrast ratio", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_color_01", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return axs.properties.hasDirectTextDescendant(a) && !axs.utils.isElementDisabled(a); + return!a.hasAttribute("alt") && "presentation" != a.getAttribute("role"); +}, code:"AX_TEXT_02"}; +axs.AuditRule.specs.linkWithUnclearPurpose = {name:"linkWithUnclearPurpose", heading:"The purpose of each link should be clear from the link text", url:"", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return axs.browserUtils.matchSelector(a, "a"); +}, test:function(a) { + return/^\s*click\s*here\s*[^a-z]?$/i.test(a.textContent); +}, code:"AX_TITLE_01"}; +axs.AuditRule.specs.lowContrastElements = {name:"lowContrastElements", heading:"Text elements should have a reasonable contrast ratio", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_color_01--text-elements-should-have-a-reasonable-contrast-ratio", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return axs.properties.hasDirectTextDescendant(a); }, test:function(a) { var b = window.getComputedStyle(a, null); - return (a = axs.utils.getContrastRatioForElementWithComputedStyle(b, a)) && axs.utils.isLowContrast(a, b); -}, code:"AX_COLOR_01"}); -axs.AuditRules.addRule({name:"mainRoleOnInappropriateElement", heading:"role=main should only appear on significant elements", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_05", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return(a = axs.utils.getContrastRatioForElementWithComputedStyle(b, a)) && axs.utils.isLowContrast(a, b); +}, code:"AX_COLOR_01"}; +axs.AuditRule.specs.mainRoleOnInappropriateElement = {name:"mainRoleOnInappropriateElement", heading:"role=main should only appear on significant elements", url:"", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { return axs.browserUtils.matchSelector(a, "[role~=main]"); }, test:function(a) { if (axs.utils.isInlineElement(a)) { - return !0; + return!0; } a = axs.properties.getTextFromDescendantContent(a); - return !a || 50 > a.length ? !0 : !1; -}, code:"AX_ARIA_05"}); -axs.AuditRules.addRule({name:"elementsWithMeaningfulBackgroundImage", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return !axs.utils.isElementOrAncestorHidden(a); -}, heading:"Meaningful images should not be used in element backgrounds", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_image_01", test:function(a) { + return!a || 50 > a.length ? !0 : !1; +}, code:"AX_ARIA_04"}; +axs.AuditRule.specs.elementsWithMeaningfulBackgroundImage = {name:"elementsWithMeaningfulBackgroundImage", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return!axs.utils.isElementOrAncestorHidden(a); +}, heading:"Meaningful images should not be used in element backgrounds", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_image_01--meaningful-images-should-not-be-used-in-element-backgrounds", test:function(a) { if (a.textContent && 0 < a.textContent.length) { - return !1; + return!1; } a = window.getComputedStyle(a, null); var b = a.backgroundImage; if (!b || "undefined" === b || "none" === b || 0 != b.indexOf("url")) { - return !1; + return!1; } b = parseInt(a.width, 10); a = parseInt(a.height, 10); return 150 > b && 150 > a; -}, code:"AX_IMAGE_01"}); -axs.AuditRules.addRule({name:"multipleAriaOwners", heading:"An element's ID must not be present in more that one aria-owns attribute at any time", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_07", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, "[aria-owns]"); +}, code:"AX_IMAGE_01"}; +axs.AuditRule.specs.nonExistentAriaLabelledbyElement = {name:"nonExistentAriaLabelledbyElement", heading:"aria-labelledby attributes should refer to an element which exists in the DOM", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_aria_02--aria-labelledby-attributes-should-refer-to-an-element-which-exists-in-the-dom", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return axs.browserUtils.matchSelector(a, "[aria-labelledby]"); }, test:function(a) { - return axs.utils.getIdReferents("aria-owns", a).some(function(a) { - return 1 < axs.utils.getAriaIdReferrers(a, "aria-owns").length; - }); -}, code:"AX_ARIA_07"}); -axs.AuditRules.addRule({name:"multipleLabelableElementsPerLabel", heading:"A label element may not have labelable descendants other than its labeled control.", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_text_03--labels-should-only-contain-one-labelable-element", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, "label"); -}, test:function(a) { - if (1 < a.querySelectorAll(axs.utils.LABELABLE_ELEMENTS_SELECTOR).length) { - return !0; - } -}, code:"AX_TEXT_03"}); -axs.AuditRules.addRule({name:"nonExistentAriaRelatedElement", heading:"ARIA attributes which refer to other elements by ID should refer to elements which exist in the DOM", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_02", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - var b = axs.utils.getAriaPropertiesByValueType(["idref", "idref_list"]), b = axs.utils.getSelectorForAriaProperties(b); - return axs.browserUtils.matchSelector(a, b); -}, test:function(a) { - for (var b = axs.utils.getAriaPropertiesByValueType(["idref", "idref_list"]), b = axs.utils.getSelectorForAriaProperties(b).split(","), c = 0, d = b.length;c < d;c++) { - var e = b[c]; - if (axs.browserUtils.matchSelector(a, e)) { - var e = e.match(/aria-[^\]]+/)[0], f = a.getAttribute(e); - if (!axs.utils.getAriaPropertyValue(e, f, a).valid) { - return !0; - } + a = a.getAttribute("aria-labelledby").split(/\s+/); + for (var b = 0;b < a.length;b++) { + if (!document.getElementById(a[b])) { + return!0; } } - return !1; -}, code:"AX_ARIA_02"}); -axs.AuditRules.addRule({name:"pageWithoutTitle", heading:"The web page should have a title that describes topic or purpose", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_title_01", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return!1; +}, code:"AX_ARIA_02"}; +axs.AuditRule.specs.pageWithoutTitle = {name:"pageWithoutTitle", heading:"The web page should have a title that describes topic or purpose", url:"", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { return "html" == a.tagName.toLowerCase(); }, test:function(a) { a = a.querySelector("head"); return a ? (a = a.querySelector("title")) ? !a.textContent : !0 : !0; -}, code:"AX_TITLE_01"}); -axs.AuditRules.addRule({name:"requiredAriaAttributeMissing", heading:"Elements with ARIA roles must have all required attributes for that role", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_03", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { +}, code:"AX_TITLE_01"}; +axs.AuditRule.specs.requiredAriaAttributeMissing = {name:"requiredAriaAttributeMissing", heading:"Elements with ARIA roles must have all required attributes for that role", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_aria_03--elements-with-aria-roles-must-have-all-required-attributes-for-that-role", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { return axs.browserUtils.matchSelector(a, "[role]"); }, test:function(a) { var b = axs.utils.getRoles(a); if (!b.valid) { - return !1; + return!1; } for (var c = 0;c < b.roles.length;c++) { var d = b.roles[c].details.requiredPropertiesSet, e; for (e in d) { - if (d = e.replace(/^aria-/, ""), !("defaultValue" in axs.constants.ARIA_PROPERTIES[d] || a.hasAttribute(e)) && 0 > axs.properties.getNativelySupportedAttributes(a).indexOf(e)) { - return !0; + if (d = e.replace(/^aria-/, ""), !("defaultValue" in axs.constants.ARIA_PROPERTIES[d] || a.hasAttribute(e))) { + return!0; } } } -}, code:"AX_ARIA_03"}); -(function() { - function a(a) { - a = axs.utils.getRoles(a); - if (!a || !a.applied) { - return []; - } - a = a.applied; - return a.valid ? a.details.mustcontain || [] : []; - } - axs.AuditRules.addRule({name:"requiredOwnedAriaRoleMissing", heading:"Elements with ARIA roles must ensure required owned elements are present", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_08", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(b) { - return axs.browserUtils.matchSelector(b, "[role]") ? 0 < a(b).length : !1; - }, test:function(b) { - if ("true" === b.getAttribute("aria-busy")) { - return !1; - } - for (var c = a(b), d = c.length - 1;0 <= d;d--) { - var e = axs.utils.findDescendantsWithRole(b, c[d]); - if (e && e.length) { - return !1; - } - } - b = axs.utils.getIdReferents("aria-owns", b); - for (d = b.length - 1;0 <= d;d--) { - if ((e = axs.utils.getRoles(b[d], !0)) && e.applied) { - for (var e = e.applied, f = c.length - 1;0 <= f;f--) { - if (e.name === c[f]) { - return !1; - } - } - } - } - return !0; - }, code:"AX_ARIA_08"}); -})(); -axs.AuditRules.addRule({name:"roleTooltipRequiresDescribedby", heading:"Elements with role=tooltip should have a corresponding element with aria-describedby", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_02", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, "[role=tooltip]") && !axs.utils.isElementOrAncestorHidden(a); -}, test:function(a) { - return 0 === axs.utils.getAriaIdReferrers(a, "aria-describedby").length; -}, code:"AX_TOOLTIP_01"}); -axs.AuditRules.addRule({name:"tabIndexGreaterThanZero", heading:"Avoid positive integer values for tabIndex", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_03", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, "[tabindex]"); -}, test:function(a) { - if (0 < a.tabIndex) { - return !0; - } -}, code:"AX_FOCUS_03"}); -(function() { - axs.AuditRules.addRule({name:"tableHasAppropriateHeaders", heading:"Tables should have appropriate headers", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_table_01", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, "table"); - }, test:function(a) { - if ("presentation" == a.getAttribute("role")) { - return 0 != a.querySelectorAll("th").length; - } - a = a.querySelectorAll("tr"); - var b; - a: { - b = a[0].children; - for (var c = 0;c < b.length;c++) { - if ("TH" != b[c].tagName) { - b = !0; - break a; - } - } - b = !1; - } - if (b) { - a: { - for (b = 0;b < a.length;b++) { - if ("TH" != a[b].children[0].tagName) { - b = !0; - break a; - } - } - b = !1; - } - } - if (b) { - a: { - b = a[0].children; - for (c = 1;c < b.length;c++) { - if ("TH" != b[c].tagName) { - b = !0; - break a; - } - } - for (c = 1;c < a.length;c++) { - if ("TH" != a[c].children[0].tagName) { - b = !0; - break a; - } - } - b = !1; - } - } - return b; - }, code:"AX_TABLE_01"}); -})(); -(function() { - axs.AuditRules.addRule({name:"uncontrolledTabpanel", heading:"A tabpanel should be related to a tab via aria-controls or aria-labelledby", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_13", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, '[role="tabpanel"]'); - }, test:function(a) { - var b; - b = document.querySelectorAll('[role="tab"][aria-controls="' + a.id + '"]'); - (b = a.id && 1 === b.length) || (a.hasAttribute("aria-labelledby") ? (a = document.querySelectorAll("#" + a.getAttribute("aria-labelledby")), b = 1 === a.length && "tab" === a[0].getAttribute("role")) : b = !1); - return !b; - }, code:"AX_ARIA_13"}); -})(); -axs.AuditRules.addRule({name:"unfocusableElementsWithOnClick", heading:"Elements with onclick handlers must be focusable", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_02", severity:axs.constants.Severity.WARNING, opt_requiresConsoleAPI:!0, relevantElementMatcher:function(a) { +}, code:"AX_ARIA_03"}; +axs.AuditRule.specs.unfocusableElementsWithOnClick = {name:"unfocusableElementsWithOnClick", heading:"Elements with onclick handlers must be focusable", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_focus_02--elements-with-onclick-handlers-must-be-focusable", severity:axs.constants.Severity.WARNING, opt_requiresConsoleAPI:!0, relevantElementMatcher:function(a) { return a instanceof a.ownerDocument.defaultView.HTMLBodyElement || axs.utils.isElementOrAncestorHidden(a) ? !1 : "click" in getEventListeners(a) ? !0 : !1; }, test:function(a) { - return !a.hasAttribute("tabindex") && !axs.utils.isElementImplicitlyFocusable(a) && !a.disabled; -}, code:"AX_FOCUS_02"}); -(function() { - var a = /^aria\-/, b = axs.utils.getSelectorForAriaProperties(axs.constants.ARIA_PROPERTIES); - axs.AuditRules.addRule({name:"unsupportedAriaAttribute", heading:"This element has an unsupported ARIA attribute", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_10", severity:axs.constants.Severity.SEVERE, relevantElementMatcher:function(a) { - return axs.browserUtils.matchSelector(a, b); - }, test:function(b) { - var d = axs.utils.getRoles(b, !0), d = d && d.applied ? d.applied.details.propertiesSet : axs.constants.GLOBAL_PROPERTIES; - b = b.attributes; - for (var e = 0, f = b.length;e < f;e++) { - var g = b[e].name; - if (a.test(g)) { - var h = g.replace(a, ""); - if (axs.constants.ARIA_PROPERTIES.hasOwnProperty(h) && !(g in d)) { - return !0; - } - } - } - return !1; - }, code:"AX_ARIA_10"}); -})(); -axs.AuditRules.addRule({name:"videoWithoutCaptions", heading:"Video elements should use <track> elements to provide captions", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_video_01", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { + return!a.hasAttribute("tabindex") && !axs.utils.isElementImplicitlyFocusable(a) && !a.disabled; +}, code:"AX_FOCUS_02"}; +axs.AuditRule.specs.videoWithoutCaptions = {name:"videoWithoutCaptions", heading:"Video elements should use <track> elements to provide captions", url:"https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#-ax_video_01--video-elements-should-use-track-elements-to-provide-captions", severity:axs.constants.Severity.WARNING, relevantElementMatcher:function(a) { return axs.browserUtils.matchSelector(a, "video"); }, test:function(a) { - return !a.querySelectorAll("track[kind=captions]").length; -}, code:"AX_VIDEO_01"}); + return!a.querySelectorAll("track[kind=captions]").length; +}, code:"AX_VIDEO_01"}; - return axs; -}); - -// Define AMD module if possible, export globals otherwise. -if (typeof define !== 'undefined' && define.amd) { - define([], fn); -} else { - var axs = fn.call(this); -}
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium index a71396a..b80685a 100644 --- a/third_party/libjingle/README.chromium +++ b/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@ Name: libjingle URL: http://www.webrtc.org Version: unknown -Revision: 10776 +Revision: 10790 License: BSD License File: source/talk/COPYING Security Critical: yes
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c index 80d4c22..ac1bb392 100644 --- a/third_party/sqlite/amalgamation/sqlite3.c +++ b/third_party/sqlite/amalgamation/sqlite3.c
@@ -7575,11 +7575,6 @@ const char* fileName, int noLock); CHROMIUM_SQLITE_API -int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, - const char* fileName, - int flags, - int* fd); -CHROMIUM_SQLITE_API void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file, int fd, int flags); @@ -30513,36 +30508,6 @@ } /* -** Search for an unused file descriptor that was opened on the database file. -** If a suitable file descriptor if found, then it is stored in *fd; otherwise, -** *fd is not modified. -** -** If a reusable file descriptor is not found, and a new UnixUnusedFd cannot -** be allocated, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK is returned. -*/ -CHROMIUM_SQLITE_API -int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, - const char* fileName, - int flags, - int* fd) { - unixFile* unixSQLite3File = (unixFile*)file; - int fileType = flags & 0xFFFFFF00; - if (fileType == SQLITE_OPEN_MAIN_DB) { - UnixUnusedFd *unusedFd = findReusableFd(fileName, flags); - if (unusedFd) { - *fd = unusedFd->fd; - } else { - unusedFd = sqlite3_malloc(sizeof(*unusedFd)); - if (!unusedFd) { - return SQLITE_NOMEM; - } - } - unixSQLite3File->pUnused = unusedFd; - } - return SQLITE_OK; -} - -/* ** Marks 'fd' as the unused file descriptor for 'pFile'. */ CHROMIUM_SQLITE_API @@ -30669,10 +30634,17 @@ chromium_sqlite3_initialize_unix_sqlite3_file(pFile); if( eType==SQLITE_OPEN_MAIN_DB ){ - rc = chromium_sqlite3_get_reusable_file_handle(pFile, zName, flags, &fd); - if( rc!=SQLITE_OK ){ - return rc; + UnixUnusedFd *pUnused; + pUnused = findReusableFd(zName, flags); + if( pUnused ){ + fd = pUnused->fd; + }else{ + pUnused = sqlite3_malloc(sizeof(*pUnused)); + if( !pUnused ){ + return SQLITE_NOMEM; + } } + p->pUnused = pUnused; /* Database filenames are double-zero terminated if they are not ** URIs with parameters. Hence, they can always be passed into
diff --git a/third_party/sqlite/amalgamation/sqlite3.h b/third_party/sqlite/amalgamation/sqlite3.h index dfa538e..2713c32 100644 --- a/third_party/sqlite/amalgamation/sqlite3.h +++ b/third_party/sqlite/amalgamation/sqlite3.h
@@ -7451,11 +7451,6 @@ const char* fileName, int noLock); CHROMIUM_SQLITE_API -int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, - const char* fileName, - int flags, - int* fd); -CHROMIUM_SQLITE_API void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file, int fd, int flags);
diff --git a/third_party/sqlite/patches/0005-Modify-default-VFS-to-support-WebDatabase.patch b/third_party/sqlite/patches/0005-Modify-default-VFS-to-support-WebDatabase.patch index 81343dad..6cff9b3 100644 --- a/third_party/sqlite/patches/0005-Modify-default-VFS-to-support-WebDatabase.patch +++ b/third_party/sqlite/patches/0005-Modify-default-VFS-to-support-WebDatabase.patch
@@ -1,7 +1,7 @@ -From 4b957c2c198a53498fe18ad9668e2817ace98b1e Mon Sep 17 00:00:00 2001 +From e646ccd23c9eaa86e4e6b0f5ee60867010407346 Mon Sep 17 00:00:00 2001 From: dumi <dumi@chromium.org> Date: Mon, 20 Jul 2009 23:40:51 +0000 -Subject: [PATCH 05/11] Modify default VFS to support WebDatabase. +Subject: [PATCH 05/12] Modify default VFS to support WebDatabase. The renderer WebDatabase implementation needs to broker certain requests to the browser. This modifies SQLite to allow monkey-patching the VFS @@ -17,13 +17,13 @@ https://codereview.chromium.org/377039 [Possibly not a complete list.] --- - third_party/sqlite/src/src/os_unix.c | 100 +++++++++++++++++++++++++++------ - third_party/sqlite/src/src/os_win.c | 8 +++ - third_party/sqlite/src/src/sqlite.h.in | 36 ++++++++++++ - 3 files changed, 128 insertions(+), 16 deletions(-) + third_party/sqlite/src/src/os_unix.c | 57 ++++++++++++++++++++++++++++++---- + third_party/sqlite/src/src/os_win.c | 8 +++++ + third_party/sqlite/src/src/sqlite.h.in | 31 ++++++++++++++++++ + 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c -index a9344ee..75b71dc 100644 +index a9344ee..c6e1b6c 100644 --- a/third_party/sqlite/src/src/os_unix.c +++ b/third_party/sqlite/src/src/os_unix.c @@ -1321,6 +1321,12 @@ static int fileHasMoved(unixFile *pFile){ @@ -39,7 +39,7 @@ return pFile->pInode!=0 && (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); #endif -@@ -5615,6 +5621,78 @@ static int findCreateFileMode( +@@ -5615,6 +5621,48 @@ static int findCreateFileMode( } /* @@ -62,36 +62,6 @@ +} + +/* -+** Search for an unused file descriptor that was opened on the database file. -+** If a suitable file descriptor if found, then it is stored in *fd; otherwise, -+** *fd is not modified. -+** -+** If a reusable file descriptor is not found, and a new UnixUnusedFd cannot -+** be allocated, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK is returned. -+*/ -+CHROMIUM_SQLITE_API -+int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, -+ const char* fileName, -+ int flags, -+ int* fd) { -+ unixFile* unixSQLite3File = (unixFile*)file; -+ int fileType = flags & 0xFFFFFF00; -+ if (fileType == SQLITE_OPEN_MAIN_DB) { -+ UnixUnusedFd *unusedFd = findReusableFd(fileName, flags); -+ if (unusedFd) { -+ *fd = unusedFd->fd; -+ } else { -+ unusedFd = sqlite3_malloc(sizeof(*unusedFd)); -+ if (!unusedFd) { -+ return SQLITE_NOMEM; -+ } -+ } -+ unixSQLite3File->pUnused = unusedFd; -+ } -+ return SQLITE_OK; -+} -+ -+/* +** Marks 'fd' as the unused file descriptor for 'pFile'. +*/ +CHROMIUM_SQLITE_API @@ -118,7 +88,7 @@ ** Open the file zPath. ** ** Previously, the SQLite OS layer used three functions in place of this -@@ -5715,20 +5793,13 @@ static int unixOpen( +@@ -5715,7 +5763,7 @@ static int unixOpen( sqlite3_randomness(0,0); } @@ -126,24 +96,8 @@ + chromium_sqlite3_initialize_unix_sqlite3_file(pFile); if( eType==SQLITE_OPEN_MAIN_DB ){ -- UnixUnusedFd *pUnused; -- pUnused = findReusableFd(zName, flags); -- if( pUnused ){ -- fd = pUnused->fd; -- }else{ -- pUnused = sqlite3_malloc(sizeof(*pUnused)); -- if( !pUnused ){ -- return SQLITE_NOMEM; -- } -+ rc = chromium_sqlite3_get_reusable_file_handle(pFile, zName, flags, &fd); -+ if( rc!=SQLITE_OK ){ -+ return rc; - } -- p->pUnused = pUnused; - - /* Database filenames are double-zero terminated if they are not - ** URIs with parameters. Hence, they can always be passed into -@@ -5798,10 +5869,7 @@ static int unixOpen( + UnixUnusedFd *pUnused; +@@ -5798,10 +5846,7 @@ static int unixOpen( *pOutFlags = flags; } @@ -155,7 +109,7 @@ if( isDelete ){ #if OS_VXWORKS -@@ -5893,7 +5961,7 @@ static int unixOpen( +@@ -5893,7 +5938,7 @@ static int unixOpen( open_finished: if( rc!=SQLITE_OK ){ @@ -182,10 +136,10 @@ + #endif /* SQLITE_OS_WIN */ diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src/sqlite.h.in -index f1d4e40..36aa999 100644 +index f1d4e40..00e4771 100644 --- a/third_party/sqlite/src/src/sqlite.h.in +++ b/third_party/sqlite/src/src/sqlite.h.in -@@ -7408,6 +7408,42 @@ int sqlite3_vtab_on_conflict(sqlite3 *); +@@ -7408,6 +7408,37 @@ int sqlite3_vtab_on_conflict(sqlite3 *); @@ -211,11 +165,6 @@ + const char* fileName, + int noLock); +CHROMIUM_SQLITE_API -+int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, -+ const char* fileName, -+ int flags, -+ int* fd); -+CHROMIUM_SQLITE_API +void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file, + int fd, + int flags); @@ -229,5 +178,5 @@ ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. -- -2.4.5 +2.6.1
diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c index eaa97cf..dc34066 100644 --- a/third_party/sqlite/src/src/os_unix.c +++ b/third_party/sqlite/src/src/os_unix.c
@@ -5644,36 +5644,6 @@ } /* -** Search for an unused file descriptor that was opened on the database file. -** If a suitable file descriptor if found, then it is stored in *fd; otherwise, -** *fd is not modified. -** -** If a reusable file descriptor is not found, and a new UnixUnusedFd cannot -** be allocated, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK is returned. -*/ -CHROMIUM_SQLITE_API -int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, - const char* fileName, - int flags, - int* fd) { - unixFile* unixSQLite3File = (unixFile*)file; - int fileType = flags & 0xFFFFFF00; - if (fileType == SQLITE_OPEN_MAIN_DB) { - UnixUnusedFd *unusedFd = findReusableFd(fileName, flags); - if (unusedFd) { - *fd = unusedFd->fd; - } else { - unusedFd = sqlite3_malloc(sizeof(*unusedFd)); - if (!unusedFd) { - return SQLITE_NOMEM; - } - } - unixSQLite3File->pUnused = unusedFd; - } - return SQLITE_OK; -} - -/* ** Marks 'fd' as the unused file descriptor for 'pFile'. */ CHROMIUM_SQLITE_API @@ -5800,10 +5770,17 @@ chromium_sqlite3_initialize_unix_sqlite3_file(pFile); if( eType==SQLITE_OPEN_MAIN_DB ){ - rc = chromium_sqlite3_get_reusable_file_handle(pFile, zName, flags, &fd); - if( rc!=SQLITE_OK ){ - return rc; + UnixUnusedFd *pUnused; + pUnused = findReusableFd(zName, flags); + if( pUnused ){ + fd = pUnused->fd; + }else{ + pUnused = sqlite3_malloc(sizeof(*pUnused)); + if( !pUnused ){ + return SQLITE_NOMEM; + } } + p->pUnused = pUnused; /* Database filenames are double-zero terminated if they are not ** URIs with parameters. Hence, they can always be passed into
diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src/sqlite.h.in index 333adfe..243835c 100644 --- a/third_party/sqlite/src/src/sqlite.h.in +++ b/third_party/sqlite/src/src/sqlite.h.in
@@ -7446,11 +7446,6 @@ const char* fileName, int noLock); CHROMIUM_SQLITE_API -int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file, - const char* fileName, - int flags, - int* fd); -CHROMIUM_SQLITE_API void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file, int fd, int flags);
diff --git a/third_party/webrtc_overrides/webrtc/base/logging.cc b/third_party/webrtc_overrides/webrtc/base/logging.cc index ce4fbd9..34618dac 100644 --- a/third_party/webrtc_overrides/webrtc/base/logging.cc +++ b/third_party/webrtc_overrides/webrtc/base/logging.cc
@@ -18,12 +18,12 @@ #include "base/logging.h" #include "base/strings/string_util.h" #include "base/threading/platform_thread.h" -#include "third_party/webrtc/base/ipaddress.h" -#include "third_party/webrtc/base/stream.h" #include "third_party/webrtc/base/stringencode.h" #include "third_party/webrtc/base/stringutils.h" -#include "third_party/webrtc/base/timeutils.h" + +// This needs to be included after base/logging.h. #include "third_party/webrtc_overrides/webrtc/base/diagnostic_logging.h" +#include "third_party/webrtc_overrides/webrtc/base/logging.h" // From this file we can't use VLOG since it expands into usage of the __FILE__ // macro (for correct filtering). The actual logging call from DIAGNOSTIC_LOG in @@ -347,9 +347,6 @@ if (delegate == g_logging_delegate_function) return; CHECK(!g_logging_delegate_function); -#ifdef NDEBUG - IPAddress::set_strip_sensitive(true); -#endif g_logging_delegate_function = delegate; if (g_extra_logging_init_function)
diff --git a/tools/grit/grit/util.py b/tools/grit/grit/util.py index b958bc2..93dce261 100755 --- a/tools/grit/grit/util.py +++ b/tools/grit/grit/util.py
@@ -483,7 +483,8 @@ '''Parses a define argument and returns the name and value. The format is either "NAME=VAL" or "NAME", using True as the default value. - Values of "1" and "0" are transformed to True and False respectively. + Values of "1"/"true" and "0"/"false" are transformed to True and False + respectively. Args: define: a string of the form "NAME=VAL" or "NAME". @@ -497,8 +498,8 @@ val = True if len(parts) > 1: val = parts[1] - if val == "1": val = True - elif val == "0": val = False + if val == "1" or val == "true": val = True + elif val == "0" or val == "false": val = False return (name, val)
diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni index 083e3d93..f60d8fa1 100644 --- a/tools/grit/grit_rule.gni +++ b/tools/grit/grit_rule.gni
@@ -244,13 +244,6 @@ "enable_settings_app", ] } -if (enable_google_now) { - grit_defines += [ - "-D", - "enable_google_now", - ] -} - if (enable_webrtc) { grit_defines += [ "-D",
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 9fbc2d6..20b3484 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -29416,7 +29416,7 @@ <summary> The time from the New Tab page being shown until the user to clicked on a most visited tile. Only recorded if the user clicked on a tile, as opposed - to e.g. searching via the omnibox. + to e.g. searching via the omnibox. Only measured on Android. </summary> </histogram> @@ -29680,7 +29680,7 @@ <summary> The visual type of each most visited tile displayed on the new tab page, e.g. actual thumbnail or placeholder thumbnail. This is recorded for each - most visited item when the NTP is opened. + most visited item when the NTP is opened. Only measured on Android. </summary> </histogram> @@ -29688,7 +29688,16 @@ <owner>newt@chromium.org</owner> <summary> The visual type of the most visited item that the user clicked on, e.g. - actual thumbnail or placeholder thumbnail. + actual thumbnail or placeholder thumbnail. Only measured on Android. + </summary> +</histogram> + +<histogram name="NewTabPage.TimeSpent" units="milliseconds"> + <owner>knn@chromium.org</owner> + <summary> + The time spent on the new tab page as measured from when it was loaded or + last brought to the foreground until it was navigated away from or hidden. + Only measured on Android. </summary> </histogram>
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn index 2e0f78c9..6b04ad9 100644 --- a/ui/aura/BUILD.gn +++ b/ui/aura/BUILD.gn
@@ -66,6 +66,8 @@ "input_state_lookup_win.h", "layout_manager.cc", "layout_manager.h", + "mus/mus_util.cc", + "mus/mus_util.h", "remote_window_tree_host_win.cc", "remote_window_tree_host_win.h", "scoped_window_targeter.cc",
diff --git a/ui/aura/mus/mus_util.cc b/ui/aura/mus/mus_util.cc new file mode 100644 index 0000000..ed57f6a --- /dev/null +++ b/ui/aura/mus/mus_util.cc
@@ -0,0 +1,21 @@ +// Copyright 2015 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 "ui/aura/mus/mus_util.h" + +#include "ui/aura/window.h" + +namespace aura { + +mus::Window* GetMusWindow(Window* window) { + if (!window) + return nullptr; + return static_cast<mus::Window*>(window->GetNativeWindowProperty("mus")); +} + +void SetMusWindow(Window* window, mus::Window* mus_window) { + window->SetNativeWindowProperty("mus", mus_window); +} + +} // namespace aura
diff --git a/ui/aura/mus/mus_util.h b/ui/aura/mus/mus_util.h new file mode 100644 index 0000000..a3f2805e --- /dev/null +++ b/ui/aura/mus/mus_util.h
@@ -0,0 +1,24 @@ +// Copyright 2015 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 UI_AURA_MUS_MUS_UTIL_H_ +#define UI_AURA_MUS_MUS_UTIL_H_ + +#include "ui/aura/aura_export.h" + +namespace mus { +class Window; +} + +namespace aura { + +class Window; + +AURA_EXPORT mus::Window* GetMusWindow(Window* window); + +AURA_EXPORT void SetMusWindow(Window* window, mus::Window* mus_window); + +} // namespace aura + +#endif // UI_AURA_MUS_MUS_UTIL_H_
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc index 5c9f25cd..bb988e1f 100644 --- a/ui/aura/window_tree_host.cc +++ b/ui/aura/window_tree_host.cc
@@ -102,11 +102,22 @@ return invert; } +void WindowTreeHost::SetOutputSurfacePadding(const gfx::Insets& padding) { + if (output_surface_padding_ == padding) + return; + + output_surface_padding_ = padding; + OnHostResized(GetBounds().size()); +} + void WindowTreeHost::UpdateRootWindowSize(const gfx::Size& host_size) { - gfx::Rect bounds(host_size); + gfx::Rect bounds(output_surface_padding_.left(), + output_surface_padding_.top(), host_size.width(), + host_size.height()); gfx::RectF new_bounds(ui::ConvertRectToDIP(window()->layer(), bounds)); window()->layer()->transform().TransformRect(&new_bounds); - window()->SetBounds(gfx::Rect(gfx::ToFlooredSize(new_bounds.size()))); + window()->SetBounds(gfx::Rect(gfx::ToFlooredPoint(new_bounds.origin()), + gfx::ToFlooredSize(new_bounds.size()))); } void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point* point) const { @@ -259,10 +270,13 @@ } void WindowTreeHost::OnHostResized(const gfx::Size& new_size) { + gfx::Size adjusted_size(new_size); + adjusted_size.Enlarge(output_surface_padding_.width(), + output_surface_padding_.height()); // The compositor should have the same size as the native root window host. // Get the latest scale from display because it might have been changed. compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), - new_size); + adjusted_size); gfx::Size layer_size = GetBounds().size(); // The layer, and the observers should be notified of the
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h index 1571969..31d6904 100644 --- a/ui/aura/window_tree_host.h +++ b/ui/aura/window_tree_host.h
@@ -13,6 +13,7 @@ #include "ui/base/cursor/cursor.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/events/event_source.h" +#include "ui/gfx/geometry/insets.h" #include "ui/gfx/native_widget_types.h" namespace gfx { @@ -78,8 +79,19 @@ virtual void SetRootTransform(const gfx::Transform& transform); virtual gfx::Transform GetInverseRootTransform() const; + // Sets padding applied to the output surface. The output surface is sized to + // to the size of the host plus output surface padding. |window()| is offset + // by |padding|, that is, |window|'s origin is set to padding.left(), + // padding.top(). + // This does not impact the bounds as returned from GetBounds(), only the + // output surface size and location of window(). Additionally window() is + // sized to the size set by bounds (more specifically the size passed to + // OnHostResized()), but the location of window() is set to that of + // |padding|. + void SetOutputSurfacePadding(const gfx::Insets& padding); + // Updates the root window's size using |host_size|, current - // transform and insets. + // transform and outsets. virtual void UpdateRootWindowSize(const gfx::Size& host_size); // Converts |point| from the root window's coordinate system to native @@ -237,6 +249,8 @@ // Whether the InputMethod instance is owned by this WindowTreeHost. bool owned_input_method_; + gfx::Insets output_surface_padding_; + DISALLOW_COPY_AND_ASSIGN(WindowTreeHost); };
diff --git a/ui/file_manager/image_loader/manifest.json b/ui/file_manager/image_loader/manifest.json index ab0fd83..0d0673f 100644 --- a/ui/file_manager/image_loader/manifest.json +++ b/ui/file_manager/image_loader/manifest.json
@@ -14,10 +14,11 @@ "fileManagerPrivate", "https://www.google-analytics.com/", "https://www.googledrive.com/", + "https://lh3.googleusercontent.com/", "metricsPrivate", "storage" ], - "content_security_policy": "default-src 'none'; script-src 'self' blob: filesystem: chrome://resources chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj; style-src 'self' blob: filesystem:; frame-src 'self' blob: filesystem:; img-src 'self' blob: filesystem: data:; media-src 'self' blob: filesystem:; connect-src 'self' blob: filesystem: https://www.googledrive.com https://www.google-analytics.com", + "content_security_policy": "default-src 'none'; script-src 'self' blob: filesystem: chrome://resources chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj; style-src 'self' blob: filesystem:; frame-src 'self' blob: filesystem:; img-src 'self' blob: filesystem: data:; media-src 'self' blob: filesystem:; connect-src 'self' blob: filesystem: https://www.googledrive.com https://www.google-analytics.com https://lh3.googleusercontent.com", "background": { "scripts": [ "chrome://resources/js/assert.js",
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index 850dc2d..de11882 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -101,6 +101,8 @@ "views/message_view_context_menu_controller.h", "views/notification_button.cc", "views/notification_button.h", + "views/notification_progress_bar.cc", + "views/notification_progress_bar.h", "views/notification_view.cc", "views/notification_view.h", "views/notifier_settings_view.cc",
diff --git a/ui/message_center/message_center.gyp b/ui/message_center/message_center.gyp index befef6a..90f6838 100644 --- a/ui/message_center/message_center.gyp +++ b/ui/message_center/message_center.gyp
@@ -90,6 +90,8 @@ 'views/message_view_context_menu_controller.h', 'views/notification_button.cc', 'views/notification_button.h', + 'views/notification_progress_bar.cc', + 'views/notification_progress_bar.h', 'views/notification_view.cc', 'views/notification_view.h', 'views/notifier_settings_view.cc',
diff --git a/ui/message_center/views/notification_progress_bar.cc b/ui/message_center/views/notification_progress_bar.cc new file mode 100644 index 0000000..b5f013e --- /dev/null +++ b/ui/message_center/views/notification_progress_bar.cc
@@ -0,0 +1,185 @@ +// Copyright 2015 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 "ui/message_center/views/notification_progress_bar.h" + +#include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/core/SkPath.h" +#include "ui/gfx/canvas.h" +#include "ui/message_center/message_center_style.h" + +namespace { + +// Dimensions. +const int kProgressBarWidth = message_center::kNotificationWidth - + message_center::kTextLeftPadding - message_center::kTextRightPadding; + +const int kAnimationFrameRateHz = 60; + +const int kAnimationDuration = 2000; // In millisecond + +} // namespace + +namespace message_center { + +// NotificationProgressBarBase ///////////////////////////////////////////////// + +gfx::Size NotificationProgressBarBase::GetPreferredSize() const { + gfx::Size pref_size(kProgressBarWidth, message_center::kProgressBarThickness); + gfx::Insets insets = GetInsets(); + pref_size.Enlarge(insets.width(), insets.height()); + return pref_size; +} + +// NotificationProgressBar ///////////////////////////////////////////////////// + +NotificationProgressBar::NotificationProgressBar() { +} + +NotificationProgressBar::~NotificationProgressBar() { +} + +bool NotificationProgressBar::is_indeterminate() { + return false; +} + +void NotificationProgressBar::OnPaint(gfx::Canvas* canvas) { + gfx::Rect content_bounds = GetContentsBounds(); + + // Draw background. + SkPath background_path; + background_path.addRoundRect(gfx::RectToSkRect(content_bounds), + message_center::kProgressBarCornerRadius, + message_center::kProgressBarCornerRadius); + SkPaint background_paint; + background_paint.setStyle(SkPaint::kFill_Style); + background_paint.setFlags(SkPaint::kAntiAlias_Flag); + background_paint.setColor(message_center::kProgressBarBackgroundColor); + canvas->DrawPath(background_path, background_paint); + + // Draw slice. + SkPath slice_path; + const int slice_width = + static_cast<int>(content_bounds.width() * GetNormalizedValue() + 0.5); + if (slice_width < 1) + return; + + gfx::Rect slice_bounds = content_bounds; + slice_bounds.set_width(slice_width); + slice_path.addRoundRect(gfx::RectToSkRect(slice_bounds), + message_center::kProgressBarCornerRadius, + message_center::kProgressBarCornerRadius); + + SkPaint slice_paint; + slice_paint.setStyle(SkPaint::kFill_Style); + slice_paint.setFlags(SkPaint::kAntiAlias_Flag); + slice_paint.setColor(message_center::kProgressBarSliceColor); + canvas->DrawPath(slice_path, slice_paint); +} + +// NotificationIndeteminateProgressBar ///////////////////////////////////////// + +NotificationIndeterminateProgressBar::NotificationIndeterminateProgressBar() { + indeterminate_bar_animation_.reset( + new gfx::LinearAnimation(kAnimationFrameRateHz, this)); + indeterminate_bar_animation_->SetDuration(kAnimationDuration); + indeterminate_bar_animation_->Start(); +} + +NotificationIndeterminateProgressBar::~NotificationIndeterminateProgressBar() { + indeterminate_bar_animation_->Stop(); // Just in case +} + +bool NotificationIndeterminateProgressBar::is_indeterminate() { + return true; +} + +void NotificationIndeterminateProgressBar::OnPaint(gfx::Canvas* canvas) { + gfx::Rect content_bounds = GetContentsBounds(); + + // Draw background. + SkPath background_path; + background_path.addRoundRect(gfx::RectToSkRect(content_bounds), + message_center::kProgressBarCornerRadius, + message_center::kProgressBarCornerRadius); + SkPaint background_paint; + background_paint.setStyle(SkPaint::kFill_Style); + background_paint.setFlags(SkPaint::kAntiAlias_Flag); + background_paint.setColor(message_center::kProgressBarBackgroundColor); + canvas->DrawPath(background_path, background_paint); + + // Draw slice. + SkPath slice_path; + double time = indeterminate_bar_animation_->GetCurrentValue(); + + // The animation spec corresponds to the material design lite's parameter. + // (cf. https://github.com/google/material-design-lite/) + double bar1_left; + double bar1_width; + double bar2_left; + double bar2_width; + if (time < 0.50) { + bar1_left = time / 2; + bar1_width = time * 1.5; + bar2_left = 0; + bar2_width = 0; + } else if (time < 0.75) { + bar1_left = time * 3 - 1.25; + bar1_width = 0.75 - (time - 0.5) * 3; + bar2_left = 0; + bar2_width = time - 0.5; + } else { + bar1_left = 1; + bar1_width = 0; + bar2_left = (time - 0.75) * 4; + bar2_width = 0.25 - (time - 0.75); + } + + int bar1_x = static_cast<int>(content_bounds.width() * bar1_left); + int bar1_w = + std::min(static_cast<int>(content_bounds.width() * bar1_width + 0.5), + content_bounds.width() - bar1_x); + int bar2_x = static_cast<int>(content_bounds.width() * bar2_left); + int bar2_w = + std::min(static_cast<int>(content_bounds.width() * bar2_width + 0.5), + content_bounds.width() - bar2_x); + + + gfx::Rect slice_bounds = content_bounds; + slice_bounds.set_x(content_bounds.x() + bar1_x); + slice_bounds.set_width(bar1_w); + slice_path.addRoundRect(gfx::RectToSkRect(slice_bounds), + message_center::kProgressBarCornerRadius, + message_center::kProgressBarCornerRadius); + slice_bounds.set_x(content_bounds.x() + bar2_x); + slice_bounds.set_width(bar2_w); + slice_path.addRoundRect(gfx::RectToSkRect(slice_bounds), + message_center::kProgressBarCornerRadius, + message_center::kProgressBarCornerRadius); + + SkPaint slice_paint; + slice_paint.setStyle(SkPaint::kFill_Style); + slice_paint.setFlags(SkPaint::kAntiAlias_Flag); + slice_paint.setColor(message_center::kProgressBarSliceColor); + canvas->DrawPath(slice_path, slice_paint); +} + +void NotificationIndeterminateProgressBar::AnimationProgressed( + const gfx::Animation* animation) { + if (animation == indeterminate_bar_animation_.get()) { + DCHECK(indeterminate_bar_animation_); + SchedulePaint(); + } +} + +void NotificationIndeterminateProgressBar::AnimationEnded( + const gfx::Animation* animation) { + // Restarts animation. + if (animation == indeterminate_bar_animation_.get()) { + DCHECK(indeterminate_bar_animation_); + indeterminate_bar_animation_->Start(); + } +} + +} // namespace message_center
diff --git a/ui/message_center/views/notification_progress_bar.h b/ui/message_center/views/notification_progress_bar.h new file mode 100644 index 0000000..4cec162 --- /dev/null +++ b/ui/message_center/views/notification_progress_bar.h
@@ -0,0 +1,64 @@ +// Copyright 2015 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 UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_PROGRESS_BAR_H_ +#define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_PROGRESS_BAR_H_ + +#include "base/macros.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/linear_animation.h" +#include "ui/message_center/message_center_export.h" +#include "ui/views/controls/progress_bar.h" + +namespace message_center { + +class MESSAGE_CENTER_EXPORT NotificationProgressBarBase + : public views::ProgressBar { + public: + virtual bool is_indeterminate() = 0; + + private: + // Overriden from views::ProgressBar (originally from views::View) + gfx::Size GetPreferredSize() const override; +}; + +class MESSAGE_CENTER_EXPORT NotificationProgressBar + : public NotificationProgressBarBase { + public: + NotificationProgressBar(); + ~NotificationProgressBar() override; + + bool is_indeterminate() override; + + private: + // Overriden from views::ProgressBar (originally from views::View) + void OnPaint(gfx::Canvas* canvas) override; + + DISALLOW_COPY_AND_ASSIGN(NotificationProgressBar); +}; + +class MESSAGE_CENTER_EXPORT NotificationIndeterminateProgressBar + : public NotificationProgressBarBase, public gfx::AnimationDelegate { + public: + NotificationIndeterminateProgressBar(); + ~NotificationIndeterminateProgressBar() override; + + bool is_indeterminate() override; + + private: + // Overriden from views::ProgressBar (originally from views::View) + void OnPaint(gfx::Canvas* canvas) override; + + // Overriden from gfx::AnimationDelegate + void AnimationProgressed(const gfx::Animation* animation) override; + void AnimationEnded(const gfx::Animation* animation) override; + + scoped_ptr<gfx::LinearAnimation> indeterminate_bar_animation_; + + DISALLOW_COPY_AND_ASSIGN(NotificationIndeterminateProgressBar); +}; + +} // namespace message_center + +#endif // UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_PROGRESS_BAR_H_
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc index 76b78276..1bb5392e 100644 --- a/ui/message_center/views/notification_view.cc +++ b/ui/message_center/views/notification_view.cc
@@ -26,6 +26,7 @@ #include "ui/message_center/views/constants.h" #include "ui/message_center/views/message_center_controller.h" #include "ui/message_center/views/notification_button.h" +#include "ui/message_center/views/notification_progress_bar.h" #include "ui/message_center/views/padded_button.h" #include "ui/message_center/views/proportional_image_view.h" #include "ui/native_theme/native_theme.h" @@ -48,8 +49,6 @@ namespace { // Dimensions. -const int kProgressBarWidth = message_center::kNotificationWidth - - message_center::kTextLeftPadding - message_center::kTextRightPadding; const int kProgressBarBottomPadding = 0; // static @@ -157,67 +156,6 @@ child_at(i)->SetVisible(visible); } -// NotificationProgressBar ///////////////////////////////////////////////////// - -class NotificationProgressBar : public views::ProgressBar { - public: - NotificationProgressBar(); - ~NotificationProgressBar() override; - - private: - // Overriden from View - gfx::Size GetPreferredSize() const override; - void OnPaint(gfx::Canvas* canvas) override; - - DISALLOW_COPY_AND_ASSIGN(NotificationProgressBar); -}; - -NotificationProgressBar::NotificationProgressBar() { -} - -NotificationProgressBar::~NotificationProgressBar() { -} - -gfx::Size NotificationProgressBar::GetPreferredSize() const { - gfx::Size pref_size(kProgressBarWidth, message_center::kProgressBarThickness); - gfx::Insets insets = GetInsets(); - pref_size.Enlarge(insets.width(), insets.height()); - return pref_size; -} - -void NotificationProgressBar::OnPaint(gfx::Canvas* canvas) { - gfx::Rect content_bounds = GetContentsBounds(); - - // Draw background. - SkPath background_path; - background_path.addRoundRect(gfx::RectToSkRect(content_bounds), - message_center::kProgressBarCornerRadius, - message_center::kProgressBarCornerRadius); - SkPaint background_paint; - background_paint.setStyle(SkPaint::kFill_Style); - background_paint.setFlags(SkPaint::kAntiAlias_Flag); - background_paint.setColor(message_center::kProgressBarBackgroundColor); - canvas->DrawPath(background_path, background_paint); - - // Draw slice. - const int slice_width = - static_cast<int>(content_bounds.width() * GetNormalizedValue() + 0.5); - if (slice_width < 1) - return; - - gfx::Rect slice_bounds = content_bounds; - slice_bounds.set_width(slice_width); - SkPath slice_path; - slice_path.addRoundRect(gfx::RectToSkRect(slice_bounds), - message_center::kProgressBarCornerRadius, - message_center::kProgressBarCornerRadius); - SkPaint slice_paint; - slice_paint.setStyle(SkPaint::kFill_Style); - slice_paint.setFlags(SkPaint::kAntiAlias_Flag); - slice_paint.setColor(message_center::kProgressBarSliceColor); - canvas->DrawPath(slice_path, slice_paint); -} - } // namespace namespace message_center { @@ -663,14 +601,27 @@ DCHECK(top_view_ != NULL); + bool is_indeterminate = (notification.progress() < 0); + if (progress_bar_view_ && + progress_bar_view_->is_indeterminate() != is_indeterminate) { + delete progress_bar_view_; + progress_bar_view_ = NULL; + } + if (!progress_bar_view_) { - progress_bar_view_ = new NotificationProgressBar(); + if (!is_indeterminate) + progress_bar_view_ = new NotificationProgressBar(); + else + progress_bar_view_ = new NotificationIndeterminateProgressBar(); + progress_bar_view_->SetBorder(MakeProgressBarBorder( message_center::kProgressBarTopPadding, kProgressBarBottomPadding)); top_view_->AddChildView(progress_bar_view_); } - progress_bar_view_->SetValue(notification.progress() / 100.0); + if (!is_indeterminate) + progress_bar_view_->SetValue(notification.progress() / 100.0); + progress_bar_view_->SetVisible(!notification.items().size()); }
diff --git a/ui/message_center/views/notification_view.h b/ui/message_center/views/notification_view.h index 07c47e4b6..2efe8e4 100644 --- a/ui/message_center/views/notification_view.h +++ b/ui/message_center/views/notification_view.h
@@ -24,6 +24,7 @@ class MessageCenter; class MessageCenterController; class NotificationButton; +class NotificationProgressBarBase; class NotificationView; class PaddedButton; class ProportionalImageView; @@ -129,7 +130,7 @@ views::View* bottom_view_; views::View* image_container_; ProportionalImageView* image_view_; - views::ProgressBar* progress_bar_view_; + NotificationProgressBarBase* progress_bar_view_; std::vector<NotificationButton*> action_buttons_; std::vector<views::View*> separators_;
diff --git a/ui/views/mus/native_widget_mus.cc b/ui/views/mus/native_widget_mus.cc index 088cc2e..042f853 100644 --- a/ui/views/mus/native_widget_mus.cc +++ b/ui/views/mus/native_widget_mus.cc
@@ -13,6 +13,7 @@ #include "ui/aura/client/window_tree_client.h" #include "ui/aura/env.h" #include "ui/aura/layout_manager.h" +#include "ui/aura/mus/mus_util.h" #include "ui/aura/window.h" #include "ui/base/hit_test.h" #include "ui/gfx/canvas.h" @@ -178,7 +179,10 @@ show_state_before_fullscreen_(ui::PLATFORM_WINDOW_STATE_UNKNOWN), ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), content_(new aura::Window(this)), - close_widget_factory_(this) {} + close_widget_factory_(this) { + // TODO(fsamuel): Figure out lifetime of |window_|. + aura::SetMusWindow(content_, window_); +} NativeWidgetMus::~NativeWidgetMus() { if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
diff --git a/ui/views/mus/surface_context_factory.cc b/ui/views/mus/surface_context_factory.cc index 298f1fd1..362d39c4 100644 --- a/ui/views/mus/surface_context_factory.cc +++ b/ui/views/mus/surface_context_factory.cc
@@ -23,7 +23,8 @@ void AddMirroringLayer(ui::Layer* layer) override {} void RemoveMirroringLayer(ui::Layer* layer) override {} }; -} + +} // namespace SurfaceContextFactory::SurfaceContextFactory( mojo::Shell* shell,
diff --git a/ui/views/mus/window_tree_host_mus.h b/ui/views/mus/window_tree_host_mus.h index 1a4473e..ea3e8fd 100644 --- a/ui/views/mus/window_tree_host_mus.h +++ b/ui/views/mus/window_tree_host_mus.h
@@ -46,7 +46,7 @@ PlatformWindowMus* platform_window(); bitmap_uploader::BitmapUploader* bitmap_uploader() { return bitmap_uploader_.get(); - }; + } ui::PlatformWindowState show_state() const { return show_state_; } private: