diff --git a/DEPS b/DEPS index 4bb68764..bd6e9de 100644 --- a/DEPS +++ b/DEPS
@@ -105,11 +105,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '9f7d4cd62a0bf201c65aa11498594b8c1dc17107', + 'skia_revision': '0bf5408286ea3dacb197c220e1033dea3eeef2a8', # 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': '5e5144a59f3800bbf1a93f7d356606514b419e1f', + 'v8_revision': 'eb15bd6c048b992781fc52187316b9d31ac3cf4c', # 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. @@ -157,7 +157,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'b532d7ce708cb5ca9bf88abaa2eb213ddcf9babb', + 'freetype_revision': '578bcf103a12fb742cdb314565819011d1ac12a7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. @@ -339,7 +339,7 @@ 'packages': [ { 'package': 'infra/tools/luci/isolate/${{platform}}', - 'version': 'git_revision:8b15ba47cbaf07a56f93326e39f0c8e5069c19e8', + 'version': 'git_revision:bc125484b8513898f17bc2501ac5e95330f44a3b', }, ], 'dep_type': 'cipd', @@ -539,7 +539,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '3b438311bbf388975e1364de66d33ea85f878553', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '2c3d9c837512db5893d3b41e24a30110b70c9374', 'condition': 'checkout_linux', }, @@ -564,7 +564,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b0e855a33353ca30a2ecb1c0e9084ca3ef26836a', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1aefad2a598268530e01aff1d32ef71fe1555617', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1034,7 +1034,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '21dbf06b5aa6c7dc8cf56314d4a3f96f57956c53', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '1899c1270f0ce4264c6a579c3d86f81ac0e98aea', + Var('webrtc_git') + '/src.git' + '@' + 'df9e9ae9ee66a97a331ab9bd1dcc36cd2b2c110c', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 6a72e23..8bbde3dc 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -962,9 +962,10 @@ return [] # Outsource work to gclient verify try: - input_api.subprocess.check_output(['gclient', 'verify']) + input_api.subprocess.check_output(['gclient', 'verify'], + stderr=input_api.subprocess.STDOUT) return [] - except input_api.subprocess.CalledProcessError, error: + except input_api.subprocess.CalledProcessError as error: return [output_api.PresubmitError( 'DEPS file must have only git dependencies.', long_text=error.output)] @@ -1265,6 +1266,7 @@ 'Version control conflict markers found, please resolve.', errors)) return results + def _CheckGoogleSupportAnswerUrl(input_api, output_api): pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer') errors = [] @@ -2248,6 +2250,7 @@ ' questions.', errors)) return results + def _CheckAndroidTestAnnotationUsage(input_api, output_api): """Checks that android.test.suitebuilder.annotation.* is no longer used.""" deprecated_annotation_import_pattern = input_api.re.compile( @@ -2497,6 +2500,7 @@ ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ), ] + def _CheckNoDeprecatedCss(input_api, output_api): """ Make sure that we don't use deprecated CSS properties, functions or values. Our external @@ -2531,6 +2535,7 @@ ( "__defineSetter__", "Object.defineProperty" ), ] + def _CheckNoDeprecatedJs(input_api, output_api): """Make sure that we don't use deprecated JS in Chrome code.""" results = [] @@ -2548,18 +2553,21 @@ (fpath.LocalPath(), lnum, deprecated, replacement))) return results + def _CheckForRiskyJsArrowFunction(line_number, line): if ' => ' in line: return "line %d, is using an => (arrow) function\n %s\n" % ( line_number, line) return '' + def _CheckForRiskyJsConstLet(input_api, line_number, line): if input_api.re.match('^\s*(const|let)\s', line): return "line %d, is using const/let keyword\n %s\n" % ( line_number, line) return '' + def _CheckForRiskyJsFeatures(input_api, output_api): maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", ) # 'ui/webui/resources/cr_components are not allowed on ios' @@ -2609,6 +2617,7 @@ return results + def _CheckForRelativeIncludes(input_api, output_api): # Need to set the sys.path so PRESUBMIT_test.py runs properly import sys @@ -3269,13 +3278,13 @@ """Checks that crbug(.com) links are correctly prefixed by https://, unless they come in the accepted form TODO(crbug.com/...) """ - white_list = r'.+%s' % _IMPLEMENTATION_EXTENSIONS + white_list = (r'.+%s' % _IMPLEMENTATION_EXTENSIONS, ) black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS) sources = lambda f: input_api.FilterSourceFile( f, white_list=white_list, black_list=black_list) pattern = input_api.re.compile(r'//.*(?<!:\/\/)crbug[.com]*') - accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*'); + accepted_pattern = input_api.re.compile(r'//.*TODO\(crbug[.com]*') problems = [] for f in input_api.AffectedSourceFiles(sources): for line_num, line in f.ChangedContents():
diff --git a/PRESUBMIT_test_mocks.py b/PRESUBMIT_test_mocks.py index 3b491d9..ed6a750 100644 --- a/PRESUBMIT_test_mocks.py +++ b/PRESUBMIT_test_mocks.py
@@ -94,12 +94,16 @@ local_path = file.LocalPath() found_in_white_list = not white_list if white_list: + if type(white_list) is str: + raise TypeError('white_list should be an iterable of strings') for pattern in white_list: compiled_pattern = re.compile(pattern) if compiled_pattern.search(local_path): found_in_white_list = True break if black_list: + if type(black_list) is str: + raise TypeError('black_list should be an iterable of strings') for pattern in black_list: compiled_pattern = re.compile(pattern) if compiled_pattern.search(local_path):
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc index e62c852..a98fd91 100644 --- a/android_webview/browser/aw_settings.cc +++ b/android_webview/browser/aw_settings.cc
@@ -35,9 +35,6 @@ namespace { void PopulateFixedRendererPreferences(RendererPreferences* prefs) { - prefs->tap_multiple_targets_strategy = - content::TAP_MULTIPLE_TARGETS_STRATEGY_NONE; - // TODO(boliu): Deduplicate with chrome/ code. CR_DEFINE_STATIC_LOCAL( const gfx::FontRenderParams, params,
diff --git a/ash/assistant/assistant_interaction_controller.cc b/ash/assistant/assistant_interaction_controller.cc index 1e7a19c..107ea9b 100644 --- a/ash/assistant/assistant_interaction_controller.cc +++ b/ash/assistant/assistant_interaction_controller.cc
@@ -155,7 +155,18 @@ assistant_interaction_model_.SetInputModality(InputModality::kVoice); assistant_interaction_model_.SetMicState(MicState::kOpen); } else { - // In the case of a non-voice interaction, we commit the pending query. + // TODO(b/112000321): It should not be possible to reach this code without + // having previously pended a query. It does currently happen, however, in + // the case of notifications and device action queries which bypass the + // AssistantInteractionController when beginning an interaction. To address + // this, we temporarily pend an empty text query to commit until we can do + // development to expose something more meaningful. + if (assistant_interaction_model_.pending_query().type() == + AssistantQueryType::kEmpty) { + assistant_interaction_model_.SetPendingQuery( + std::make_unique<AssistantTextQuery>()); + } + assistant_interaction_model_.CommitPendingQuery(); assistant_interaction_model_.SetMicState(MicState::kClosed);
diff --git a/ash/assistant/model/assistant_interaction_model.cc b/ash/assistant/model/assistant_interaction_model.cc index f110de4..87ebc2b 100644 --- a/ash/assistant/model/assistant_interaction_model.cc +++ b/ash/assistant/model/assistant_interaction_model.cc
@@ -76,6 +76,8 @@ } void AssistantInteractionModel::CommitPendingQuery() { + DCHECK_NE(pending_query_->type(), AssistantQueryType::kEmpty); + committed_query_ = std::move(pending_query_); pending_query_ = std::make_unique<AssistantEmptyQuery>();
diff --git a/ash/assistant/model/assistant_query.h b/ash/assistant/model/assistant_query.h index 8efa1adb..08f76c2a7 100644 --- a/ash/assistant/model/assistant_query.h +++ b/ash/assistant/model/assistant_query.h
@@ -13,6 +13,7 @@ // AssistantQueryType ---------------------------------------------------------- +// TODO(dmblack): Rename kEmpty to kNull. // Defines possible types of an Assistant query. enum class AssistantQueryType { kEmpty, // See AssistantEmptyQuery. @@ -44,6 +45,7 @@ // AssistantEmptyQuery --------------------------------------------------------- +// TODO(dmblack): Rename to AssistantNullQuery. // An empty Assistant query used to signify the absence of an Assistant query. class AssistantEmptyQuery : public AssistantQuery { public: @@ -63,7 +65,7 @@ // An Assistant text query. class AssistantTextQuery : public AssistantQuery { public: - explicit AssistantTextQuery(const std::string& text) + explicit AssistantTextQuery(const std::string& text = std::string()) : AssistantQuery(AssistantQueryType::kText), text_(text) {} ~AssistantTextQuery() override = default;
diff --git a/ash/assistant/ui/main_stage/assistant_main_stage.cc b/ash/assistant/ui/main_stage/assistant_main_stage.cc index 080f726c..6634b00 100644 --- a/ash/assistant/ui/main_stage/assistant_main_stage.cc +++ b/ash/assistant/ui/main_stage/assistant_main_stage.cc
@@ -119,16 +119,6 @@ PreferredSizeChanged(); } -void AssistantMainStage::OnViewIsDeleting(views::View* view) { - if (view == committed_query_view_) { - committed_query_view_ = nullptr; - UpdateCommittedQueryViewSpacer(); - } else if (view == pending_query_view_) { - pending_query_view_ = nullptr; - UpdateSuggestionContainer(); - } -} - void AssistantMainStage::InitLayout(AssistantController* assistant_controller) { SetLayoutManager(std::make_unique<views::FillLayout>()); @@ -209,7 +199,11 @@ return; query_layout_container_->RemoveChildView(committed_query_view_); + delete committed_query_view_; + committed_query_view_ = nullptr; + + UpdateCommittedQueryViewSpacer(); } void AssistantMainStage::OnPendingQueryChanged(const AssistantQuery& query) { @@ -232,13 +226,12 @@ void AssistantMainStage::OnPendingQueryCleared() { if (pending_query_view_) { query_layout_container_->RemoveChildView(pending_query_view_); + delete pending_query_view_; - } else { - // We only need to update the suggestion container when we are not deleting - // the pending query view. Deleting the pending query view will trigger an - // update on the suggestion container itself. - UpdateSuggestionContainer(); + pending_query_view_ = nullptr; } + + UpdateSuggestionContainer(); } void AssistantMainStage::UpdateCommittedQueryViewSpacer() {
diff --git a/ash/assistant/ui/main_stage/assistant_main_stage.h b/ash/assistant/ui/main_stage/assistant_main_stage.h index 9d861c5..7be74700 100644 --- a/ash/assistant/ui/main_stage/assistant_main_stage.h +++ b/ash/assistant/ui/main_stage/assistant_main_stage.h
@@ -35,7 +35,6 @@ void OnViewBoundsChanged(views::View* view) override; void OnViewPreferredSizeChanged(views::View* view) override; void OnViewVisibilityChanged(views::View* view) override; - void OnViewIsDeleting(views::View* view) override; // AssistantInteractionModelObserver: void OnCommittedQueryChanged(const AssistantQuery& query) override;
diff --git a/ash/assistant/ui/main_stage/assistant_query_view.cc b/ash/assistant/ui/main_stage/assistant_query_view.cc index 25802b27..306a75c 100644 --- a/ash/assistant/ui/main_stage/assistant_query_view.cc +++ b/ash/assistant/ui/main_stage/assistant_query_view.cc
@@ -88,7 +88,7 @@ break; } case AssistantQueryType::kEmpty: - label_->SetText(base::string16()); + SetText(std::string()); break; } } @@ -123,7 +123,6 @@ label_->SizeToFit(width()); PreferredSizeChanged(); - SetVisible(true); } } // namespace ash
diff --git a/ash/system/message_center/ash_popup_alignment_delegate.cc b/ash/system/message_center/ash_popup_alignment_delegate.cc index fae8ba0..0cb6439 100644 --- a/ash/system/message_center/ash_popup_alignment_delegate.cc +++ b/ash/system/message_center/ash_popup_alignment_delegate.cc
@@ -55,6 +55,8 @@ } void AshPopupAlignmentDelegate::SetTrayBubbleHeight(int height) { + const int old_tray_bubble_height = tray_bubble_height_; + tray_bubble_height_ = height; // If the shelf is shown during auto-hide state, the distance from the edge @@ -69,7 +71,8 @@ else tray_bubble_height_ = 0; - DoUpdateIfPossible(); + if (old_tray_bubble_height != tray_bubble_height_) + ResetBounds(); } int AshPopupAlignmentDelegate::GetToastOriginX( @@ -104,9 +107,10 @@ return GetAlignment() == SHELF_ALIGNMENT_LEFT; } -void AshPopupAlignmentDelegate::RecomputeAlignment( +bool AshPopupAlignmentDelegate::RecomputeAlignment( const display::Display& display) { // Nothing needs to be done. + return false; } void AshPopupAlignmentDelegate::ConfigureWidgetInitParamsForContainer( @@ -134,8 +138,12 @@ } void AshPopupAlignmentDelegate::UpdateWorkArea() { - work_area_ = shelf_->GetUserWorkAreaBounds(); - DoUpdateIfPossible(); + gfx::Rect new_work_area = shelf_->GetUserWorkAreaBounds(); + if (work_area_ == new_work_area) + return; + + work_area_ = new_work_area; + ResetBounds(); } ///////////////////////////////////////////////////////////////////////////////
diff --git a/ash/system/message_center/ash_popup_alignment_delegate.h b/ash/system/message_center/ash_popup_alignment_delegate.h index ab262995..060d9e0 100644 --- a/ash/system/message_center/ash_popup_alignment_delegate.h +++ b/ash/system/message_center/ash_popup_alignment_delegate.h
@@ -53,7 +53,7 @@ gfx::Rect GetWorkArea() const override; bool IsTopDown() const override; bool IsFromLeft() const override; - void RecomputeAlignment(const display::Display& display) override; + bool RecomputeAlignment(const display::Display& display) override; void ConfigureWidgetInitParamsForContainer( views::Widget* widget, views::Widget::InitParams* init_params) override;
diff --git a/ash/system/message_center/notification_tray.cc b/ash/system/message_center/notification_tray.cc index d8badbac..602dd546 100644 --- a/ash/system/message_center/notification_tray.cc +++ b/ash/system/message_center/notification_tray.cc
@@ -321,7 +321,7 @@ popup_alignment_delegate_ = std::make_unique<AshPopupAlignmentDelegate>(shelf); popup_collection_ = std::make_unique<message_center::MessagePopupCollection>( - message_center(), popup_alignment_delegate_.get()); + popup_alignment_delegate_.get()); display::Screen* screen = display::Screen::GetScreen(); popup_alignment_delegate_->StartObserving( screen, screen->GetDisplayNearestWindow(status_area_window_)); @@ -425,7 +425,7 @@ if (IsMessageCenterVisible()) return false; - popup_collection_->DoUpdate(); + popup_collection_->Update(); return true; }
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc index cfb1e8b..37c6c63f 100644 --- a/ash/system/unified/unified_system_tray.cc +++ b/ash/system/unified/unified_system_tray.cc
@@ -70,7 +70,6 @@ std::make_unique<AshPopupAlignmentDelegate>(owner->shelf()); message_popup_collection_ = std::make_unique<message_center::MessagePopupCollection>( - message_center::MessageCenter::Get(), popup_alignment_delegate_.get()); display::Screen* screen = display::Screen::GetScreen(); popup_alignment_delegate_->StartObserving( @@ -87,7 +86,7 @@ bool UnifiedSystemTray::UiDelegate::ShowPopups() { if (owner_->IsBubbleShown()) return false; - message_popup_collection_->DoUpdate(); + message_popup_collection_->Update(); return true; }
diff --git a/ash/system/unified/user_chooser_view.cc b/ash/system/unified/user_chooser_view.cc index 99d930e..94a060d 100644 --- a/ash/system/unified/user_chooser_view.cc +++ b/ash/system/unified/user_chooser_view.cc
@@ -203,6 +203,8 @@ auto* icon = new views::ImageView; icon->SetImage( gfx::CreateVectorIcon(kSystemMenuNewUserIcon, kUnifiedMenuIconColor)); + icon->SetTooltipText( + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT)); AddChildView(icon); auto* label = new views::Label( @@ -212,7 +214,7 @@ label->SetSubpixelRenderingEnabled(false); AddChildView(label); - SetTooltipText( + SetAccessibleName( l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT)); SetFocusPainter(TrayPopupUtils::CreateFocusPainter()); SetFocusForPlatform();
diff --git a/build/config/android/BUILD.gn b/build/config/android/BUILD.gn index 5f77c4a..bdc192e 100644 --- a/build/config/android/BUILD.gn +++ b/build/config/android/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/android/config.gni") +import("//build/config/compiler/compiler.gni") import("//build/config/c++/c++.gni") import("//build/config/sanitizers/sanitizers.gni") @@ -204,5 +205,10 @@ config("default_orderfile_instrumentation") { if (use_order_profiling) { cflags = [ "-finstrument-function-entry-bare" ] + if (use_thin_lto) { + # TODO(pcc): This should not be necessary. Remove once + # https://reviews.llvm.org/D50017 lands and gets rolled in. + ldflags = [ "-Wl,-u,__cyg_profile_func_enter_bare" ] + } } }
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index db2f45df..76f24c9 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -592,7 +592,10 @@ # example by disabling the optimize configuration. # TODO(pcc): Make this conditional on is_official_build rather than on gn # flags for specific features. - if (!is_debug && use_thin_lto && current_toolchain == default_toolchain) { + if (!is_debug && use_thin_lto && + (current_toolchain == default_toolchain || + (is_android && defined(android_secondary_abi_toolchain) && + current_toolchain == android_secondary_abi_toolchain))) { assert(use_lld || target_os == "chromeos", "gold plugin only supported with ChromeOS")
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index 0b13302..9ae979d6 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -43,7 +43,7 @@ # Enables support for ThinLTO, which links 3x-10x faster than full LTO. See # also http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html - use_thin_lto = is_cfi + use_thin_lto = is_cfi || (is_android && is_official_build) # Tell VS to create a PDB that references information in .obj files rather # than copying it all. This should improve linker performance. mspdbcmf.exe @@ -209,7 +209,9 @@ # them off, but keep them on for Official builds and Chromecast builds. symbol_level = 2 } else if (using_sanitizer) { - # Sanitizers require symbols for filename suppressions to work. + # Sanitizers need line table info for stack traces. They don't need type + # info or variable info, so we can leave that out to speed up the build. + # Sanitizers also require symbols for filename suppressions to work. symbol_level = 1 } else { symbol_level = 0
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn index ba5edc1..faa533b 100644 --- a/build/config/sanitizers/BUILD.gn +++ b/build/config/sanitizers/BUILD.gn
@@ -249,25 +249,16 @@ config("common_sanitizer_flags") { cflags = [] - # Sanitizers need line table info for stack traces. They don't need type info - # or variable info, so we can leave that out to speed up the build (unless - # it's explicitly asked for by setting |sanitizer_keep_symbols| to true). if (using_sanitizer) { assert(is_clang, "sanitizers only supported with clang") assert(!is_official_build, "sanitizers not supported in official builds") - if (!sanitizer_no_symbols) { - if (!sanitizer_keep_symbols) { - cflags += [ "-gline-tables-only" ] - } - - cflags += [ - # Column info in debug data confuses Visual Studio's debugger, so don't - # use this by default. However, clusterfuzz needs it for good - # attribution of reports to CLs, so turn it on there. - "-gcolumn-info", - ] - } + cflags += [ + # Column info in debug data confuses Visual Studio's debugger, so don't + # use this by default. However, clusterfuzz needs it for good + # attribution of reports to CLs, so turn it on there. + "-gcolumn-info", + ] # Frame pointers are controlled in //build/config/compiler:default_stack_frames }
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index 1c62186..0f4255e6 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -102,16 +102,6 @@ # Default value when unset and use_sanitizer_coverage=true: # trace-pc-guard,indirect-calls sanitizer_coverage_flags = "" - - # Keep symbol level when building with sanitizers. When sanitizers are - # enabled, the default is to compile with the minimum debug info level - # necessary, overriding any other symbol level arguments that may be set. - # Setting this to true prevents this. - sanitizer_keep_symbols = false - - # Builds fuzzer/sanitizers without symbols. Use with symbol_level=0. - # Useful for reducing binary size when building with use_clang_coverage=true. - sanitizer_no_symbols = false } # Disable sanitizers for non-default toolchains.
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/cc/mojo_embedder/async_layer_tree_frame_sink.cc index 2445fe6..ebaee44 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.cc +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.cc
@@ -7,7 +7,9 @@ #include <utility> #include "base/bind.h" +#include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" +#include "cc/base/histograms.h" #include "cc/trees/layer_tree_frame_sink_client.h" #include "components/viz/client/hit_test_data_provider.h" #include "components/viz/client/local_surface_id_provider.h" @@ -207,6 +209,16 @@ } void AsyncLayerTreeFrameSink::OnBeginFrame(const viz::BeginFrameArgs& args) { + // Note that client_name is constant during the lifetime of the process and + // it's either "Browser" or "Renderer". + if (const char* client_name = GetClientNameForMetrics()) { + base::TimeDelta frame_difference = base::TimeTicks::Now() - args.frame_time; + UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( + base::StringPrintf("GraphicsPipeline.%s.ReceivedBeginFrame", + client_name), + frame_difference, base::TimeDelta::FromMicroseconds(1), + base::TimeDelta::FromMilliseconds(100), 50); + } if (!needs_begin_frames_) { TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Graphics.Pipeline", TRACE_ID_GLOBAL(args.trace_id),
diff --git a/chrome/VERSION b/chrome/VERSION index 6d1277b..284fe4a6 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=70 MINOR=0 -BUILD=3508 +BUILD=3509 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ConnectivityTask.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ConnectivityTask.java index 8002bfa7..e79fa36 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ConnectivityTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ConnectivityTask.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.feedback; import android.os.SystemClock; +import android.support.annotation.IntDef; import org.chromium.base.Log; import org.chromium.base.ThreadUtils; @@ -13,8 +14,9 @@ import org.chromium.net.ConnectionType; import org.chromium.net.NetworkChangeNotifier; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Collections; -import java.util.EnumMap; import java.util.HashMap; import java.util.Map; @@ -74,22 +76,22 @@ @VisibleForTesting static final String SYSTEM_HTTPS_KEY = "HTTPS connection check (Android network stack)"; - private static String getHumanReadableType(Type type) { + private static String getHumanReadableType(@Type int type) { switch (type) { - case CHROME_HTTP: + case Type.CHROME_HTTP: return CHROME_HTTP_KEY; - case CHROME_HTTPS: + case Type.CHROME_HTTPS: return CHROME_HTTPS_KEY; - case SYSTEM_HTTP: + case Type.SYSTEM_HTTP: return SYSTEM_HTTP_KEY; - case SYSTEM_HTTPS: + case Type.SYSTEM_HTTPS: return SYSTEM_HTTPS_KEY; default: throw new IllegalArgumentException("Unknown connection type: " + type); } } - static String getHumanReadableResult(int result) { + static String getHumanReadableResult(@ConnectivityCheckResult int result) { switch (result) { case ConnectivityCheckResult.UNKNOWN: return "UNKNOWN"; @@ -106,7 +108,7 @@ } } - static String getHumanReadableConnectionType(int connectionType) { + static String getHumanReadableConnectionType(@ConnectionType int connectionType) { switch (connectionType) { case ConnectionType.CONNECTION_UNKNOWN: return "Unknown"; @@ -143,12 +145,12 @@ * FeedbackData contains the set of information that is to be included in a feedback report. */ static final class FeedbackData { - private final Map<Type, Integer> mConnections; + private final Map<Integer, Integer> mConnections; private final int mTimeoutMs; private final long mElapsedTimeMs; private final int mConnectionType; - FeedbackData(Map<Type, Integer> connections, int timeoutMs, long elapsedTimeMs, + FeedbackData(Map<Integer, Integer> connections, int timeoutMs, long elapsedTimeMs, int connectionType) { mConnections = connections; mTimeoutMs = timeoutMs; @@ -161,7 +163,7 @@ * types. */ @VisibleForTesting - Map<Type, Integer> getConnections() { + Map<Integer, Integer> getConnections() { return Collections.unmodifiableMap(mConnections); } @@ -186,7 +188,7 @@ */ Map<String, String> toMap() { Map<String, String> map = new HashMap<>(); - for (Map.Entry<Type, Integer> entry : mConnections.entrySet()) { + for (Map.Entry<Integer, Integer> entry : mConnections.entrySet()) { map.put(getHumanReadableType(entry.getKey()), getHumanReadableResult(entry.getValue())); } @@ -199,12 +201,20 @@ /** * The type of network stack and connectivity check this result is about. */ - public enum Type { CHROME_HTTP, CHROME_HTTPS, SYSTEM_HTTP, SYSTEM_HTTPS } + @IntDef({Type.CHROME_HTTP, Type.CHROME_HTTPS, Type.SYSTEM_HTTP, Type.SYSTEM_HTTPS}) + @Retention(RetentionPolicy.SOURCE) + public @interface Type { + int CHROME_HTTP = 0; + int CHROME_HTTPS = 1; + int SYSTEM_HTTP = 2; + int SYSTEM_HTTPS = 3; + int NUM_ENTRIES = 4; + } private class SingleTypeTask implements ConnectivityChecker.ConnectivityCheckerCallback { - private final Type mType; + private final @Type int mType; - public SingleTypeTask(Type type) { + public SingleTypeTask(@Type int type) { mType = type; } @@ -216,18 +226,18 @@ public void start(Profile profile, int timeoutMs) { Log.v(TAG, "Starting task for " + mType); switch (mType) { - case CHROME_HTTP: + case Type.CHROME_HTTP: ConnectivityChecker.checkConnectivityChromeNetworkStack( profile, false, timeoutMs, this); break; - case CHROME_HTTPS: + case Type.CHROME_HTTPS: ConnectivityChecker.checkConnectivityChromeNetworkStack( profile, true, timeoutMs, this); break; - case SYSTEM_HTTP: + case Type.SYSTEM_HTTP: ConnectivityChecker.checkConnectivitySystemNetworkStack(false, timeoutMs, this); break; - case SYSTEM_HTTPS: + case Type.SYSTEM_HTTPS: ConnectivityChecker.checkConnectivitySystemNetworkStack(true, timeoutMs, this); break; default: @@ -255,7 +265,7 @@ } } - private final Map<Type, Integer> mResult = new EnumMap<Type, Integer>(Type.class); + private final Map<Integer, Integer> mResult = new HashMap<>(); private final int mTimeoutMs; private final ConnectivityResult mCallback; private final long mStartCheckTimeMs; @@ -270,7 +280,8 @@ @VisibleForTesting void init(Profile profile, int timeoutMs) { - for (Type t : Type.values()) { + assert Type.CHROME_HTTP == 0; + for (@Type int t = Type.CHROME_HTTP; t < Type.NUM_ENTRIES; t++) { SingleTypeTask task = new SingleTypeTask(t); task.start(profile, timeoutMs); } @@ -281,7 +292,7 @@ */ public boolean isDone() { ThreadUtils.assertOnUiThread(); - return mResult.size() == Type.values().length; + return mResult.size() == Type.NUM_ENTRIES; } /** @@ -292,9 +303,10 @@ */ public FeedbackData get() { ThreadUtils.assertOnUiThread(); - Map<Type, Integer> result = new EnumMap<Type, Integer>(Type.class); + Map<Integer, Integer> result = new HashMap<>(); + assert Type.CHROME_HTTP == 0; // Ensure the map is filled with a result for all {@link Type}s. - for (Type type : Type.values()) { + for (@Type int type = Type.CHROME_HTTP; type < Type.NUM_ENTRIES; type++) { if (mResult.containsKey(type)) { result.put(type, mResult.get(type)); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java index fabbc97..77015793 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java
@@ -20,6 +20,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; +import org.chromium.base.StrictModeContext; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.IntentHandler; @@ -183,8 +184,13 @@ // This indicates that we don't want to kill Chrome when changing component enabled state. int flags = PackageManager.DONT_KILL_APP; - if (packageManager.getComponentEnabledSetting(componentName) != newState) - packageManager.setComponentEnabledSetting(componentName, newState, flags); + if (packageManager.getComponentEnabledSetting(componentName) != newState) { + // setComponentEnabledSetting ends up both reading and writing to disk, which ends up + // causing StrictMode violations. So, explicitly allow them briefly. + try (StrictModeContext unused = StrictModeContext.allowDiskReads().allowDiskWrites()) { + packageManager.setComponentEnabledSetting(componentName, newState, flags); + } + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferenceUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferenceUtils.java index 11a58db..966b09b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferenceUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferenceUtils.java
@@ -18,6 +18,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver.OnScrollChangedListener; +import android.widget.ImageView; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; @@ -95,8 +96,25 @@ } if (menuView == null) return false; View overflowButton = menuView.getChildAt(menuView.getChildCount() - 1); - if (overflowButton == null) return false; + if (!isOverflowMenuButton(overflowButton, menuView)) return false; overflowButton.setVisibility(visibility); return true; } + + /** + * There is no regular way to access the overflow button of an {@link ActionMenuView}. + * Checking whether a given view is an {@link ImageView} with the correct icon is an + * approximation to this issue as the exact icon that the parent menu will set is always known. + * + * @param button A view in the |parentMenu| that might be the overflow menu. + * @param parentMenu The menu that created the overflow button. + * @return True, if the given button can belong to the overflow menu. False otherwise. + */ + private static boolean isOverflowMenuButton(View button, ActionMenuView parentMenu) { + if (button == null) return false; + if (!(button instanceof ImageView)) + return false; // Normal items are usually TextView or LinearLayouts. + ImageView imageButton = (ImageView) button; + return imageButton.getDrawable() == parentMenu.getOverflowIcon(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchUtils.java index 3e935451..0d2a7f6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchUtils.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.preferences; +import android.app.Activity; import android.support.annotation.NonNull; import android.support.v7.widget.SearchView; import android.view.MenuItem; @@ -19,7 +20,7 @@ public class SearchUtils { /** * This interface allows to react to changed search queries when initialized with - * {@link SearchUtils#initializeSearchView(MenuItem, String, QueryChangeListener)}. + * {@link SearchUtils#initializeSearchView(MenuItem, String, Activity, QueryChangeListener)}. */ public interface QueryChangeListener { /** @@ -35,11 +36,13 @@ * search icon, box and close icon. * @param searchItem The existing item that can trigger the search action view. * @param initialQuery The query that the search field should be opened with. + * @param activity Optional. If set, overflow icons in the activity's action bar will be hidden. * @param changeListener The listener to be notified when the user changes the query. */ public static void initializeSearchView(@NonNull MenuItem searchItem, - @Nullable String initialQuery, @NonNull QueryChangeListener changeListener) { - SearchView searchView = getSearchView(searchItem); + @Nullable String initialQuery, @Nullable Activity activity, + @NonNull QueryChangeListener changeListener) { + SearchView searchView = (SearchView) searchItem.getActionView(); searchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN); // Restore the search view if a query was recovered. @@ -47,11 +50,12 @@ searchItem.expandActionView(); searchView.setIconified(false); searchView.setQuery(initialQuery, false); + updateActionBarButtons(searchItem, initialQuery, activity); } // Clicking the menu item hides the clear button and triggers search for an empty query. searchItem.setOnMenuItemClickListener((MenuItem m) -> { - updateSearchClearButtonVisibility(searchItem, ""); + updateActionBarButtons(searchItem, "", activity); changeListener.onQueryTextChange(""); return false; // Continue with the default action. }); @@ -60,13 +64,20 @@ searchView.findViewById(org.chromium.chrome.R.id.search_close_btn) .setOnClickListener((View v) -> { searchView.setQuery("", false); - updateSearchClearButtonVisibility(searchItem, ""); + updateActionBarButtons(searchItem, "", activity); changeListener.onQueryTextChange(""); }); - // Ensure that a changed search view triggers the search - independent from use code path. + // Ensure the clear button doesn't reappear with layout changes (e.g. keyboard visibility). + findSearchClearButton(searchView) + .addOnLayoutChangeListener( + (view, i, i1, i2, i3, i4, i5, i6, i7) + -> updateActionBarButtons( + searchItem, searchView.getQuery().toString(), activity)); + + // Ensure that a changed search view triggers the search - independent from used code path. searchView.setOnSearchClickListener(view -> { - updateSearchClearButtonVisibility(searchItem, ""); + updateActionBarButtons(searchItem, "", activity); changeListener.onQueryTextChange(""); }); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @@ -78,7 +89,7 @@ @Override public boolean onQueryTextChange(String query) { // TODO(fhorschig) Exit early if a tracked query indicates no changes. - updateSearchClearButtonVisibility(searchItem, query); + updateActionBarButtons(searchItem, query, activity); changeListener.onQueryTextChange(query); return true; // Consume event. } @@ -91,30 +102,38 @@ * @param selectedItem The user-selected menu item. * @param searchItem The menu item known to contain the search view. * @param query The current search query. + * @param activity Optional. If set, overflow icons in the activity's action bar will be hidden. * @return Returns true if the item is a search item and could be handled. False otherwise. */ - public static boolean handleSearchNavigation( - @NonNull MenuItem selectedItem, @NonNull MenuItem searchItem, @Nullable String query) { + public static boolean handleSearchNavigation(@NonNull MenuItem selectedItem, + @NonNull MenuItem searchItem, @Nullable String query, @Nullable Activity activity) { if (selectedItem.getItemId() != android.R.id.home || query == null) return false; - SearchView searchView = (SearchView) searchItem.getActionView(); - searchView.setQuery(null, false); - searchView.setIconified(true); - searchItem.collapseActionView(); + clearSearch(searchItem, activity); return true; } /** - * Shorthand to easily access a search item's action view. - * @param searchItem The menu item containing search item. - * @return The search view associated with the menu item. + * Reset a search item by clearing and collapsing it. + * @param searchItem The menu item that contains the search item. + * @param activity Optional. If set, overflow icons in the activity's action bar will be hidden. */ - public static SearchView getSearchView(MenuItem searchItem) { - return (SearchView) searchItem.getActionView(); + public static void clearSearch(@NonNull MenuItem searchItem, @Nullable Activity activity) { + SearchView searchView = (SearchView) searchItem.getActionView(); + searchView.setQuery(null, false); + searchView.setIconified(true); + searchItem.collapseActionView(); + updateActionBarButtons(searchItem, null, activity); } - private static void updateSearchClearButtonVisibility(MenuItem searchItem, String query) { - ImageView clearButton = findSearchClearButton(getSearchView(searchItem)); + private static void updateActionBarButtons( + MenuItem searchItem, String query, @Nullable Activity activity) { + SearchView searchView = (SearchView) searchItem.getActionView(); + ImageView clearButton = findSearchClearButton(searchView); clearButton.setVisibility(query == null || query.equals("") ? View.GONE : View.VISIBLE); + if (activity != null) { + PreferenceUtils.setOverflowMenuVisibility( + activity, query != null ? View.GONE : View.VISIBLE); + } } private static ImageView findSearchClearButton(SearchView searchView) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java index b2cd0e35..7632441 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
@@ -21,7 +21,6 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.view.View; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.VisibleForTesting; @@ -32,7 +31,6 @@ import org.chromium.chrome.browser.preferences.ChromeBasePreference; import org.chromium.chrome.browser.preferences.ChromeSwitchPreference; import org.chromium.chrome.browser.preferences.PrefServiceBridge; -import org.chromium.chrome.browser.preferences.PreferenceUtils; import org.chromium.chrome.browser.preferences.Preferences; import org.chromium.chrome.browser.preferences.PreferencesLauncher; import org.chromium.chrome.browser.preferences.SearchUtils; @@ -145,7 +143,7 @@ mSearchItem.setVisible(providesPasswordSearch()); if (providesPasswordSearch()) { mHelpItem = menu.findItem(R.id.menu_id_general_help); - SearchUtils.initializeSearchView(mSearchItem, mSearchQuery, (query) -> { + SearchUtils.initializeSearchView(mSearchItem, mSearchQuery, getActivity(), (query) -> { maybeRecordTriggeredPasswordSearch(true); filterPasswords(query); }); @@ -178,7 +176,7 @@ mExportFlow.startExporting(); return true; } - if (SearchUtils.handleSearchNavigation(item, mSearchItem, mSearchQuery)) { + if (SearchUtils.handleSearchNavigation(item, mSearchItem, mSearchQuery, getActivity())) { filterPasswords(null); return true; } @@ -187,13 +185,8 @@ private void filterPasswords(String query) { mSearchQuery = query; - if (mSearchQuery == null) { - mHelpItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - PreferenceUtils.setOverflowMenuVisibility(getActivity(), View.VISIBLE); - } else { - mHelpItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - PreferenceUtils.setOverflowMenuVisibility(getActivity(), View.GONE); - } + mHelpItem.setShowAsAction(mSearchQuery == null ? MenuItem.SHOW_AS_ACTION_IF_ROOM + : MenuItem.SHOW_AS_ACTION_NEVER); rebuildPasswordLists(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java index 565f122..a8ba140 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
@@ -328,7 +328,7 @@ inflater.inflate(R.menu.website_preferences_menu, menu); mSearchItem = menu.findItem(R.id.search); - SearchUtils.initializeSearchView(mSearchItem, mSearch, (query) -> { + SearchUtils.initializeSearchView(mSearchItem, mSearch, getActivity(), (query) -> { mSearch = query; getInfoForOrigins(); }); @@ -365,7 +365,7 @@ getActivity(), getString(helpContextResId), Profile.getLastUsedProfile(), null); return true; } - if (handleSearchNavigation(item, mSearchItem, mSearch)) { + if (handleSearchNavigation(item, mSearchItem, mSearch, getActivity())) { mSearch = null; getInfoForOrigins(); return true; @@ -382,13 +382,6 @@ return false; } - if (mSearch != null) { - // Clear out any lingering searches, so that the full list is shown - // when coming back to this page. - mSearch = null; - SearchUtils.getSearchView(mSearchItem).setQuery("", false); - } - if (preference instanceof WebsitePreference) { WebsitePreference website = (WebsitePreference) preference; website.setFragment(SingleWebsitePreferences.class.getName()); @@ -524,6 +517,10 @@ public void onResume() { super.onResume(); + if (mSearch == null && mSearchItem != null) { + SearchUtils.clearSearch(mSearchItem, getActivity()); + } + getInfoForOrigins(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/ConnectivityTaskTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/ConnectivityTaskTest.java index d71f63c5..b6a686c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/ConnectivityTaskTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/ConnectivityTaskTest.java
@@ -75,16 +75,16 @@ } private static void verifyConnections(FeedbackData feedback, int expectedHttpsValue) { - Map<Type, Integer> results = feedback.getConnections(); + Map<Integer, Integer> results = feedback.getConnections(); Assert.assertEquals("Should have 4 results.", 4, results.size()); - for (Map.Entry<Type, Integer> result : results.entrySet()) { + for (Map.Entry<Integer, Integer> result : results.entrySet()) { switch (result.getKey()) { - case CHROME_HTTP: - case SYSTEM_HTTP: + case Type.CHROME_HTTP: + case Type.SYSTEM_HTTP: assertResult(ConnectivityCheckResult.CONNECTED, result); break; - case CHROME_HTTPS: - case SYSTEM_HTTPS: + case Type.CHROME_HTTPS: + case Type.SYSTEM_HTTPS: assertResult(expectedHttpsValue, result); break; default: @@ -95,7 +95,7 @@ "The elapsed time should be non-negative.", feedback.getElapsedTimeMs() >= 0); } - private static void assertResult(int expectedValue, Map.Entry<Type, Integer> actualEntry) { + private static void assertResult(int expectedValue, Map.Entry<Integer, Integer> actualEntry) { Assert.assertEquals("Wrong result for " + actualEntry.getKey(), ConnectivityTask.getHumanReadableResult(expectedValue), ConnectivityTask.getHumanReadableResult(actualEntry.getValue())); @@ -202,7 +202,7 @@ @SmallTest @Feature({"Feedback"}) public void testFeedbackDataConversion() { - Map<Type, Integer> connectionMap = new HashMap<>(); + Map<Integer, Integer> connectionMap = new HashMap<>(); connectionMap.put(Type.CHROME_HTTP, ConnectivityCheckResult.NOT_CONNECTED); connectionMap.put(Type.CHROME_HTTPS, ConnectivityCheckResult.CONNECTED); connectionMap.put(Type.SYSTEM_HTTP, ConnectivityCheckResult.UNKNOWN);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java index c538317..46be3f84 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
@@ -1787,8 +1787,8 @@ Espresso.onView(isRoot()).check( (root, e) -> waitForView((ViewGroup) root, - withContentDescription( - R.string.abc_action_menu_overflow_description), + withParent(withContentDescription( + R.string.abc_action_menu_overflow_description)), VIEW_INVISIBLE | VIEW_GONE | VIEW_NULL)); Espresso.onView(withContentDescription(R.string.abc_action_bar_up_description))
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index e7efb90..ee3fbdb4 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2677,6 +2677,12 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT" desc="Label on a selection menu to choose the sorting method to display the All Sites list by."> Sort by </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_MOST_VISITED" desc="A selection menu option to sort the All Sites list by the most visited sites."> + Most visited + </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_STORAGE" desc="A selection menu option to sort the All Sites list by the sites that use the most disk space."> + Data stored + </message> <message name="IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_NAME" desc="A selection menu option to sort the All Sites list by the name of the site, which is derived from its URL."> Name </message>
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index 740029ec..ba4592ab 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -1030,7 +1030,8 @@ ->GetCryptohomeClient() ->TpmAttestationDeleteKeys( chromeos::attestation::KEY_USER, - cryptohome::Identification(user->GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId( + user->GetAccountId()), chromeos::attestation::kContentProtectionKeyPrefix, base::BindOnce( &ChromeBrowsingDataRemoverDelegate::OnClearPlatformKeys,
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index 8ef6c21..d8ee02e 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -232,7 +232,7 @@ public: void TpmAttestationDeleteKeys( chromeos::attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_prefix, chromeos::DBusMethodCallback<bool> callback) override { ++delete_keys_call_count_;
diff --git a/chrome/browser/browsing_data/counters/site_settings_counter.cc b/chrome/browser/browsing_data/counters/site_settings_counter.cc index 86d8174..af15057 100644 --- a/chrome/browser/browsing_data/counters/site_settings_counter.cc +++ b/chrome/browser/browsing_data/counters/site_settings_counter.cc
@@ -53,7 +53,8 @@ // TODO(crbug.com/762560): Check the conceptual SettingSource instead of // ContentSettingPatternSource.source if (content_setting.source == "preference" || - content_setting.source == "notification_android") { + content_setting.source == "notification_android" || + content_setting.source == "ephemeral") { base::Time last_modified = map_->GetSettingLastModifiedDate( content_setting.primary_pattern, content_setting.secondary_pattern, type);
diff --git a/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.cc b/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.cc index 7ecc940..65dc26a 100644 --- a/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.cc +++ b/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.cc
@@ -37,14 +37,16 @@ void MockBrowsingDataLocalStorageHelper::AddLocalStorageSamples() { const GURL kOrigin1("http://host1:1/"); const GURL kOrigin2("http://host2:2/"); - response_.push_back( - BrowsingDataLocalStorageHelper::LocalStorageInfo( - kOrigin1, 1, base::Time())); - origins_[kOrigin1] = true; - response_.push_back( - BrowsingDataLocalStorageHelper::LocalStorageInfo( - kOrigin2, 2, base::Time())); - origins_[kOrigin2] = true; + AddLocalStorageForOrigin(kOrigin1, 1); + AddLocalStorageForOrigin(kOrigin2, 2); +} + +void MockBrowsingDataLocalStorageHelper::AddLocalStorageForOrigin( + const GURL& origin, + size_t size) { + response_.push_back(BrowsingDataLocalStorageHelper::LocalStorageInfo( + origin, size, base::Time())); + origins_[origin] = true; } void MockBrowsingDataLocalStorageHelper::Notify() {
diff --git a/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h b/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h index 3143b3c3..cb82914 100644 --- a/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h +++ b/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h
@@ -27,6 +27,9 @@ // Adds some LocalStorageInfo samples. void AddLocalStorageSamples(); + // Add a LocalStorageInfo entry for a single origin. + void AddLocalStorageForOrigin(const GURL& origin, size_t size); + // Notifies the callback. void Notify();
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 63540e2..5ec6e10 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1546,6 +1546,8 @@ "power/power_data_collector.h", "power/power_metrics_reporter.cc", "power/power_metrics_reporter.h", + "power/process_data_collector.cc", + "power/process_data_collector.h", "power/renderer_freezer.cc", "power/renderer_freezer.h", "preferences.cc", @@ -2177,6 +2179,7 @@ "power/ml/user_activity_ukm_logger_unittest.cc", "power/power_data_collector_unittest.cc", "power/power_metrics_reporter_unittest.cc", + "power/process_data_collector_unittest.cc", "power/renderer_freezer_unittest.cc", "preferences_unittest.cc", "printing/cups_printers_manager_unittest.cc",
diff --git a/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc index d25c306..2bf7673 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc
@@ -63,9 +63,11 @@ void SetUpCommandLine(base::CommandLine* command_line) override { const AccountId account_id = AccountId::FromUserEmail(GetTestAppUserId()); - const cryptohome::Identification cryptohome_id(account_id); + const cryptohome::AccountIdentifier cryptohome_id = + cryptohome::CreateAccountIdentifierFromAccountId(account_id); - command_line->AppendSwitchASCII(switches::kLoginUser, cryptohome_id.id()); + command_line->AppendSwitchASCII(switches::kLoginUser, + cryptohome_id.account_id()); command_line->AppendSwitchASCII( switches::kLoginProfile, CryptohomeClient::GetStubSanitizedUsername(cryptohome_id));
diff --git a/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc b/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc index eae992a..897478a5 100644 --- a/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc +++ b/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc
@@ -162,8 +162,9 @@ chromeos::SessionManagerClient* session_manager_client = chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); - session_manager_client->EmitArcBooted(cryptohome::Identification(account_id_), - base::BindOnce(&OnEmitArcBooted)); + session_manager_client->EmitArcBooted( + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), + base::BindOnce(&OnEmitArcBooted)); ArcSessionManager* arc_session_manager = ArcSessionManager::Get(); DCHECK(arc_session_manager);
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc index a9258bb..302ae38 100644 --- a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc +++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
@@ -190,7 +190,7 @@ weak_factory_.GetWeakPtr()); cryptohome_client_->TpmAttestationDoesKeyExist( KEY_DEVICE, - cryptohome::Identification(), // Not used. + cryptohome::AccountIdentifier(), // Not used. kEnterpriseMachineKey, base::BindOnce(DBusBoolRedirectCallback, on_does_exist, on_does_not_exist, base::Bind(&AttestationPolicyObserver::Reschedule, @@ -224,7 +224,7 @@ void AttestationPolicyObserver::GetExistingCertificate() { cryptohome_client_->TpmAttestationGetCertificate( KEY_DEVICE, - cryptohome::Identification(), // Not used. + cryptohome::AccountIdentifier(), // Not used. kEnterpriseMachineKey, base::Bind(DBusStringCallback, base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry, @@ -296,7 +296,7 @@ base::Callback<void(const std::string&)> callback) { cryptohome_client_->TpmAttestationGetKeyPayload( KEY_DEVICE, - cryptohome::Identification(), // Not used. + cryptohome::AccountIdentifier(), // Not used. kEnterpriseMachineKey, base::Bind(DBusStringCallback, callback, base::Bind(&AttestationPolicyObserver::Reschedule, @@ -324,7 +324,7 @@ } cryptohome_client_->TpmAttestationSetKeyPayload( KEY_DEVICE, - cryptohome::Identification(), // Not used. + cryptohome::AccountIdentifier(), // Not used. kEnterpriseMachineKey, new_payload, base::BindRepeating(DBusBoolRedirectCallback, base::RepeatingClosure(), base::RepeatingClosure(), base::RepeatingClosure(),
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index e66c1526..3be9d47 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -83,6 +83,7 @@ #include "chrome/browser/chromeos/power/ml/user_activity_controller.h" #include "chrome/browser/chromeos/power/power_data_collector.h" #include "chrome/browser/chromeos/power/power_metrics_reporter.h" +#include "chrome/browser/chromeos/power/process_data_collector.h" #include "chrome/browser/chromeos/power/renderer_freezer.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/resource_reporter/resource_reporter.h" @@ -383,6 +384,7 @@ // Initialize PowerDataCollector after DBusThreadManager is initialized. PowerDataCollector::Initialize(); + ProcessDataCollector::Initialize(); LoginState::Initialize(); TPMTokenLoader::Initialize(); @@ -423,6 +425,7 @@ finch_features_service_.reset(); vm_applications_service_.reset(); drive_file_stream_service_.reset(); + ProcessDataCollector::Shutdown(); PowerDataCollector::Shutdown(); if (features::IsAshInBrowserProcess()) PowerPolicyController::Shutdown();
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc index bc15972a..9d09a111 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -23,13 +23,11 @@ #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_pref_names.h" #include "chrome/browser/chromeos/drive/file_system_util.h" -#include "chrome/browser/chromeos/file_manager/app_id.h" +#include "chrome/browser/chromeos/file_manager/file_manager_test_util.h" #include "chrome/browser/chromeos/file_manager/mount_test_util.h" #include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/chromeos/file_manager/volume_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/extensions/component_loader.h" -#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_features.h" @@ -44,11 +42,11 @@ #include "components/drive/chromeos/file_system_interface.h" #include "components/drive/drive_pref_names.h" #include "components/drive/service/fake_drive_service.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" #include "extensions/browser/api/test/test_api.h" -#include "extensions/browser/extension_system.h" #include "extensions/browser/notification_types.h" #include "google_apis/drive/drive_api_parser.h" #include "google_apis/drive/test_util.h" @@ -1019,22 +1017,7 @@ // The test resources are setup: enable and add default ChromeOS component // extensions now and not before: crbug.com/831074, crbug.com/804413 - extensions::ComponentLoader::EnableBackgroundExtensionsForTesting(); - extensions::ExtensionService* service = - extensions::ExtensionSystem::Get(profile())->extension_service(); - service->component_loader()->AddDefaultComponentExtensions(false); - - // The File Manager component extension should have been added for loading - // into the user profile, but not into the sign-in profile. - CHECK(extensions::ExtensionSystem::Get(profile()) - ->extension_service() - ->component_loader() - ->Exists(kFileManagerAppId)); - CHECK(!extensions::ExtensionSystem::Get( - chromeos::ProfileHelper::GetSigninProfile()) - ->extension_service() - ->component_loader() - ->Exists(kFileManagerAppId)); + test::AddDefaultComponentExtensionsOnMainThread(profile()); } bool FileManagerBrowserTestBase::GetEnableDriveFs() const {
diff --git a/chrome/browser/chromeos/file_manager/file_manager_test_util.cc b/chrome/browser/chromeos/file_manager/file_manager_test_util.cc new file mode 100644 index 0000000..494888b6 --- /dev/null +++ b/chrome/browser/chromeos/file_manager/file_manager_test_util.cc
@@ -0,0 +1,38 @@ +// Copyright 2018 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 "chrome/browser/chromeos/file_manager/file_manager_test_util.h" + +#include "chrome/browser/chromeos/file_manager/app_id.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/extensions/component_loader.h" +#include "chrome/browser/extensions/extension_service.h" +#include "extensions/browser/extension_system.h" + +namespace file_manager { +namespace test { + +void AddDefaultComponentExtensionsOnMainThread(Profile* profile) { + CHECK(profile); + + extensions::ComponentLoader::EnableBackgroundExtensionsForTesting(); + extensions::ExtensionService* service = + extensions::ExtensionSystem::Get(profile)->extension_service(); + service->component_loader()->AddDefaultComponentExtensions(false); + + // The File Manager component extension should have been added for loading + // into the user profile, but not into the sign-in profile. + CHECK(extensions::ExtensionSystem::Get(profile) + ->extension_service() + ->component_loader() + ->Exists(kFileManagerAppId)); + CHECK(!extensions::ExtensionSystem::Get( + chromeos::ProfileHelper::GetSigninProfile()) + ->extension_service() + ->component_loader() + ->Exists(kFileManagerAppId)); +} + +} // namespace test +} // namespace file_manager
diff --git a/chrome/browser/chromeos/file_manager/file_manager_test_util.h b/chrome/browser/chromeos/file_manager/file_manager_test_util.h new file mode 100644 index 0000000..934bf26 --- /dev/null +++ b/chrome/browser/chromeos/file_manager/file_manager_test_util.h
@@ -0,0 +1,20 @@ +// Copyright 2018 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 CHROME_BROWSER_CHROMEOS_FILE_MANAGER_FILE_MANAGER_TEST_UTIL_H_ +#define CHROME_BROWSER_CHROMEOS_FILE_MANAGER_FILE_MANAGER_TEST_UTIL_H_ + +class Profile; + +namespace file_manager { +namespace test { + +// Load the default set of component extensions used on ChromeOS. This should be +// done in an override of InProcessBrowserTest::SetUpOnMainThread(). +void AddDefaultComponentExtensionsOnMainThread(Profile* profile); + +} // namespace test +} // namespace file_manager + +#endif // CHROME_BROWSER_CHROMEOS_FILE_MANAGER_FILE_MANAGER_TEST_UTIL_H_
diff --git a/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc b/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc new file mode 100644 index 0000000..740dde2 --- /dev/null +++ b/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc
@@ -0,0 +1,132 @@ +// Copyright 2018 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 "chrome/browser/chromeos/file_manager/file_tasks.h" + +#include "chrome/browser/chromeos/file_manager/app_id.h" +#include "chrome/browser/chromeos/file_manager/file_manager_test_util.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "extensions/browser/entry_info.h" +#include "net/base/mime_util.h" + +namespace file_manager { +namespace file_tasks { + +class FileTasksBrowserTest : public InProcessBrowserTest { + public: + void SetUpOnMainThread() override { + test::AddDefaultComponentExtensionsOnMainThread(browser()->profile()); + } +}; + +// Tests the default handlers for various file types in ChromeOS. This test +// exists to ensure the default app that launches when you open a file in the +// ChromeOS file manager does not change unexpectedly. Multiple default apps are +// allowed to register a handler for the same file type. Without that, it is not +// possible for an app to open that type even when given explicit direction via +// the chrome.fileManagerPrivate.executeTask API. The current conflict +// resolution mechanism is "sort by extension ID", which has the desired result. +// If desires change, we'll need to update ChooseAndSetDefaultTask() with some +// additional logic. +IN_PROC_BROWSER_TEST_F(FileTasksBrowserTest, DefaultHandlerChangeDetector) { + constexpr struct { + const char* file_extension; + const char* app_id; + bool has_mime = true; + } kExpectations[] = { + // Images. + {"bmp", kGalleryAppId}, + {"gif", kGalleryAppId}, + {"ico", kGalleryAppId}, + {"jpg", kGalleryAppId}, + {"jpeg", kGalleryAppId}, + {"png", kGalleryAppId}, + {"webp", kGalleryAppId}, + + // Raw. + {"arw", kGalleryAppId, false}, + {"cr2", kGalleryAppId, false}, + {"dng", kGalleryAppId, false}, + {"nef", kGalleryAppId, false}, + {"nrw", kGalleryAppId, false}, + {"orf", kGalleryAppId, false}, + {"raf", kGalleryAppId, false}, + {"rw2", kGalleryAppId, false}, + + // Video. + {"3gp", kVideoPlayerAppId, false}, + {"avi", kVideoPlayerAppId, false}, + {"m4v", kVideoPlayerAppId}, + {"mkv", kVideoPlayerAppId, false}, + {"mov", kVideoPlayerAppId, false}, + {"mp4", kVideoPlayerAppId}, + {"mpeg", kVideoPlayerAppId}, + {"mpeg4", kVideoPlayerAppId, false}, + {"mpg", kVideoPlayerAppId}, + {"mpg4", kVideoPlayerAppId, false}, + {"ogm", kVideoPlayerAppId}, + {"ogv", kVideoPlayerAppId}, + {"ogx", kVideoPlayerAppId, false}, + {"webm", kVideoPlayerAppId}, + + // Audio. + {"amr", kAudioPlayerAppId, false}, + {"flac", kAudioPlayerAppId}, + {"m4a", kAudioPlayerAppId}, + {"mp3", kAudioPlayerAppId}, + {"oga", kAudioPlayerAppId}, + {"ogg", kAudioPlayerAppId}, + {"wav", kAudioPlayerAppId}, + }; + + base::RunLoop run_loop; + int remaining = base::size(kExpectations); + auto callback = base::BindRepeating( + [](base::RepeatingClosure quit, int* remaining, + const char* file_extension, const char* expected_app_id, + std::unique_ptr<std::vector<FullTaskDescriptor>> result) { + ASSERT_TRUE(result) << file_extension; + + // There can be multiple handlers. The one at index 0 will be picked by + // ChooseAndSetDefaultTask() since prefs should be empty in the test. + ASSERT_LE(1u, result->size()) << file_extension; + + EXPECT_EQ(expected_app_id, result->at(0).task_descriptor().app_id) + << " for extension: " << file_extension; + + // Verify expected behavior of ChooseAndSetDefaultTask(). + EXPECT_TRUE(result->at(0).is_default()) << file_extension; + for (size_t i = 1; i < result->size(); ++i) + EXPECT_FALSE(result->at(i).is_default()) << file_extension; + + if (--*remaining == 0) + quit.Run(); + }, + run_loop.QuitClosure(), &remaining); + + const drive::DriveAppRegistry* const kDriveAppRegistry = nullptr; + const base::FilePath prefix = base::FilePath().AppendASCII("file"); + + for (const auto& test : kExpectations) { + base::FilePath path = prefix.AddExtension(test.file_extension); + + // Fetching a mime type is part of the default app determination, but it + // doesn't need to succeed. + std::string mime_type; + EXPECT_EQ(test.has_mime, net::GetMimeTypeFromFile(path, &mime_type)) + << test.file_extension; + + std::vector<extensions::EntryInfo> entries = {{path, mime_type, false}}; + std::vector<GURL> file_urls{GURL()}; + FindAllTypesOfTasks( + browser()->profile(), kDriveAppRegistry, entries, file_urls, + base::BindRepeating(callback, test.file_extension, test.app_id)); + } + run_loop.Run(); + EXPECT_EQ(0, remaining); +} + +} // namespace file_tasks +} // namespace file_manager
diff --git a/chrome/browser/chromeos/file_system_provider/scoped_file_opener.cc b/chrome/browser/chromeos/file_system_provider/scoped_file_opener.cc index a60159f5..fbf9eb0 100644 --- a/chrome/browser/chromeos/file_system_provider/scoped_file_opener.cc +++ b/chrome/browser/chromeos/file_system_provider/scoped_file_opener.cc
@@ -17,18 +17,16 @@ class ScopedFileOpener::Runner : public base::RefCounted<ScopedFileOpener::Runner> { public: - Runner(ProvidedFileSystemInterface* file_system, - const base::FilePath& file_path, - OpenFileMode mode, - OpenFileCallback callback) - : file_system_(file_system->GetWeakPtr()), - open_callback_(std::move(callback)), - aborting_requested_(false), - open_completed_(false), - file_handle_(0) { - abort_callback_ = file_system_->OpenFile( + static scoped_refptr<Runner> Create(ProvidedFileSystemInterface* file_system, + const base::FilePath& file_path, + OpenFileMode mode, + OpenFileCallback callback) { + auto runner = + base::WrapRefCounted(new Runner(file_system, std::move(callback))); + runner->abort_callback_ = file_system->OpenFile( file_path, mode, - base::Bind(&ScopedFileOpener::Runner::OnOpenFileCompleted, this)); + base::Bind(&ScopedFileOpener::Runner::OnOpenFileCompleted, runner)); + return runner; } // Aborts pending open operation, or closes a file if it's already opened. @@ -59,6 +57,13 @@ private: friend class base::RefCounted<ScopedFileOpener::Runner>; + Runner(ProvidedFileSystemInterface* file_system, OpenFileCallback callback) + : file_system_(file_system->GetWeakPtr()), + open_callback_(std::move(callback)), + aborting_requested_(false), + open_completed_(false), + file_handle_(0) {} + ~Runner() {} // Called when opening is completed with either a success or an error. @@ -127,7 +132,8 @@ const base::FilePath& file_path, OpenFileMode mode, OpenFileCallback callback) - : runner_(new Runner(file_system, file_path, mode, std::move(callback))) {} + : runner_( + Runner::Create(file_system, file_path, mode, std::move(callback))) {} ScopedFileOpener::~ScopedFileOpener() { runner_->AbortOrClose();
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc index 97b8de7..9d68638 100644 --- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
@@ -37,6 +37,7 @@ #include "chromeos/dbus/cryptohome/rpc.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_cryptohome_client.h" +#include "chromeos/dbus/util/account_identifier_operators.h" #include "chromeos/login/auth/key.h" #include "chromeos/login/auth/mock_auth_status_consumer.h" #include "chromeos/login/auth/mock_url_fetchers.h" @@ -134,7 +135,7 @@ TestCryptohomeClient() = default; ~TestCryptohomeClient() override = default; - void set_expected_id(const cryptohome::Identification& id) { + void set_expected_id(const cryptohome::AccountIdentifier& id) { expected_id_ = id; } @@ -154,7 +155,7 @@ mount_guest_should_succeed_ = should_succeed; } - void MountEx(const cryptohome::Identification& cryptohome_id, + void MountEx(const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::MountRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override { @@ -176,7 +177,7 @@ FROM_HERE, base::BindOnce(std::move(callback), reply)); } - void CheckKeyEx(const cryptohome::Identification& cryptohome_id, + void CheckKeyEx(const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::CheckKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override { @@ -192,7 +193,7 @@ const cryptohome::AuthorizationRequest& auth_request, const cryptohome::MigrateKeyRequest& migrate_request, DBusMethodCallback<cryptohome::BaseReply> callback) override { - EXPECT_EQ(expected_id_.id(), account.account_id()); + EXPECT_EQ(expected_id_.account_id(), account.account_id()); cryptohome::BaseReply reply; if (!migrate_key_should_succeed_) @@ -214,7 +215,7 @@ } private: - cryptohome::Identification expected_id_; + cryptohome::AccountIdentifier expected_id_; std::string expected_authorization_secret_; bool is_create_attempt_expected_ = false; bool migrate_key_should_succeed_ = false; @@ -370,7 +371,8 @@ cryptohome::AddKeyRequest request; cryptohome::KeyDefinitionToKey(key_definition, request.mutable_key()); fake_cryptohome_client_->AddKeyEx( - cryptohome::Identification(user_context_.GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId()), cryptohome::AuthorizationRequest(), request, base::BindOnce([](base::Optional<cryptohome::BaseReply> reply) { EXPECT_TRUE(reply.has_value()); @@ -380,7 +382,8 @@ void ExpectMountExCall(bool expect_create_attempt) { fake_cryptohome_client_->set_expected_id( - cryptohome::Identification(user_context_.GetAccountId())); + cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId())); fake_cryptohome_client_->set_expected_authorization_secret( transformed_key_.GetSecret()); fake_cryptohome_client_->set_is_create_attempt_expected( @@ -389,14 +392,16 @@ void ExpectCheckKeyExCall() { fake_cryptohome_client_->set_expected_id( - cryptohome::Identification(user_context_.GetAccountId())); + cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId())); fake_cryptohome_client_->set_expected_authorization_secret( transformed_key_.GetSecret()); } void ExpectMigrateKeyExCall(bool should_succeed) { fake_cryptohome_client_->set_expected_id( - cryptohome::Identification(user_context_.GetAccountId())); + cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId())); fake_cryptohome_client_->set_migrate_key_should_succeed(should_succeed); }
diff --git a/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc b/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc index e39dc27..4cc3a61 100644 --- a/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc +++ b/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc
@@ -145,12 +145,13 @@ command_line->AppendSwitchASCII(flag.name, flag.value); } - void StartSession(const cryptohome::Identification& cryptohome_id) override { + void StartSession( + const cryptohome::AccountIdentifier& cryptohome_id) override { FakeSessionManagerClient::StartSession(cryptohome_id); std::string user_id_hash = CryptohomeClient::GetStubSanitizedUsername(cryptohome_id); - login_args_ = {{"login-user", cryptohome_id.id()}, + login_args_ = {{"login-user", cryptohome_id.account_id()}, {"login-profile", user_id_hash}}; } @@ -162,7 +163,7 @@ bool SupportsRestartToApplyUserFlags() const override { return true; } - void SetFlagsForUser(const cryptohome::Identification& identification, + void SetFlagsForUser(const cryptohome::AccountIdentifier& identification, const std::vector<std::string>& flags) override { extra_args_.clear(); FakeSessionManagerClient::SetFlagsForUser(identification, flags);
diff --git a/chrome/browser/chromeos/login/crash_restore_browsertest.cc b/chrome/browser/chromeos/login/crash_restore_browsertest.cc index 215956298..11edad1a 100644 --- a/chrome/browser/chromeos/login/crash_restore_browsertest.cc +++ b/chrome/browser/chromeos/login/crash_restore_browsertest.cc
@@ -55,7 +55,8 @@ ~CrashRestoreSimpleTest() override {} void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitchASCII(switches::kLoginUser, cryptohome_id1_.id()); + command_line->AppendSwitchASCII(switches::kLoginUser, + cryptohome_id1_.account_id()); command_line->AppendSwitchASCII( switches::kLoginProfile, CryptohomeClient::GetStubSanitizedUsername(cryptohome_id1_)); @@ -73,12 +74,12 @@ const AccountId account_id1_ = AccountId::FromUserEmail(kUserId1); const AccountId account_id2_ = AccountId::FromUserEmail(kUserId2); const AccountId account_id3_ = AccountId::FromUserEmail(kUserId3); - const cryptohome::Identification cryptohome_id1_ = - cryptohome::Identification(account_id1_); - const cryptohome::Identification cryptohome_id2_ = - cryptohome::Identification(account_id2_); - const cryptohome::Identification cryptohome_id3_ = - cryptohome::Identification(account_id3_); + const cryptohome::AccountIdentifier cryptohome_id1_ = + cryptohome::CreateAccountIdentifierFromAccountId(account_id1_); + const cryptohome::AccountIdentifier cryptohome_id2_ = + cryptohome::CreateAccountIdentifierFromAccountId(account_id2_); + const cryptohome::AccountIdentifier cryptohome_id3_ = + cryptohome::CreateAccountIdentifierFromAccountId(account_id3_); }; IN_PROC_BROWSER_TEST_F(CrashRestoreSimpleTest, RestoreSessionForOneUser) {
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc index 681112fb..8da23936 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc
@@ -51,12 +51,13 @@ } void EasyUnlockGetKeysOperation::GetKeyData() { - const cryptohome::Identification id(user_context_.GetAccountId()); cryptohome::GetKeyDataRequest request; request.mutable_key()->mutable_data()->set_label( EasyUnlockKeyManager::GetKeyLabel(key_index_)); DBusThreadManager::Get()->GetCryptohomeClient()->GetKeyDataEx( - id, cryptohome::AuthorizationRequest(), request, + cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId()), + cryptohome::AuthorizationRequest(), request, base::BindOnce(&EasyUnlockGetKeysOperation::OnGetKeyData, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/chromeos/login/quick_unlock/pin_storage_cryptohome.cc b/chrome/browser/chromeos/login/quick_unlock/pin_storage_cryptohome.cc index 08a0728..2104b18 100644 --- a/chrome/browser/chromeos/login/quick_unlock/pin_storage_cryptohome.cc +++ b/chrome/browser/chromeos/login/quick_unlock/pin_storage_cryptohome.cc
@@ -164,7 +164,7 @@ cryptohome::GetKeyDataRequest request; request.mutable_key()->mutable_data()->set_label(kCryptohomePinLabel); chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->GetKeyDataEx( - cryptohome::Identification(account_id), + cryptohome::CreateAccountIdentifierFromAccountId(account_id), cryptohome::AuthorizationRequest(), request, base::AdaptCallbackForRepeating( base::BindOnce(&CheckCryptohomePinKey, std::move(result), @@ -264,7 +264,7 @@ cryptohome::GetKeyDataRequest request; request.mutable_key()->mutable_data()->set_label(kCryptohomePinLabel); chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->GetKeyDataEx( - cryptohome::Identification(account_id), + cryptohome::CreateAccountIdentifierFromAccountId(account_id), cryptohome::AuthorizationRequest(), request, base::AdaptCallbackForRepeating( base::BindOnce(&CheckCryptohomePinKey, std::move(result),
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index 278e2722..a9ea5d0 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -289,7 +289,7 @@ public: SecretInterceptingFakeCryptohomeClient(); - void MountEx(const cryptohome::Identification& id, + void MountEx(const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::MountRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; @@ -306,7 +306,7 @@ SecretInterceptingFakeCryptohomeClient() {} void SecretInterceptingFakeCryptohomeClient::MountEx( - const cryptohome::Identification& id, + const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::MountRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) {
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc index 123991b..02a6191 100644 --- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc +++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -294,9 +294,8 @@ return; } - const cryptohome::Identification cryptohome_id(account_id); DBusThreadManager::Get()->GetCryptohomeClient()->NeedsDircryptoMigration( - cryptohome_id, + cryptohome::CreateAccountIdentifierFromAccountId(account_id), base::BindOnce(&DircryptoMigrationChecker:: OnCryptohomeNeedsDircryptoMigrationCallback, weak_ptr_factory_.GetWeakPtr(), account_id));
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 5fbc88ae..d07620d7 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -535,7 +535,8 @@ if (!about_flags::AreSwitchesIdenticalToCurrentCommandLine( user_flags, *base::CommandLine::ForCurrentProcess(), NULL)) { DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser( - cryptohome::Identification(user_manager::GuestAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId( + user_manager::GuestAccountId()), base::CommandLine::StringVector()); } @@ -1081,7 +1082,8 @@ BootTimesRecorder* btl = BootTimesRecorder::Get(); btl->AddLoginTimeMarker("StartSession-Start", false); DBusThreadManager::Get()->GetSessionManagerClient()->StartSession( - cryptohome::Identification(user_context_.GetAccountId())); + cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId())); btl->AddLoginTimeMarker("StartSession-End", false); } @@ -1720,9 +1722,11 @@ user_manager->GetActiveUser()->GetAccountId()); for (auto& item : sessions.value()) { - if (active_cryptohome_id == item.first) + cryptohome::Identification id = + cryptohome::Identification::FromString(item.first); + if (active_cryptohome_id == id) continue; - pending_user_sessions_[item.first.GetAccountId()] = std::move(item.second); + pending_user_sessions_[id.GetAccountId()] = std::move(item.second); } RestorePendingUserSessions(); } @@ -2148,7 +2152,8 @@ SessionManagerClient* session_manager_client = DBusThreadManager::Get()->GetSessionManagerClient(); session_manager_client->SetFlagsForUser( - cryptohome::Identification(account_id), all_switches); + cryptohome::CreateAccountIdentifierFromAccountId(account_id), + all_switches); } void UserSessionManager::CreateTokenUtilIfMissing() {
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc index a8bf4fb6..c252874 100644 --- a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc +++ b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
@@ -334,8 +334,8 @@ AccountId::FromUserEmailGaiaId(kTestUser2, kTestUser2GaiaId); const AccountId enterprise_account_id_ = AccountId::FromUserEmailGaiaId(kEnterpriseUser1, kEnterpriseUser1GaiaId); - const cryptohome::Identification cryptohome_id_ = - cryptohome::Identification(enterprise_account_id_); + const cryptohome::AccountIdentifier cryptohome_id_ = + cryptohome::CreateAccountIdentifierFromAccountId(enterprise_account_id_); private: DISALLOW_COPY_AND_ASSIGN(UserImageManagerTest);
diff --git a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc index 77bb3bf..7dbbe6a 100644 --- a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc +++ b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
@@ -152,7 +152,7 @@ EXPECT_TRUE(base::PathService::Get(DIR_USER_POLICY_KEYS, &user_keys_dir)); const std::string sanitized_user_id = CryptohomeClient::GetStubSanitizedUsername( - cryptohome::Identification(account_id)); + cryptohome::CreateAccountIdentifierFromAccountId(account_id)); const base::FilePath user_key_file = user_keys_dir.AppendASCII(sanitized_user_id).AppendASCII("policy.pub"); std::string user_key_bits = @@ -294,7 +294,8 @@ } builder->Build(); fake_session_manager_client_->set_user_policy( - cryptohome::Identification(account_id), builder->GetBlob()); + cryptohome::CreateAccountIdentifierFromAccountId(account_id), + builder->GetBlob()); const user_manager::User* user = user_manager::UserManager::Get()->FindUser(account_id); ASSERT_TRUE(user);
diff --git a/chrome/browser/chromeos/policy/affiliation_test_helper.cc b/chrome/browser/chromeos/policy/affiliation_test_helper.cc index cfe65d7..1639e271 100644 --- a/chrome/browser/chromeos/policy/affiliation_test_helper.cc +++ b/chrome/browser/chromeos/policy/affiliation_test_helper.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" #include "chromeos/chromeos_paths.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/dbus/cryptohome_client.h" #include "chromeos/dbus/fake_session_manager_client.h" #include "chromeos/dbus/session_manager_client.h" @@ -56,7 +57,7 @@ base::PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &user_keys_dir)); const std::string sanitized_username = chromeos::CryptohomeClient::GetStubSanitizedUsername( - cryptohome::Identification(account_id)); + cryptohome::CreateAccountIdentifierFromAccountId(account_id)); const base::FilePath user_key_file = user_keys_dir.AppendASCII(sanitized_username).AppendASCII("policy.pub"); std::string user_key_bits = user_policy->GetPublicSigningKeyAsString(); @@ -99,7 +100,8 @@ } user_policy->Build(); fake_session_manager_client->set_user_policy( - cryptohome::Identification(user_account_id), user_policy->GetBlob()); + cryptohome::CreateAccountIdentifierFromAccountId(user_account_id), + user_policy->GetBlob()); } void PreLoginUser(const AccountId& account_id) {
diff --git a/chrome/browser/chromeos/policy/cached_policy_key_loader_chromeos.cc b/chrome/browser/chromeos/policy/cached_policy_key_loader_chromeos.cc index 47b36c0..8bd9030 100644 --- a/chrome/browser/chromeos/policy/cached_policy_key_loader_chromeos.cc +++ b/chrome/browser/chromeos/policy/cached_policy_key_loader_chromeos.cc
@@ -86,7 +86,7 @@ // Get the hashed username that's part of the key's path, to determine // |cached_policy_key_path_|. cryptohome_client_->GetSanitizedUsername( - cryptohome::Identification(account_id_), + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), base::BindOnce(&CachedPolicyKeyLoaderChromeOS::OnGetSanitizedUsername, weak_factory_.GetWeakPtr())); } @@ -96,7 +96,7 @@ const std::string sanitized_username = cryptohome_client_->BlockingGetSanitizedUsername( - cryptohome::Identification(account_id_)); + cryptohome::CreateAccountIdentifierFromAccountId(account_id_)); if (sanitized_username.empty()) return false; @@ -125,7 +125,7 @@ // Get the hashed username that's part of the key's path, to determine // |cached_policy_key_path_|. cryptohome_client_->GetSanitizedUsername( - cryptohome::Identification(account_id_), + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), base::BindOnce(&CachedPolicyKeyLoaderChromeOS::OnGetSanitizedUsername, weak_factory_.GetWeakPtr())); } else {
diff --git a/chrome/browser/chromeos/policy/cached_policy_key_loader_chromeos_unittest.cc b/chrome/browser/chromeos/policy/cached_policy_key_loader_chromeos_unittest.cc index b5af786..0624ab32 100644 --- a/chrome/browser/chromeos/policy/cached_policy_key_loader_chromeos_unittest.cc +++ b/chrome/browser/chromeos/policy/cached_policy_key_loader_chromeos_unittest.cc
@@ -14,6 +14,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/single_thread_task_runner.h" #include "base/test/scoped_task_environment.h" +#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/dbus/fake_cryptohome_client.h" #include "testing/gtest/include/gtest/gtest.h" @@ -72,8 +73,8 @@ base::test::ScopedTaskEnvironment::MainThreadType::UI}; chromeos::FakeCryptohomeClient cryptohome_client_; const AccountId account_id_ = AccountId::FromUserEmail(kTestUserName); - const cryptohome::Identification cryptohome_id_ = - cryptohome::Identification(account_id_); + const cryptohome::AccountIdentifier cryptohome_id_ = + cryptohome::CreateAccountIdentifierFromAccountId(account_id_); std::unique_ptr<CachedPolicyKeyLoaderChromeOS> cached_policy_key_loader_;
diff --git a/chrome/browser/chromeos/policy/power_policy_browsertest.cc b/chrome/browser/chromeos/policy/power_policy_browsertest.cc index 40b990c5..64648c6 100644 --- a/chrome/browser/chromeos/policy/power_policy_browsertest.cc +++ b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
@@ -35,6 +35,7 @@ #include "chrome/test/base/testing_profile.h" #include "chromeos/chromeos_paths.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/dbus/cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_power_manager_client.h" @@ -211,7 +212,8 @@ base::PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &user_keys_dir)); std::string sanitized_username = chromeos::CryptohomeClient::GetStubSanitizedUsername( - cryptohome::Identification(user_manager::StubAccountId())); + cryptohome::CreateAccountIdentifierFromAccountId( + user_manager::StubAccountId())); base::FilePath user_key_file = user_keys_dir.AppendASCII(sanitized_username) .AppendASCII("policy.pub"); @@ -227,7 +229,7 @@ // Install the new user policy blob in session manager client. user_policy_.Build(); session_manager_client()->set_user_policy( - cryptohome::Identification( + cryptohome::CreateAccountIdentifierFromAccountId( AccountId::FromUserEmail(user_policy_.policy_data().username())), user_policy_.GetBlob());
diff --git a/chrome/browser/chromeos/policy/pre_signin_policy_fetcher.cc b/chrome/browser/chromeos/policy/pre_signin_policy_fetcher.cc index e824d918..9aa2278 100644 --- a/chrome/browser/chromeos/policy/pre_signin_policy_fetcher.cc +++ b/chrome/browser/chromeos/policy/pre_signin_policy_fetcher.cc
@@ -17,6 +17,7 @@ #include "base/task_scheduler/task_traits.h" #include "base/time/time.h" #include "chromeos/chromeos_paths.h" +#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/cryptohome/cryptohome_util.h" #include "chromeos/cryptohome/homedir_methods.h" #include "chromeos/dbus/cryptohome_client.h" @@ -73,7 +74,8 @@ cryptohome::MountRequest mount; mount.set_hidden_mount(true); chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->MountEx( - cryptohome::Identification(account_id_), auth, mount, + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), auth, + mount, base::Bind(&PreSigninPolicyFetcher::OnMountTemporaryUserHome, weak_ptr_factory_.GetWeakPtr())); } @@ -97,7 +99,7 @@ } session_manager_client_->RetrievePolicyForUserWithoutSession( - cryptohome::Identification(account_id_), + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), base::Bind(&PreSigninPolicyFetcher::OnCachedPolicyRetrieved, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/chromeos/policy/pre_signin_policy_fetcher_unittest.cc b/chrome/browser/chromeos/policy/pre_signin_policy_fetcher_unittest.cc index 768cafe..b745a91 100644 --- a/chrome/browser/chromeos/policy/pre_signin_policy_fetcher_unittest.cc +++ b/chrome/browser/chromeos/policy/pre_signin_policy_fetcher_unittest.cc
@@ -93,8 +93,8 @@ // regular gaia user and AD user. virtual const AccountId& GetAccountId() const = 0; - cryptohome::Identification GetCryptohomeIdentification() const { - return cryptohome::Identification(GetAccountId()); + cryptohome::AccountIdentifier GetCryptohomeAccountIdentifier() const { + return cryptohome::CreateAccountIdentifierFromAccountId(GetAccountId()); } void StoreUserPolicyKey(const std::string& public_key) { @@ -111,7 +111,7 @@ base::FilePath user_policy_key_file() const { const std::string sanitized_username = chromeos::CryptohomeClient::GetStubSanitizedUsername( - GetCryptohomeIdentification()); + GetCryptohomeAccountIdentifier()); return user_policy_keys_dir() .AppendASCII(sanitized_username) .AppendASCII("policy.pub"); @@ -211,7 +211,7 @@ // session_manager's RetrievePolicy* methods signal that there is no policy by // passing an empty string as policy blob. session_manager_client_.set_user_policy_without_session( - GetCryptohomeIdentification(), std::string()); + GetCryptohomeAccountIdentifier(), std::string()); ExpectNoFreshPolicyFetchOnClient(); ExecuteFetchPolicy(); @@ -257,7 +257,7 @@ StoreUserPolicyKey(cached_policy_.GetPublicSigningKeyAsString()); session_manager_client_.set_user_policy_without_session( - GetCryptohomeIdentification(), cached_policy_.GetBlob()); + GetCryptohomeAccountIdentifier(), cached_policy_.GetBlob()); ExpectNoFreshPolicyFetchOnClient(); ExecuteFetchPolicy(); @@ -280,7 +280,7 @@ // attempt to fetch fresh policy in this case. TEST_F(PreSigninPolicyFetcherTest, NoCachedPolicyKeyAccessible) { session_manager_client_.set_user_policy_without_session( - GetCryptohomeIdentification(), cached_policy_.GetBlob()); + GetCryptohomeAccountIdentifier(), cached_policy_.GetBlob()); ExpectNoFreshPolicyFetchOnClient(); ExecuteFetchPolicy(); @@ -304,7 +304,7 @@ TEST_F(PreSigninPolicyFetcherTest, FreshPolicyFetchFails) { StoreUserPolicyKey(cached_policy_.GetPublicSigningKeyAsString()); session_manager_client_.set_user_policy_without_session( - GetCryptohomeIdentification(), cached_policy_.GetBlob()); + GetCryptohomeAccountIdentifier(), cached_policy_.GetBlob()); ExpectFreshPolicyFetchOnClient(PolicyBuilder::kFakeToken, PolicyBuilder::kFakeDeviceId); @@ -335,7 +335,7 @@ StoreUserPolicyKey(cached_policy_.GetPublicSigningKeyAsString()); session_manager_client_.set_user_policy_without_session( - GetCryptohomeIdentification(), cached_policy_.GetBlob()); + GetCryptohomeAccountIdentifier(), cached_policy_.GetBlob()); ExpectFreshPolicyFetchOnClient(PolicyBuilder::kFakeToken, PolicyBuilder::kFakeDeviceId); @@ -366,7 +366,7 @@ StoreUserPolicyKey(cached_policy_.GetPublicSigningKeyAsString()); session_manager_client_.set_user_policy_without_session( - GetCryptohomeIdentification(), cached_policy_.GetBlob()); + GetCryptohomeAccountIdentifier(), cached_policy_.GetBlob()); ExpectFreshPolicyFetchOnClient(PolicyBuilder::kFakeToken, PolicyBuilder::kFakeDeviceId); @@ -404,7 +404,7 @@ StoreUserPolicyKey(cached_policy_.GetPublicSigningKeyAsString()); session_manager_client_.set_user_policy_without_session( - GetCryptohomeIdentification(), cached_policy_.GetBlob()); + GetCryptohomeAccountIdentifier(), cached_policy_.GetBlob()); ExpectFreshPolicyFetchOnClient(PolicyBuilder::kFakeToken, PolicyBuilder::kFakeDeviceId); @@ -448,7 +448,7 @@ // key and no fresh policy fetch is attempted currently. TEST_F(PreSigninPolicyFetcherTestAD, UnsignedCachedPolicyForActiveDirectory) { session_manager_client_.set_user_policy_without_session( - GetCryptohomeIdentification(), cached_policy_.GetBlob()); + GetCryptohomeAccountIdentifier(), cached_policy_.GetBlob()); ExpectNoFreshPolicyFetchOnClient(); ExecuteFetchPolicy();
diff --git a/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc b/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc index 898aa9f..41e2f2e 100644 --- a/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc +++ b/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc
@@ -392,7 +392,8 @@ AccountId::FromUserEmailGaiaId(GetAccount(), kTestUserGaiaId); std::vector<std::string> flags_for_user; bool has_flags_for_user = fake_session_manager_client()->GetFlagsForUser( - cryptohome::Identification(test_account_id), &flags_for_user); + cryptohome::CreateAccountIdentifierFromAccountId(test_account_id), + &flags_for_user); EXPECT_TRUE(has_flags_for_user); // Remove flag sentinels. Keep whatever is between those sentinels, to
diff --git a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc index aaa6bec..c68d92e13 100644 --- a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc +++ b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
@@ -116,9 +116,10 @@ affiliation_test_helper::AppendCommandLineSwitchesForLoginManager( command_line); } else { - const cryptohome::Identification cryptohome_id(account_id_); + const cryptohome::AccountIdentifier cryptohome_id = + cryptohome::CreateAccountIdentifierFromAccountId(account_id_); command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, - cryptohome_id.id()); + cryptohome_id.account_id()); command_line->AppendSwitchASCII( chromeos::switches::kLoginProfile, chromeos::CryptohomeClient::GetStubSanitizedUsername(cryptohome_id));
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc index b92dbce..3336601 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
@@ -71,7 +71,7 @@ // Cancel all pending requests. weak_factory_.InvalidateWeakPtrs(); session_manager_client_->RetrievePolicyForUser( - cryptohome::Identification(account_id_), + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), base::BindOnce(&UserCloudPolicyStoreChromeOS::OnPolicyRetrieved, weak_factory_.GetWeakPtr())); } @@ -88,7 +88,8 @@ std::string policy_blob; RetrievePolicyResponseType response_type = session_manager_client_->BlockingRetrievePolicyForUser( - cryptohome::Identification(account_id_), &policy_blob); + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), + &policy_blob); if (response_type == RetrievePolicyResponseType::GET_SERVICE_FAIL) { LOG(ERROR) @@ -173,7 +174,8 @@ } session_manager_client_->StorePolicyForUser( - cryptohome::Identification(account_id_), policy_blob, + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), + policy_blob, base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyStored, weak_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc index c42c7d8..e95a090 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc
@@ -19,8 +19,10 @@ #include "base/single_thread_task_runner.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" +#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/dbus/fake_cryptohome_client.h" #include "chromeos/dbus/fake_session_manager_client.h" +#include "chromeos/dbus/util/account_identifier_operators.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" #include "components/policy/core/common/cloud/policy_builder.h" @@ -53,7 +55,7 @@ base::FilePath GetUserPolicyKeyFile( const base::FilePath& user_policy_dir, - const cryptohome::Identification& cryptohome_id) { + const cryptohome::AccountIdentifier& cryptohome_id) { const std::string sanitized_username = chromeos::CryptohomeClient::GetStubSanitizedUsername(cryptohome_id); return user_policy_dir.AppendASCII(sanitized_username) @@ -61,7 +63,7 @@ } bool StoreUserPolicyKey(const base::FilePath& user_policy_dir, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& public_key) { base::FilePath user_policy_key_file = GetUserPolicyKeyFile(user_policy_dir, cryptohome_id); @@ -80,7 +82,7 @@ : user_policy_dir_(user_policy_dir), weak_ptr_factory_(this) {} // SessionManagerClient override: - void StorePolicyForUser(const cryptohome::Identification& cryptohome_id, + void StorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob, chromeos::VoidDBusMethodCallback callback) override { chromeos::FakeSessionManagerClient::StorePolicyForUser( @@ -90,13 +92,13 @@ std::move(callback))); } - void set_user_public_key(const cryptohome::Identification& cryptohome_id, + void set_user_public_key(const cryptohome::AccountIdentifier& cryptohome_id, const std::string& public_key) { public_key_map_[cryptohome_id] = public_key; } private: - void OnStorePolicyForUser(const cryptohome::Identification& cryptohome_id, + void OnStorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id, chromeos::VoidDBusMethodCallback callback, bool result) { if (result) { @@ -108,7 +110,7 @@ } const base::FilePath user_policy_dir_; - std::map<cryptohome::Identification, std::string> public_key_map_; + std::map<cryptohome::AccountIdentifier, std::string> public_key_map_; base::WeakPtrFactory<FakeSessionManagerClient> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(FakeSessionManagerClient); @@ -227,8 +229,8 @@ std::unique_ptr<UserCloudPolicyStoreChromeOS> store_; const AccountId account_id_ = AccountId::FromUserEmail(PolicyBuilder::kFakeUsername); - const cryptohome::Identification cryptohome_id_ = - cryptohome::Identification(account_id_); + const cryptohome::AccountIdentifier cryptohome_id_ = + cryptohome::CreateAccountIdentifierFromAccountId(account_id_); private: base::ScopedTempDir tmp_dir_;
diff --git a/chrome/browser/chromeos/power/process_data_collector.cc b/chrome/browser/chromeos/power/process_data_collector.cc new file mode 100644 index 0000000..10deccd --- /dev/null +++ b/chrome/browser/chromeos/power/process_data_collector.cc
@@ -0,0 +1,698 @@ +// Copyright 2018 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 "chrome/browser/chromeos/power/process_data_collector.h" + +#include <sys/types.h> + +#include <algorithm> +#include <fstream> +#include <iostream> +#include <limits> +#include <numeric> +#include <string> +#include <unordered_map> +#include <unordered_set> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/i18n/number_formatting.h" +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/synchronization/lock.h" +#include "base/task_scheduler/post_task.h" +#include "base/threading/platform_thread.h" +#include "base/threading/thread_restrictions.h" +#include "base/time/time.h" +#include "base/values.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/power_manager_client.h" +#include "content/public/browser/browser_thread.h" + +namespace chromeos { + +ProcessDataCollector* g_process_data_collector = nullptr; + +namespace { + +// The command line that will used to invoke the Crostini concierge daemon. +constexpr char kConciergeCmdline[] = "/usr/bin/vm_concierge"; + +// The full file path that will be used to invoke chrome. +constexpr char kChromeCmdPath[] = "/opt/google/chrome/chrome"; + +// Sampling frequency. +constexpr base::TimeDelta kSampleDelay = base::TimeDelta::FromSeconds(15); + +// Time after which a sample is invalid. Must be greater than |kSampleDelay|. +constexpr base::TimeDelta kExcessiveDelay = base::TimeDelta::FromSeconds(30); + +// Represents a map of all processes; maps a PPID to a PID. +using PpidToPidMap = std::unordered_multimap<pid_t, pid_t>; + +// Represents the CPU and power exponential moving averages. +struct CpuUsageAndPowerAverage { + // Represents an accumulated average; this will change depending on the + // |AveragingTechnique| specified. + double accumulated_cpu_usages; + + // Represents the the average power usage that is calculated from the + // |accumulated_cpu_usages|. How it is calculated depends on the + // |AveragingTechnique|. + double power_average; +}; + +// Represents the CPU time a process has used and its PPID. +using ProcCpuUsageAndPpid = std::pair<int64_t, pid_t>; + +// Returns ARC's init PID. +base::Optional<pid_t> GetAndroidInitPid( + const base::FilePath& android_pid_file) { + // This function does I/O and must be done on a blocking thread. + base::AssertBlockingAllowed(); + + std::string android_pid_contents; + if (!base::ReadFileToString(android_pid_file, &android_pid_contents)) + return base::nullopt; + + // This file contains a single number which contains the PID of the Android + // init PID. + pid_t android_pid; + base::TrimWhitespaceASCII(android_pid_contents, base::TRIM_ALL, + &android_pid_contents); + if (!base::StringToInt(android_pid_contents, &android_pid)) + return base::nullopt; + + return android_pid; +} + +// Calculates the total CPU time used in jiffies. +base::Optional<int64_t> ComputeCpuTimeJiffies(const base::FilePath& stat_file) { + // This function does I/O and must be done on a blocking thread. + base::AssertBlockingAllowed(); + + std::string stat_contents; + if (!base::ReadFileToString(stat_file, &stat_contents)) + return base::nullopt; + + // This file looks like: + // cpu <num1> <num2> ... + // cpu0 <num1> <num2> ... + // cpu1 <num1> <num2> ... + // ... + // Where each number represents the amount of time in jiffies a certain CPU is + // in some state. The first line presents the total amount of time in jiffies + // the system is in some state across all CPUs. The first line beginning with + // "cpu " needs to be singled out and all the numbers on that line need to be + // summed to obtain the total amount of time in jiffies the system has been + // running across all states. + std::vector<std::string> stat_lines = base::SplitString( + stat_contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + for (const auto& line : stat_lines) { + // Find the line that starts with "cpu " and sum everything on that line to + // get the total amount of jiffies used. + if (base::StartsWith(line, "cpu ", base::CompareCase::SENSITIVE)) { + std::vector<std::string> cpu_info_parts = base::SplitString( + line, " \t", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (cpu_info_parts.size() <= 1) + return base::nullopt; + + int64_t total_time = 0; + // Start from cpu_info_parts.begin() + 1 to skip the "cpu " prefix and + // start from the second column. + for (auto iter = cpu_info_parts.begin() + 1; iter != cpu_info_parts.end(); + iter++) { + int64_t curr; + if (!base::StringToInt64(*iter, &curr)) + return base::nullopt; + total_time += curr; + } + return total_time; + } + } + return base::nullopt; +} + +// Calculates the total CPU time used by a single process in jiffies and its +// PPID. +base::Optional<ProcCpuUsageAndPpid> ComputeProcCpuTimeJiffiesAndPpid( + const base::FilePath& proc_stat_file) { + // This function does I/O and must be done on a blocking thread. + base::AssertBlockingAllowed(); + + std::string proc_stat_contents; + if (!base::ReadFileToString(proc_stat_file, &proc_stat_contents)) + return base::nullopt; + + // This file looks like: + // <num1> (<str>) <char> <num2> <num3> ... + // Where each of the numbers represent the amount of CPU time in jiffies a + // process was in a state. The entries at 0-based indices 13 and 14 represent + // the amount of time the process was in user mode and kernel mode. By + // isolating and summing those two numbers, the total amount of CPU time in + // jiffies the process has used can be approximated. Additionally the entry at + // index 3, represents the PPID of the process. However, the entry at index 1 + // represents a filename, which can have an arbitrary number of spaces, so + // skip it by finding the last parenthesis. + + // Skip PID and comm fields. + const auto last_parenthesis = proc_stat_contents.find_last_of(')'); + if (last_parenthesis == std::string::npos || + last_parenthesis + 1 > proc_stat_contents.length()) + return base::nullopt; + + // Skip the parenthesis itself. + const std::string truncated_proc_stat_contents = + proc_stat_contents.substr(last_parenthesis + 1); + + std::vector<std::string> proc_stat_split = + base::SplitString(truncated_proc_stat_contents, " \t\n", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + + // The first 2 entries of the file were removed earlier, so all the indices + // for the entries will be shifted by 2. + if (proc_stat_split.size() < 12) + return base::nullopt; + + int64_t user_time; + // These two entries contain the total time this process spent in user mode + // and kernel mode. This is roughly the total CPU time that the process has + // used. + if (!base::StringToInt64(proc_stat_split[11], &user_time)) + return base::nullopt; + + int64_t kernel_time; + if (!base::StringToInt64(proc_stat_split[12], &kernel_time)) + return base::nullopt; + + int64_t proc_cpu_time = user_time + kernel_time; + + uint64_t ppid; + if (!base::StringToUint64(proc_stat_split[1], &ppid)) + return base::nullopt; + + return std::make_pair(proc_cpu_time, ppid); +} + +// Reads a process' name from |comm_file|, a file like "/proc/%u/comm". +base::Optional<std::string> GetProcName(const base::FilePath& comm_file) { + // This function does I/O and must be done on a blocking thread. + base::AssertBlockingAllowed(); + + std::string comm_contents; + if (!base::ReadFileToString(comm_file, &comm_contents)) + return base::nullopt; + + base::TrimWhitespaceASCII(comm_contents, base::TRIM_ALL, &comm_contents); + + return comm_contents.empty() ? base::nullopt + : base::make_optional(comm_contents); +} + +// Reads a process's command line from |cmdline|, a path like +// "/proc/%u/cmdline". +base::Optional<std::string> GetProcCmdline(const base::FilePath& cmdline) { + // This function does I/O and must be done on a blocking thread. + base::AssertBlockingAllowed(); + + std::string cmdline_contents; + if (!base::ReadFileToString(cmdline, &cmdline_contents)) + return base::nullopt; + + base::TrimWhitespaceASCII(cmdline_contents, base::TRIM_ALL, + &cmdline_contents); + + return cmdline_contents.empty() ? base::nullopt + : base::make_optional(cmdline_contents); +} + +// Finds all children of a root PID recursively and stores the results in +// |visited|. +void GetChildPids(const PpidToPidMap& ppid_to_pid, + pid_t root, + std::unordered_set<pid_t>* visited) { + visited->insert(root); + auto adj = ppid_to_pid.equal_range(root); + for (auto iter = adj.first; iter != adj.second; iter++) { + pid_t pid = iter->second; + if (visited->find(pid) == visited->end()) + GetChildPids(ppid_to_pid, pid, visited); + } +} + +// Returns a new average given a |summed_averages| aggregated over |num_samples| +// samples and a |new_sample|. +CpuUsageAndPowerAverage ComputeNormalAverages(int64_t num_samples, + double summed_averages, + double new_sample) { + // When the |AveragingTechnique| used is |AveragingTechnique::AVERAGE|, the + // |summed_averages| that should be passed into this function should be + // accumulated sums of the average CPU usages over all of the previous + // intervals. Specifically, say that n averages over n intervals have been + // calculated, a1,...,an and the a(n+1)th sample is just passed, then: + // |num_samples| = n + // |summed_averages| = a1 + a2 + ... + an + // |new_sample| = a(n+1) + double accumulated_cpu_usages = summed_averages + new_sample; + double new_power_average = accumulated_cpu_usages / (num_samples + 1); + return {accumulated_cpu_usages, new_power_average}; +} + +// Returns new exponential moving averages calculated as follows: +// Let a = the weight for CPU averages and b = the weight for power averages. +// First calculate: +// c_new = (1 - a) * c_old + a * c_curr +// b_new = (1 - b) * b_old + b * c_new +// Where c_new is the new exponential moving average for CPU usages, c_old is +// the currently aggregated CPU usages, and c_curr is the new CPU average over a +// single interval. Similarly, b_old is the old power exponential moving +// average and b_new is the newly calculated exponential moving average. The +// function returns c_new and b_new. +CpuUsageAndPowerAverage ComputeExponentialMovingAverages( + double curr_cpu_average, + double curr_power_average, + double new_sample) { + double new_cpu_average = + (1 - ProcessDataCollector::kCpuUsageExponentialMovingAverageWeight) * + curr_cpu_average + + ProcessDataCollector::kCpuUsageExponentialMovingAverageWeight * + new_sample; + double new_power_average = + (1 - ProcessDataCollector::kPowerUsageExponentialMovingAverageWeight) * + curr_power_average + + ProcessDataCollector::kPowerUsageExponentialMovingAverageWeight * + new_cpu_average; + return {new_cpu_average, new_power_average}; +} + +} // namespace + +ProcessDataCollector::ProcessUsageData::ProcessUsageData( + const ProcessData& process_data, + double power_usage_fraction) + : process_data(process_data), power_usage_fraction(power_usage_fraction) {} + +ProcessDataCollector::ProcessUsageData::ProcessUsageData( + const ProcessUsageData& p) = default; + +ProcessDataCollector::ProcessUsageData::~ProcessUsageData() = default; + +ProcessDataCollector::Config::Config(const base::FilePath& procfs, + const base::FilePath& total_cpu_time, + const base::FilePath& android_init, + const std::string& cmdline_fmt, + const std::string& stat_fmt, + const std::string& comm_fmt, + base::TimeDelta delay, + AveragingTechnique technique) + : proc_dir(procfs), + total_cpu_time_path(total_cpu_time), + android_init_pid_path(android_init), + proc_cmdline_fmt(cmdline_fmt), + proc_stat_fmt(stat_fmt), + proc_comm_fmt(comm_fmt), + sample_delay(delay), + averaging_technique(technique) {} + +ProcessDataCollector::Config::Config(const Config& config) = default; + +ProcessDataCollector::Config::~Config() = default; + +// static +void ProcessDataCollector::Initialize() { + DCHECK(!g_process_data_collector); + + // A |ProcessDataCollector::Config| struct that contains a set of parameters + // to be used in a production environment. + const ProcessDataCollector::Config kRealConfig( + // /proc directory which stores process information. + base::FilePath("/proc"), + // Contains the total amount of CPU time used. + base::FilePath("/proc/stat"), + // Contains the PID of the ARC init process. + base::FilePath("/run/containers/android-run_oci/container.pid"), + // Contains the command used to start a process. + "/proc/%u/cmdline", + // Contains the amount of CPU time a process has used and its PPID. + "/proc/%u/stat", + // Contains the name of the process. + "/proc/%u/comm", kSampleDelay, + ProcessDataCollector::Config::AveragingTechnique::AVERAGE); + + g_process_data_collector = new ProcessDataCollector(kRealConfig); + g_process_data_collector->StartSamplingCpuUsage(); +} + +// static +void ProcessDataCollector::InitializeForTesting(const Config& config) { + DCHECK(!g_process_data_collector); + g_process_data_collector = new ProcessDataCollector(config); +} + +// static +ProcessDataCollector* ProcessDataCollector::Get() { + DCHECK(g_process_data_collector); + return g_process_data_collector; +} + +// static +void ProcessDataCollector::Shutdown() { + DCHECK(g_process_data_collector); + delete g_process_data_collector; + g_process_data_collector = nullptr; +} + +void ProcessDataCollector::SampleCpuUsageForTesting() { + DCHECK(g_process_data_collector); + SamplesAndSummaryInfo samples_and_summary_info = + g_process_data_collector->ComputeSampleAsync( + g_process_data_collector->config_, + g_process_data_collector->prev_samples_, + g_process_data_collector->curr_samples_, + g_process_data_collector->curr_summary_); + g_process_data_collector->SaveSamplesOnUIThread(samples_and_summary_info); +} + +const std::vector<ProcessDataCollector::ProcessUsageData> +ProcessDataCollector::GetProcessUsages() { + std::vector<ProcessUsageData> process_list; + + // Gather the summarized statistics and generate user-facing information. + for (const auto& proc : curr_summary_) { + process_list.emplace_back(ProcessDataCollector::ProcessUsageData( + ProcessData(proc.second.process_data), + proc.second.power_usage_fraction)); + } + + // Since the sampling will give us approximate CPU usages and some processes + // are discarded in |GetValidProcesses|, the total fraction of CPU usages in + // this list of processes may not sum up to 1. Normalizing ensures that the + // fractions make sense. + double total = std::accumulate( + process_list.begin(), process_list.end(), 0., + [](const auto& i, const auto& s) { return i + s.power_usage_fraction; }); + if (total != 0) { + std::for_each(process_list.begin(), process_list.end(), + [&total](auto& c) { c.power_usage_fraction /= total; }); + } + + return process_list; +} + +ProcessDataCollector::ProcessData::ProcessData() = default; +ProcessDataCollector::ProcessData::ProcessData(pid_t pid, + const std::string& name, + const std::string& cmdline, + PowerConsumerType type) + : pid(pid), name(name), cmdline(cmdline), type(type) {} +ProcessDataCollector::ProcessData::ProcessData(const ProcessData& p) = default; +ProcessDataCollector::ProcessData::~ProcessData() = default; + +ProcessDataCollector::ProcessSample::ProcessSample() = default; +ProcessDataCollector::ProcessSample::ProcessSample(const ProcessSample& p) = + default; +ProcessDataCollector::ProcessSample::~ProcessSample() = default; + +ProcessDataCollector::ProcessStoredData::ProcessStoredData() = default; +ProcessDataCollector::ProcessStoredData::ProcessStoredData( + const ProcessStoredData& p) = default; +ProcessDataCollector::ProcessStoredData::~ProcessStoredData() = default; + +ProcessDataCollector::ProcessDataCollector(const Config& config) + : config_(config), weak_ptr_factory_(this) {} + +ProcessDataCollector::~ProcessDataCollector() = default; + +void ProcessDataCollector::StartSamplingCpuUsage() { + cpu_data_task_runner_ = base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); + cpu_data_timer_.Start(FROM_HERE, config_.sample_delay, this, + &ProcessDataCollector::SampleCpuUsage); +} + +void ProcessDataCollector::SampleCpuUsage() { + base::PostTaskAndReplyWithResult( + cpu_data_task_runner_.get(), FROM_HERE, + base::BindOnce(&ProcessDataCollector::ComputeSampleAsync, config_, + prev_samples_, curr_samples_, curr_summary_), + base::BindOnce(&ProcessDataCollector::SaveSamplesOnUIThread, + weak_ptr_factory_.GetWeakPtr())); +} + +// static +ProcessDataCollector::ProcessSampleMap ProcessDataCollector::GetValidProcesses( + const Config& config) { + // This function does I/O and must be done on a blocking thread. + base::AssertBlockingAllowed(); + + base::FileEnumerator proc_files(config.proc_dir, false, + base::FileEnumerator::DIRECTORIES); + ProcessSampleMap procs; + + for (base::FilePath path = proc_files.Next(); !path.empty(); + path = proc_files.Next()) { + pid_t proc; + if (!base::StringToInt(path.BaseName().value(), &proc)) + continue; + + // Don't track if either the process name or cmdline are empty or + // non-existent. + base::Optional<std::string> proc_name = GetProcName( + base::FilePath(base::StringPrintf(config.proc_comm_fmt.c_str(), proc))); + if (!proc_name) + continue; + base::Optional<std::string> proc_cmdline = GetProcCmdline(base::FilePath( + base::StringPrintf(config.proc_cmdline_fmt.c_str(), proc))); + if (!proc_cmdline) + continue; + + ProcessSample psample; + psample.valid = true; + psample.process_data.pid = proc; + psample.process_data.name = proc_name.value(); + psample.process_data.cmdline = proc_cmdline.value(); + // Set every process type to be a system process. Once procfs is sampled in + // more detail, the actual type of power consumer can be set and determined. + psample.process_data.type = ProcessDataCollector::PowerConsumerType::SYSTEM; + psample.now = base::TimeTicks::Now(); + + // |procs| starts off as an empty |ProcessSampleMap| and for every + // iteration of this loop, |proc| will correspond to the PID of a different + // process. Thus, this call to |std::unordered_map::emplace| should never be + // called with the same key twice. + procs.emplace(std::make_pair(proc, std::move(psample))); + } + + return procs; +} + +// static +ProcessDataCollector::ProcessSampleMap ProcessDataCollector::ComputeSample( + ProcessSampleMap curr_samples, + const Config& config) { + // First the amount of CPU time used by the machine is gathered. Then, for + // each process, the PPID and the amount of CPU time it has used is gathered. + // All this information is stored in the process sample so that an average can + // later be calculated. Additionally, a PPID to PID map is constructed so that + // different types of processes can be classified; this is needed to classify + // ARC process for example. + base::Optional<int64_t> total_cpu_time = + ComputeCpuTimeJiffies(config.total_cpu_time_path); + // If this can't be read, then the average CPU usage over this interval can't + // be calculated. Ignore these samples. + if (!total_cpu_time.value()) { + // Set all the samples to be invalid. + for (auto& sample : curr_samples) + sample.second.valid = false; + return curr_samples; + } + + base::Optional<int64_t> concierge_pid = base::nullopt; + std::unordered_map<pid_t, int64_t> pid_to_cpu_usage_before; + std::unordered_set<uint64_t> chrome_pids; + PpidToPidMap proc_ppid_to_pid; + + for (auto& sample : curr_samples) { + base::Optional<ProcCpuUsageAndPpid> proc_cpu_time_and_ppid = + ComputeProcCpuTimeJiffiesAndPpid(base::FilePath( + base::StringPrintf(config.proc_stat_fmt.c_str(), sample.first))); + + // If this failed, it could be that a process terminated while sampling it. + // Ignore these processes; since the process will be invalid, it will never + // be aggregated into |ProcessStoredData|. + sample.second.valid = proc_cpu_time_and_ppid.has_value(); + if (!sample.second.valid) + continue; + + uint64_t proc_cpu_time = proc_cpu_time_and_ppid.value().first; + pid_t ppid = proc_cpu_time_and_ppid.value().second; + + sample.second.total_cpu_time_jiffies = total_cpu_time.value(); + sample.second.proc_cpu_time_jiffies = proc_cpu_time; + proc_ppid_to_pid.insert({ppid, sample.first}); + + // Get the PID of the Concierge daemon if it exists. + if (base::StartsWith(sample.second.process_data.cmdline, kConciergeCmdline, + base::CompareCase::SENSITIVE)) + concierge_pid = sample.second.process_data.pid; + + // Get all process that are Chrome processes. + if (base::StartsWith(sample.second.process_data.cmdline, kChromeCmdPath, + base::CompareCase::SENSITIVE)) + chrome_pids.insert(sample.first); + } + + std::unordered_set<pid_t> arc_pids; + base::Optional<pid_t> android_init_pid = + GetAndroidInitPid(config.android_init_pid_path); + // Compute all processes associated with ARC. + if (android_init_pid.has_value()) + GetChildPids(proc_ppid_to_pid, android_init_pid.value(), &arc_pids); + + std::unordered_set<pid_t> crostini_pids; + // Compute all process associated with Crostini. + if (concierge_pid.has_value()) + GetChildPids(proc_ppid_to_pid, concierge_pid.value(), &crostini_pids); + + // Change the process types appropriately depending on the previous + // information gathered. Currently, these are the only 3 types of process that + // are classified. Everything else is classified as a |SYSTEM| process, which + // was the default value set in |GetValidProcesses|. + for (auto& sample : curr_samples) { + if (arc_pids.count(sample.first)) { + sample.second.process_data.type = + ProcessDataCollector::PowerConsumerType::ARC; + } else if (crostini_pids.count(sample.first)) { + sample.second.process_data.type = + ProcessDataCollector::PowerConsumerType::CROSTINI; + } else if (chrome_pids.count(sample.first)) { + sample.second.process_data.type = + ProcessDataCollector::PowerConsumerType::CHROME; + } + } + + return curr_samples; +} + +// static +ProcessDataCollector::ProcessStoredDataMap ProcessDataCollector::ComputeSummary( + Config::AveragingTechnique averaging_technique, + const ProcessSampleMap& prev_samples, + const ProcessSampleMap& curr_samples, + const ProcessStoredDataMap& curr_summary) { + ProcessStoredDataMap next_summary; + + // For each pair of valid samples, samples that are neither invalid nor + // separated by a time delay greater than a preset amount, across two + // timeslices, calculate the average CPU usage for each process. Once this has + // been calculated, aggregate this average of one interval to the average + // across all intervals this process has been sampled for; the average can be + // a normal average or an exponential moving average. Store the newly updated + // averages into ProcessStoredData and update |curr_summary_| with the latest + // calculations. + for (const auto& sample : curr_samples) { + auto prev_iter = prev_samples.find(sample.first); + // If the process has not been sampled for more than two timeslices, then + // there is no way to compute an average across an interval, so skip this + // process for now. When the next timeslice comes around, if the process is + // still running, it can be sampled again and there will be two samples in + // two different timeslices so that an average over an interval can be + // computed. + if (prev_iter == prev_samples.end()) + continue; + const ProcessSample& curr_sample = sample.second; + const ProcessSample& prev_sample = prev_iter->second; + + // If there's too much of a delay between the last sample and our current + // sample, then throw away all of the previous information, since there was + // some problem that caused it to delay. + if (base::TimeDelta(curr_sample.now - prev_sample.now) > kExcessiveDelay) + continue; + + // Computes the average CPU usage over a single interval. + double cpu_usage = + (static_cast<double>(curr_sample.proc_cpu_time_jiffies - + prev_sample.proc_cpu_time_jiffies)) / + (static_cast<double>(curr_sample.total_cpu_time_jiffies - + prev_sample.total_cpu_time_jiffies)); + + ProcessStoredData& new_summary = next_summary[sample.first]; + + new_summary.process_data.pid = curr_sample.process_data.pid; + new_summary.process_data.name = curr_sample.process_data.name; + new_summary.process_data.type = curr_sample.process_data.type; + new_summary.process_data.cmdline = curr_sample.process_data.cmdline; + + auto summary_iter = curr_summary.find(sample.first); + // If this is the first sample, there is no power usage and only one + // sample. + if (summary_iter == curr_summary.end()) { + new_summary.accumulated_cpu_usages = cpu_usage; + new_summary.power_usage_fraction = cpu_usage; + new_summary.num_samples = 1; + } else { + // Otherwise, depending on the averaging technique calculate the average + // CPU usage across all processes so far; e.g. for time step i + 1, + // ProcessStoredData should have aggregated the first i time steps. + if (averaging_technique == + ProcessDataCollector::Config::AveragingTechnique ::EXPONENTIAL) { + const CpuUsageAndPowerAverage averages = + ComputeExponentialMovingAverages( + summary_iter->second.accumulated_cpu_usages, + summary_iter->second.power_usage_fraction, cpu_usage); + new_summary.accumulated_cpu_usages = averages.accumulated_cpu_usages; + new_summary.power_usage_fraction = averages.power_average; + } else if (averaging_technique == + ProcessDataCollector::Config::AveragingTechnique ::AVERAGE) { + const CpuUsageAndPowerAverage averages = ComputeNormalAverages( + summary_iter->second.num_samples, + summary_iter->second.accumulated_cpu_usages, cpu_usage); + new_summary.accumulated_cpu_usages = averages.accumulated_cpu_usages; + new_summary.power_usage_fraction = averages.power_average; + } else { + NOTREACHED(); + } + new_summary.num_samples = summary_iter->second.num_samples + 1; + } + } + + return next_summary; +} + +// static +ProcessDataCollector::SamplesAndSummaryInfo +ProcessDataCollector::ComputeSampleAsync(Config config, + ProcessSampleMap prev_samples, + ProcessSampleMap curr_samples, + ProcessStoredDataMap curr_summary) { + ProcessSampleMap procs = GetValidProcesses(config); + + prev_samples = std::move(curr_samples); + curr_samples = ComputeSample(std::move(procs), config); + ProcessStoredDataMap next_summary = ComputeSummary( + config.averaging_technique, prev_samples, curr_samples, curr_summary); + + return std::make_tuple(std::move(prev_samples), std::move(curr_samples), + std::move(next_summary)); +} + +void ProcessDataCollector::SaveSamplesOnUIThread( + const SamplesAndSummaryInfo& samples_and_summary_info) { + // Modifies |prev_samples_|, |curr_samples_|, and |next_summary|, thus this + // must be run on the UI thread. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + std::tie(prev_samples_, curr_samples_, curr_summary_) = + samples_and_summary_info; +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/power/process_data_collector.h b/chrome/browser/chromeos/power/process_data_collector.h new file mode 100644 index 0000000..9021f39 --- /dev/null +++ b/chrome/browser/chromeos/power/process_data_collector.h
@@ -0,0 +1,336 @@ +// Copyright 2018 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 CHROME_BROWSER_CHROMEOS_POWER_PROCESS_DATA_COLLECTOR_H_ +#define CHROME_BROWSER_CHROMEOS_POWER_PROCESS_DATA_COLLECTOR_H_ + +#include <sys/types.h> + +#include <cstdint> +#include <memory> +#include <string> +#include <tuple> +#include <unordered_map> +#include <unordered_set> +#include <utility> +#include <vector> + +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "base/sequence_checker.h" +#include "base/sequenced_task_runner.h" +#include "base/strings/string16.h" +#include "base/synchronization/lock.h" +#include "base/timer/timer.h" +#include "chrome/browser/chromeos/power/process_data_collector.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/power_manager_client.h" + +namespace chromeos { + +// A class which starts collecting metrics about processes as soon as it is +// initialized with |Initialize|. This class depends on the DBusThreadManager +// and is implemented as a global singleton. +class CHROMEOS_EXPORT ProcessDataCollector { + public: + // The different sources of power consumption being tracked. + enum class PowerConsumerType { + SCREEN, + KEYBOARD, + CROSTINI, + ARC, + CHROME, + SYSTEM + }; + + // Contains basic information about a process like its PID, its name, etc. The + // |pid|, |process_name|, and |process_cmdline| will be dummy values for + // non-process |PowerConsumerType|'s. + struct ProcessData { + ProcessData(); + ProcessData(pid_t pid, + const std::string& name, + const std::string& cmdline, + PowerConsumerType type); + ~ProcessData(); + ProcessData(const ProcessData& p); + + // The PID of the process. + pid_t pid; + + // The file name of this process as invoked from the command line. + std::string name; + + // The full command line which spawned this process. + std::string cmdline; + + // The type of power consumer this is. + PowerConsumerType type; + }; + + // Data that gets used for displaying process information. + struct ProcessUsageData { + ProcessUsageData(const ProcessData& process_data, + double power_usage_fraction); + ProcessUsageData(const ProcessUsageData& p); + ~ProcessUsageData(); + + // Basic information about the process. + ProcessData process_data; + + // The calculated amount of power usage in [0.0, 1.0]. Represents what + // fraction of the system's total power consumption at some point was + // consumed by this process. + double power_usage_fraction; + }; + + // Metadata used to configure the data collector. Used to differentiate + // between production and test environments. + struct Config { + // The technique used to average CPU usages to approximate battery usage. + enum class AveragingTechnique { + EXPONENTIAL, // An exponential moving average. + AVERAGE, // A pure average. + }; + + Config(const base::FilePath& procfs, + const base::FilePath& total_cpu_time, + const base::FilePath& android_init, + const std::string& cmdline_fmt, + const std::string& stat_fmt, + const std::string& comm_fmt, + base::TimeDelta delay, + AveragingTechnique technique); + Config(const Config& s); + ~Config(); + + // Corresponds to /proc on a real machine. + base::FilePath proc_dir; + + // Corresponds to /proc/stat on a real machine. + base::FilePath total_cpu_time_path; + + // Corresponds to /run/containers/android-run_oci/container.pid on a real + // machine, which contains the PID of ARC's init process. + base::FilePath android_init_pid_path; + + // Corresponds to the general format for a process' specific cmdline file, + // /proc/%u/cmdline on a real machine. + std::string proc_cmdline_fmt; + + // Corresponds to the general format for a process' stat file, /proc/%u/stat + // on a real machine. + std::string proc_stat_fmt; + + // Corresponds to the general format for a process' comm file, + // /proc/%u/comm on a real machine. + std::string proc_comm_fmt; + + // The delay between sampling the procfs specified in |proc_dir|. + base::TimeDelta sample_delay; + + // The |AveragingTechnique| that will be used to aggregate all the samples + // for different processes collected over time. + AveragingTechnique averaging_technique; + }; + + // Weights for an exponential moving average strategy for approximating power + // usage. + static constexpr double kCpuUsageExponentialMovingAverageWeight = 0.2; + static constexpr double kPowerUsageExponentialMovingAverageWeight = 0.1; + + // Check to make sure the weights used make sense. + static_assert( + 0 <= kCpuUsageExponentialMovingAverageWeight && + kCpuUsageExponentialMovingAverageWeight <= 1, + "The weight of an exponential moving average has to be in [0., 1.]"); + static_assert( + 0 <= kPowerUsageExponentialMovingAverageWeight && + kPowerUsageExponentialMovingAverageWeight <= 1, + "The weight of an exponential moving average has to be in [0., 1.]"); + + // Initializes the singleton. + static void Initialize(); + + // Should be called for testing. + static void InitializeForTesting(const Config& config); + + // Gets the global ProcessDataCollector* instance, should only be called after + // |Initialize| or |InitializeForTesting|. + static ProcessDataCollector* Get(); + + // Should only be called after Initialize() is called and before + // DBusThreadManager is shut down. + static void Shutdown(); + + // The analog for the |SampleCpuUsage| function but for testing. Do not call + // this while a |ProcessDataCollector| has been initialized with |Initialize| + // rather than |InitializeForTesting|. + void SampleCpuUsageForTesting(); + + // Gets a list of processes and their information. + const std::vector<ProcessUsageData> GetProcessUsages(); + + private: + // A sample of a process's information at one moment of time. + struct ProcessSample { + ProcessSample(); + ProcessSample(const ProcessSample& p); + ~ProcessSample(); + + // Basic information about the process. + ProcessData process_data; + + // Total CPU time consumed between the point when |ProcessDataCollector| was + // initialized and the point at which this sample was collected. + int64_t total_cpu_time_jiffies = 0; + + // Total CPU time consumed by this process between the point when the + // |ProcessDataCollector| was initialized and the point at which this sample + // was collected. + int64_t proc_cpu_time_jiffies = 0; + + // Whether this sample represents a valid process, i.e. whether it should be + // displayed on the chrome://power page. This is also used to indicate + // whether a sample of a process was successfully completed, so a process + // that was terminated while being sampled can be properly dealt with. + // An invalid process is a process that doesn't have a displayable name, + // has an empty cmdline, or was terminated while it was being sampled. This + // is relevant so that ProcessStoredData knows which samples it should + // consider when it accumulates information into its running total. + bool valid = false; + + // The time at which this sample took place. + base::TimeTicks now; + }; + + // Data that gets stored across samples. + struct ProcessStoredData { + ProcessStoredData(); + ProcessStoredData(const ProcessStoredData& p); + ~ProcessStoredData(); + + // Basic information about the process. + ProcessData process_data; + + // The number of samples that were accumulated together at this point in + // time. + int64_t num_samples = 0; + + // The calculated amount of power used at this point in time; this will be + // in [0.0, 1.0]. + double power_usage_fraction = 0; + + // The total CPU usage across |num_samples| intervals. If a1,...,an are the + // average CPU usages across n intervals, this will aggregate those averages + // into a single number depending on which averaging technique is specified + // in |config_|. + double accumulated_cpu_usages = 0; + }; + + using ProcessSampleMap = std::unordered_map<pid_t, ProcessSample>; + using ProcessStoredDataMap = std::unordered_map<pid_t, ProcessStoredData>; + + // Only use a custom configuration while |testing|. + explicit ProcessDataCollector(const Config& config); + + ~ProcessDataCollector(); + + // Initializes |cpu_data_task_runner_| and starts |cpu_data_timer_|. This is + // called from |Initialize| but not from |InitializeForTesting|. + void StartSamplingCpuUsage(); + + // Aggregates information, classifies, and approximates the used battery. This + // function samples the CPU usage from the procfs specified in |config_|, + // updates |prev_samples_| and |curr_samples_|. Then this function will + // aggregate this information and update |curr_summary_|. + void SampleCpuUsage(); + + // Prunes all processes to only those processes that are displayable; in + // other words, it discards all processes that have empty cmdlines or names + // from all the processes that are read from procfs. This is a helper function + // that is meant to be used in |ComputeSampleAsync| and returns a partially + // filled-out map of PID's to |ProcessSample|s with the process name and the + // process cmdline filled out. This function is static and private because it + // needs access to |ProcessSample| and |Config|. + static ProcessSampleMap GetValidProcesses(const Config& config); + + // Samples the CPU usage of all valid processes from |GetValidProcesses|. + // This is a helper function meant to be used in |ComputeSampleAsync|. This + // function returns a completely filled out set of current samples. It + // performs the actual sampling and reads everything from procfs. Should be + // run on the |cpu_data_task_runner_|. + static ProcessSampleMap ComputeSample(ProcessSampleMap curr_samples, + const Config& config); + + // Given a set of samples from a previous time step and a set of samples from + // the current timestep, this function computes the aggregated information. + static ProcessStoredDataMap ComputeSummary( + Config::AveragingTechnique averaging_technique, + const ProcessSampleMap& prev_samples, + const ProcessSampleMap& curr_samples, + const ProcessStoredDataMap& curr_summary); + + // Represents the previous and current samples as well as the summary + // information for those set of samples. + using SamplesAndSummaryInfo = + std::tuple<ProcessSampleMap, ProcessSampleMap, ProcessStoredDataMap>; + + // This function is called from |SampleCpuUsage| and performs the sampling of + // CPU usage. This function must be static; using a base::WeakPtrFactory to + // pass in a this won't work here, since |ComputeSampleAsync| is running on + // the |cpu_data_task_runner_|. Additionally, it must be a member because it + // uses |Config|, which is private. This function returns the updated + // previous and current samples after sampling from procfs. + static SamplesAndSummaryInfo ComputeSampleAsync( + Config config, + ProcessSampleMap prev_samples, + ProcessSampleMap curr_samples, + ProcessStoredDataMap curr_summary); + + // This function saves the CPU usage information previously aggregated into + // |curr_summary_|; this should only be run on the UI thread in order to + // prevent data races. This function is the reply callback function of the + // |cpu_data_task_runner_| after all the I/O operations are done. This + // function updates the |curr_samples_| and |prev_samples_| to their new + // values after sampling from procfs and also calculates the new battery usage + // approximation from the current samples and the previously aggregated + // samples. + void SaveSamplesOnUIThread( + const SamplesAndSummaryInfo& samples_and_summary_info); + + // The timer that's used to periodically sample CPU usage; this timer will + // call |SampleCpuUsage| at intervals of |Config::Config::sample_delay|. + base::RepeatingTimer cpu_data_timer_; + + // Used to sequentially run the task associated with |cpu_data_timer_| on a + // non-UI thread. This is necessary because the sampling does IO. Also, + // repeating tasks shouldn't be run concurrently. + scoped_refptr<base::SequencedTaskRunner> cpu_data_task_runner_; + + // Samples before and after an interval. Used to approximate the average CPU + // usage over this interval. + ProcessSampleMap prev_samples_; + ProcessSampleMap curr_samples_; + + // The summary information across all intervals samples so far for all + // currently active processes. + ProcessStoredDataMap curr_summary_; + + // Paths and parameters to configure the class. + Config config_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<ProcessDataCollector> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ProcessDataCollector); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_POWER_PROCESS_DATA_COLLECTOR_H_
diff --git a/chrome/browser/chromeos/power/process_data_collector_unittest.cc b/chrome/browser/chromeos/power/process_data_collector_unittest.cc new file mode 100644 index 0000000..5f674d7 --- /dev/null +++ b/chrome/browser/chromeos/power/process_data_collector_unittest.cc
@@ -0,0 +1,562 @@ +// Copyright 2018 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 <sys/types.h> + +#include <array> +#include <cstring> +#include <fstream> +#include <memory> +#include <numeric> +#include <string> +#include <unordered_map> +#include <unordered_set> +#include <vector> + +#include "base/bind.h" +#include "base/files/file.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/format_macros.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/strings/string_piece.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/task_scheduler/post_task.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/platform_thread.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "chrome/browser/chromeos/power/process_data_collector.h" +#include "content/public/browser/browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +// The tests are structured as follows; this is taken from |RunTest|: +// 1. First, there's a call to |SetUpProcfs| which sets up the dummy procfs that +// will be used during testing. +// 2. |TimeStepExpectedResult| structures are constructed, which contain the +// expected results for each time step that the |ProcessDataCollector| is +// sampled. +// 3. |RunTest| is called which calls |ValidateProcessList| to check whether the +// |TimeStepExpectedResult|s for each time step match; after a time step is +// checked, the procfs of the next time step is set up with |SetUpProcfs|. + +namespace chromeos { + +namespace { + +// The path component for a custom stat; this corresponds to a real /proc/stat. +constexpr char kCustomCpuTimeFile[] = "stat"; + +// The path component for a custom file where Android's init PID lives. +constexpr char kCustomAndroidInitPidFile[] = "container.pid"; + +// The number of jiffies per iteration of the simulated procfs. +constexpr uint64_t kJiffiesPerIteration = 100; + +using ProcessData = ProcessDataCollector::ProcessData; +using Config = ProcessDataCollector::Config; +using PowerConsumerType = ProcessDataCollector::PowerConsumerType; +using ProcessUsageData = ProcessDataCollector::ProcessUsageData; + +// A process information container containing the minimum amount of information +// for testing. +struct ProcessTestData { + ProcessTestData() = default; + ProcessTestData(ProcessData process_data, + pid_t ppid, + double cpu_usage_fraction) + : process_data(process_data), + ppid(ppid), + cpu_usage_fraction(cpu_usage_fraction) {} + + // Information about the process. + ProcessData process_data; + + // The PPID of the process. + pid_t ppid = 0; + + // The fraction of CPU used by this process. + double cpu_usage_fraction = 0.; +}; + +// The total number of entries that will be in the simulated /proc/%u/stat. +constexpr uint64_t kProcStatNumEntries = 52; + +// The number of faked data entries in the following data. Update this number as +// necessary. +constexpr uint64_t kNumProcStatFakedEntries = 16; + +// The number of zeroed entries. +constexpr uint64_t kNumProcStatZeroedEntries = + kProcStatNumEntries - kNumProcStatFakedEntries; + +// Generates a suitable string for to be written in a /proc/%u/stat. +std::string GenerateProcPidStatString(const std::string& name, + pid_t ppid, + uint64_t user_time, + uint64_t kernel_time) { + return base::StringPrintf( + "0 (%s) S %" PRId32 " %s %" PRIu64 " %" PRIu64 " ", name.c_str(), + ppid, + // Pad 9 0's between the PPID and the user and + // kernel times. + base::JoinString(std::vector<std::string>(9, "0"), " ").c_str(), + user_time, kernel_time) + + base::JoinString( + std::vector<std::string>(kNumProcStatZeroedEntries, "0"), " ") + + "\n"; +} + +// Writes |data| to |file_path| and checks that the write succeeded. +void WriteStringToFile(const base::FilePath& file_path, + const std::string& data) { + ASSERT_EQ(base::WriteFile(file_path, data.c_str(), data.length()), + static_cast<int>(data.length())); +} + +// Sets up a procfs-like directory with certain processes and stat files +// corresponding to a certain time step within a custom directory. For example, +// say a process has a fixed CPU usage of 0.03 or 4% of the total CPU usage. +// Then the number of jiffies used would be this; +// timestep: 3 +// timestep: 6 +// timestep: 9 +// ... +// When written /proc/%u/stat, this total will be split into the user and kernel +// times. Additionally, each time step, the CPU itself uses 100 jiffies. So for +// the first time step this process will 3 / 100 = 0.03 of the total CPU, and +// the second time step, (3 + 3) / (100 + 100) = 6 / 200 = 0.03. Thus the +// fraction of CPU usage will remain fixed. +void SetUpProcfs(const base::FilePath& root_dir, + const std::vector<ProcessTestData>& processes, + int iteration) { + for (const auto& process_info : processes) { + uint64_t jiffies = (iteration + 1) * kJiffiesPerIteration * + process_info.cpu_usage_fraction; + std::string proc_stat_file_contents = GenerateProcPidStatString( + process_info.process_data.name, process_info.ppid, + // Above, the number of jiffies used in total by the process was + // calculated for this time step. If the number of jiffies is odd, + // division by 2 won't work since it'll be one short, so compensate for + // that. + jiffies / 2 /* user time */, (jiffies + 1) / 2 /* kernel time*/); + std::string proc_comm_file_contents = process_info.process_data.name + "\n"; + + ASSERT_TRUE(base::CreateDirectory(base::FilePath(base::StringPrintf( + "%s/%u", root_dir.value().c_str(), process_info.process_data.pid)))); + WriteStringToFile(base::FilePath(base::StringPrintf( + // Corresponds to a real /proc/%u/cmdline. + "%s/%u/cmdline", root_dir.value().c_str(), + process_info.process_data.pid)), + process_info.process_data.cmdline); + WriteStringToFile(base::FilePath(base::StringPrintf( + // Correponds to a real /proc/%u/stat. + "%s/%u/stat", root_dir.value().c_str(), + process_info.process_data.pid)), + proc_stat_file_contents); + WriteStringToFile(base::FilePath(base::StringPrintf( + // Corresponds to a real /proc/%u/comm. + "%s/%u/comm", root_dir.value().c_str(), + process_info.process_data.pid)), + proc_comm_file_contents); + } + + // Let each time step use |kJiffiesPerIteration| jiffies. + std::string stat_file_contents = + "cpu " + std::to_string(kJiffiesPerIteration * (iteration + 1)) + + // Pad some zeros. + " 0 0 0 0 0 0 0\n"; + + WriteStringToFile(base::FilePath(base::StringPrintf( + "%s/%s", root_dir.value().c_str(), kCustomCpuTimeFile)), + stat_file_contents); + + // The hard coded PID used for Android's init process. + std::string android_init_pid_contents = "10\n"; + WriteStringToFile( + base::FilePath(base::StringPrintf("%s/%s", root_dir.value().c_str(), + kCustomAndroidInitPidFile)), + android_init_pid_contents); +} + +// Represents the expected results for a single time step. +struct TimeStepExpectedResult { + TimeStepExpectedResult() = default; + TimeStepExpectedResult( + const std::unordered_set<pid_t>& expected_pids, + const std::unordered_map<pid_t, double>& expected_avgs, + const std::unordered_map<pid_t, ProcessTestData>& pid_to_proc) + : expected_pids(expected_pids), + expected_averages(expected_avgs), + pid_infos(pid_to_proc) {} + + // The expected PID's to be returned; these should only be valid PIDs. + std::unordered_set<pid_t> expected_pids; + + // The expected averages. + std::unordered_map<pid_t, double> expected_averages; + + // Maps PID's to |ProcessTestData| structs. This is used to valid process + // types and process names. + std::unordered_map<pid_t, ProcessTestData> pid_infos; +}; + +// Normalizes the average CPU usages of processes with |valid_pids| such +// that their sum is 1.0. +void NormalizeProcessAverages( + const std::unordered_set<pid_t>& valid_pids, + std::unordered_map<pid_t, double>* process_averages) { + double total = 0.; + for (const auto& pid : valid_pids) + total += (*process_averages)[pid]; + if (total == 0.) + return; // No more work needs to be done. + for (auto& average : *process_averages) + average.second /= total; +} + +} // namespace + +class ProcessDataCollectorTest : public testing::Test { + public: + ProcessDataCollectorTest() { + InitializeStats(); + + // Create a temporary directory for the simulated procfs. + CHECK(proc_dir_.CreateUniqueTempDir()); + } + + ~ProcessDataCollectorTest() override { ProcessDataCollector::Shutdown(); } + + protected: + // Faked process data. + // The process information will be truncated a lot, since most of the data in + // a typical /proc/%u directory is unnecessary for testing. + + // Below are processes of different kinds: Crostini, ARC, Base and System, + // both of which are system processes but Base corresponds to the root of the + // process hierarchy, and Chrome (corresponding to separate types of processes + // in |ProcessDataCollector::ProcessType|. These all contain trimmed down + // information from various files in procfs. + const std::vector<ProcessTestData> kAllProcessTestData = { + ProcessTestData(ProcessData(0, "", "", PowerConsumerType::SYSTEM), + 0 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData( + ProcessData(1, "init", "/usr/bin/init\n", PowerConsumerType::SYSTEM), + 0 /* ppid */, + 0.01 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(2, + "chrome", + "/opt/google/chrome/chrome\n", + PowerConsumerType::CHROME), + 1 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData( + ProcessData( + 3, + "chrome", + "/opt/google/chrome/chrome --other --commandline --options\n", + PowerConsumerType::CHROME), + 1 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData( + ProcessData(4, + "chrome", + "/opt/google/chrome/chrome --even --more --commandline" + "--options\n", + PowerConsumerType::CHROME), + 2 /* ppid */, + 0.03 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(5, + "chrome", + "/opt/google/chrome/chrome\n", + PowerConsumerType::CHROME), + 1 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(6, + "vm_concierge", + "/usr/bin/vm_concierge\n", + PowerConsumerType::CROSTINI), + 1 /* ppid */, + 0.1 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(7, + "some_container", + "some_container\n", + PowerConsumerType::CROSTINI), + 6 /* ppid */, + 0.03 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(8, + "nested_under_some_container", + "nested_under_some_container\n", + PowerConsumerType::CROSTINI), + 7 /* ppid */, + 0.04 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(9, + "other_container", + "other_container\n", + PowerConsumerType::CROSTINI), + 6 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData( + ProcessData(10, "init", "/init --android\n", PowerConsumerType::ARC), + 1 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(11, + "org.google.chromium.1", + "org.google.chromium.1\n", + PowerConsumerType::ARC), + 10 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(12, + "org.google.chromium.2", + "org.google.chromium.2\n", + PowerConsumerType::ARC), + 11 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(13, + "org.google.chromium.3", + "org.google.chromium.3\n", + PowerConsumerType::ARC), + 10 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData( + ProcessData(14, "powerd", "powerd\n", PowerConsumerType::SYSTEM), + 1 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(15, + "powerd_loggerd", + "powerd_loggerd\n", + PowerConsumerType::SYSTEM), + 14 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData( + ProcessData(16, "garcon", "garcon\n", PowerConsumerType::SYSTEM), + 1 /* ppid */, + 0.02 /* cpu_usage_fraction */), + ProcessTestData(ProcessData(17, "", "\n", PowerConsumerType::SYSTEM), + 1 /* ppid */, + 0.02 /* cpu_usage_fraction */)}; + + // Helper function to generate a |Config| struct that will be passed to the + // |ProcessDataCollector| to initialize it with an appropriate testing + // configuration. + Config CreateConfig(const base::FilePath& proc_path, + Config::AveragingTechnique technique); + + // A helper function that wraps |ValidateProcessList| for a convenient + // testing setup. + void RunTest(const std::vector<TimeStepExpectedResult>& expected_results, + Config::AveragingTechnique averaging_technique); + + // Contains the PIDs of all the valid processes from |kProcessTestData|. + std::unordered_set<pid_t> all_valid_pids_; + + // Represents the root of the simulated procfs. + base::ScopedTempDir proc_dir_; + + // Makes sure that the |base::AssertBlockingAllowed| calls from + // |ProcessDataCollector| work. + base::test::ScopedTaskEnvironment scoped_task_environment_; + + // The current time step, used in testing functions. + int timestep_ = 0; + + // Maps each PID to its respective |ProcessTestData| struct. + std::unordered_map<pid_t, ProcessTestData> pid_infos_; + + // Contains the normalized averages of all the valid processes. + std::unordered_map<pid_t, double> all_process_averages_; + + private: + // Initialize relevant statistics like process averages. + void InitializeStats(); + + // Checks whether all of the processes that are returned from + // |ProcessDataCollector::GetProcessUsages| are valid. + void CheckValidProcesses(const std::vector<ProcessUsageData>& process_list, + const std::unordered_set<pid_t>& expected_pids); + + // Checks whether all given processes match their expected results. This + // should only be called after |CheckValidProcesses|. + void CheckProcessUsages(const std::vector<ProcessUsageData>& process_list, + const TimeStepExpectedResult& timestep_info); + + // Makes sure that the calculated results match the expected results. + // |timestep_info| represents the expected results for a single time step. + // |process_list| contains the calculated results from the + // |ProcessDataCollector| which needs to compared against |timestep_info|. + void ValidateProcessList(const TimeStepExpectedResult& timestep_info, + const std::vector<ProcessUsageData>& process_list); + + DISALLOW_COPY_AND_ASSIGN(ProcessDataCollectorTest); +}; + +ProcessDataCollector::Config ProcessDataCollectorTest::CreateConfig( + const base::FilePath& proc_path, + ProcessDataCollector::Config::AveragingTechnique technique) { + std::string cmdline_fmt = proc_path.value() + "/%u/cmdline"; + std::string stat_fmt = proc_path.value() + "/%u/stat"; + std::string comm_fmt = proc_path.value() + "/%u/comm"; + // The delay is arbitrary and shouldn't actually be used since the + // |ProcessDataCollector| will be initialized with |InitializeForTesting|. + return ProcessDataCollector::Config( + proc_path, proc_path.AppendASCII(kCustomCpuTimeFile), + proc_path.AppendASCII(kCustomAndroidInitPidFile), cmdline_fmt, stat_fmt, + comm_fmt, base::TimeDelta(), technique); +} + +void ProcessDataCollectorTest::RunTest( + const std::vector<TimeStepExpectedResult>& expected_results, + Config::AveragingTechnique averaging_technique) { + // Initialize the testing environment with all processes for the 0th time + // step. + SetUpProcfs(proc_dir_.GetPath(), kAllProcessTestData, 0); + + ProcessDataCollector::Config config = + CreateConfig(proc_dir_.GetPath(), averaging_technique); + + ProcessDataCollector::InitializeForTesting(config); + ProcessDataCollector* process_data_collector = ProcessDataCollector::Get(); + + for (timestep_ = 0; timestep_ < static_cast<int>(expected_results.size()); + timestep_++) { + // Sample from the simulated procfs. + process_data_collector->SampleCpuUsageForTesting(); + + // Set up the next iteration of the procfs. + SetUpProcfs(proc_dir_.GetPath(), kAllProcessTestData, timestep_ + 1); + + // If the 0th |timestep_| was just sampled, then there are no results to + // check. Just go to the next iteration. At least 2 samples from the + // simulated procfs need to be gathered before an average can be calculated. + if (timestep_ == 0) + continue; + + const TimeStepExpectedResult& expected_result = expected_results[timestep_]; + const std::vector<ProcessDataCollector::ProcessUsageData>& process_list = + process_data_collector->GetProcessUsages(); + ValidateProcessList(expected_result, process_list); + } +} + +void ProcessDataCollectorTest::InitializeStats() { + // Map each PID to a |ProcessTestData| and gather the PIDs of all the valid + // processes. + for (const auto& process_info : kAllProcessTestData) { + pid_infos_[process_info.process_data.pid] = process_info; + if (!process_info.process_data.name.empty() && + !process_info.process_data.cmdline.empty()) { + all_valid_pids_.insert(process_info.process_data.pid); + } + } + + // Make sure that the given fractions sum to less than 100% of the total CPU + // time. + double total_cpu_usage = 0.; + for (const auto& process_info : kAllProcessTestData) + total_cpu_usage += process_info.cpu_usage_fraction; + ASSERT_LE(total_cpu_usage, 1.); + + // The average CPU usage for the first time step for each process. + for (const auto& process_info : kAllProcessTestData) + all_process_averages_[process_info.process_data.pid] = + process_info.cpu_usage_fraction; + + // Normalize the averages for the first time step for a normal averaging + // technique. + NormalizeProcessAverages(all_valid_pids_, &all_process_averages_); +} + +void ProcessDataCollectorTest::CheckValidProcesses( + const std::vector<ProcessUsageData>& process_list, + const std::unordered_set<pid_t>& expected_pids) { + std::unordered_set<pid_t> calculated_pids; + for (const auto& process : process_list) + calculated_pids.insert(process.process_data.pid); + ASSERT_EQ(expected_pids, calculated_pids); +} + +void ProcessDataCollectorTest::CheckProcessUsages( + const std::vector<ProcessUsageData>& process_list, + const TimeStepExpectedResult& timestep_info) { + for (const auto& process : process_list) { + pid_t pid = process.process_data.pid; + + EXPECT_DOUBLE_EQ(process.power_usage_fraction, + timestep_info.expected_averages.at(pid)) + << "For PID " << pid + << " the expected and calculated average CPU " + "usages didn't match."; + + const ProcessTestData& process_info = timestep_info.pid_infos.at(pid); + + // Make sure that the |ProcessDataCollector::PowerConsumerType|s match. + EXPECT_EQ(process.process_data.type, process_info.process_data.type) + << "For PID " << pid + << " the expected and calculated process types " + "didn't match."; + + // Make sure the process name matches what is expected. + EXPECT_EQ(process_info.process_data.name, process.process_data.name) + << "For PID " << pid + << " the expected and calculated process names " + "didn't match."; + } +} + +void ProcessDataCollectorTest::ValidateProcessList( + const TimeStepExpectedResult& timestep_info, + const std::vector<ProcessUsageData>& process_list) { + CheckValidProcesses(process_list, timestep_info.expected_pids); + + CheckProcessUsages(process_list, timestep_info); +} + +// Averages for one time step and checks normal averages. +TEST_F(ProcessDataCollectorTest, AveragingBasic) { + std::vector<TimeStepExpectedResult> expected_results; + // For each time step, insert a dummy set of expected results for the 0th time + // step, since there will be no expected results. + expected_results.push_back(TimeStepExpectedResult()); + expected_results.push_back(TimeStepExpectedResult( + all_valid_pids_, all_process_averages_, pid_infos_)); + RunTest(expected_results, Config::AveragingTechnique::AVERAGE); +} + +// Averages for one time steps and checks exponential averages. +TEST_F(ProcessDataCollectorTest, ExpAveragingBasic) { + std::vector<TimeStepExpectedResult> expected_results; + expected_results.push_back(TimeStepExpectedResult()); + expected_results.push_back(TimeStepExpectedResult( + all_valid_pids_, all_process_averages_, pid_infos_)); + RunTest(expected_results, Config::AveragingTechnique::EXPONENTIAL); +} + +// Averages for two time steps and checks both normal averages. +TEST_F(ProcessDataCollectorTest, AveragingMultistep) { + std::vector<TimeStepExpectedResult> expected_results; + expected_results.push_back(TimeStepExpectedResult()); + expected_results.push_back(TimeStepExpectedResult( + all_valid_pids_, all_process_averages_, pid_infos_)); + expected_results.push_back(TimeStepExpectedResult( + all_valid_pids_, all_process_averages_, pid_infos_)); + RunTest(expected_results, Config::AveragingTechnique::AVERAGE); +} + +// Averages for two time steps and checks exponential moving averages. +TEST_F(ProcessDataCollectorTest, ExpAveragingMultistep) { + std::vector<TimeStepExpectedResult> expected_results; + expected_results.push_back(TimeStepExpectedResult()); + expected_results.push_back(TimeStepExpectedResult( + all_valid_pids_, all_process_averages_, pid_infos_)); + expected_results.push_back(TimeStepExpectedResult( + all_valid_pids_, all_process_averages_, pid_infos_)); + RunTest(expected_results, Config::AveragingTechnique::EXPONENTIAL); +} + +} // namespace chromeos
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc index f73ed9b6..6022dfc 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -24,6 +24,7 @@ #include "chrome/test/base/testing_profile_manager.h" #include "chromeos/attestation/mock_attestation_flow.h" #include "chromeos/cryptohome/async_method_caller.h" +#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/cryptohome/mock_async_method_caller.h" #include "chromeos/dbus/attestation_constants.h" #include "chromeos/dbus/dbus_method_call_status.h" @@ -511,7 +512,8 @@ TEST_F(EPKChallengeUserKeyTest, KeyExists) { cryptohome_client_.SetTpmAttestationUserCertificate( - cryptohome::Identification(AccountId::FromUserEmail(kUserEmail)), + cryptohome::CreateAccountIdentifierFromAccountId( + AccountId::FromUserEmail(kUserEmail)), "attest-ent-user", std::string()); // GetCertificate must not be called if the key exists. EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _)).Times(0);
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc index 8435980e..ba1f604 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
@@ -224,7 +224,8 @@ } // Attestation is available, see if the key we need already exists. cryptohome_client_->TpmAttestationDoesKeyExist( - context.key_type, cryptohome::Identification(context.account_id), + context.key_type, + cryptohome::CreateAccountIdentifierFromAccountId(context.account_id), context.key_name, base::BindOnce(&EPKPChallengeKeyBase::DoesKeyExistCallback, base::Unretained(this), context));
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc index fb7241aa..2ff23cd 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -485,7 +485,8 @@ TEST_F(EPKPChallengeUserKeyTest, KeyExists) { cryptohome_client_.SetTpmAttestationUserCertificate( - cryptohome::Identification(AccountId::FromUserEmail(kUserEmail)), + cryptohome::CreateAccountIdentifierFromAccountId( + AccountId::FromUserEmail(kUserEmail)), "attest-ent-user", std::string()); // GetCertificate must not be called if the key exists. EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc index 475010d..afb0efe 100644 --- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc +++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -220,10 +220,9 @@ // TODO(pneubeck): Remove the following hack, once the NetworkingPrivateAPI // uses the ProfileHelper to obtain the userhash crbug/238623. - const cryptohome::Identification login_user = - cryptohome::Identification::FromString( - user_manager::CanonicalizeUserID(command_line->GetSwitchValueNative( - chromeos::switches::kLoginUser))); + cryptohome::AccountIdentifier login_user; + login_user.set_account_id(user_manager::CanonicalizeUserID( + command_line->GetSwitchValueNative(chromeos::switches::kLoginUser))); const std::string sanitized_user = CryptohomeClient::GetStubSanitizedUsername(login_user); command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, @@ -236,7 +235,7 @@ CHECK(user); std::string userhash; DBusThreadManager::Get()->GetCryptohomeClient()->GetSanitizedUsername( - cryptohome::Identification(user->GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId()), base::BindOnce( [](std::string* out, base::Optional<std::string> result) { CHECK(result.has_value());
diff --git a/chrome/browser/extensions/extension_keybinding_apitest.cc b/chrome/browser/extensions/extension_keybinding_apitest.cc index 451b92b..ebea6bc2 100644 --- a/chrome/browser/extensions/extension_keybinding_apitest.cc +++ b/chrome/browser/extensions/extension_keybinding_apitest.cc
@@ -28,6 +28,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/javascript_test_observer.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/test_event_router_observer.h" #include "extensions/common/extension.h" #include "extensions/common/feature_switch.h" #include "extensions/common/manifest_constants.h" @@ -187,6 +188,9 @@ #endif // OS_CHROMEOS }; +class IncognitoCommandsApiTest : public CommandsApiTest, + public testing::WithParamInterface<bool> {}; + // Test the basic functionality of the Keybinding API: // - That pressing the shortcut keys should perform actions (activate the // browser action or send an event). @@ -1054,4 +1058,48 @@ ASSERT_TRUE(RunComponentExtensionTest("keybinding/component")) << message_; } +// Test Keybinding in incognito mode. +IN_PROC_BROWSER_TEST_P(IncognitoCommandsApiTest, IncognitoMode) { + ASSERT_TRUE(embedded_test_server()->Start()); + + bool is_incognito_enabled = GetParam(); + + if (is_incognito_enabled) + ASSERT_TRUE(RunExtensionTestIncognito("keybinding/basics")) << message_; + else + ASSERT_TRUE(RunExtensionTest("keybinding/basics")) << message_; + + // Open incognito window and navigate to test page. + Browser* incognito_browser = OpenURLOffTheRecord( + browser()->profile(), + embedded_test_server()->GetURL("/extensions/test_file.html")); + + ui_test_utils::NavigateToURL( + incognito_browser, + embedded_test_server()->GetURL("/extensions/test_file.txt")); + + TestEventRouterObserver test_observer( + EventRouter::Get(incognito_browser->profile())); + + // Activate the browser action shortcut (Ctrl+Shift+F). + ASSERT_TRUE(ui_test_utils::SendKeyPressSync(incognito_browser, ui::VKEY_F, + true, true, false, false)); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(is_incognito_enabled, + base::ContainsKey(test_observer.dispatched_events(), + "browserAction.onClicked")); + + test_observer.ClearEvents(); + + // Activate the command shortcut (Ctrl+Shift+Y). + ASSERT_TRUE(ui_test_utils::SendKeyPressSync(incognito_browser, ui::VKEY_Y, + true, true, false, false)); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(is_incognito_enabled, + base::ContainsKey(test_observer.dispatched_events(), + "commands.onCommand")); +} + +INSTANTIATE_TEST_CASE_P(, IncognitoCommandsApiTest, testing::Bool()); + } // namespace extensions
diff --git a/chrome/browser/media/cast_mirroring_service_host.cc b/chrome/browser/media/cast_mirroring_service_host.cc index 230704b..06b3a2b 100644 --- a/chrome/browser/media/cast_mirroring_service_host.cc +++ b/chrome/browser/media/cast_mirroring_service_host.cc
@@ -9,11 +9,14 @@ #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "base/task_scheduler/post_task.h" +#include "chrome/browser/media/cast_remoting_connector.h" #include "chrome/browser/net/default_network_context_params.h" #include "components/mirroring/browser/single_client_video_capture_host.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/network_service_instance.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/video_capture_device_launcher.h" +#include "content/public/browser/web_contents.h" #include "mojo/public/cpp/bindings/strong_binding.h" using content::BrowserThread; @@ -56,6 +59,14 @@ return content::MediaStreamType::MEDIA_NO_SERVICE; } +// Get the content::WebContents associated with the given |id|. +content::WebContents* GetContents( + const content::WebContentsMediaCaptureId& id) { + return content::WebContents::FromRenderFrameHost( + content::RenderFrameHost::FromID(id.render_process_id, + id.main_render_frame_id)); +} + } // namespace CastMirroringServiceHost::CastMirroringServiceHost( @@ -106,7 +117,14 @@ void CastMirroringServiceHost::ConnectToRemotingSource( media::mojom::RemoterPtr remoter, media::mojom::RemotingSourceRequest request) { - // TODO(xjz): Implementation will be added in a later CL. + if (source_media_id_.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) { + content::WebContents* source_contents = + GetContents(source_media_id_.web_contents_id); + if (source_contents) { + CastRemotingConnector::Get(source_contents) + ->ConnectWithMediaRemoter(std::move(remoter), std::move(request)); + } + } } } // namespace mirroring
diff --git a/chrome/browser/media/cast_remoting_connector.cc b/chrome/browser/media/cast_remoting_connector.cc index 3682fdf0..aa524f5d4 100644 --- a/chrome/browser/media/cast_remoting_connector.cc +++ b/chrome/browser/media/cast_remoting_connector.cc
@@ -195,9 +195,9 @@ tab_id_(tab_id), permission_request_callback_(std::move(permission_request_callback)), active_bridge_(nullptr), + deprecated_binding_(this), binding_(this), weak_factory_(this) { - VLOG(2) << "Register CastRemotingConnector for tab_id = " << tab_id_; DCHECK(permission_request_callback_); media_router_->RegisterRemotingSource(tab_id_, this); } @@ -218,17 +218,16 @@ void CastRemotingConnector::ConnectToService( media::mojom::MirrorServiceRemotingSourceRequest source_request, media::mojom::MirrorServiceRemoterPtr remoter) { - DCHECK(!binding_.is_bound()); - DCHECK(!remoter_); + DCHECK(!deprecated_binding_); + DCHECK(!deprecated_remoter_); DCHECK(remoter); DCHECK_CURRENTLY_ON(BrowserThread::UI); - VLOG(2) << __func__; - binding_.Bind(std::move(source_request)); - binding_.set_connection_error_handler(base::BindOnce( + deprecated_binding_.Bind(std::move(source_request)); + deprecated_binding_.set_connection_error_handler(base::BindOnce( &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this))); - remoter_ = std::move(remoter); - remoter_.set_connection_error_handler(base::BindOnce( + deprecated_remoter_ = std::move(remoter); + deprecated_remoter_.set_connection_error_handler(base::BindOnce( &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this))); } @@ -236,11 +235,31 @@ remoting_allowed_.reset(); } +void CastRemotingConnector::ConnectWithMediaRemoter( + media::mojom::RemoterPtr remoter, + media::mojom::RemotingSourceRequest request) { + DCHECK(!binding_); + DCHECK(!remoter_); + DCHECK(remoter); + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DVLOG(2) << __func__; + + binding_.Bind(std::move(request)); + binding_.set_connection_error_handler(base::BindOnce( + &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this))); + remoter_ = std::move(remoter); + remoter_.set_connection_error_handler(base::BindOnce( + &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this))); +} + void CastRemotingConnector::OnMirrorServiceStopped() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - VLOG(2) << __func__; + DVLOG(2) << __func__; - if (binding_.is_bound()) + if (deprecated_binding_) + deprecated_binding_.Close(); + deprecated_remoter_.reset(); + if (binding_) binding_.Close(); remoter_.reset(); @@ -263,7 +282,8 @@ DCHECK(bridges_.find(bridge) == bridges_.end()); bridges_.insert(bridge); - if (remoter_ && !active_bridge_ && remoting_allowed_.value_or(true)) + if ((deprecated_remoter_ || remoter_) && !active_bridge_ && + remoting_allowed_.value_or(true)) bridge->OnSinkAvailable(sink_metadata_); } @@ -280,17 +300,16 @@ void CastRemotingConnector::StartRemoting(RemotingBridge* bridge) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(bridges_.find(bridge) != bridges_.end()); - VLOG(2) << __func__; // Refuse to start if there is no remoting route available, or if remoting is // already active. - if (!remoter_) { - VLOG(2) << "Remoting start failed: No mirror service connected."; + if (!deprecated_remoter_ && !remoter_) { + DVLOG(2) << "Remoting start failed: No mirror service connected."; bridge->OnStartFailed(RemotingStartFailReason::SERVICE_NOT_CONNECTED); return; } if (active_bridge_) { - VLOG(2) << "Remoting start failed: Cannot start multiple."; + DVLOG(2) << "Remoting start failed: Cannot start multiple."; bridge->OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE); return; } @@ -334,11 +353,17 @@ return; if (remoting_allowed_.value()) { - remoter_->Start(); + if (deprecated_remoter_) { + DCHECK(!remoter_); + deprecated_remoter_->Start(); - // Assume the remoting session is always started successfully. If any - // failure occurs, OnError() will be called. - active_bridge_->OnStarted(); + // Assume the remoting session is always started successfully. If any + // failure occurs, OnError() will be called. + active_bridge_->OnStarted(); + } else { + DCHECK(remoter_); + remoter_->Start(); + } } else { // TODO(xjz): Add an extra reason for this failure. active_bridge_->OnStartFailed(RemotingStartFailReason::ROUTE_TERMINATED); @@ -354,11 +379,10 @@ media::mojom::RemotingDataStreamSenderRequest audio_sender_request, media::mojom::RemotingDataStreamSenderRequest video_sender_request) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - VLOG(2) << __func__; // Refuse to start if there is no remoting route available, or if remoting is // not active for this |bridge|. - if (!remoter_ || active_bridge_ != bridge) + if ((!deprecated_remoter_ && !remoter_) || active_bridge_ != bridge) return; // Also, if neither audio nor video pipe was provided, or if a request for a // RemotingDataStreamSender was not provided for a data pipe, error-out early. @@ -369,14 +393,22 @@ return; } - const bool want_audio = audio_sender_request.is_pending(); - const bool want_video = video_sender_request.is_pending(); - remoter_->StartDataStreams( - want_audio, want_video, - base::BindOnce(&CastRemotingConnector::OnDataStreamsStarted, - weak_factory_.GetWeakPtr(), std::move(audio_pipe), - std::move(video_pipe), std::move(audio_sender_request), - std::move(video_sender_request))); + if (deprecated_remoter_) { + DCHECK(!remoter_); + const bool want_audio = audio_sender_request.is_pending(); + const bool want_video = video_sender_request.is_pending(); + deprecated_remoter_->StartDataStreams( + want_audio, want_video, + base::BindOnce(&CastRemotingConnector::OnDataStreamsStarted, + weak_factory_.GetWeakPtr(), std::move(audio_pipe), + std::move(video_pipe), std::move(audio_sender_request), + std::move(video_sender_request))); + } else { + DCHECK(remoter_); + remoter_->StartDataStreams(std::move(audio_pipe), std::move(video_pipe), + std::move(audio_sender_request), + std::move(video_sender_request)); + } } void CastRemotingConnector::OnDataStreamsStarted( @@ -387,12 +419,11 @@ int32_t audio_stream_id, int32_t video_stream_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(remoter_); - VLOG(2) << __func__ << ": audio_stream_id = " << audio_stream_id - << " video_stream_id = " << video_stream_id; + DCHECK(deprecated_remoter_); + DCHECK(!remoter_); if (!active_bridge_) { - remoter_->Stop(media::mojom::RemotingStopReason::SOURCE_GONE); + deprecated_remoter_->Stop(media::mojom::RemotingStopReason::SOURCE_GONE); return; } @@ -414,7 +445,6 @@ RemotingStopReason reason, bool is_initiated_by_source) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - VLOG(2) << __func__ << ": reason = " << reason; if (active_bridge_ != bridge) return; @@ -446,15 +476,20 @@ bridge->OnSinkGone(); // Note: At this point, all sources should think the sink is gone. - if (remoter_) + if (deprecated_remoter_) { + DCHECK(!remoter_); + deprecated_remoter_->Stop(reason); + } + if (remoter_) { + DCHECK(!deprecated_remoter_); remoter_->Stop(reason); + } bridge->OnStopped(reason); } void CastRemotingConnector::OnStopped(RemotingStopReason reason) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - VLOG(2) << __func__ << ": reason = " << reason; if (active_bridge_) { // This call will reset |sink_metadata_| and notify the source that sink is @@ -475,9 +510,15 @@ // During an active remoting session, simply pass all binary messages through // to the sink. - if (!remoter_ || active_bridge_ != bridge) + if ((!deprecated_remoter_ && !remoter_) || active_bridge_ != bridge) return; - remoter_->SendMessageToSink(message); + if (deprecated_remoter_) { + DCHECK(!remoter_); + deprecated_remoter_->SendMessageToSink(message); + } else { + DCHECK(!deprecated_remoter_); + remoter_->SendMessageToSink(message); + } } void CastRemotingConnector::OnMessageFromSink( @@ -493,8 +534,8 @@ void CastRemotingConnector::EstimateTransmissionCapacity( media::mojom::Remoter::EstimateTransmissionCapacityCallback callback) { - if (remoter_) - remoter_->EstimateTransmissionCapacity(std::move(callback)); + if (deprecated_remoter_) + deprecated_remoter_->EstimateTransmissionCapacity(std::move(callback)); else std::move(callback).Run(0); } @@ -502,7 +543,7 @@ void CastRemotingConnector::OnSinkAvailable( media::mojom::RemotingSinkMetadataPtr metadata) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - VLOG(2) << __func__; + DVLOG(2) << __func__; // The receiver's metadata should be unchanged during an active remoting // session. @@ -525,15 +566,39 @@ void CastRemotingConnector::OnError() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - VLOG(2) << __func__; if (active_bridge_) StopRemoting(active_bridge_, RemotingStopReason::UNEXPECTED_FAILURE, false); } +void CastRemotingConnector::OnSinkGone() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DVLOG(2) << __func__; + sink_metadata_ = RemotingSinkMetadata(); + if (active_bridge_) + StopRemoting(active_bridge_, RemotingStopReason::SERVICE_GONE, false); + for (RemotingBridge* notifyee : bridges_) + notifyee->OnSinkGone(); +} + +void CastRemotingConnector::OnStarted() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(remoter_); + if (active_bridge_) { + active_bridge_->OnStarted(); + } else { + remoter_->Stop(RemotingStopReason::SOURCE_GONE); + } +} + +void CastRemotingConnector::OnStartFailed(RemotingStartFailReason reason) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (active_bridge_) + active_bridge_->OnStartFailed(reason); +} + void CastRemotingConnector::OnDataSendFailed() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - VLOG(2) << __func__; // A single data send failure is treated as fatal to an active remoting // session.
diff --git a/chrome/browser/media/cast_remoting_connector.h b/chrome/browser/media/cast_remoting_connector.h index 1878779..33597f2 100644 --- a/chrome/browser/media/cast_remoting_connector.h +++ b/chrome/browser/media/cast_remoting_connector.h
@@ -72,8 +72,12 @@ // Please see the unit tests in cast_remoting_connector_unittest.cc as a // reference for how CastRemotingConnector and a MediaRemoter interact to // start/execute/stop remoting sessions. +// +// TODO(xjz): Remove media::mojom::MirrorServiceRemotingSource interface and +// implementation after Mirroring Service is launched. class CastRemotingConnector : public base::SupportsUserData::Data, - public media::mojom::MirrorServiceRemotingSource { + public media::mojom::MirrorServiceRemotingSource, + public media::mojom::RemotingSource { public: ~CastRemotingConnector() final; @@ -98,6 +102,10 @@ // Called at the start of mirroring to reset the permission. void ResetRemotingPermission(); + // Used by Mirroring Service to connect the media remoter with this source. + void ConnectWithMediaRemoter(media::mojom::RemoterPtr remoter, + media::mojom::RemotingSourceRequest request); + private: // Allow unit tests access to the private constructor and CreateBridge() // method, since unit tests don't have a complete browser (i.e., with a @@ -135,12 +143,20 @@ void DeregisterBridge(RemotingBridge* bridge, media::mojom::RemotingStopReason reason); - // media::mojom::MirrorServiceRemotingSource implementations. + // media::mojom::MirrorServiceRemotingSource implementation. + // media::mojom::RemotingSource implementation. void OnSinkAvailable(media::mojom::RemotingSinkMetadataPtr metadata) override; void OnMessageFromSink(const std::vector<uint8_t>& message) override; void OnStopped(media::mojom::RemotingStopReason reason) override; + + // media::mojom::MirrorServiceRemotingSource implementation. void OnError() override; + // media::mojom::RemotingSource implementation. + void OnSinkGone() override; + void OnStarted() override; + void OnStartFailed(media::mojom::RemotingStartFailReason reason) override; + // These methods are called by RemotingBridge to forward media::mojom::Remoter // calls from a source through to this connector. They ensure that only one // source is allowed to be in a remoting session at a time, and that no source @@ -201,8 +217,12 @@ // pointing to the RemotingBridge being used to communicate with the source. RemotingBridge* active_bridge_; - mojo::Binding<media::mojom::MirrorServiceRemotingSource> binding_; - media::mojom::MirrorServiceRemoterPtr remoter_; + // TODO(xjz): Remove these after Mirroring Service is launched. + mojo::Binding<media::mojom::MirrorServiceRemotingSource> deprecated_binding_; + media::mojom::MirrorServiceRemoterPtr deprecated_remoter_; + + mojo::Binding<media::mojom::RemotingSource> binding_; + media::mojom::RemoterPtr remoter_; // Permission is checked the first time remoting requested to start for each // casting session.
diff --git a/chrome/browser/media/cast_remoting_connector_unittest.cc b/chrome/browser/media/cast_remoting_connector_unittest.cc index b129cc2..35fedbb 100644 --- a/chrome/browser/media/cast_remoting_connector_unittest.cc +++ b/chrome/browser/media/cast_remoting_connector_unittest.cc
@@ -122,43 +122,104 @@ mojo::Binding<media::mojom::RemotingSource> binding_; }; -class MockMediaRemoter : public media::mojom::MirrorServiceRemoter { +// TODO(xjz): Remove the media::mojom::MirrorServiceRemoter implementation after +// Mirroring Service is launched. +class MockMediaRemoter final : public media::mojom::MirrorServiceRemoter, + public media::mojom::Remoter { public: - explicit MockMediaRemoter(FakeMediaRouter* media_router) : binding_(this) { + // TODO(xjz): Remove this ctor after Mirroring Service is launched. + explicit MockMediaRemoter(FakeMediaRouter* media_router) + : deprecated_binding_(this), binding_(this) { MirrorServiceRemoterPtr remoter; - binding_.Bind(mojo::MakeRequest(&remoter)); + deprecated_binding_.Bind(mojo::MakeRequest(&remoter)); media_router->OnMediaRemoterCreated(kRemotingTabId, std::move(remoter), - mojo::MakeRequest(&source_)); + mojo::MakeRequest(&deprecated_source_)); } + + explicit MockMediaRemoter(CastRemotingConnector* connector) + : deprecated_binding_(this), binding_(this) { + RemoterPtr remoter; + binding_.Bind(mojo::MakeRequest(&remoter)); + connector->ConnectWithMediaRemoter(std::move(remoter), + mojo::MakeRequest(&source_)); + } + ~MockMediaRemoter() final {} - void OnSinkAvailable() { source_->OnSinkAvailable(GetDefaultSinkMetadata()); } - - void EstimateTransmissionCapacity( - media::mojom::Remoter::EstimateTransmissionCapacityCallback callback) - final { - std::move(callback).Run(0); + void OnSinkAvailable() { + if (deprecated_source_) { + EXPECT_FALSE(source_); + deprecated_source_->OnSinkAvailable(GetDefaultSinkMetadata()); + } else { + EXPECT_TRUE(source_); + source_->OnSinkAvailable(GetDefaultSinkMetadata()); + } } void SendMessageToSource(const std::vector<uint8_t>& message) { - source_->OnMessageFromSink(message); + if (deprecated_source_) { + EXPECT_FALSE(source_); + deprecated_source_->OnMessageFromSink(message); + } else { + EXPECT_TRUE(source_); + source_->OnMessageFromSink(message); + } } - void OnStopped(RemotingStopReason reason) { source_->OnStopped(reason); } + void OnStopped(RemotingStopReason reason) { + if (deprecated_source_) { + EXPECT_FALSE(source_); + deprecated_source_->OnStopped(reason); + } else { + EXPECT_TRUE(source_); + source_->OnStopped(reason); + } + } - void OnError() { source_->OnError(); } + void OnError() { + if (deprecated_source_) { + EXPECT_FALSE(source_); + deprecated_source_->OnError(); + } else { + EXPECT_TRUE(source_); + source_->OnStopped(RemotingStopReason::UNEXPECTED_FAILURE); + } + } - // media::mojom::MirrorServiceRemoter implementations. + // media::mojom::MirrorServiceRemoter implementation. + // media::mojom::Remoter implementation. + MOCK_METHOD0(RequestStart, void()); + MOCK_METHOD1(Stop, void(RemotingStopReason)); + MOCK_METHOD1(SendMessageToSink, void(const std::vector<uint8_t>&)); + MOCK_METHOD1( + EstimateTransmissionCapacity, + void(media::mojom::Remoter::EstimateTransmissionCapacityCallback)); + void Start() override { + RequestStart(); + if (source_) + source_->OnStarted(); + } + + // media::mojom::MirrorServiceRemoter implementation. void StartDataStreams(bool audio, bool video, StartDataStreamsCallback callback) override {} - MOCK_METHOD0(Start, void()); - MOCK_METHOD1(Stop, void(RemotingStopReason)); - MOCK_METHOD1(SendMessageToSink, void(const std::vector<uint8_t>&)); + + // media::mojom::Remoter implementation. + MOCK_METHOD4( + StartDataStreams, + void(mojo::ScopedDataPipeConsumerHandle audio_pipe, + mojo::ScopedDataPipeConsumerHandle video_pipe, + media::mojom::RemotingDataStreamSenderRequest audio_sender_request, + media::mojom::RemotingDataStreamSenderRequest video_sender_request)); private: - mojo::Binding<media::mojom::MirrorServiceRemoter> binding_; - MirrorServiceRemotingSourcePtr source_; + // TODO(xjz): Remove these after Mirroring Service is launched. + mojo::Binding<media::mojom::MirrorServiceRemoter> deprecated_binding_; + MirrorServiceRemotingSourcePtr deprecated_source_; + + mojo::Binding<media::mojom::Remoter> binding_; + RemotingSourcePtr source_; }; } // namespace @@ -207,10 +268,15 @@ EXPECT_EQ(kRemotingTabId, media_router_.tab_id()); } - FakeMediaRouter media_router_; + CastRemotingConnector* GetConnector() const { return connector_.get(); } + + FakeMediaRouter* GetMediaRouter() const { + return const_cast<FakeMediaRouter*>(&media_router_); + } private: content::TestBrowserThreadBundle browser_thread_bundle_; + FakeMediaRouter media_router_; std::unique_ptr<CastRemotingConnector> connector_; }; @@ -228,7 +294,7 @@ RemoterPtr remoter = CreateRemoter(&source); std::unique_ptr<MockMediaRemoter> media_remoter = - std::make_unique<MockMediaRemoter>(&media_router_); + std::make_unique<MockMediaRemoter>(GetConnector()); EXPECT_CALL(source, OnSinkAvailable(_)).Times(1); media_remoter->OnSinkAvailable(); @@ -247,7 +313,7 @@ RemoterPtr remoter2 = CreateRemoter(&source2); std::unique_ptr<MockMediaRemoter> media_remoter = - std::make_unique<MockMediaRemoter>(&media_router_); + std::make_unique<MockMediaRemoter>(GetConnector()); EXPECT_CALL(source1, OnSinkAvailable(_)).Times(1); EXPECT_CALL(source2, OnSinkAvailable(_)).Times(1); @@ -265,7 +331,7 @@ RemoterPtr remoter = CreateRemoter(source.get()); std::unique_ptr<MockMediaRemoter> media_remoter = - std::make_unique<MockMediaRemoter>(&media_router_); + std::make_unique<MockMediaRemoter>(GetConnector()); EXPECT_CALL(*source, OnSinkAvailable(_)).Times(1); media_remoter->OnSinkAvailable(); @@ -280,7 +346,7 @@ RemoterPtr remoter = CreateRemoter(&source); std::unique_ptr<MockMediaRemoter> media_remoter = - std::make_unique<MockMediaRemoter>(&media_router_); + std::make_unique<MockMediaRemoter>(GetConnector()); EXPECT_CALL(source, OnSinkAvailable(_)).Times(1); media_remoter->OnSinkAvailable(); @@ -308,7 +374,7 @@ RemoterPtr remoter2 = CreateRemoter(&source2); std::unique_ptr<MockMediaRemoter> media_remoter = - std::make_unique<MockMediaRemoter>(&media_router_); + std::make_unique<MockMediaRemoter>(GetConnector()); EXPECT_CALL(source1, OnSinkAvailable(_)).Times(1); EXPECT_CALL(source2, OnSinkAvailable(_)).Times(1); @@ -328,7 +394,7 @@ MockRemotingSource source; RemoterPtr remoter = CreateRemoter(&source); std::unique_ptr<MockMediaRemoter> media_remoter = - std::make_unique<MockMediaRemoter>(&media_router_); + std::make_unique<MockMediaRemoter>(GetMediaRouter()); EXPECT_CALL(source, OnStartFailed(RemotingStartFailReason::ROUTE_TERMINATED)) .Times(1); @@ -368,7 +434,7 @@ std::unique_ptr<MockRemotingSource> other_source(new MockRemotingSource()); RemoterPtr other_remoter = CreateRemoter(other_source.get()); std::unique_ptr<MockMediaRemoter> media_remoter = - std::make_unique<MockMediaRemoter>(&media_router_); + std::make_unique<MockMediaRemoter>(GetConnector()); // Throughout this test |other_source| should not participate in the // remoting session, and so these method calls should never occur: @@ -388,7 +454,7 @@ // and |source| is notified that its request was successful. EXPECT_CALL(*source, OnStarted()).Times(1).RetiresOnSaturation(); EXPECT_CALL(*other_source, OnSinkGone()).Times(1).RetiresOnSaturation(); - EXPECT_CALL(*media_remoter, Start()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*media_remoter, RequestStart()).Times(1).RetiresOnSaturation(); remoter->Start(); RunUntilIdle(); @@ -565,3 +631,314 @@ ROUTE_TERMINATES, EXTERNAL_FAILURE, USER_DISABLED)); + +// TODO(xjz): Remove the following tests after Mirroring Service is launched. +TEST_F(CastRemotingConnectorTest, + DeprecatedNotifiesWhenSinkIsAvailableAndThenGone) { + MockRemotingSource source; + RemoterPtr remoter = CreateRemoter(&source); + + std::unique_ptr<MockMediaRemoter> media_remoter = + std::make_unique<MockMediaRemoter>(GetMediaRouter()); + + EXPECT_CALL(source, OnSinkAvailable(_)).Times(1); + media_remoter->OnSinkAvailable(); + RunUntilIdle(); + + EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(1)); + media_remoter.reset(); + RunUntilIdle(); +} + +TEST_F(CastRemotingConnectorTest, + DeprecatedNotifiesMultipleSourcesWhenSinkIsAvailableAndThenGone) { + MockRemotingSource source1; + RemoterPtr remoter1 = CreateRemoter(&source1); + MockRemotingSource source2; + RemoterPtr remoter2 = CreateRemoter(&source2); + + std::unique_ptr<MockMediaRemoter> media_remoter = + std::make_unique<MockMediaRemoter>(GetMediaRouter()); + + EXPECT_CALL(source1, OnSinkAvailable(_)).Times(1); + EXPECT_CALL(source2, OnSinkAvailable(_)).Times(1); + media_remoter->OnSinkAvailable(); + RunUntilIdle(); + + EXPECT_CALL(source1, OnSinkGone()).Times(AtLeast(1)); + EXPECT_CALL(source2, OnSinkGone()).Times(AtLeast(1)); + media_remoter.reset(); + RunUntilIdle(); +} + +TEST_F(CastRemotingConnectorTest, + DeprecatedHandlesTeardownOfRemotingSourceFirst) { + std::unique_ptr<MockRemotingSource> source(new MockRemotingSource); + RemoterPtr remoter = CreateRemoter(source.get()); + + std::unique_ptr<MockMediaRemoter> media_remoter = + std::make_unique<MockMediaRemoter>(GetMediaRouter()); + + EXPECT_CALL(*source, OnSinkAvailable(_)).Times(1); + media_remoter->OnSinkAvailable(); + RunUntilIdle(); + + source.reset(); + RunUntilIdle(); +} + +TEST_F(CastRemotingConnectorTest, DeprecatedHandlesTeardownOfRemoterFirst) { + MockRemotingSource source; + RemoterPtr remoter = CreateRemoter(&source); + + std::unique_ptr<MockMediaRemoter> media_remoter = + std::make_unique<MockMediaRemoter>(GetMediaRouter()); + + EXPECT_CALL(source, OnSinkAvailable(_)).Times(1); + media_remoter->OnSinkAvailable(); + RunUntilIdle(); + + remoter.reset(); + RunUntilIdle(); +} + +TEST_F(CastRemotingConnectorTest, DeprecatedUserDisableRemoting) { + MockRemotingSource source1; + RemoterPtr remoter1 = CreateRemoter(&source1); + MockRemotingSource source2; + RemoterPtr remoter2 = CreateRemoter(&source2); + + std::unique_ptr<MockMediaRemoter> media_remoter = + std::make_unique<MockMediaRemoter>(GetMediaRouter()); + + EXPECT_CALL(source1, OnSinkAvailable(_)).Times(1); + EXPECT_CALL(source2, OnSinkAvailable(_)).Times(1); + media_remoter->OnSinkAvailable(); + RunUntilIdle(); + + // All sources will get notified that sink is gone when user explicitly + // disabled media remoting. + EXPECT_CALL(source1, OnSinkGone()).Times(AtLeast(1)); + EXPECT_CALL(source2, OnSinkGone()).Times(AtLeast(1)); + DisableRemoting(); + RunUntilIdle(); +} + +class DeprecatedCastRemotingConnectorFullSessionTest + : public CastRemotingConnectorTest, + public ::testing::WithParamInterface<HowItEnds> { + public: + HowItEnds how_it_ends() const { return GetParam(); } +}; + +// Performs a full run-through of starting and stopping remoting, with +// communications between source and sink established at the correct times, and +// tests that end-to-end behavior is correct depending on what caused the +// remoting session to end. +TEST_P(DeprecatedCastRemotingConnectorFullSessionTest, + GoesThroughAllTheMotions) { + std::unique_ptr<MockRemotingSource> source(new MockRemotingSource()); + RemoterPtr remoter = CreateRemoter(source.get()); + std::unique_ptr<MockRemotingSource> other_source(new MockRemotingSource()); + RemoterPtr other_remoter = CreateRemoter(other_source.get()); + std::unique_ptr<MockMediaRemoter> media_remoter = + std::make_unique<MockMediaRemoter>(GetMediaRouter()); + + // Throughout this test |other_source| should not participate in the + // remoting session, and so these method calls should never occur: + EXPECT_CALL(*other_source, OnStarted()).Times(0); + EXPECT_CALL(*other_source, OnStopped(_)).Times(0); + EXPECT_CALL(*other_source, OnMessageFromSink(_)).Times(0); + + // Both sinks should be notified when the Cast Provider tells the connector + // a remoting sink is available. + EXPECT_CALL(*source, OnSinkAvailable(_)).Times(1); + EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(1); + media_remoter->OnSinkAvailable(); + RunUntilIdle(); + + // When |source| starts a remoting session, |other_source| is notified the + // sink is gone, the Cast Provider is notified that remoting has started, + // and |source| is notified that its request was successful. + EXPECT_CALL(*source, OnStarted()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*other_source, OnSinkGone()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*media_remoter, RequestStart()).Times(1).RetiresOnSaturation(); + remoter->Start(); + RunUntilIdle(); + + // The |source| should now be able to send binary messages to the sink. + // |other_source| should not! + const std::vector<uint8_t> message_to_sink = {3, 1, 4, 1, 5, 9}; + EXPECT_CALL(*media_remoter, SendMessageToSink(message_to_sink)) + .Times(1) + .RetiresOnSaturation(); + remoter->SendMessageToSink(message_to_sink); + const std::vector<uint8_t> ignored_message_to_sink = {1, 2, 3}; + EXPECT_CALL(*media_remoter, SendMessageToSink(ignored_message_to_sink)) + .Times(0); + other_remoter->SendMessageToSink(ignored_message_to_sink); + RunUntilIdle(); + + // The sink should also be able to send binary messages to the |source|. + const std::vector<uint8_t> message_to_source = {2, 7, 1, 8, 2, 8}; + EXPECT_CALL(*source, OnMessageFromSink(message_to_source)) + .Times(1) + .RetiresOnSaturation(); + media_remoter->SendMessageToSource(message_to_source); + RunUntilIdle(); + + // The |other_source| should not be allowed to start a remoting session. + EXPECT_CALL(*other_source, + OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE)) + .Times(1) + .RetiresOnSaturation(); + other_remoter->Start(); + RunUntilIdle(); + + // What happens from here depends on how this remoting session will end... + switch (how_it_ends()) { + case SOURCE_TERMINATES: { + // When the |source| stops the remoting session, the Cast Provider is + // notified the session has stopped, and the |source| receives both an + // OnStopped() and an OnSinkGone() notification. + const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK; + EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*source, OnStopped(reason)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*media_remoter, Stop(reason)).Times(1).RetiresOnSaturation(); + remoter->Stop(reason); + RunUntilIdle(); + + // Since remoting is stopped, any further messaging in either direction + // must be dropped. + const std::vector<uint8_t> message_to_sink = {1, 6, 1, 8, 0, 3}; + const std::vector<uint8_t> message_to_source = {6, 2, 8, 3, 1, 8}; + EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); + EXPECT_CALL(*media_remoter, SendMessageToSink(_)).Times(0); + remoter->SendMessageToSink(message_to_sink); + media_remoter->SendMessageToSource(message_to_source); + RunUntilIdle(); + + // When the sink is ready, the Cast Provider sends a notification to the + // connector. The connector will notify both sources that a sink is once + // again available. + EXPECT_CALL(*source, OnSinkAvailable(_)).Times(1); + EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(1); + media_remoter->OnSinkAvailable(); + RunUntilIdle(); + + // When the sink is no longer available, the Cast Provider notifies the + // connector, and both sources are then notified the sink is gone. + EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); + EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); + media_remoter.reset(); + RunUntilIdle(); + + break; + } + + case MOJO_PIPE_CLOSES: + // When the Mojo pipes for |other_source| close, this should not affect + // the current remoting session. + EXPECT_CALL(*media_remoter, Stop(_)).Times(0); + other_source.reset(); + other_remoter.reset(); + RunUntilIdle(); + + // Now, when the Mojo pipes for |source| close, the Cast Provider will be + // notified that the session has stopped. + EXPECT_CALL(*media_remoter, Stop(_)).Times(1).RetiresOnSaturation(); + source.reset(); + remoter.reset(); + RunUntilIdle(); + + break; + + case ROUTE_TERMINATES: + // When the Media Router terminates the route (e.g., because a user + // terminated the route from the UI), the source and sink are immediately + // cut off from one another. + EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); + EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(0)); + // Furthermore, the connector and Cast Provider are also cut off from one + // another and should not be able to exchange messages anymore. Therefore, + // the connector will never try to notify the sources that the sink is + // available again. + EXPECT_CALL(*source, OnSinkAvailable(_)).Times(0); + EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(0); + EXPECT_CALL(*source, OnStopped(RemotingStopReason::SERVICE_GONE)) + .Times(1) + .RetiresOnSaturation(); + media_remoter.reset(); + RunUntilIdle(); + + break; + + case EXTERNAL_FAILURE: { + // When the Cast Provider is cut-off from the sink, it sends a fail + // notification to the connector. The connector, in turn, force-stops the + // remoting session and notifies the |source|. + EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*source, OnStopped(RemotingStopReason::UNEXPECTED_FAILURE)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*media_remoter, Stop(RemotingStopReason::UNEXPECTED_FAILURE)) + .Times(1) + .RetiresOnSaturation(); + media_remoter->OnError(); + RunUntilIdle(); + + // Since remoting is stopped, any further messaging in either direction + // must be dropped. + const std::vector<uint8_t> message_to_sink = {1, 6, 1, 8, 0, 3}; + const std::vector<uint8_t> message_to_source = {6, 2, 8, 3, 1, 8}; + EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); + EXPECT_CALL(*media_remoter, SendMessageToSink(_)).Times(0); + remoter->SendMessageToSink(message_to_sink); + media_remoter->SendMessageToSource(message_to_source); + RunUntilIdle(); + + // When the sink is no longer available, the Cast Provider notifies the + // connector, and both sources are then notified the sink is gone. + EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); + EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); + media_remoter.reset(); + RunUntilIdle(); + + break; + } + + case USER_DISABLED: { + // When user explicitly disabled remoting, the active remoting session + // will be stopped. + EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); + EXPECT_CALL(*other_source, OnSinkGone()).Times(0); + EXPECT_CALL(*source, OnSinkAvailable(_)).Times(0); + EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(0); + EXPECT_CALL(*source, OnStopped(RemotingStopReason::USER_DISABLED)) + .Times(1); + EXPECT_CALL(*media_remoter, Stop(RemotingStopReason::USER_DISABLED)) + .Times(1); + DisableRemoting(); + + // All sources will get notified that sink is gone, and no further + // remoting sessions can be initiated before user re-enables remoting. + RunUntilIdle(); + EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); + EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); + EXPECT_CALL(*source, OnSinkAvailable(_)).Times(0); + EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(0); + media_remoter->OnStopped(RemotingStopReason::USER_DISABLED); + RunUntilIdle(); + + break; + } + } +} + +INSTANTIATE_TEST_CASE_P(, + DeprecatedCastRemotingConnectorFullSessionTest, + ::testing::Values(SOURCE_TERMINATES, + MOJO_PIPE_CLOSES, + ROUTE_TERMINATES, + EXTERNAL_FAILURE, + USER_DISABLED));
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc index feb24748..975b291 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -5,7 +5,6 @@ #include "content/public/browser/picture_in_picture_window_controller.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" @@ -19,7 +18,6 @@ #include "content/public/common/content_switches.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" -#include "media/base/media_switches.h" #include "net/dns/mock_host_resolver.h" #if !defined(OS_ANDROID) @@ -31,16 +29,7 @@ class PictureInPictureWindowControllerBrowserTest : public InProcessBrowserTest { public: - PictureInPictureWindowControllerBrowserTest() { - feature_list_.InitWithFeatures( - {media::kPictureInPicture, media::kUseSurfaceLayerForVideo}, {}); - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - InProcessBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitch( - switches::kEnableExperimentalWebPlatformFeatures); - } + PictureInPictureWindowControllerBrowserTest() = default; void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); @@ -106,11 +95,20 @@ private: content::PictureInPictureWindowController* pip_window_controller_ = nullptr; - base::test::ScopedFeatureList feature_list_; DISALLOW_COPY_AND_ASSIGN(PictureInPictureWindowControllerBrowserTest); }; +class ControlPictureInPictureWindowControllerBrowserTest + : public PictureInPictureWindowControllerBrowserTest { + public: + void SetUpCommandLine(base::CommandLine* command_line) override { + PictureInPictureWindowControllerBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitch( + switches::kEnableExperimentalWebPlatformFeatures); + } +}; + // Checks the creation of the window controller, as well as basic window // creation and visibility. IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest, @@ -213,7 +211,7 @@ // Tests that when a custom control is clicked on a Picture-in-Picture window // an event is sent to the caller. -IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest, +IN_PROC_BROWSER_TEST_F(ControlPictureInPictureWindowControllerBrowserTest, PictureInPictureControlEventFired) { GURL test_page_url = ui_test_utils::GetTestUrl( base::FilePath(base::FilePath::kCurrentDirectory),
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc index 136e926..6d4ce1d4 100644 --- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc +++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -286,7 +286,7 @@ &user_policy_key_dir)); std::string sanitized_username = chromeos::CryptohomeClient::GetStubSanitizedUsername( - cryptohome::Identification( + cryptohome::CreateAccountIdentifierFromAccountId( AccountId::FromUserEmail(GetTestUser()))); user_policy_key_file_ = user_policy_key_dir.AppendASCII(sanitized_username) .AppendASCII("policy.pub");
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 4334513..f9e86900 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -306,7 +306,7 @@ prefs::kPasswordProtectionChangePasswordURL, base::Value::Type::STRING}, { key::kSafeSitesFilterBehavior, - prefs::kSafeSitesFilterBehavior, + policy_prefs::kSafeSitesFilterBehavior, base::Value::Type::INTEGER}, #if defined(OS_POSIX) { key::kNtlmV2Enabled,
diff --git a/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chrome/browser/prefs/pref_service_incognito_whitelist.cc index 370834b0..b514e64 100644 --- a/chrome/browser/prefs/pref_service_incognito_whitelist.cc +++ b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -22,7 +22,6 @@ #include "components/network_time/network_time_pref_names.h" #include "components/omnibox/browser/omnibox_pref_names.h" #include "components/onc/onc_pref_names.h" -#include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/proxy_config/proxy_config_pref_names.h" #include "components/proxy_config/proxy_prefs.h" #include "components/rappor/rappor_pref_names.h" @@ -231,7 +230,6 @@ #endif prefs::kForceGoogleSafeSearch, prefs::kForceYouTubeRestrict, prefs::kForceSessionSync, prefs::kAllowedDomainsForApps, - prefs::kSafeSitesFilterBehavior, #if defined(OS_LINUX) && !defined(OS_CHROMEOS) prefs::kUsesSystemTheme, #endif @@ -925,31 +923,6 @@ onc::prefs::kDeviceOpenNetworkConfiguration, onc::prefs::kOpenNetworkConfiguration, - // components/password_manager/core/common/password_manager_pref_names.h - password_manager::prefs::kCredentialsEnableAutosignin, - password_manager::prefs::kCredentialsEnableService, - -#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX) - password_manager::prefs::kLocalProfileId, -#endif - -#if defined(OS_WIN) - password_manager::prefs::kOsPasswordBlank, - password_manager::prefs::kOsPasswordLastChanged, -#endif - -#if defined(OS_MACOSX) - password_manager::prefs::kKeychainMigrationStatus, -#endif - - password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, - password_manager::prefs::kWasSignInPasswordPromoClicked, - password_manager::prefs::kNumberSignInPasswordPromoShown, - password_manager::prefs::kSyncPasswordHash, - password_manager::prefs::kSyncPasswordLengthAndHashSalt, - password_manager::prefs::kBlacklistedCredentialsStripped, - password_manager::prefs::kPasswordHashDataList, - // components/proxy_config/proxy_config_pref_names.h // proxy_config::prefs::kProxy, proxy_config::prefs::kUseSharedProxies,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc index 8f18c86..2dc7b56 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -1215,9 +1215,6 @@ IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ContextMenuForVideoNotInPictureInPicture) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(media::kPictureInPicture); - content::ContextMenuParams params; params.media_type = blink::WebContextMenuData::kMediaTypeVideo; params.media_flags |= blink::WebContextMenuData::kMediaCanPictureInPicture; @@ -1233,9 +1230,6 @@ IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ContextMenuForVideoInPictureInPicture) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(media::kPictureInPicture); - content::ContextMenuParams params; params.media_type = blink::WebContextMenuData::kMediaTypeVideo; params.media_flags |= blink::WebContextMenuData::kMediaCanPictureInPicture;
diff --git a/chrome/browser/resources/chromeos/arc_support/images/ic_checkmark.svg b/chrome/browser/resources/chromeos/arc_support/images/ic_checkmark.svg index e8bd0fb..5552518 100644 --- a/chrome/browser/resources/chromeos/arc_support/images/ic_checkmark.svg +++ b/chrome/browser/resources/chromeos/arc_support/images/ic_checkmark.svg
@@ -1,5 +1,16 @@ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> - <g fill="none" fill-rule="evenodd"> + <defs> + <filter id="ic_check_circle-1x-a" width="154.2%" height="154.2%" x="-27.1%" y="-22.9%" filterUnits="objectBoundingBox"> + <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/> + <feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="2"/> + <feColorMatrix in="shadowBlurOuter1" result="shadowMatrixOuter1" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.34 0"/> + <feMerge> + <feMergeNode in="shadowMatrixOuter1"/> + <feMergeNode in="SourceGraphic"/> + </feMerge> + </filter> + </defs> + <g fill="none" fill-rule="evenodd" filter="url(#ic_check_circle-1x-a)"> <polygon points="0 0 24 0 24 24 0 24"/> <path fill="#1A73E8" d="M12,2 C6.48,2 2,6.48 2,12 C2,17.52 6.48,22 12,22 C17.52,22 22,17.52 22,12 C22,6.48 17.52,2 12,2 L12,2 Z"/> <polygon fill="#FFF" points="10 17 5 12.202 6.41 10.848 10 14.284 17.59 7 19 8.363"/>
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.css b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.css index 20f437d..78406965 100644 --- a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.css +++ b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.css
@@ -9,12 +9,30 @@ } body { - margin: 12px 0 0 2px; + margin: 0; padding: 0; } +#recommend-apps-container { + max-height: 300px; + overflow: auto; + padding: 12px 64px 0 64px; +} + +.shadow { + height: 10px; + margin-top: -10px; +} + +#scroll-top.shadow { + box-shadow: 0 5px 6px -3px rgba(33, 33, 36, 0.06); +} + +#scroll-bottom.shadow { + box-shadow: inset 0 -5px 6px -3px rgba(33, 33, 36, 0.06); +} + #recommend-apps-container .item { - cursor: pointer; float: left; position: relative; } @@ -31,6 +49,10 @@ margin-bottom: 22px; } +#recommend-apps-container .item:nth-last-child(-n+3) { + margin-bottom: 5px; +} + #recommend-apps-container .item .image-picker { background: url(images/ic_checkmark.svg) no-repeat; display: none; @@ -48,9 +70,42 @@ #recommend-apps-container .item .chip { border-radius: 4px; - box-shadow: 1px 1px 4px rgba(60, 64, 67, 0.3), 1px 2px 4px 1px rgba(60, 64, 67, 0.15); + box-shadow: + 1px 1px 4px rgba(60, 64, 67, 0.30), + 1px 2px 4px 1px rgba(60, 64, 67, 0.15); height: 60px; + overflow: hidden; + position: relative; width: 192px; + --x: 0; + --y: 0; +} + +@keyframes ripple { + 30% { + transform: scale(7); + } + 100% { + opacity: 0; + } +} + +#recommend-apps-container .item .chip .ripple { + animation: ripple 1s forwards; + background: rgba(32, 33, 36, 0.14); + border-radius: 50%; + height: 100px; + left: calc(var(--x) * 1px); + position: absolute; + top: calc(var(--y) * 1px); + transform: translate(-50%, -50%); + width: 100px; +} + +#recommend-apps-container .item .chip:active { + box-shadow: + 0 1px 2px 0 rgba(60, 64, 67, 0.30), + 0 3px 6px 2px rgba(60, 64, 67, 0.15); } img.app-icon {
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.html b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.html index 9efeb8c7..b8ad55c8 100644 --- a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.html +++ b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.html
@@ -4,6 +4,8 @@ <link rel="stylesheet" type="text/css" href="recommend_app_list_view.css"> </head> <body> + <div id="scroll-top"></div> <div id="recommend-apps-container"></div> + <div id="scroll-bottom"></div> </body> </html>
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js index a36cb9b..376e0e60 100644 --- a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js +++ b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js
@@ -11,7 +11,6 @@ item.classList.add('item'); item.classList.add('checked'); item.setAttribute('data-packagename', appPackageName); - item.onclick = toggleCheckStatus; var imagePicker = doc.createElement('div'); imagePicker.classList.add('image-picker'); @@ -19,6 +18,9 @@ var chip = doc.createElement('div'); chip.classList.add('chip'); + chip.addEventListener('mousedown', addRippleCircle); + chip.addEventListener('mouseup', toggleCheckStatus); + chip.addEventListener('animationend', removeRippleCircle); item.appendChild(chip); var img = doc.createElement('img'); @@ -35,10 +37,32 @@ recommendAppsContainer.appendChild(item); } +// Add a layer on top of the chip to create the ripple effect. +function addRippleCircle(e) { + let chip = e.currentTarget; + let item = chip.parentNode; + let offsetX = e.pageX - item.offsetLeft; + let offsetY = e.pageY - item.offsetTop; + chip.style.setProperty('--x', offsetX); + chip.style.setProperty('--y', offsetY); + chip.innerHTML += '<div class="ripple"></div>'; +} + +// After the animation ends, remove the ripple layer. +function removeRippleCircle(e) { + let chip = e.currentTarget; + let rippleLayers = chip.querySelectorAll('.ripple'); + for (let rippleLayer of rippleLayers) { + if (rippleLayer.className === 'ripple') { + rippleLayer.remove(); + } + } +} + // Toggle the check status of an app. If an app is selected, add the "checked" // class so that the checkmark is visible. Otherwise, remove the checked class. function toggleCheckStatus(e) { - var item = e.currentTarget; + var item = e.currentTarget.parentNode; item.classList.toggle('checked'); } @@ -49,4 +73,20 @@ selectedPackages.push(checkedItem.dataset.packagename); } return selectedPackages; -} \ No newline at end of file +} + +// Add the scrolling shadow effect. +(function() { +const shadowThreshold = 5; +var doc = document; +doc.getElementById('recommend-apps-container').onscroll = function() { + doc.getElementById('scroll-top') + .classList[this.scrollTop > shadowThreshold ? 'add' : 'remove']('shadow'); + doc.getElementById('scroll-bottom') + .classList + [this.scrollHeight - this.clientHeight - this.scrollTop < + shadowThreshold ? + 'remove' : + 'add']('shadow'); +}; +})(); \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/images/welcome_illustration_1x.png b/chrome/browser/resources/chromeos/login/images/welcome_illustration_1x.png new file mode 100644 index 0000000..31342a6b --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/welcome_illustration_1x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/images/welcome_illustration_2x.png b/chrome/browser/resources/chromeos/login/images/welcome_illustration_2x.png new file mode 100644 index 0000000..bbdbccf3b --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/welcome_illustration_2x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_1x.png b/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_1x.png new file mode 100644 index 0000000..7f50829f --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_1x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_2x.png b/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_2x.png new file mode 100644 index 0000000..fc281935 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_2x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_portraight_1x.png b/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_portraight_1x.png new file mode 100644 index 0000000..c1558bb3 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_portraight_1x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_portraight_2x.png b/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_portraight_2x.png new file mode 100644 index 0000000..6c651a9 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/welcome_illustration_tablet_mode_portraight_2x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js index ab8a912..876d61e 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome.js +++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -94,10 +94,6 @@ if (behavior.onBeforeShow) behavior.onBeforeShow.call(this); }); - - let activeScreen = this.getActiveScreen_(); - if (activeScreen.show) - activeScreen.show(); }, /**
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html index 3770d49..75e2650b1 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html +++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
@@ -66,25 +66,17 @@ <div class="layout vertical end-justified" id="titleContainer"> <h1 id="title">[[i18nDynamic(locale, 'welcomeScreenGreeting')]]</h1> </div> - <div class="welcome-illustration"> - <if expr="chromeos and _google_chrome"> - <video muted hidden oobe_devices="laptop" - oobe_orientations="portrait,landscape" oobe_types="intro" - src="../../../internal/resources/chromeos/animations/oobe-welcome/welcome_laptop_chrome_intro.mp4"> - </video> - <video muted loop hidden oobe_devices="laptop" - oobe_orientations="portrait,landscape" oobe_types="loop" - src="../../../internal/resources/chromeos/animations/oobe-welcome/welcome_laptop_chrome_loop.mp4"> - </video> - <video muted hidden oobe_devices="tablet" - oobe_orientations="portrait,landscape" oobe_types="intro" - src="../../../internal/resources/chromeos/animations/oobe-welcome/welcome_tablet_chrome_intro.mp4"> - </video> - <video muted loop hidden oobe_devices="tablet" - oobe_orientations="portrait,landscape" oobe_types="loop" - src="../../../internal/resources/chromeos/animations/oobe-welcome/welcome_tablet_chrome_loop.mp4"> - </video> - </if> + <div class="welcome-illustration" hidden="[[isInTabletMode]]"> + <img srcset="images/welcome_illustration_1x.png 1x, + images/welcome_illustration_2x.png 2x"> + </div> + <div class="welcome-illustration" hidden="[[!isInTabletMode]]"> + <img hidden="[[!isInPortraitMode]]" + srcset="images/welcome_illustration_tablet_mode_portraight_1x.png 1x, + images/welcome_illustration_tablet_mode_portraight_2x.png 2x"> + <img hidden="[[isInPortraitMode]]" + srcset="images/welcome_illustration_tablet_mode_1x.png 1x, + images/welcome_illustration_tablet_mode_2x.png 2x"> </div> <div hidden="[[!debuggingLinkVisible]]"> <a href="#" on-tap="onDebuggingLinkClicked_">
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js index db75975..60a3b14 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js +++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js
@@ -3,9 +3,9 @@ // found in the LICENSE file. { - let LONG_TOUCH_TIME_MS = 1000; + var LONG_TOUCH_TIME_MS = 1000; - function TitleLongTouchDetector(element, callback) { + function LongTouchDetector(element, callback) { this.callback_ = callback; element.addEventListener('touchstart', this.onTouchStart_.bind(this)); @@ -17,7 +17,7 @@ element.addEventListener('mouseleave', this.killTimer_.bind(this)); } - TitleLongTouchDetector.prototype = { + LongTouchDetector.prototype = { /** * This is timeout ID used to kill window timeout that fires "detected" * callback if touch event was cancelled. @@ -57,196 +57,6 @@ }, }; - const VIDEO_DEVICE = { - LAPTOP: 'laptop', - TABLET: 'tablet', - }; - - const VIDEO_ORIENTATION = { - PORTRAIT: 'portrait', - LANDSCAPE: 'landscape', - }; - - const VIDEO_TYPE = { - INTRO: 'intro', - LOOP: 'loop', - }; - - class WelcomeVideoController { - /** - * This calculates key that is used to identify <video> node in internal - * mapping between possible video configurations and actual videos. - * - * @param {VIDEO_DEVICE} device Allowed device type. - * @param {VIDEO_ORIENTATION} orientation Allowed orientation. - * @param {VIDEO_TYPE} type Allowed type. - * @return {String} Returns <video> key to be stored in this.videos. - * @private - */ - calcKey_(device, orientation, type) { - return device + '-' + orientation + '-' + type; - } - - /** - * @param {VIDEO_DEVICE} device Allowed device type. - * @param {VIDEO_ORIENTATION} orientation Allowed orientation. - */ - constructor(device, orientation) { - this.devices = new Set(); - this.orientations = new Set(); - this.types = new Set(); - for (let key in VIDEO_DEVICE) - this.devices.add(VIDEO_DEVICE[key]); - - for (let key in VIDEO_ORIENTATION) - this.orientations.add(VIDEO_ORIENTATION[key]); - - for (let key in VIDEO_TYPE) - this.types.add(VIDEO_TYPE[key]); - - assert(this.devices.has(device)); - assert(this.orientations.has(orientation)); - - this.device = device; - this.orientation = orientation; - this.type = VIDEO_TYPE.INTRO; - - // This is map from 'device-orientation-video_type' to video DOM object. - this.videos = new Map(); - } - - /** - * Returns currently playing video. - * If none are playing, falls back to currently visible one, because - * it might have accidentally stopped because of media error. - * - * @return {Object|null} Returns <video> DOM node. - * @private - */ - getActiveVideo_() { - for (let node of this.videos.values()) { - if (!node.paused) - return node; - } - // Media decode error stops video play. Try 'hidden' instead. - for (let node of this.videos.values()) { - if (!node.hasAttribute('hidden')) - return node; - } - return null; - } - - /** - * @param {Object} video <video> DOM node with valid |oobe_devices|, - * |oobe_orientations| and |oobe_types|. - * |oobe_devices| is a comma-separated list of VIDEO_DEVICE values. - * |oobe_orientations| is a comma-separated list of VIDEO_ORIENTATION - * values. - * |oobe_types| is a comma-separated list of VIDEO_TYPE values. - */ - add(video) { - // Split strings by comma and trim space. - let devices = video.getAttribute('oobe_devices') - .split(',') - .map((str) => str.replace(/\s/g, '')); - let orientations = video.getAttribute('oobe_orientations') - .split(',') - .map((str) => str.replace(/\s/g, '')); - let types = video.getAttribute('oobe_types') - .split(',') - .map((str) => str.replace(/\s/g, '')); - - for (let device of devices) { - assert(this.devices.has(device)); - - for (let orientation of orientations) { - assert(this.orientations.has(orientation)); - - for (let type of types) { - assert(this.types.has(type)); - - let key = this.calcKey_(device, orientation, type); - assert(!this.videos.has(key)); - - this.videos.set(key, video); - - if (type == VIDEO_TYPE.INTRO) - video.addEventListener('ended', (event) => { - event.target.setAttribute('hidden', ''); - this.type = VIDEO_TYPE.LOOP; - this.play(); - }); - } - } - } - } - - /** - * Hides all videos. - * @private - */ - hideAll_() { - for (let node of this.videos.values()) - node.setAttribute('hidden', ''); - } - - /** - * Updates screen configuration, and switches to appropriate video to match - * it. - * - * @param {String} device Allowed device type. - * @param {String} orientation Allowed orientation. - */ - updateConfiguration(device, orientation) { - assert(this.devices.has(device)); - assert(this.orientations.has(orientation)); - - if (device === this.device && orientation === this.orientation) - return; - - this.device = device; - this.orientation = orientation; - let previousVideo = this.getActiveVideo_(); - let nextKey = this.calcKey_(device, orientation, this.type); - let nextVideo = this.videos.get(nextKey); - - // Some video may match more than one key. - if (previousVideo === nextVideo) - return; - - let paused = true; - if (previousVideo) { - paused = previousVideo.paused; - previousVideo.pause(); - } - if (previousVideo && nextVideo) - nextVideo.currentTime = previousVideo.currentTime; - - this.hideAll_(); - if (nextVideo) { - nextVideo.removeAttribute('hidden'); - if (!paused) - nextVideo.play(); - } - } - - /** - * Starts active video. - */ - play() { - if (this.getActiveVideo_()) - return; - - let key = this.calcKey_(this.device, this.orientation, this.type); - let video = this.videos.get(key); - - if (video) { - video.removeAttribute('hidden'); - video.play(); - } - } - } - Polymer({ is: 'oobe-welcome-dialog', @@ -277,45 +87,20 @@ /** * True when in tablet mode. */ - isInTabletMode: { - type: Boolean, - observer: 'updateVideoMode_', - }, + isInTabletMode: Boolean, /** - * True when scree orientation is portrait. + * True when scree orientation is portraight. */ - isInPortraitMode: { - type: Boolean, - observer: 'updateVideoMode_', - } - }, - - getVideoDeviceType_: function() { - return this.isInTabletMode ? VIDEO_DEVICE.TABLET : VIDEO_DEVICE.LAPTOP; - }, - - getVideoOrientationType_: function() { - return this.isInPortraitMode ? VIDEO_ORIENTATION.PORTRAIT : - VIDEO_ORIENTATION.LANDSCAPE; - }, - - updateVideoMode_: function() { - this.welcomeVideoController_.updateConfiguration( - this.getVideoDeviceType_(), this.getVideoOrientationType_()); + isInPortraitMode: Boolean, }, /** - * @private {TitleLongTouchDetector} + * @private {LongTouchDetector} */ titleLongTouchDetector_: null, /** - * @private {WelcomeVideoController} - */ - welcomeVideoController_: null, - - /** * This is stored ID of currently focused element to restore id on returns * to this dialog from Language / Timezone Selection dialogs. */ @@ -356,20 +141,14 @@ }, attached: function() { - this.welcomeVideoController_ = new WelcomeVideoController( - this.getVideoDeviceType_(), this.getVideoOrientationType_()); - let videos = Polymer.dom(this.root).querySelectorAll('video'); - for (let video of videos) - this.welcomeVideoController_.add(video); - - this.titleLongTouchDetector_ = new TitleLongTouchDetector( + this.titleLongTouchDetector_ = new LongTouchDetector( this.$.title, this.onTitleLongTouch_.bind(this)); this.focus(); }, focus: function() { this.onWindowResize(); - let focusedElement = this.$[this.focusedElement_]; + var focusedElement = this.$[this.focusedElement_]; if (focusedElement) focusedElement.focus(); }, @@ -379,7 +158,6 @@ */ show: function() { this.focus(); - this.welcomeVideoController_.play(); }, /**
diff --git a/chrome/browser/resources/chromeos/login/recommend_apps.css b/chrome/browser/resources/chromeos/login/recommend_apps.css index 45348145..1e134a0f 100644 --- a/chrome/browser/resources/chromeos/login/recommend_apps.css +++ b/chrome/browser/resources/chromeos/login/recommend_apps.css
@@ -35,6 +35,7 @@ } #app-list-view-container { - height: 100%; - padding: 0 52px 0 62px; + height: 312px; + margin-top: 8px; + padding: 0; } \ No newline at end of file
diff --git a/chrome/browser/resources/local_ntp/custom_backgrounds.css b/chrome/browser/resources/local_ntp/custom_backgrounds.css index 5633720..c26b9906 100644 --- a/chrome/browser/resources/local_ntp/custom_backgrounds.css +++ b/chrome/browser/resources/local_ntp/custom_backgrounds.css
@@ -102,6 +102,14 @@ margin: 0 16px 0 0; } +.bg-option.bg-option-disabled { + opacity: 0.28; +} + +.bg-option.bg-option-disabled:hover { + background-color: transparent; +} + #edit-bg-google-photos .bg-option-img { background: url(icons/photos.svg) no-repeat center; }
diff --git a/chrome/browser/resources/local_ntp/custom_backgrounds.js b/chrome/browser/resources/local_ntp/custom_backgrounds.js index 51575cf..593f861 100644 --- a/chrome/browser/resources/local_ntp/custom_backgrounds.js +++ b/chrome/browser/resources/local_ntp/custom_backgrounds.js
@@ -35,13 +35,14 @@ CANCEL: 'bg-sel-footer-cancel', CONNECT_GOOGLE_PHOTOS: 'edit-bg-google-photos', CONNECT_GOOGLE_PHOTOS_TEXT: 'edit-bg-google-photos-text', - CUSTOM_LINK_RESTORE_DEFAULT: 'custom-link-restore-default', - CUSTOM_LINK_RESTORE_DEFAULT_TEXT: 'custom-link-restore-default-text', + CUSTOM_LINKS_RESTORE_DEFAULT: 'custom-links-restore-default', + CUSTOM_LINKS_RESTORE_DEFAULT_TEXT: 'custom-links-restore-default-text', DEFAULT_WALLPAPERS: 'edit-bg-default-wallpapers', DEFAULT_WALLPAPERS_TEXT: 'edit-bg-default-wallpapers-text', DONE: 'bg-sel-footer-done', EDIT_BG: 'edit-bg', EDIT_BG_DIALOG: 'edit-bg-dialog', + EDIT_BG_DIVIDER: 'edit-bg-divider', EDIT_BG_GEAR: 'edit-bg-gear', MSG_BOX: 'message-box', MSG_BOX_MSG: 'message-box-message', @@ -76,13 +77,14 @@ DONE_AVAILABLE: 'done-available', FLOAT_UP: 'float-up', HAS_LINK: 'has-link', + HIDE_MSG_BOX: 'message-box-hide', IMAGE_DIALOG: 'is-img-sel', + OPTION_DISABLED: 'bg-option-disabled', // The menu option is disabled. PLUS_ICON: 'plus-icon', MOUSE_NAV: 'using-mouse-nav', SELECTED_BORDER: 'selected-border', SELECTED_CHECK: 'selected-check', SELECTED_CIRCLE: 'selected-circle', - HIDE_MSG_BOX: 'message-box-hide', }; /** @@ -107,6 +109,7 @@ CHROME_BACKGROUNDS: 1, UPLOAD_IMAGE: 2, RESTORE_DEFAULT: 3, + RESTORE_DEFAULT_CUSTOM_LINKS: 4, }; customBackgrounds.CUSTOM_BACKGROUND_OVERLAY = @@ -641,6 +644,7 @@ entries.push($(customBackgrounds.IDS.DEFAULT_WALLPAPERS)); entries.push($(customBackgrounds.IDS.UPLOAD_IMAGE)); entries.push($(customBackgrounds.IDS.RESTORE_DEFAULT)); + entries.push($(customBackgrounds.IDS.RESTORE_DEFAULT_CUSTOM_LINKS)); var idx = current_index; do { @@ -649,7 +653,9 @@ idx = 3; if (idx === 4) idx = 0; - } while (entries[idx].hidden); + } while (entries[idx].hidden || + entries[idx].classList.contains( + customBackgrounds.CLASSES.OPTION_DISABLED)); return entries[idx]; }; @@ -662,8 +668,122 @@ }; /** - * Initialize the custom backgrounds dialogs. Set the text and event handlers - * for the various elements. + * Initialize the settings menu, custom backgrounds dialogs, and custom links + * menu items. Set the text and event handlers for the various elements. + */ +customBackgrounds.init = function() { + let editDialog = $(customBackgrounds.IDS.EDIT_BG_DIALOG); + let menu = $(customBackgrounds.IDS.MENU); + + $(customBackgrounds.IDS.OPTIONS_TITLE).textContent = + configData.translatedStrings.customizeBackground; + + $(customBackgrounds.IDS.EDIT_BG_GEAR) + .setAttribute( + 'aria-label', configData.translatedStrings.customizeThisPage); + + // Edit gear icon interaction events. + let editBackgroundInteraction = function() { + editDialog.showModal(); + }; + $(customBackgrounds.IDS.EDIT_BG).onclick = function(event) { + editDialog.classList.add(customBackgrounds.CLASSES.MOUSE_NAV); + editBackgroundInteraction(); + }; + $(customBackgrounds.IDS.EDIT_BG).onkeyup = function(event) { + if (event.keyCode === customBackgrounds.KEYCODES.ENTER || + event.keyCode === customBackgrounds.KEYCODES.SPACE) { + editDialog.classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); + editBackgroundInteraction(); + // Find the first menu option that is not hidden or disabled. + for (let i = 1; i < editDialog.children.length; i++) { + let option = editDialog.children[i]; + if (!option.hidden && + !option.classList.contains( + customBackgrounds.CLASSES.OPTION_DISABLED)) { + option.focus(); + return; + } + } + } + }; + + // Handle focus state for the gear icon. + $(customBackgrounds.IDS.EDIT_BG).onmousedown = function() { + $(customBackgrounds.IDS.EDIT_BG) + .classList.add(customBackgrounds.CLASSES.MOUSE_NAV); + }; + + // Interactions to close the customization option dialog. + let editDialogInteraction = function() { + editDialog.close(); + }; + editDialog.onclick = function(event) { + if (event.target == editDialog) + editDialogInteraction(); + }; + editDialog.onkeyup = function(event) { + if (event.keyCode === customBackgrounds.KEYCODES.ESC) { + editDialogInteraction(); + } + // If keyboard navigation is attempted, remove mouse-only mode. + else if ( + event.keyCode === customBackgrounds.KEYCODES.TAB || + event.keyCode === customBackgrounds.KEYCODES.LEFT || + event.keyCode === customBackgrounds.KEYCODES.UP || + event.keyCode === customBackgrounds.KEYCODES.RIGHT || + event.keyCode === customBackgrounds.KEYCODES.DOWN) { + editDialog.classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); + } + }; + + if (configData.isCustomLinksEnabled) + customBackgrounds.initCustomLinksItems(); + if (configData.isCustomBackgroundsEnabled) + customBackgrounds.initCustomBackgrounds(); +}; + +/** + * Initialize custom link items in the settings menu dialog. Set the text + * and event handlers for the various elements. + */ +customBackgrounds.initCustomLinksItems = function() { + let editDialog = $(customBackgrounds.IDS.EDIT_BG_DIALOG); + let menu = $(customBackgrounds.IDS.MENU); + + $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT_TEXT).textContent = + configData.translatedStrings.restoreDefaultLinks; + + // Interactions with the "Restore default shortcuts" option. + let customLinksRestoreDefaultInteraction = function() { + editDialog.close(); + window.chrome.embeddedSearch.newTabPage.resetCustomLinks(); + }; + $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT).onclick = + customLinksRestoreDefaultInteraction; + $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT).onkeyup = function( + event) { + if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { + customLinksRestoreDefaultInteraction(event); + } + // Handle arrow key navigation. + else if (event.keyCode === customBackgrounds.KEYCODES.UP) { + customBackgrounds + .getNextOption( + customBackgrounds.MENU_ENTRIES.RESTORE_DEFAULT_CUSTOM_LINKS, -1) + .focus(); + } else if (event.keyCode === customBackgrounds.KEYCODES.DOWN) { + customBackgrounds + .getNextOption( + customBackgrounds.MENU_ENTRIES.RESTORE_DEFAULT_CUSTOM_LINKS, 1) + .focus(); + } + }; +}; + +/** + * Initialize the settings menu and custom backgrounds dialogs. Set the + * text and event handlers for the various elements. */ customBackgrounds.initCustomBackgrounds = function() { var editDialog = $(customBackgrounds.IDS.EDIT_BG_DIALOG); @@ -677,10 +797,6 @@ configData.translatedStrings.uploadImage; $(customBackgrounds.IDS.RESTORE_DEFAULT_TEXT).textContent = configData.translatedStrings.restoreDefaultBackground; - $(customBackgrounds.IDS.CUSTOM_LINK_RESTORE_DEFAULT_TEXT).textContent = - configData.translatedStrings.restoreDefaultLinks; - $(customBackgrounds.IDS.OPTIONS_TITLE).textContent = - configData.translatedStrings.customizeBackground; $(customBackgrounds.IDS.REFRESH_TEXT).textContent = configData.translatedStrings.dailyRefresh; $(customBackgrounds.IDS.DONE).textContent = @@ -706,9 +822,6 @@ .setAttribute('aria-label', configData.translatedStrings.selectionCancel); $(customBackgrounds.IDS.DONE) .setAttribute('aria-label', configData.translatedStrings.selectionDone); - $(customBackgrounds.IDS.EDIT_BG_GEAR) - .setAttribute( - 'aria-label', configData.translatedStrings.customizeThisPage); // Interactions with the "Upload an image" option. var uploadImageInteraction = function(event) { @@ -734,52 +847,6 @@ } }; - // Edit gear icon interaction events. - var editBackgroundInteraction = function(event) { - editDialog.showModal(); - }; - $(customBackgrounds.IDS.EDIT_BG).onclick = function(event) { - editDialog.classList.add(customBackgrounds.CLASSES.MOUSE_NAV); - editBackgroundInteraction(event); - }; - $(customBackgrounds.IDS.EDIT_BG).onkeyup = function(event) { - if (event.keyCode === customBackgrounds.KEYCODES.ENTER || - event.keyCode === customBackgrounds.KEYCODES.SPACE) { - editDialog.classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); - editBackgroundInteraction(event); - $(customBackgrounds.IDS.CONNECT_GOOGLE_PHOTOS).focus(); - } - }; - - // Handle focus state for the gear icon. - $(customBackgrounds.IDS.EDIT_BG).onmousedown = function() { - $(customBackgrounds.IDS.EDIT_BG) - .classList.add(customBackgrounds.CLASSES.MOUSE_NAV); - }; - - // Interactions to close the customization option dialog. - var editDialogInteraction = function(event) { - editDialog.close(); - }; - editDialog.onclick = function(event) { - if (event.target == editDialog) - editDialogInteraction(event); - }; - editDialog.onkeyup = function(event) { - if (event.keyCode === customBackgrounds.KEYCODES.ESC) { - editDialogInteraction(event); - } - - // If keyboard navigation is attempted, remove mouse-only mode. - if (event.keyCode === customBackgrounds.KEYCODES.TAB || - event.keyCode === customBackgrounds.KEYCODES.LEFT || - event.keyCode === customBackgrounds.KEYCODES.UP || - event.keyCode === customBackgrounds.KEYCODES.RIGHT || - event.keyCode === customBackgrounds.KEYCODES.DOWN) { - editDialog.classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); - } - }; - // Interactions with the "Restore default background" option. var restoreDefaultInteraction = function(event) { editDialog.close(); @@ -804,20 +871,6 @@ } }; - // Interactions with the "Restore default shortcuts" option. - var customLinksRestoreDefaultInteraction = function(event) { - editDialog.close(); - window.chrome.embeddedSearch.newTabPage.resetCustomLinks(); - }; - $(customBackgrounds.IDS.CUSTOM_LINK_RESTORE_DEFAULT).onclick = - customLinksRestoreDefaultInteraction; - $(customBackgrounds.IDS.CUSTOM_LINK_RESTORE_DEFAULT).onkeyup = function( - event) { - if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { - customLinksRestoreDefaultInteraction(event); - } - }; - // Interactions with the "Chrome backgrounds" option. var defaultWallpapersInteraction = function(event) { customBackgrounds.loadChromeBackgrounds(); @@ -861,7 +914,7 @@ customBackgrounds.loadGooglePhotosAlbums(); $('ntp-album-loader').onload = function() { if (typeof albums != 'undefined' && !albums_errors.auth_error && - !albums.net_error && !albums.service_error) { + !albums_errors.net_error && !albums_errors.service_error) { editDialog.close(); customBackgrounds.showCollectionSelectionDialog( customBackgrounds.SOURCES.GOOGLE_PHOTOS); @@ -877,10 +930,15 @@ } }; }; - $(customBackgrounds.IDS.CONNECT_GOOGLE_PHOTOS).onclick = - googlePhotosInteraction; + $(customBackgrounds.IDS.CONNECT_GOOGLE_PHOTOS).onclick = function(event) { + $(customBackgrounds.IDS.MENU) + .classList.add(customBackgrounds.CLASSES.MOUSE_NAV); + googlePhotosInteraction(event); + }; $(customBackgrounds.IDS.CONNECT_GOOGLE_PHOTOS).onkeyup = function(event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { + $(customBackgrounds.IDS.MENU) + .classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); googlePhotosInteraction(event); }
diff --git a/chrome/browser/resources/local_ntp/custom_links_edit.js b/chrome/browser/resources/local_ntp/custom_links_edit.js index 10cf1db..ccf299a1 100644 --- a/chrome/browser/resources/local_ntp/custom_links_edit.js +++ b/chrome/browser/resources/local_ntp/custom_links_edit.js
@@ -164,7 +164,7 @@ * Send a message to close the edit dialog, clears the url and title fields, and * resets the button statuses. Called when the edit flow has been completed. */ -function closeDialog(event) { +function closeDialog() { window.parent.postMessage({cmd: 'closeDialog'}, DOMAIN_ORIGIN); $(IDS.FORM).reset(); $(IDS.URL_FIELD_CONTAINER).classList.remove('invalid');
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html index ff88204..5ef8a501 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.html +++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -8,12 +8,10 @@ <link rel="stylesheet" href="chrome-search://local-ntp/local-ntp.css"></link> <link rel="stylesheet" href="chrome-search://local-ntp/voice.css"></link> <link rel="stylesheet" href="chrome-search://local-ntp/custom-backgrounds.css"></link> - <script src="chrome-search://local-ntp/local-ntp.js" - {{LOCAL_NTP_INTEGRITY}}></script> - <script src="chrome-search://local-ntp/voice.js" - {{LOCAL_NTP_VOICE_INTEGRITY}}></script> <script src="chrome-search://local-ntp/custom-backgrounds.js" {{LOCAL_NTP_CUSTOM_BG_INTEGRITY}}></script> + <script src="chrome-search://local-ntp/local-ntp.js" + {{LOCAL_NTP_INTEGRITY}}></script> <meta charset="utf-8"> <meta name="google" value="notranslate"> </head> @@ -90,7 +88,7 @@ <dialog div id="edit-bg-dialog"> <div id="edit-bg-title"></div> - <div id="edit-bg-google-photos" class="bg-option" tabindex="0"> + <div id="edit-bg-google-photos" class="bg-option" tabindex="0" hidden> <div class="bg-option-img"></div> <div id="edit-bg-google-photos-text" class="bg-option-text"></div> </div> @@ -104,11 +102,11 @@ <div id="edit-bg-upload-image-text" class="bg-option-text"></div> </div> <div id="edit-bg-divider"></div> - <div id="custom-link-restore-default" class="bg-option" tabindex="0"> + <div id="custom-links-restore-default" class="bg-option bg-option-disabled" tabindex="0"> <div class="bg-option-img"></div> - <div id="custom-link-restore-default-text" class="bg-option-text"></div> + <div id="custom-links-restore-default-text" class="bg-option-text"></div> </div> - <div id="edit-bg-restore-default" class="bg-option" tabindex="0"> + <div id="edit-bg-restore-default" class="bg-option bg-option-disabled" tabindex="0"> <div class="bg-option-img"></div> <div id="edit-bg-restore-default-text" class="bg-option-text"></div> </div> @@ -165,5 +163,8 @@ </dialog> <div id="one-google-end-of-body"></div> + + <script defer src="chrome-search://local-ntp/voice.js" + {{LOCAL_NTP_VOICE_INTEGRITY}}></script> </body> </html>
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index e1acb52..2170e54 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -318,12 +318,18 @@ customBackgrounds.setAttribution( info.attribution1, info.attribution2, info.attributionActionUrl); } - $(customBackgrounds.IDS.RESTORE_DEFAULT).hidden = - !info.customBackgroundConfigured; + + $(customBackgrounds.IDS.RESTORE_DEFAULT) + .classList.toggle( + customBackgrounds.CLASSES.OPTION_DISABLED, + !info.customBackgroundConfigured); if (configData.isGooglePage) { + // Hide the settings menu if the user has a theme. Do not hide if custom + // links is enabled. $('edit-bg').hidden = - !configData.isCustomBackgroundsEnabled || !info.usingDefaultTheme; + (!configData.isCustomBackgroundsEnabled || !info.usingDefaultTheme) && + !configData.isCustomLinksEnabled; } } @@ -682,6 +688,12 @@ injectOneGoogleBar(og); }; } + if (configData.isCustomLinksEnabled) { + $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT) + .classList.toggle( + customBackgrounds.CLASSES.OPTION_DISABLED, + !args.showRestoreDefault); + } } else if (cmd === 'tileBlacklisted') { showNotification(); lastBlacklistedTile = args.tid; @@ -846,8 +858,27 @@ enableMDIcons(); } - if (configData.isCustomBackgroundsEnabled) - customBackgrounds.initCustomBackgrounds(); + if (configData.isCustomBackgroundsEnabled || + configData.isCustomLinksEnabled) { + customBackgrounds.init(); + + // Hide items in the settings menu if a feature is disabled. + if (configData.isCustomBackgroundsEnabled && + !configData.isCustomLinksEnabled) { + // Only custom backgrounds enabled, hide all custom link options. + $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT).hidden = true; + } else if ( + !configData.isCustomBackgroundsEnabled && + configData.isCustomLinksEnabled) { + // Only custom links enabled, hide all custom background options. + $(customBackgrounds.IDS.CONNECT_GOOGLE_PHOTOS).hidden = true; + $(customBackgrounds.IDS.DEFAULT_WALLPAPERS).hidden = true; + $(customBackgrounds.IDS.UPLOAD_IMAGE).hidden = true; + $(customBackgrounds.IDS.RESTORE_DEFAULT).hidden = true; + $(customBackgrounds.IDS.EDIT_BG_DIVIDER).hidden = true; + } + } + // Set up the fakebox (which only exists on the Google NTP). ntpApiHandle.oninputstart = onInputStart;
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js index a233668..bd743f89 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.js +++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -154,6 +154,13 @@ /** + * True if the tiles to be shown are custom links. + * @type {boolean} + */ +let tilesAreCustomLinks = false; + + +/** * Log an event on the NTP. * @param {number} eventType Event from LOG_TYPE. */ @@ -205,7 +212,15 @@ if (loadedCounter <= 0) { swapInNewTiles(); logEvent(LOG_TYPE.NTP_ALL_TILES_LOADED); - window.parent.postMessage({cmd: 'loaded'}, DOMAIN_ORIGIN); + // Tell the parent page whether to show the restore default shortcuts option + // in the menu. + window.parent.postMessage( + { + cmd: 'loaded', + showRestoreDefault: (isCustomLinksEnabled && tilesAreCustomLinks) + }, + DOMAIN_ORIGIN); + tilesAreCustomLinks = false; // Reset to 1, so that any further 'show' message will cause us to swap in // fresh tiles. loadedCounter = 1; @@ -602,6 +617,9 @@ return mdTile; } + if (data.isCustomLink) + tilesAreCustomLinks = true; + // The tile will be appended to tiles. const position = tiles.children.length; // This is set in the load/error event for the favicon image.
diff --git a/chrome/browser/resources/print_preview/new/destination_list.html b/chrome/browser/resources/print_preview/new/destination_list.html index 403e6c86..74b40b7 100644 --- a/chrome/browser/resources/print_preview/new/destination_list.html +++ b/chrome/browser/resources/print_preview/new/destination_list.html
@@ -20,10 +20,6 @@ user-select: none; } - :host #list { - height: 100%; - } - :host > header { background-color: transparent; border-bottom: 1px solid #d2d2d2;
diff --git a/chrome/browser/resources/print_preview/new/destination_list.js b/chrome/browser/resources/print_preview/new/destination_list.js index e731eccb..74d7a15 100644 --- a/chrome/browser/resources/print_preview/new/destination_list.js +++ b/chrome/browser/resources/print_preview/new/destination_list.js
@@ -41,6 +41,7 @@ hasDestinations_: { type: Boolean, value: true, + observer: 'hasDestinationsChanged_', }, /** @private {boolean} */ @@ -116,5 +117,12 @@ onDestinationSelected_: function(e) { this.fire('destination-selected', e.target); }, + + /** @private */ + hasDestinationsChanged_: function() { + // If there are no destinations, leave space for "no destinations" message. + this.$.list.style.height = this.hasDestinations_ ? + 'calc(100% - 1rem - 9px)' : 'calc(100% - 2rem - 9px)'; + }, }); })();
diff --git a/chrome/browser/resources/settings/downloads_page/downloads_page.html b/chrome/browser/resources/settings/downloads_page/downloads_page.html index 90e4ca90..86bc093 100644 --- a/chrome/browser/resources/settings/downloads_page/downloads_page.html +++ b/chrome/browser/resources/settings/downloads_page/downloads_page.html
@@ -24,7 +24,7 @@ <div class="settings-box first two-line"> <div class="start"> <div>$i18n{downloadLocation}</div> - <div class="secondary"> + <div class="secondary" id="defaultDownloadPath"> <if expr="not chromeos"> [[prefs.download.default_directory.value]] </if>
diff --git a/chrome/browser/resources/settings/downloads_page/downloads_page.js b/chrome/browser/resources/settings/downloads_page/downloads_page.js index 11a50db..4c8a6cb 100644 --- a/chrome/browser/resources/settings/downloads_page/downloads_page.js +++ b/chrome/browser/resources/settings/downloads_page/downloads_page.js
@@ -112,10 +112,17 @@ getDownloadLocation_: function(path) { // Replace /special/drive-<hash>/root with "Google Drive" for remote files, // /home/chronos/user/Downloads or /home/chronos/u-<hash>/Downloads with - // "Downloads" for local paths, and '/' with ' \u203a ' (angled quote sign) - // everywhere. It is used only for display purpose. + // "Downloads" for local paths, /run/arc/sdcard/write/emulated/0 with + // "Play files" for Android files, and '/' with ' \u203a ' + // (angled quote sign) everywhere. It is used only for display purpose. + // TODO(fukino): Move the logic of converting these special paths to + // something else to C++ side so that UI side does not depend on these + // hard-coded paths. path = path.replace(/^\/special\/drive[^\/]*\/root/, 'Google Drive'); path = path.replace(/^\/home\/chronos\/(user|u-[^\/]*)\//, ''); + path = path.replace( + /^\/run\/arc\/sdcard\/write\/emulated\/0/, + loadTimeData.getString('downloadsAndroidFilesRootLabel')); path = path.replace(/\//g, ' \u203a '); return path; },
diff --git a/chrome/browser/resources/settings/site_settings/BUILD.gn b/chrome/browser/resources/settings/site_settings/BUILD.gn index 078b92e..1acbbbf00 100644 --- a/chrome/browser/resources/settings/site_settings/BUILD.gn +++ b/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -261,6 +261,7 @@ js_library("zoom_levels") { deps = [ ":site_settings_behavior", + "//ui/webui/resources/js:list_property_update_behavior", "//ui/webui/resources/js:web_ui_listener_behavior", ] }
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.html b/chrome/browser/resources/settings/site_settings/all_sites.html index dab0069..6577af6 100644 --- a/chrome/browser/resources/settings/site_settings/all_sites.html +++ b/chrome/browser/resources/settings/site_settings/all_sites.html
@@ -40,20 +40,24 @@ <label id="sortLabel">$i18n{siteSettingsAllSitesSort}</label> <select id="sortMethod" class="md-select" aria-labelledby="sortLabel" on-change="onSortMethodChanged_"> - <!-- TODO(https://crbug.com/835712): Implement remaining two sort - methods. --> + <option value="[[sortMethods_.mostVisited]]"> + $i18n{siteSettingsAllSitesSortMethodMostVisited} + </option> + <option value="[[sortMethods_.storage]]"> + $i18n{siteSettingsAllSitesSortMethodStorage} + </option> <option value="[[sortMethods_.name]]"> $i18n{siteSettingsAllSitesSortMethodName} </option> </select> </div> </div> - <div class="list-frame" hidden$="[[siteGroupList.length]]"> + <div class="list-frame" hidden$="[[siteGroupMap.size]]"> <div class="list-item secondary">$i18n{noSitesAdded}</div> </div> <div class="list-frame without-heading" id="listContainer"> <iron-list id="allSitesList" - items="[[filterPopulatedList_(siteGroupList, searchQuery_)]]" + items="[[filterPopulatedList_(siteGroupMap, searchQuery_)]]" scroll-target="[[subpageScrollTarget]]"> <template> <site-entry site-group="[[item]]" list-index="[[index]]"
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.js b/chrome/browser/resources/settings/site_settings/all_sites.js index 8b022b8..b424251 100644 --- a/chrome/browser/resources/settings/site_settings/all_sites.js +++ b/chrome/browser/resources/settings/site_settings/all_sites.js
@@ -19,13 +19,14 @@ properties: { /** - * Array of sites to display in the widget, grouped into their eTLD+1s. - * @type {!Array<!SiteGroup>} + * Map containing sites to display in the widget, grouped into their + * eTLD+1 names. + * @type {!Map<string, !SiteGroup>} */ - siteGroupList: { - type: Array, + siteGroupMap: { + type: Object, value: function() { - return []; + return new Map(); }, }, @@ -51,17 +52,15 @@ /** * All possible sort methods. - * @type {Object} + * @type {!{name: string, mostVisited: string, storage: string}} * @private */ sortMethods_: { type: Object, - value: function() { - return { - name: 'name', - mostVisited: 'most-visited', - storage: 'data-stored', - }; + value: { + name: 'name', + mostVisited: 'most-visited', + storage: 'data-stored', }, readOnly: true, }, @@ -83,20 +82,34 @@ }, }, + /** @private {?settings.LocalDataBrowserProxy} */ + localDataBrowserProxy_: null, + + /** @override */ + created: function() { + this.localDataBrowserProxy_ = + settings.LocalDataBrowserProxyImpl.getInstance(); + }, + /** @override */ ready: function() { - this.browserProxy_ = - settings.SiteSettingsPrefsBrowserProxyImpl.getInstance(); + this.addWebUIListener( + 'onLocalStorageListFetched', this.onLocalStorageListFetched.bind(this)); this.addWebUIListener( 'contentSettingSitePermissionChanged', this.populateList_.bind(this)); this.addEventListener( - 'site-entry-resized', this.resizeListIfScrollTargetActive_.bind(this)); - this.addEventListener( 'site-entry-selected', (/** @type {!{detail: !{item: !SiteGroup, index: number}}} */ e) => { this.selectedItem_ = e.detail; }); - + this.addEventListener('site-entry-storage-updated', () => { + this.debounce('site-entry-storage-updated', () => { + if (this.sortMethods_ && + this.$.sortMethod.value == this.sortMethods_.storage) { + this.onSortMethodChanged_(); + } + }, 500); + }); this.populateList_(); }, @@ -121,27 +134,62 @@ if (!contentTypes.includes(settings.ContentSettingsTypes.COOKIES)) contentTypes.push(settings.ContentSettingsTypes.COOKIES); - this.browserProxy_.getAllSites(contentTypes).then((response) => { - this.siteGroupList = this.sortSiteGroupList_(response); + this.browserProxy.getAllSites(contentTypes).then((response) => { + response.forEach(siteGroup => { + this.siteGroupMap.set(siteGroup.etldPlus1, siteGroup); + }); + this.forceListUpdate_(); }); }, /** - * Filters |this.siteGroupList| with the given search query text. - * @param {!Array<!SiteGroup>} siteGroupList The list of sites to filter. + * Integrate sites using local storage into the existing sites map, as there + * may be overlap between the existing sites. + * @param {!Array<!SiteGroup>} list The list of sites using local storage. + */ + onLocalStorageListFetched: function(list) { + list.forEach(storageSiteGroup => { + if (this.siteGroupMap.has(storageSiteGroup.etldPlus1)) { + const siteGroup = this.siteGroupMap.get(storageSiteGroup.etldPlus1); + const storageOriginInfoMap = new Map(); + storageSiteGroup.origins.forEach( + originInfo => + storageOriginInfoMap.set(originInfo.origin, originInfo)); + + // If there is an overlapping origin, update the original + // |originInfo|. + siteGroup.origins.forEach(originInfo => { + if (!storageOriginInfoMap.has(originInfo.origin)) + return; + Object.apply(originInfo, storageOriginInfoMap.get(originInfo.origin)); + storageOriginInfoMap.delete(originInfo.origin); + }); + // Otherwise, add it to the list. + storageOriginInfoMap.forEach( + originInfo => siteGroup.origins.push(originInfo)); + } else { + this.siteGroupMap.set(storageSiteGroup.etldPlus1, storageSiteGroup); + } + }); + this.forceListUpdate_(); + }, + + /** + * Filters the all sites list with the given search query text. + * @param {!Map<string, !SiteGroup>} siteGroupMap The map of sites to filter. * @param {string} searchQuery The filter text. * @return {!Array<!SiteGroup>} * @private */ - filterPopulatedList_: function(siteGroupList, searchQuery) { - if (searchQuery.length == 0) - return siteGroupList; - - return siteGroupList.filter((siteGroup) => { - return siteGroup.origins.find(origin => { - return origin.includes(searchQuery); - }); - }); + filterPopulatedList_: function(siteGroupMap, searchQuery) { + const result = []; + for (const [etldPlus1, siteGroup] of siteGroupMap) { + if (siteGroup.origins.find( + originInfo => originInfo.origin.includes(searchQuery))) { + result.push(siteGroup); + } + } + return this.sortSiteGroupList_(result); }, /** @@ -152,11 +200,89 @@ */ sortSiteGroupList_: function(siteGroupList) { const sortMethod = this.$.sortMethod.value; - if (sortMethod == this.sortMethods_.name) + if (!this.sortMethods_) + return siteGroupList; + + if (sortMethod == this.sortMethods_.mostVisited) { + siteGroupList.sort(this.mostVisitedComparator_); + } else if (sortMethod == this.sortMethods_.storage) { + // Storage is loaded asynchronously, so make sure it's updated for every + // item in the list to ensure the sorting is correct. + const etldPlus1List = siteGroupList.reduce((list, siteGroup) => { + if (siteGroup.origins.length > 1 && siteGroup.etldPlus1.length > 0) + list.push(siteGroup.etldPlus1); + return list; + }, []); + + this.localDataBrowserProxy_.getNumCookiesList(etldPlus1List) + .then(numCookiesList => { + assert(etldPlus1List.length == numCookiesList.length); + numCookiesList.forEach(cookiesPerEtldPlus1 => { + this.siteGroupMap.get(cookiesPerEtldPlus1.etldPlus1).numCookies = + cookiesPerEtldPlus1.numCookies; + }); + + // |siteGroupList| by this point should have already been provided + // to the iron list, so just sort in-place here and make sure to + // re-render the item order. + siteGroupList.sort(this.storageComparator_); + this.$.allSitesList.fire('iron-resize'); + }); + } else if (sortMethod == this.sortMethods_.name) { siteGroupList.sort(this.nameComparator_); + } return siteGroupList; }, + /** + * Comparator used to sort SiteGroups by the amount of engagement the user has + * with the origins listed inside it. Note only the maximum engagement is used + * for each SiteGroup (as opposed to the sum) in order to prevent domains with + * higher numbers of origins from always floating to the top of the list. + * @param {!SiteGroup} siteGroup1 + * @param {!SiteGroup} siteGroup2 + * @private + */ + mostVisitedComparator_: function(siteGroup1, siteGroup2) { + const getMaxEngagement = (max, originInfo) => { + return (max > originInfo.engagement) ? max : originInfo.engagement; + }; + const score1 = siteGroup1.origins.reduce(getMaxEngagement, 0); + const score2 = siteGroup2.origins.reduce(getMaxEngagement, 0); + return score2 - score1; + }, + + /** + * Comparator used to sort SiteGroups by the amount of storage they use. Note + * this sorts in descending order. + * TODO(https://crbug.com/835712): Account for website storage in sorting by + * storage used. + * @param {!SiteGroup} siteGroup1 + * @param {!SiteGroup} siteGroup2 + * @private + */ + storageComparator_: function(siteGroup1, siteGroup2) { + const getOverallUsage = siteGroup => { + let usage = 0; + siteGroup.origins.forEach(originInfo => { + usage += originInfo.usage; + }); + return usage; + }; + + const siteGroup1Size = getOverallUsage(siteGroup1); + const siteGroup2Size = getOverallUsage(siteGroup2); + // Use the number of cookies as a tie breaker. + return siteGroup2Size - siteGroup1Size || + siteGroup2.numCookies - siteGroup1.numCookies; + }, + + /** + * Comparator used to sort SiteGroups by their eTLD+1 name (domain). + * @param {!SiteGroup} siteGroup1 + * @param {!SiteGroup} siteGroup2 + * @private + */ nameComparator_: function(siteGroup1, siteGroup2) { return siteGroup1.etldPlus1.localeCompare(siteGroup2.etldPlus1); }, @@ -176,19 +302,21 @@ * @private */ onSortMethodChanged_: function() { - this.siteGroupList = this.sortSiteGroupList_(this.siteGroupList); + this.$.allSitesList.items = + this.sortSiteGroupList_(this.$.allSitesList.items); // Force the iron-list to rerender its items, as the order has changed. this.$.allSitesList.fire('iron-resize'); }, /** - * Called when a list item changes its size, and thus the positions and sizes - * of the items in the entire list also need updating. + * Forces the all sites list to update its list of items, taking into account + * the search query and the sort method, then re-renders it. * @private */ - resizeListIfScrollTargetActive_: function() { - if (settings.getCurrentRoute() == this.subpageRoute) - this.$.allSitesList.fire('iron-resize'); + forceListUpdate_: function() { + this.$.allSitesList.items = + this.filterPopulatedList_(this.siteGroupMap, this.searchQuery_); + this.$.allSitesList.fire('iron-resize'); }, /** @@ -206,14 +334,14 @@ const onNavigatedTo = () => { this.async(() => { - if (this.selectedItem_ == null || this.siteGroupList.length == 0) + if (this.selectedItem_ == null || this.siteGroupMap.size == 0) return; // Focus the site-entry to ensure the iron-list renders it, otherwise // the query selector will not be able to find it. Note the index is // used here instead of the item, in case the item was already removed. const index = Math.max( - 0, Math.min(this.selectedItem_.index, this.siteGroupList.length)); + 0, Math.min(this.selectedItem_.index, this.siteGroupMap.size)); this.$.allSitesList.focusItem(index); this.selectedItem_ = null; });
diff --git a/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js b/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js index f23a71fe..19db72fa 100644 --- a/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js +++ b/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
@@ -33,6 +33,15 @@ */ let LocalDataList; +/** + * Number of cookies attached to a given domain / eTLD+1. + * @typedef {{ + * etldPlus1: string, + * numCookies: number, + * }} + */ +let EtldPlus1CookieNumber; + cr.define('settings', function() { /** @interface */ class LocalDataBrowserProxy { @@ -69,11 +78,20 @@ getCookieDetails(site) {} /** - * Gets the number of cookies formatted in a plural string, given a site. - * @param {string} site The site to count cookies for. + * Gets a list containing the number of cookies for each domain (eTLD+1 + * names) given in |siteList|. This will always return a result array the + * same length and in the same order as |siteList|. + * @param {!Array<string>} siteList The list of sites to count cookies for. + * @return {!Promise<!Array<!EtldPlus1CookieNumber>>} + */ + getNumCookiesList(siteList) {} + + /** + * Gets the plural string for a given number of cookies. + * @param {number} numCookies The number of cookies. * @return {!Promise<string>} */ - getNumCookiesString(site) {} + getNumCookiesString(numCookies) {} /** * Reloads all local data. @@ -120,8 +138,13 @@ } /** @override */ - getNumCookiesString(site) { - return cr.sendWithPromise('localData.getNumCookiesString', site); + getNumCookiesList(siteList) { + return cr.sendWithPromise('localData.getNumCookiesList', siteList); + } + + /** @override */ + getNumCookiesString(numCookies) { + return cr.sendWithPromise('localData.getNumCookiesString', numCookies); } /** @override */
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.html b/chrome/browser/resources/settings/site_settings/site_entry.html index 6305a2b..cd3876e 100644 --- a/chrome/browser/resources/settings/site_settings/site_entry.html +++ b/chrome/browser/resources/settings/site_settings/site_entry.html
@@ -26,9 +26,23 @@ display: flex; } - #cookies { + .second-line { margin-top: 0.1em; } + + /* Data units such as "0 KB" should always read left-to-right. */ + .data-unit { + direction: ltr; + unicode-bidi: isolate; + } + + #collapseChild .data-unit { + padding-inline-start: 1ch; + } + + .list-frame { + padding-inline-end: 0; + } </style> <div id="collapseParent"> <div class$="settings-box list-item [[getClassForIndex_(listIndex)]]"> @@ -47,8 +61,11 @@ [[scheme_(siteGroup, -1)]] </span> </div> - <div id="cookies" class="secondary" hidden$="[[!cookieString_]]"> - [[cookieString_]] + <div class="second-line secondary"> + <span class="data-unit">[[overallUsageString_]]</span> + <span id="cookies" hidden$="[[!siteGroup.numCookies]]"> + · [[cookieString_]] + </span> </div> </div> <paper-icon-button-light id="expandIcon" class="icon-expand-more" @@ -77,10 +94,11 @@ <template is="dom-repeat" items="[[siteGroup.origins]]"> <div class="settings-box list-item" on-click="onOriginTap_" actionable> - <div class="favicon-image" style$="[[computeSiteIcon(item)]]"> + <div class="favicon-image" + style$="[[computeSiteIcon(item.origin)]]"> </div> <div class="site-representation middle text-elide"> - <span class="url-directionality"> + <span id="originSiteRepresentation" class="url-directionality"> [[siteRepresentation_(siteGroup, index)]] </span> <span class="secondary" @@ -91,7 +109,13 @@ hidden$="[[!scheme_(siteGroup, index)]]"> [[scheme_(siteGroup, index)]] </span> + <span class="secondary data-unit" hidden$="[[!item.usage]]"> + [[originUsagesItem_(originUsages_.*, index)]] + </span> </div> + <paper-icon-button-light class="subpage-arrow"> + <button aria-labelledby$="originSiteRepresentation"></button> + </paper-icon-button-light> </div> </template> </div>
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.js b/chrome/browser/resources/settings/site_settings/site_entry.js index 0cb5e4f0..2b3e983 100644 --- a/chrome/browser/resources/settings/site_settings/site_entry.js +++ b/chrome/browser/resources/settings/site_settings/site_entry.js
@@ -32,10 +32,7 @@ * The string to display when there is a non-zero number of cookies. * @private */ - cookieString_: { - type: String, - value: '', - }, + cookieString_: String, /** * The position of this site-entry in its parent list. @@ -44,6 +41,25 @@ type: Number, value: -1, }, + + /** + * The string to display showing the overall usage of this site-entry. + * @private + */ + overallUsageString_: String, + + /** + * An array containing the strings to display showing the individual disk + * usage for each origin in |siteGroup|. + * @type {!Array<string>} + * @private + */ + originUsages_: { + type: Array, + value: function() { + return []; + }, + }, }, listeners: { @@ -93,7 +109,7 @@ // was computed. } originIndex = this.getIndexBoundToOriginList_(siteGroup, originIndex); - const url = this.toUrl(siteGroup.origins[originIndex]); + const url = this.toUrl(siteGroup.origins[originIndex].origin); return url.host; }, @@ -109,21 +125,32 @@ if (this.$.collapseChild.opened) this.toggleCollapsible_(); // Ungrouped site-entries should not show cookies. - if (this.cookieString_) { + if (this.cookieString_) this.cookieString_ = ''; - this.fire('site-entry-resized'); - } } - if (!siteGroup || !this.grouped_(siteGroup)) + if (!siteGroup) + return; + this.calculateUsageInfo_(siteGroup); + + if (!this.grouped_(siteGroup)) return; - this.localDataBrowserProxy_.getNumCookiesString(this.displayName_) - .then(string => { - // If there was no cookie string previously and now there is, or vice - // versa, the height of this site-entry will have changed. - if ((this.cookieString_ == '') != (string == '')) - this.fire('site-entry-resized'); + const siteList = [this.displayName_]; + this.localDataBrowserProxy_.getNumCookiesList(siteList) + .then(numCookiesList => { + assert(siteList.length == numCookiesList.length); + const numCookies = numCookiesList[0].numCookies; + if (siteGroup.numCookies != numCookies) + this.fire('site-entry-storage-updated'); + siteGroup.numCookies = numCookies; + this.notifyPath('siteGroup.numCookies'); + + return numCookies == 0 ? + Promise.resolve('') : + this.localDataBrowserProxy_.getNumCookiesString(numCookies); + }) + .then(string => { this.cookieString_ = string; }); }, @@ -143,7 +170,7 @@ return ''; originIndex = this.getIndexBoundToOriginList_(siteGroup, originIndex); - const url = this.toUrl(siteGroup.origins[originIndex]); + const url = this.toUrl(siteGroup.origins[originIndex].origin); const scheme = url.protocol.replace(new RegExp(':*$'), ''); /** @type{string} */ const HTTPS_SCHEME = 'https'; if (scheme == HTTPS_SCHEME) @@ -161,7 +188,48 @@ getSiteGroupIcon_: function(siteGroup) { // TODO(https://crbug.com/835712): Implement heuristic for finding a good // favicon. - return this.computeSiteIcon(siteGroup.origins[0]); + return this.computeSiteIcon(siteGroup.origins[0].origin); + }, + + /** + * Calculates the amount of disk storage used by the given group of origins + * and eTLD+1. Also updates the corresponding display strings. + * TODO(https://crbug.com/835712): Add website storage as well. + * @param {SiteGroup} siteGroup The eTLD+1 group of origins. + * @private + */ + calculateUsageInfo_: function(siteGroup) { + const getFormattedBytesForSize = (numBytes) => { + if (numBytes == 0) + return Promise.resolve('0 B'); + return this.browserProxy.getFormattedBytes(numBytes); + }; + + let overallUsage = 0; + this.originUsages_ = new Array(siteGroup.origins.length); + siteGroup.origins.forEach((originInfo, i) => { + overallUsage += originInfo.usage; + if (this.grouped_(siteGroup)) { + getFormattedBytesForSize(originInfo.usage).then((string) => { + this.set(`originUsages_.${i}`, string); + }); + } + }); + + getFormattedBytesForSize(overallUsage).then(string => { + this.overallUsageString_ = string; + }); + }, + + /** + * Array binding for the |originUsages_| array for use in the HTML. + * @param {!{base: !Array<string>}} change The change record for the array. + * @param {number} index The index of the array item. + * @return {string} + * @private + */ + originUsagesItem_: function(change, index) { + return change.base[index]; }, /** @@ -184,7 +252,7 @@ * @private */ onOriginTap_: function(e) { - this.navigateToSiteDetails_(this.siteGroup.origins[e.model.index]); + this.navigateToSiteDetails_(this.siteGroup.origins[e.model.index].origin); }, /** @@ -195,7 +263,7 @@ onSiteEntryTap_: function() { // Individual origins don't expand - just go straight to Site Details. if (!this.grouped_(this.siteGroup)) { - this.navigateToSiteDetails_(this.siteGroup.origins[0]); + this.navigateToSiteDetails_(this.siteGroup.origins[0].origin); return; } this.toggleCollapsible_(); @@ -210,7 +278,7 @@ * @private */ toggleCollapsible_: function() { - let collapseChild = + const collapseChild = /** @type {IronCollapseElement} */ (this.$.collapseChild); collapseChild.toggle(); this.$.toggleButton.setAttribute('aria-expanded', collapseChild.opened); @@ -252,7 +320,7 @@ onResetSettings_: function(e) { const contentSettingsTypes = this.getCategoryList(); for (let i = 0; i < this.siteGroup.origins.length; ++i) { - const origin = this.siteGroup.origins[i]; + const origin = this.siteGroup.origins[i].origin; this.browserProxy.setOriginPermissions( origin, contentSettingsTypes, settings.ContentSetting.DEFAULT); if (contentSettingsTypes.includes(settings.ContentSettingsTypes.PLUGINS))
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js index 9ee9e90f..c4a59ce 100644 --- a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js +++ b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
@@ -19,12 +19,21 @@ }; /** + * Stores origin information. + * @typedef {{origin: string, + * engagement: number, + * usage: number}} + */ +let OriginInfo; + +/** * Represents a list of sites, grouped under the same eTLD+1. For example, an * origin "https://www.example.com" would be grouped together with * "https://login.example.com" and "http://example.com" under a common eTLD+1 of * "example.com". * @typedef {{etldPlus1: string, - * origins: Array<string>}} + * numCookies: number, + * origins: Array<OriginInfo>}} */ let SiteGroup; @@ -118,13 +127,21 @@ /** * Gets a list of sites, grouped by eTLD+1, affected by any of the content * settings specified by |contentTypes|. - * @param {string} contentTypes A list of the content types to retrieve - * sites for. + * @param {!Array<!settings.ContentSettingsTypes>} contentTypes A list of + * the content types to retrieve sites for. * @return {!Promise<!Array<!SiteGroup>>} */ getAllSites(contentTypes) {} /** + * Converts a given number of bytes into a human-readable format, with data + * units. + * @param {number} numBytes The number of bytes to convert. + * @return {!Promise<string>} + */ + getFormattedBytes(numBytes) {} + + /** * Gets the exceptions (site list) for a particular category. * @param {string} contentType The name of the category to query. * @return {!Promise<!Array<!RawSiteException>>} @@ -322,6 +339,11 @@ } /** @override */ + getFormattedBytes(numBytes) { + return cr.sendWithPromise('getFormattedBytes', numBytes); + } + + /** @override */ getExceptionList(contentType) { return cr.sendWithPromise('getExceptionList', contentType); }
diff --git a/chrome/browser/resources/settings/site_settings/zoom_levels.html b/chrome/browser/resources/settings/site_settings/zoom_levels.html index b390327..9f6e903 100644 --- a/chrome/browser/resources/settings/site_settings/zoom_levels.html +++ b/chrome/browser/resources/settings/site_settings/zoom_levels.html
@@ -2,8 +2,9 @@ <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> +<link rel="import" href="chrome://resources/html/list_property_update_behavior.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="site_settings_behavior.html"> @@ -26,28 +27,28 @@ } </style> <div class="list-frame vertical-list" id="listContainer"> - <template is="dom-repeat" items="[[sites_]]" id="list"> - <div class="list-item"> - <div class="favicon-image" - style$="[[computeSiteIcon(item.originForFavicon)]]"> - </div> - <div class="middle"> - <span class="url-directionality">[[item.displayName]]</span> - </div> - <div class="zoom-label">[[item.zoom]]</div> - <div> + <iron-list id="list" preserve-focus items="[[sites_]]" + class="cr-separators" risk-selection> + <template> + <div class="list-item" first$="[[!index]]"> + <div class="favicon-image" + style$="[[computeSiteIcon(item.originForFavicon)]]"> + </div> + <div class="middle"> + <span class="url-directionality">[[item.displayName]]</span> + </div> + <div class="zoom-label">[[item.zoom]]</div> <paper-icon-button-light class="icon-clear"> <button on-click="removeZoomLevel_" - title="$i18n{siteSettingsRemoveZoomLevel}"></button> + title="$i18n{siteSettingsRemoveZoomLevel}" + tabindex$="[[tabIndex]]"></button> </paper-icon-button-light> </div> - </div> - </template> - <template is="dom-if" if="[[!sites_.length]]"> - <div id="empty"> - $i18n{siteSettingsNoZoomedSites} - </div> - </template> + </template> + </iron-list> + <div id="empty" hidden$="[[!showNoSites_]]"> + $i18n{siteSettingsNoZoomedSites} + </div> </div> </template> <script src="zoom_levels.js"></script>
diff --git a/chrome/browser/resources/settings/site_settings/zoom_levels.js b/chrome/browser/resources/settings/site_settings/zoom_levels.js index eeeb057..1614243c 100644 --- a/chrome/browser/resources/settings/site_settings/zoom_levels.js +++ b/chrome/browser/resources/settings/site_settings/zoom_levels.js
@@ -11,14 +11,27 @@ Polymer({ is: 'zoom-levels', - behaviors: [SiteSettingsBehavior, WebUIListenerBehavior], + behaviors: [ + ListPropertyUpdateBehavior, + SiteSettingsBehavior, + WebUIListenerBehavior, + ], properties: { /** * Array of sites that are zoomed in or out. * @type {!Array<ZoomLevelEntry>} */ - sites_: Array, + sites_: { + type: Array, + value: () => [], + }, + + /** @private */ + showNoSites_: { + type: Boolean, + value: false, + }, }, /** @override */ @@ -34,7 +47,8 @@ * their zoom levels. */ onZoomLevelsChanged_: function(sites) { - this.sites_ = sites; + this.updateList('sites_', item => `${item.origin}_${item.zoom}`, sites); + this.showNoSites_ = this.sites_.length == 0; }, /**
diff --git a/chrome/browser/ui/views/message_center/popups_only_ui_delegate.cc b/chrome/browser/ui/views/message_center/popups_only_ui_delegate.cc index d8e5e31..621d0af37 100644 --- a/chrome/browser/ui/views/message_center/popups_only_ui_delegate.cc +++ b/chrome/browser/ui/views/message_center/popups_only_ui_delegate.cc
@@ -17,8 +17,8 @@ PopupsOnlyUiDelegate::PopupsOnlyUiDelegate() { ui_controller_.reset(new message_center::UiController(this)); alignment_delegate_.reset(new message_center::DesktopPopupAlignmentDelegate); - popup_collection_.reset(new message_center::MessagePopupCollection( - message_center(), alignment_delegate_.get())); + popup_collection_.reset( + new message_center::MessagePopupCollection(alignment_delegate_.get())); message_center()->SetHasMessageCenterView(false); } @@ -35,7 +35,7 @@ bool PopupsOnlyUiDelegate::ShowPopups() { alignment_delegate_->StartObserving(display::Screen::GetScreen()); - popup_collection_->DoUpdate(); + popup_collection_->Update(); return true; }
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc index a035371..7d56b1b 100644 --- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -574,8 +574,9 @@ auth_request = CreateAuthorizationRequest(); } DBusThreadManager::Get()->GetCryptohomeClient()->MountEx( - cryptohome::Identification(user_context_.GetAccountId()), auth_request, - mount, + cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId()), + auth_request, mount, base::BindOnce(&EncryptionMigrationScreenHandler::OnMountExistingVault, weak_ptr_factory_.GetWeakPtr())); } @@ -601,7 +602,9 @@ request.set_minimal_migration(IsMinimalMigration()); DBusThreadManager::Get()->GetCryptohomeClient()->AddObserver(this); DBusThreadManager::Get()->GetCryptohomeClient()->MigrateToDircrypto( - cryptohome::Identification(user_context_.GetAccountId()), request, + cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId()), + request, base::Bind(&EncryptionMigrationScreenHandler::OnMigrationRequested, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc index 567d7be..2e0ac71 100644 --- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc +++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc
@@ -19,6 +19,7 @@ #include "chromeos/dbus/fake_cryptohome_client.h" #include "chromeos/dbus/fake_power_manager_client.h" #include "chromeos/dbus/power_policy_controller.h" +#include "chromeos/dbus/util/account_identifier_operators.h" #include "chromeos/login/auth/key.h" #include "chromeos/login/auth/user_context.h" #include "components/account_id/account_id.h" @@ -230,7 +231,8 @@ encryption_migration_screen_handler_->fake_wake_lock()->HasWakeLock()); EXPECT_TRUE(fake_cryptohome_client_->to_migrate_from_ecryptfs()); EXPECT_TRUE(fake_cryptohome_client_->minimal_migration()); - EXPECT_EQ(cryptohome::Identification(user_context_.GetAccountId()), + EXPECT_EQ(cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId()), fake_cryptohome_client_->get_id_for_disk_migrated_to_dircrypto()); EXPECT_EQ( user_context_.GetKey()->GetSecret(), @@ -254,7 +256,8 @@ EXPECT_TRUE(continue_login_callback_called_); EXPECT_TRUE(fake_cryptohome_client_->to_migrate_from_ecryptfs()); EXPECT_TRUE(fake_cryptohome_client_->minimal_migration()); - EXPECT_EQ(cryptohome::Identification(user_context_.GetAccountId()), + EXPECT_EQ(cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId()), fake_cryptohome_client_->get_id_for_disk_migrated_to_dircrypto()); EXPECT_EQ( user_context_.GetKey()->GetSecret(), @@ -280,7 +283,8 @@ EXPECT_TRUE(restart_login_callback_called_); EXPECT_TRUE(fake_cryptohome_client_->to_migrate_from_ecryptfs()); EXPECT_TRUE(fake_cryptohome_client_->minimal_migration()); - EXPECT_EQ(cryptohome::Identification(user_context_.GetAccountId()), + EXPECT_EQ(cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId()), fake_cryptohome_client_->get_id_for_disk_migrated_to_dircrypto()); EXPECT_EQ( user_context_.GetKey()->GetSecret(), @@ -308,7 +312,8 @@ Mock::VerifyAndClearExpectations(mock_async_method_caller_); EXPECT_TRUE(fake_cryptohome_client_->to_migrate_from_ecryptfs()); EXPECT_TRUE(fake_cryptohome_client_->minimal_migration()); - EXPECT_EQ(cryptohome::Identification(user_context_.GetAccountId()), + EXPECT_EQ(cryptohome::CreateAccountIdentifierFromAccountId( + user_context_.GetAccountId()), fake_cryptohome_client_->get_id_for_disk_migrated_to_dircrypto()); EXPECT_EQ( user_context_.GetKey()->GetSecret(),
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc index daa0759..8ae0ff4 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
@@ -363,7 +363,7 @@ continue; other_users_.push_back(user); DBusThreadManager::Get()->GetCryptohomeClient()->GetAccountDiskUsage( - cryptohome::Identification(user->GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId()), base::BindOnce(&StorageHandler::OnGetOtherUserSize, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 0339dfc..de9468e 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -831,6 +831,8 @@ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE}, {"smbShareAddedMountExistsMessage", IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE}, + {"downloadsAndroidFilesRootLabel", + IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL} #endif }; AddLocalizedStringsBulk(html_source, localized_strings, @@ -2211,6 +2213,10 @@ IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_DESCRIPTION}, {"siteSettingsAllSitesSearch", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SEARCH}, {"siteSettingsAllSitesSort", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT}, + {"siteSettingsAllSitesSortMethodMostVisited", + IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_MOST_VISITED}, + {"siteSettingsAllSitesSortMethodStorage", + IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_STORAGE}, {"siteSettingsAllSitesSortMethodName", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_NAME}, {"siteSettingsSiteRepresentationSeparator",
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc index 9150748c..12b0a2a 100644 --- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc +++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
@@ -45,6 +45,9 @@ namespace { +constexpr char kEffectiveTopLevelDomainPlus1Name[] = "etldPlus1"; +constexpr char kNumCookies[] = "numCookies"; + int GetCategoryLabelID(CookieTreeNode::DetailedInfo::NodeType node_type) { constexpr struct { CookieTreeNode::DetailedInfo::NodeType node_type; @@ -174,6 +177,10 @@ base::BindRepeating(&CookiesViewHandler::HandleGetCookieDetails, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "localData.getNumCookiesList", + base::BindRepeating(&CookiesViewHandler::HandleGetNumCookiesList, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "localData.getNumCookiesString", base::BindRepeating(&CookiesViewHandler::HandleGetNumCookiesString, base::Unretained(this))); @@ -309,53 +316,73 @@ SendCookieDetails(node); } +void CookiesViewHandler::HandleGetNumCookiesList(const base::ListValue* args) { + CHECK_EQ(2U, args->GetSize()); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + const base::ListValue* etld_plus1_list; + CHECK(args->GetList(1, &etld_plus1_list)); + + AllowJavascript(); + CHECK(cookies_tree_model_.get()); + + base::string16 etld_plus1; + base::Value result(base::Value::Type::LIST); + for (size_t i = 0; i < etld_plus1_list->GetSize(); ++i) { + etld_plus1_list->GetString(i, &etld_plus1); + // This method is only interested in the number of cookies, so don't save + // |etld_plus1| as a new filter and keep the existing |sorted_sites_| list. + cookies_tree_model_->UpdateSearchResults(etld_plus1); + + int num_cookies = 0; + const CookieTreeNode* root = cookies_tree_model_->GetRoot(); + for (int i = 0; i < root->child_count(); ++i) { + const CookieTreeNode* site = root->GetChild(i); + const base::string16& title = site->GetTitle(); + if (!base::EndsWith(title, etld_plus1, + base::CompareCase::INSENSITIVE_ASCII)) { + continue; + } + + for (int j = 0; j < site->child_count(); ++j) { + const CookieTreeNode* category = site->GetChild(j); + if (category->GetDetailedInfo().node_type != + CookieTreeNode::DetailedInfo::TYPE_COOKIES) { + continue; + } + + for (int k = 0; k < category->child_count(); ++k) { + if (category->GetChild(k)->GetDetailedInfo().node_type != + CookieTreeNode::DetailedInfo::TYPE_COOKIE) { + continue; + } + + ++num_cookies; + } + } + } + + base::Value cookies_per_etld_plus1(base::Value::Type::DICTIONARY); + cookies_per_etld_plus1.SetKey(kEffectiveTopLevelDomainPlus1Name, + base::Value(etld_plus1)); + cookies_per_etld_plus1.SetKey(kNumCookies, base::Value(num_cookies)); + result.GetList().emplace_back(std::move(cookies_per_etld_plus1)); + } + ResolveJavascriptCallback(base::Value(callback_id), result); + + // Restore the original |filter_|. + cookies_tree_model_->UpdateSearchResults(filter_); +} + void CookiesViewHandler::HandleGetNumCookiesString( const base::ListValue* args) { CHECK_EQ(2U, args->GetSize()); std::string callback_id; CHECK(args->GetString(0, &callback_id)); - base::string16 etld_plus1; - CHECK(args->GetString(1, &etld_plus1)); + int num_cookies; + CHECK(args->GetInteger(1, &num_cookies)); AllowJavascript(); - CHECK(cookies_tree_model_.get()); - // This method is only interested in the number of cookies, so don't save the - // filter and keep the existing |sorted_sites_| list. - if (etld_plus1 != filter_) - cookies_tree_model_->UpdateSearchResults(etld_plus1); - - int num_cookies = 0; - const CookieTreeNode* root = cookies_tree_model_->GetRoot(); - for (int i = 0; i < root->child_count(); ++i) { - const CookieTreeNode* site = root->GetChild(i); - const base::string16& title = site->GetTitle(); - if (!base::EndsWith(title, etld_plus1, - base::CompareCase::INSENSITIVE_ASCII)) { - continue; - } - - for (int j = 0; j < site->child_count(); ++j) { - const CookieTreeNode* category = site->GetChild(j); - if (category->GetDetailedInfo().node_type != - CookieTreeNode::DetailedInfo::TYPE_COOKIES) { - continue; - } - - for (int k = 0; k < category->child_count(); ++k) { - if (category->GetChild(k)->GetDetailedInfo().node_type != - CookieTreeNode::DetailedInfo::TYPE_COOKIE) { - continue; - } - - ++num_cookies; - } - } - } - - if (etld_plus1 != filter_) { - // Restore the original |filter_|. - cookies_tree_model_->UpdateSearchResults(filter_); - } const base::string16 string = num_cookies > 0 ? l10n_util::GetPluralStringFUTF16( IDS_SETTINGS_SITE_SETTINGS_NUM_COOKIES, num_cookies)
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h index 0b74257..bba06ea 100644 --- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h +++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h
@@ -61,7 +61,12 @@ // Retrieve cookie details for a specific site. void HandleGetCookieDetails(const base::ListValue* args); - // Gets the number of cookies formatted in a plural string, given a site. + // Gets a list containing the number of cookies for each domain (eTLD+1 names) + // given in |siteList|. This will always return a result array the same length + // and in the same order as |siteList|. + void HandleGetNumCookiesList(const base::ListValue* args); + + // Gets a plural string for the given number of cookies. void HandleGetNumCookiesString(const base::ListValue* args); // Remove all sites data.
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc index fa895237..b37396a 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -17,10 +17,10 @@ #include "base/macros.h" #include "base/metrics/user_metrics.h" #include "base/values.h" -#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/web_site_settings_uma_util.h" +#include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/permissions/permission_decision_auto_blocker.h" @@ -66,6 +66,7 @@ constexpr char kEffectiveTopLevelDomainPlus1Name[] = "etldPlus1"; constexpr char kOriginList[] = "origins"; +constexpr char kNumCookies[] = "numCookies"; constexpr char kZoom[] = "zoom"; // Return an appropriate API Permission ID for the given string name. @@ -149,12 +150,41 @@ } } +// Converts a given |site_group_map| to a list of base::DictionaryValues, adding +// the site engagement score for each origin. +void ConvertSiteGroupMapToListValue( + const std::map<std::string, std::set<std::string>>& site_group_map, + base::Value* list_value, + Profile* profile) { + DCHECK_EQ(base::Value::Type::LIST, list_value->type()); + DCHECK(profile); + SiteEngagementService* engagement_service = + SiteEngagementService::Get(profile); + for (const auto& entry : site_group_map) { + // eTLD+1 is the effective top level domain + 1. + base::Value site_group(base::Value::Type::DICTIONARY); + site_group.SetKey(kEffectiveTopLevelDomainPlus1Name, + base::Value(entry.first)); + base::Value origin_list(base::Value::Type::LIST); + for (const std::string& origin : entry.second) { + base::Value origin_object(base::Value::Type::DICTIONARY); + origin_object.SetKey("origin", base::Value(origin)); + origin_object.SetKey( + "engagement", + base::Value(engagement_service->GetScore(GURL(origin)))); + origin_object.SetKey("usage", base::Value(0)); + origin_list.GetList().emplace_back(std::move(origin_object)); + } + site_group.SetKey(kNumCookies, base::Value(0)); + site_group.SetKey(kOriginList, std::move(origin_list)); + list_value->GetList().push_back(std::move(site_group)); + } +} + } // namespace - SiteSettingsHandler::SiteSettingsHandler(Profile* profile) - : profile_(profile), observer_(this) { -} + : profile_(profile), observer_(this), local_storage_helper_(nullptr) {} SiteSettingsHandler::~SiteSettingsHandler() { } @@ -190,6 +220,10 @@ base::BindRepeating(&SiteSettingsHandler::HandleGetAllSites, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "getFormattedBytes", + base::BindRepeating(&SiteSettingsHandler::HandleGetFormattedBytes, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "getExceptionList", base::BindRepeating(&SiteSettingsHandler::HandleGetExceptionList, base::Unretained(this))); @@ -425,9 +459,7 @@ base::Unretained(this), barrier)); // Also clear the *local* storage data. - scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper = - new BrowsingDataLocalStorageHelper(profile_); - local_storage_helper->DeleteOrigin(url, barrier); + GetLocalStorageHelper()->DeleteOrigin(url, barrier); } } @@ -560,6 +592,10 @@ // TODO(https://crbug.com/835712): Assess performance of this method for // unusually large numbers of stored content settings. + // Add sites that are using any local storage to the list. + GetLocalStorageHelper()->StartFetching(base::BindRepeating( + &SiteSettingsHandler::OnLocalStorageFetched, base::Unretained(this))); + // Retrieve a list of embargoed settings to check separately. This ensures // that only settings included in |content_types| will be listed in all sites. ContentSettingsForOneType embargo_settings; @@ -584,9 +620,6 @@ // Convert |types| to a list of ContentSettingsTypes. for (ContentSettingsType content_type : content_types) { - // TODO(https://crbug.com/835712): Add extension content settings, plus - // sites that use any non-zero amount of storage. - ContentSettingsForOneType entries; map->GetSettingsForOneType(content_type, std::string(), &entries); for (const ContentSettingPatternSource& e : entries) { @@ -596,23 +629,53 @@ } } - // Convert |all_sites_map| to a list of base::DictionaryValues. base::Value result(base::Value::Type::LIST); - for (const auto& entry : all_sites_map) { - // eTLD+1 is the effective top level domain + 1. - base::Value site_group(base::Value::Type::DICTIONARY); - site_group.SetKey(kEffectiveTopLevelDomainPlus1Name, - base::Value(entry.first)); - base::Value origin_list(base::Value::Type::LIST); - for (const std::string& origin : entry.second) { - origin_list.GetList().emplace_back(origin); - } - site_group.SetKey(kOriginList, std::move(origin_list)); - result.GetList().push_back(std::move(site_group)); - } + ConvertSiteGroupMapToListValue(all_sites_map, &result, profile); ResolveJavascriptCallback(*callback_id, result); } +void SiteSettingsHandler::OnLocalStorageFetched( + const std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>& + local_storage_info) { + std::map<std::string, int> origin_size_map; + std::map<std::string, std::set<std::string>> all_sites_map; + for (const BrowsingDataLocalStorageHelper::LocalStorageInfo& info : + local_storage_info) { + origin_size_map.emplace(info.origin_url.spec(), info.size); + CreateOrAppendSiteGroupEntry(&all_sites_map, info.origin_url); + } + base::Value result(base::Value::Type::LIST); + ConvertSiteGroupMapToListValue(all_sites_map, &result, profile_); + + // Merge the origin usage number into |result|. + for (size_t i = 0; i < result.GetList().size(); ++i) { + base::Value* site_group = &result.GetList()[i]; + base::Value* origin_list = site_group->FindKey(kOriginList); + + for (size_t i = 0; i < origin_list->GetList().size(); ++i) { + base::Value* origin_info = &origin_list->GetList()[i]; + const std::string& origin = origin_info->FindKey("origin")->GetString(); + const auto& size_info = origin_size_map.find(origin); + if (size_info != origin_size_map.end()) + origin_info->SetKey("usage", base::Value(size_info->second)); + } + } + FireWebUIListener("onLocalStorageListFetched", result); +} + +void SiteSettingsHandler::HandleGetFormattedBytes(const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(2U, args->GetSize()); + const base::Value* callback_id; + CHECK(args->Get(0, &callback_id)); + int num_bytes; + CHECK(args->GetInteger(1, &num_bytes)); + + const base::string16 string = ui::FormatBytes(num_bytes); + ResolveJavascriptCallback(*callback_id, base::Value(string)); +} + void SiteSettingsHandler::HandleGetExceptionList(const base::ListValue* args) { AllowJavascript(); @@ -1053,4 +1116,16 @@ host_zoom_map->SetZoomLevelForHost(origin, default_level); } +void SiteSettingsHandler::SetBrowsingDataLocalStorageHelperForTesting( + scoped_refptr<BrowsingDataLocalStorageHelper> helper) { + DCHECK(!local_storage_helper_); + local_storage_helper_ = helper; +} + +BrowsingDataLocalStorageHelper* SiteSettingsHandler::GetLocalStorageHelper() { + if (!local_storage_helper_) + local_storage_helper_ = new BrowsingDataLocalStorageHelper(profile_); + return local_storage_helper_.get(); +} + } // namespace settings
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h index 3f5b4a4..4d27fd1 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -10,6 +10,7 @@ #include <vector> #include "base/scoped_observer.h" +#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" #include "chrome/browser/storage/storage_info_fetcher.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "components/content_settings/core/browser/content_settings_observer.h" @@ -85,6 +86,7 @@ FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAndSetForInvalidURLs); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Incognito); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAllSites); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAllSitesLocalStorage); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Origins); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Patterns); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ZoomLevels); @@ -113,6 +115,16 @@ // 1, affected by any of the content settings specified in |args|. void HandleGetAllSites(const base::ListValue* args); + // Called when the list of origins using local storage has been fetched, and + // sends this list back to the front end. + void OnLocalStorageFetched( + const std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>& + local_storage_info); + + // Converts a given number of bytes into a human-readable format, with data + // units. + void HandleGetFormattedBytes(const base::ListValue* args); + // Returns the list of site exceptions for a given content settings type. void HandleGetExceptionList(const base::ListValue* args); @@ -151,6 +163,11 @@ // Removes a particular zoom level for a given host. void HandleRemoveZoomLevel(const base::ListValue* args); + void SetBrowsingDataLocalStorageHelperForTesting( + scoped_refptr<BrowsingDataLocalStorageHelper> helper); + + BrowsingDataLocalStorageHelper* GetLocalStorageHelper(); + Profile* profile_; content::NotificationRegistrar notification_registrar_; @@ -173,6 +190,8 @@ std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; #endif + scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper_; + DISALLOW_COPY_AND_ASSIGN(SiteSettingsHandler); };
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index 2b1e370..88cd0a42 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -9,6 +9,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" +#include "chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/extensions/extension_service.h" @@ -407,8 +408,10 @@ site_group.FindKey("origins")->GetList(); EXPECT_EQ("example.com", etld_plus1_string); EXPECT_EQ(2UL, origin_list.size()); - EXPECT_EQ(url1.spec(), origin_list[0].GetString()); - EXPECT_EQ(url2.spec(), origin_list[1].GetString()); + EXPECT_EQ(url1.spec(), origin_list[0].FindKey("origin")->GetString()); + EXPECT_EQ(0, origin_list[0].FindKey("engagement")->GetDouble()); + EXPECT_EQ(url2.spec(), origin_list[1].FindKey("origin")->GetString()); + EXPECT_EQ(0, origin_list[1].FindKey("engagement")->GetDouble()); } } @@ -434,7 +437,7 @@ site_group.FindKey("origins")->GetList(); if (etld_plus1_string == "example2.net") { EXPECT_EQ(1UL, origin_list.size()); - EXPECT_EQ(url3.spec(), origin_list[0].GetString()); + EXPECT_EQ(url3.spec(), origin_list[0].FindKey("origin")->GetString()); } else { EXPECT_EQ("example.com", etld_plus1_string); } @@ -444,6 +447,9 @@ // Test embargoed settings also appear. PermissionDecisionAutoBlocker* auto_blocker = PermissionDecisionAutoBlocker::GetForProfile(profile()); + base::SimpleTestClock clock; + clock.SetNow(base::Time::Now()); + auto_blocker->SetClockForTesting(&clock); const GURL url4("https://example2.co.uk"); for (int i = 0; i < 3; ++i) { auto_blocker->RecordDismissAndEmbargo(url4, @@ -465,11 +471,24 @@ EXPECT_EQ(3UL, site_groups.size()); } - // Add an expired embargo setting to a) an existing eTLD+1 group and b) a new - // eTLD+1 group. - base::SimpleTestClock clock; - clock.SetNow(base::Time::Now()); - auto_blocker->SetClockForTesting(&clock); + // Check |url4| disappears from the list when its embargo expires. + clock.Advance(base::TimeDelta::FromDays(8)); + handler()->HandleGetAllSites(&get_all_sites_args); + + { + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIResponse", data.function_name()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); + ASSERT_TRUE(data.arg2()->GetBool()); + + const base::Value::ListStorage& site_groups = data.arg3()->GetList(); + EXPECT_EQ(2UL, site_groups.size()); + EXPECT_EQ("example.com", site_groups[0].FindKey("etldPlus1")->GetString()); + EXPECT_EQ("example2.net", site_groups[1].FindKey("etldPlus1")->GetString()); + } + + // Add an expired embargo setting to an existing eTLD+1 group and make sure it + // still appears. for (int i = 0; i < 3; ++i) { auto_blocker->RecordDismissAndEmbargo(url3, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); @@ -484,6 +503,7 @@ auto_blocker->GetEmbargoResult(url3, CONTENT_SETTINGS_TYPE_NOTIFICATIONS) .content_setting); + handler()->HandleGetAllSites(&get_all_sites_args); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); @@ -491,10 +511,12 @@ ASSERT_TRUE(data.arg2()->GetBool()); const base::Value::ListStorage& site_groups = data.arg3()->GetList(); - EXPECT_EQ(3UL, site_groups.size()); + EXPECT_EQ(2UL, site_groups.size()); + EXPECT_EQ("example.com", site_groups[0].FindKey("etldPlus1")->GetString()); + EXPECT_EQ("example2.net", site_groups[1].FindKey("etldPlus1")->GetString()); } - clock.SetNow(base::Time::Now()); + // Add an expired embargo to a new eTLD+1 and make sure it doesn't appear. const GURL url5("http://test.example5.com"); for (int i = 0; i < 3; ++i) { auto_blocker->RecordDismissAndEmbargo(url5, @@ -510,6 +532,7 @@ auto_blocker->GetEmbargoResult(url5, CONTENT_SETTINGS_TYPE_NOTIFICATIONS) .content_setting); + handler()->HandleGetAllSites(&get_all_sites_args); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); @@ -517,8 +540,71 @@ ASSERT_TRUE(data.arg2()->GetBool()); const base::Value::ListStorage& site_groups = data.arg3()->GetList(); - EXPECT_EQ(3UL, site_groups.size()); + EXPECT_EQ(2UL, site_groups.size()); + EXPECT_EQ("example.com", site_groups[0].FindKey("etldPlus1")->GetString()); + EXPECT_EQ("example2.net", site_groups[1].FindKey("etldPlus1")->GetString()); } + + // Each call to HandleGetAllSites() above added a callback to the profile's + // BrowsingDataLocalStorageHelper, so make sure these aren't stuck waiting to + // run at the end of the test. + base::RunLoop run_loop; + run_loop.RunUntilIdle(); +} + +TEST_F(SiteSettingsHandlerTest, GetAllSitesLocalStorage) { + scoped_refptr<MockBrowsingDataLocalStorageHelper> + mock_browsing_data_local_storage_helper = + new MockBrowsingDataLocalStorageHelper(profile()); + handler()->SetBrowsingDataLocalStorageHelperForTesting( + mock_browsing_data_local_storage_helper); + + // Add local storage for |origin|. + const GURL origin("https://example.com:12378"); + mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin(origin, 1); + + // Check these sites are included in the callback. + base::ListValue get_all_sites_args; + get_all_sites_args.AppendString(kCallbackId); + base::Value category_list(base::Value::Type::LIST); + get_all_sites_args.GetList().push_back(std::move(category_list)); + + // Wait for the fetch handler to finish, then check it includes |origin| in + // its result. + handler()->HandleGetAllSites(&get_all_sites_args); + EXPECT_EQ(1U, web_ui()->call_data().size()); + mock_browsing_data_local_storage_helper->Notify(); + EXPECT_EQ(2U, web_ui()->call_data().size()); + base::RunLoop run_loop; + run_loop.RunUntilIdle(); + + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); + + std::string callback_id; + ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); + EXPECT_EQ("onLocalStorageListFetched", callback_id); + + const base::ListValue* local_storage_list; + ASSERT_TRUE(data.arg2()->GetAsList(&local_storage_list)); + EXPECT_EQ(1U, local_storage_list->GetSize()); + + const base::DictionaryValue* site_group; + ASSERT_TRUE(local_storage_list->GetDictionary(0, &site_group)); + + std::string etld_plus1_string; + ASSERT_TRUE(site_group->GetString("etldPlus1", &etld_plus1_string)); + ASSERT_EQ("example.com", etld_plus1_string); + + const base::ListValue* origin_list; + ASSERT_TRUE(site_group->GetList("origins", &origin_list)); + EXPECT_EQ(1U, origin_list->GetSize()); + + const base::DictionaryValue* origin_info; + ASSERT_TRUE(origin_list->GetDictionary(0, &origin_info)); + EXPECT_EQ(origin.spec(), origin_info->FindKey("origin")->GetString()); + EXPECT_EQ(0, origin_info->FindKey("engagement")->GetDouble()); + EXPECT_EQ(1, origin_info->FindKey("usage")->GetDouble()); } TEST_F(SiteSettingsHandlerTest, Origins) {
diff --git a/chrome/browser/vr/test/vr_browser_test.h b/chrome/browser/vr/test/vr_browser_test.h deleted file mode 100644 index 7a3b3c1..0000000 --- a/chrome/browser/vr/test/vr_browser_test.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2018 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 CHROME_BROWSER_VR_TEST_VR_BROWSER_TEST_H_ -#define CHROME_BROWSER_VR_TEST_VR_BROWSER_TEST_H_ - -#include "chrome/browser/vr/test/vr_xr_browser_test.h" -#include "chrome/common/chrome_features.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/content_features.h" -#include "content/public/common/content_switches.h" - -namespace vr { - -// VR-specific test base class. -class VrBrowserTestBase : public VrXrBrowserTestBase { - public: - // Returns true if the JavaScript in the given WebContents has found a - // WebVR VRDisplay, false otherwise. - static bool VrDisplayFound(content::WebContents* web_contents); - - void EnterPresentation(content::WebContents* web_contents) override; - void EnterPresentationOrFail(content::WebContents* web_contents) override; - void ExitPresentation(content::WebContents* web_contents) override; - void ExitPresentationOrFail(content::WebContents* web_contents) override; -}; - -// Test class with standard features enabled: WebVR, OpenVR support, and the -// Gamepad API. -class VrBrowserTestStandard : public VrBrowserTestBase { - public: - VrBrowserTestStandard() { - append_switches_.push_back(switches::kEnableWebVR); - enable_features_.push_back(features::kOpenVR); - enable_features_.push_back(features::kGamepadExtensions); - } -}; - -// Test class with WebVR disabled. -class VrBrowserTestWebVrDisabled : public VrBrowserTestBase { - public: - VrBrowserTestWebVrDisabled() { - enable_features_.push_back(features::kOpenVR); - enable_features_.push_back(features::kGamepadExtensions); - } -}; - -// Test class with OpenVR support disabled. -class VrBrowserTestOpenVrDisabled : public VrBrowserTestBase { - public: - VrBrowserTestOpenVrDisabled() { - append_switches_.push_back(switches::kEnableWebVR); - enable_features_.push_back(features::kGamepadExtensions); - } -}; - -} // namespace vr - -#endif // CHROME_BROWSER_VR_TEST_VR_BROWSER_TEST_H_
diff --git a/chrome/browser/vr/test/vr_xr_browser_test.cc b/chrome/browser/vr/test/vr_xr_browser_test.cc deleted file mode 100644 index 454fe60..0000000 --- a/chrome/browser/vr/test/vr_xr_browser_test.cc +++ /dev/null
@@ -1,233 +0,0 @@ -// Copyright 2017 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 <cstring> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/environment.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" -#include "base/threading/platform_thread.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/vr/test/vr_browser_test.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/browser_test_utils.h" -#include "url/gurl.h" - -namespace vr { - -constexpr base::TimeDelta VrXrBrowserTestBase::kPollCheckIntervalShort; -constexpr base::TimeDelta VrXrBrowserTestBase::kPollCheckIntervalLong; -constexpr base::TimeDelta VrXrBrowserTestBase::kPollTimeoutShort; -constexpr base::TimeDelta VrXrBrowserTestBase::kPollTimeoutLong; -constexpr char VrXrBrowserTestBase::kVrOverrideEnvVar[]; -constexpr char VrXrBrowserTestBase::kVrOverrideVal[]; -constexpr char VrXrBrowserTestBase::kVrConfigPathEnvVar[]; -constexpr char VrXrBrowserTestBase::kVrConfigPathVal[]; -constexpr char VrXrBrowserTestBase::kVrLogPathEnvVar[]; -constexpr char VrXrBrowserTestBase::kVrLogPathVal[]; - -VrXrBrowserTestBase::VrXrBrowserTestBase() - : env_(base::Environment::Create()) {} - -VrXrBrowserTestBase::~VrXrBrowserTestBase() = default; - -// We need an std::string that is an absolute file path, which requires -// platform-specific logic since Windows uses std::wstring instead of -// std::string for FilePaths, but SetVar only accepts std::string -#ifdef OS_WIN -#define MAKE_ABSOLUTE(x) \ - base::WideToUTF8( \ - base::MakeAbsoluteFilePath(base::FilePath(base::UTF8ToWide(x))).value()) -#else -#define MAKE_ABSOLUTE(x) base::MakeAbsoluteFilePath(base::FilePath(x)).value() -#endif - -void VrXrBrowserTestBase::SetUp() { - // Set the environment variable to use the mock OpenVR client. - EXPECT_TRUE(env_->SetVar(kVrOverrideEnvVar, MAKE_ABSOLUTE(kVrOverrideVal))); - EXPECT_TRUE( - env_->SetVar(kVrConfigPathEnvVar, MAKE_ABSOLUTE(kVrConfigPathVal))); - EXPECT_TRUE(env_->SetVar(kVrLogPathEnvVar, MAKE_ABSOLUTE(kVrLogPathVal))); - - // Set any command line flags that subclasses have set, e.g. enabling WebVR - // and OpenVR support - for (const auto& switch_string : append_switches_) { - base::CommandLine::ForCurrentProcess()->AppendSwitch(switch_string); - } - scoped_feature_list_.InitWithFeatures(enable_features_, {}); - - InProcessBrowserTest::SetUp(); -} - -GURL VrXrBrowserTestBase::GetHtmlTestFile(const std::string& test_name) { - return ui_test_utils::GetTestUrl( - base::FilePath(FILE_PATH_LITERAL("xr/e2e_test_files/html")), -#ifdef OS_WIN - base::FilePath(base::UTF8ToWide(test_name + ".html") -#else - base::FilePath(test_name + ".html") -#endif - )); -} - -content::WebContents* VrXrBrowserTestBase::GetFirstTabWebContents() { - return browser()->tab_strip_model()->GetWebContentsAt(0); -} - -void VrXrBrowserTestBase::LoadUrlAndAwaitInitialization(const GURL& url) { - ui_test_utils::NavigateToURL(browser(), url); - EXPECT_TRUE(PollJavaScriptBoolean( - "isInitializationComplete()", kPollTimeoutShort, - browser()->tab_strip_model()->GetActiveWebContents())) - << "Timed out waiting for JavaScript test initialization."; -} - -VrXrBrowserTestBase::TestStatus VrXrBrowserTestBase::CheckTestStatus( - content::WebContents* web_contents) { - std::string result_string = - RunJavaScriptAndExtractStringOrFail("resultString", web_contents); - bool test_passed = - RunJavaScriptAndExtractBoolOrFail("testPassed", web_contents); - if (test_passed) { - return VrXrBrowserTestBase::TestStatus::STATUS_PASSED; - } else if (!test_passed && result_string == "") { - return VrXrBrowserTestBase::TestStatus::STATUS_RUNNING; - } - // !test_passed && result_string != "" - return VrXrBrowserTestBase::TestStatus::STATUS_FAILED; -} - -void VrXrBrowserTestBase::EndTest(content::WebContents* web_contents) { - switch (CheckTestStatus(web_contents)) { - case VrXrBrowserTestBase::TestStatus::STATUS_PASSED: - break; - case VrXrBrowserTestBase::TestStatus::STATUS_FAILED: - FAIL() << "JavaScript testharness failed with result: " - << RunJavaScriptAndExtractStringOrFail("resultString", - web_contents); - break; - case VrXrBrowserTestBase::TestStatus::STATUS_RUNNING: - FAIL() << "Attempted to end test in C++ without finishing in JavaScript"; - break; - default: - FAIL() << "Received unknown test status."; - } -} - -bool VrXrBrowserTestBase::PollJavaScriptBoolean( - const std::string& bool_expression, - const base::TimeDelta& timeout, - content::WebContents* web_contents) { - return BlockOnConditionUnsafe( - base::BindRepeating(RunJavaScriptAndExtractBoolOrFail, bool_expression, - web_contents), - timeout); -} - -void VrXrBrowserTestBase::WaitOnJavaScriptStep( - content::WebContents* web_contents) { - // Make sure we aren't trying to wait on a JavaScript test step without the - // code to do so. - bool code_available = RunJavaScriptAndExtractBoolOrFail( - "typeof javascriptDone !== 'undefined'", web_contents); - EXPECT_TRUE(code_available) << "Attempted to wait on a JavaScript test step " - << "without the code to do so. You either forgot " - << "to import webvr_e2e.js or " - << "are incorrectly using a C++ function."; - - // Actually wait for the step to finish - bool success = - PollJavaScriptBoolean("javascriptDone", kPollTimeoutLong, web_contents); - - // Check what state we're in to make sure javascriptDone wasn't called - // because the test failed. - VrXrBrowserTestBase::TestStatus test_status = CheckTestStatus(web_contents); - if (!success || - test_status == VrXrBrowserTestBase::TestStatus::STATUS_FAILED) { - // Failure states: Either polling failed or polling succeeded, but because - // the test failed. - std::string reason; - if (!success) { - reason = "Polling JavaScript boolean javascriptDone timed out."; - } else { - reason = - "Polling JavaScript boolean javascriptDone succeeded, but test " - "failed."; - } - - std::string result_string = - RunJavaScriptAndExtractStringOrFail("resultString", web_contents); - if (result_string == "") { - reason += " Did not obtain specific reason from testharness."; - } else { - reason += " Testharness reported failure: " + result_string; - } - FAIL() << reason; - } - - // Reset the synchronization boolean - EXPECT_TRUE(content::ExecuteScript(web_contents, "javascriptDone = false")); -} - -void VrXrBrowserTestBase::ExecuteStepAndWait( - const std::string& step_function, - content::WebContents* web_contents) { - EXPECT_TRUE(content::ExecuteScript(web_contents, step_function)); - WaitOnJavaScriptStep(web_contents); -} - -bool VrXrBrowserTestBase::BlockOnConditionUnsafe( - base::RepeatingCallback<bool()> condition, - const base::TimeDelta& timeout, - const base::TimeDelta& period) { - base::Time start = base::Time::Now(); - bool successful = false; - while (base::Time::Now() - start < timeout) { - successful = condition.Run(); - if (successful) { - break; - } - base::PlatformThread::Sleep(period); - } - return successful; -} - -bool VrXrBrowserTestBase::RunJavaScriptAndExtractBoolOrFail( - const std::string& js_expression, - content::WebContents* web_contents) { - bool result; - DLOG(ERROR) << "Run javascript: " << js_expression; - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - web_contents, - "window.domAutomationController.send(" + js_expression + ")", &result)); - return result; -} - -std::string VrXrBrowserTestBase::RunJavaScriptAndExtractStringOrFail( - const std::string& js_expression, - content::WebContents* web_contents) { - std::string result; - EXPECT_TRUE(content::ExecuteScriptAndExtractString( - web_contents, - "window.domAutomationController.send(" + js_expression + ")", &result)); - return result; -} - -void VrXrBrowserTestBase::EnterPresentationAndWait( - content::WebContents* web_contents) { - EnterPresentation(web_contents); - WaitOnJavaScriptStep(web_contents); -} - -} // namespace vr
diff --git a/chrome/browser/vr/test/vr_xr_browser_test.h b/chrome/browser/vr/test/vr_xr_browser_test.h deleted file mode 100644 index b128bb50..0000000 --- a/chrome/browser/vr/test/vr_xr_browser_test.h +++ /dev/null
@@ -1,153 +0,0 @@ -// Copyright 2017 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 CHROME_BROWSER_VR_TEST_VR_XR_BROWSER_TEST_H_ -#define CHROME_BROWSER_VR_TEST_VR_XR_BROWSER_TEST_H_ - -#include "base/callback.h" -#include "base/environment.h" -#include "base/test/scoped_feature_list.h" -#include "base/time/time.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/common/chrome_features.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/content_features.h" -#include "content/public/common/content_switches.h" -#include "url/gurl.h" - -#define REQUIRES_GPU(x) DISABLED_##x - -namespace vr { - -// Base browser test class for running VR/XR-related tests. -// This is essentially a C++ port of the way Android does similar tests in -// //chrome/android/javatests/src/.../browser/vr/TestFramework.java -// This must be subclassed for VR or XR in order to handle the few differences -// between WebVR and WebXR. -class VrXrBrowserTestBase : public InProcessBrowserTest { - public: - static constexpr base::TimeDelta kPollCheckIntervalShort = - base::TimeDelta::FromMilliseconds(50); - static constexpr base::TimeDelta kPollCheckIntervalLong = - base::TimeDelta::FromMilliseconds(100); - static constexpr base::TimeDelta kPollTimeoutShort = - base::TimeDelta::FromMilliseconds(1000); - static constexpr base::TimeDelta kPollTimeoutLong = - base::TimeDelta::FromMilliseconds(10000); - static constexpr char kVrOverrideEnvVar[] = "VR_OVERRIDE"; - static constexpr char kVrOverrideVal[] = "./mock_vr_clients/"; - static constexpr char kVrConfigPathEnvVar[] = "VR_CONFIG_PATH"; - static constexpr char kVrConfigPathVal[] = "./"; - static constexpr char kVrLogPathEnvVar[] = "VR_LOG_PATH"; - static constexpr char kVrLogPathVal[] = "./"; - enum class TestStatus { - STATUS_RUNNING = 0, - STATUS_PASSED = 1, - STATUS_FAILED = 2 - }; - - VrXrBrowserTestBase(); - ~VrXrBrowserTestBase() override; - - void SetUp() override; - - // Returns a GURL to the VR test HTML file of the given name, e.g. - // GetHtmlTestFile("foo") returns a GURL for the foo.html file in the VR - // test HTML directory. - GURL GetHtmlTestFile(const std::string& test_name); - - // Convenience function for accessing the WebContents belonging to the first - // tab open in the browser. - content::WebContents* GetFirstTabWebContents(); - - // Loads the given GURL and blocks until the JavaScript on the page has - // signalled that pre-test initialization is complete. - void LoadUrlAndAwaitInitialization(const GURL& url); - - // Retrieves the current status of the JavaScript test and returns an enum - // corresponding to it. - static TestStatus CheckTestStatus(content::WebContents* web_contents); - - // Asserts that the JavaScript test code completed successfully. - static void EndTest(content::WebContents* web_contents); - - // Blocks until the given JavaScript expression evaluates to true or the - // timeout is reached. Returns true if the expression evaluated to true or - // false on timeout. - static bool PollJavaScriptBoolean(const std::string& bool_expression, - const base::TimeDelta& timeout, - content::WebContents* web_contents); - - // Blocks until the JavaScript in the given WebContents signals that it is - // finished. - static void WaitOnJavaScriptStep(content::WebContents* web_contents); - - // Executes the given step/JavaScript expression and blocks until JavaScript - // signals that it is finished. - static void ExecuteStepAndWait(const std::string& step_function, - content::WebContents* web_contents); - - // Blocks until the given callback returns true or the timeout is reached. - // Returns true if the condition successfully resolved or false on timeout. - // This is unsafe because it relies on the provided callback checking a result - // from a different thread. This isn't an issue when blocking on some - // JavaScript condition to be true, but could be problematic if forced into - // use elsewhere. - static bool BlockOnConditionUnsafe( - base::RepeatingCallback<bool()> condition, - const base::TimeDelta& timeout = kPollTimeoutLong, - const base::TimeDelta& period = kPollCheckIntervalLong); - - // Convenience function for ensuring ExecuteScriptAndExtractBool runs - // successfully and for directly getting the result instead of needing to pass - // a pointer to be filled. - static bool RunJavaScriptAndExtractBoolOrFail( - const std::string& js_expression, - content::WebContents* web_contents); - - // Convenience function for ensuring ExecuteScripteAndExtractString runs - // successfully and for directly getting the result instead of needing to pass - // a pointer to be filled. - static std::string RunJavaScriptAndExtractStringOrFail( - const std::string& js_expression, - content::WebContents* web_contents); - - // Enters either WebVR presentation or WebXR presentation (immersive session). - virtual void EnterPresentation(content::WebContents* web_contents) = 0; - - // Enters either WebVR presentation or WebXR presentation and waits for the - // JavaScript step to end. - void EnterPresentationAndWait(content::WebContents* web_contents); - - // Enters either WebVR presentation or WebXR presentation, failing the test if - // it is not able to. - virtual void EnterPresentationOrFail(content::WebContents* web_contents) = 0; - - // Exits either WebVR presentation or WebXR presentation (immersive session). - virtual void ExitPresentation(content::WebContents* web_contents) = 0; - - // Exits either WebVR presentation or WebXR presentation and waits for the - // JavaScript step to end. - void ExitPresentationAndWait(content::WebContents* web_contents); - - // Exits either WebVR presentation or WebXR presentation, failing the test if - // it is not able to. - virtual void ExitPresentationOrFail(content::WebContents* web_contents) = 0; - - Browser* browser() { return InProcessBrowserTest::browser(); } - - protected: - std::unique_ptr<base::Environment> env_; - std::vector<base::Feature> enable_features_; - std::vector<std::string> append_switches_; - - private: - base::test::ScopedFeatureList scoped_feature_list_; - DISALLOW_COPY_AND_ASSIGN(VrXrBrowserTestBase); -}; - -} // namespace vr - -#endif // CHROME_BROWSER_VR_TEST_VR_XR_BROWSER_TEST_H_
diff --git a/chrome/browser/vr/test/vr_browser_test.cc b/chrome/browser/vr/test/webvr_browser_test.cc similarity index 71% rename from chrome/browser/vr/test/vr_browser_test.cc rename to chrome/browser/vr/test/webvr_browser_test.cc index e96b01da..22d420f 100644 --- a/chrome/browser/vr/test/vr_browser_test.cc +++ b/chrome/browser/vr/test/webvr_browser_test.cc
@@ -4,37 +4,38 @@ #include <cstring> -#include "chrome/browser/vr/test/vr_browser_test.h" +#include "chrome/browser/vr/test/webvr_browser_test.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" namespace vr { -bool VrBrowserTestBase::VrDisplayFound(content::WebContents* web_contents) { +bool WebVrBrowserTestBase::XrDeviceFound(content::WebContents* web_contents) { return RunJavaScriptAndExtractBoolOrFail("vrDisplay != null", web_contents); } -void VrBrowserTestBase::EnterPresentation(content::WebContents* web_contents) { +void WebVrBrowserTestBase::EnterSessionWithUserGesture( + content::WebContents* web_contents) { // ExecuteScript runs with a user gesture, so we can just directly call // requestPresent instead of having to do the hacky workaround the // instrumentation tests use of actually sending a click event to the canvas. EXPECT_TRUE(content::ExecuteScript(web_contents, "onVrRequestPresent()")); } -void VrBrowserTestBase::EnterPresentationOrFail( +void WebVrBrowserTestBase::EnterSessionWithUserGestureOrFail( content::WebContents* web_contents) { - EnterPresentation(web_contents); + EnterSessionWithUserGesture(web_contents); EXPECT_TRUE(PollJavaScriptBoolean("vrDisplay.isPresenting", kPollTimeoutLong, web_contents)); } -void VrBrowserTestBase::ExitPresentation(content::WebContents* web_contents) { +void WebVrBrowserTestBase::EndSession(content::WebContents* web_contents) { EXPECT_TRUE(content::ExecuteScript(web_contents, "vrDisplay.exitPresent()")); } -void VrBrowserTestBase::ExitPresentationOrFail( +void WebVrBrowserTestBase::EndSessionOrFail( content::WebContents* web_contents) { - ExitPresentation(web_contents); + EndSession(web_contents); EXPECT_TRUE(PollJavaScriptBoolean("vrDisplay.isPresenting == false", kPollTimeoutLong, web_contents)); }
diff --git a/chrome/browser/vr/test/webvr_browser_test.h b/chrome/browser/vr/test/webvr_browser_test.h new file mode 100644 index 0000000..6f4b517e --- /dev/null +++ b/chrome/browser/vr/test/webvr_browser_test.h
@@ -0,0 +1,66 @@ +// Copyright 2018 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 CHROME_BROWSER_VR_TEST_WEBVR_BROWSER_TEST_H_ +#define CHROME_BROWSER_VR_TEST_WEBVR_BROWSER_TEST_H_ + +#include "chrome/browser/vr/test/webxr_vr_browser_test.h" +#include "chrome/common/chrome_features.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_features.h" +#include "content/public/common/content_switches.h" + +namespace vr { + +// WebVR-specific test base class. +class WebVrBrowserTestBase : public WebXrVrBrowserTestBase { + public: + bool XrDeviceFound(content::WebContents* web_contents) override; + void EnterSessionWithUserGesture(content::WebContents* web_contents) override; + void EnterSessionWithUserGestureOrFail( + content::WebContents* web_contents) override; + void EndSession(content::WebContents* web_contents) override; + void EndSessionOrFail(content::WebContents* web_contents) override; + + // Necessary to use the WebContents-less versions of functions. + using WebXrBrowserTestBase::XrDeviceFound; + using WebXrBrowserTestBase::EnterSessionWithUserGesture; + using WebXrBrowserTestBase::EnterSessionWithUserGestureAndWait; + using WebXrBrowserTestBase::EnterSessionWithUserGestureOrFail; + using WebXrBrowserTestBase::EndSession; + using WebXrBrowserTestBase::EndSessionOrFail; +}; + +// Test class with standard features enabled: WebVR, OpenVR support, and the +// Gamepad API. +class WebVrBrowserTestStandard : public WebVrBrowserTestBase { + public: + WebVrBrowserTestStandard() { + append_switches_.push_back(switches::kEnableWebVR); + enable_features_.push_back(features::kOpenVR); + enable_features_.push_back(features::kGamepadExtensions); + } +}; + +// Test class with WebVR disabled. +class WebVrBrowserTestWebVrDisabled : public WebVrBrowserTestBase { + public: + WebVrBrowserTestWebVrDisabled() { + enable_features_.push_back(features::kOpenVR); + enable_features_.push_back(features::kGamepadExtensions); + } +}; + +// Test class with OpenVR support disabled. +class WebVrBrowserTestOpenVrDisabled : public WebVrBrowserTestBase { + public: + WebVrBrowserTestOpenVrDisabled() { + append_switches_.push_back(switches::kEnableWebVR); + enable_features_.push_back(features::kGamepadExtensions); + } +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_TEST_WEBVR_BROWSER_TEST_H_
diff --git a/chrome/browser/vr/test/webxr_browser_test.cc b/chrome/browser/vr/test/webxr_browser_test.cc new file mode 100644 index 0000000..9441da2 --- /dev/null +++ b/chrome/browser/vr/test/webxr_browser_test.cc
@@ -0,0 +1,44 @@ +// Copyright 2018 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 "chrome/browser/vr/test/webxr_browser_test.h" +#include "content/public/browser/web_contents.h" + +namespace vr { + +bool WebXrBrowserTestBase::XrDeviceFound(content::WebContents* web_contents) { + return RunJavaScriptAndExtractBoolOrFail("xrDevice != null", web_contents); +} + +bool WebXrBrowserTestBase::XrDeviceFound() { + return XrDeviceFound(GetFirstTabWebContents()); +} + +void WebXrBrowserTestBase::EnterSessionWithUserGesture() { + EnterSessionWithUserGesture(GetFirstTabWebContents()); +} + +void WebXrBrowserTestBase::EnterSessionWithUserGestureAndWait( + content::WebContents* web_contents) { + EnterSessionWithUserGesture(web_contents); + WaitOnJavaScriptStep(web_contents); +} + +void WebXrBrowserTestBase::EnterSessionWithUserGestureAndWait() { + EnterSessionWithUserGestureAndWait(GetFirstTabWebContents()); +} + +void WebXrBrowserTestBase::EnterSessionWithUserGestureOrFail() { + EnterSessionWithUserGestureOrFail(GetFirstTabWebContents()); +} + +void WebXrBrowserTestBase::EndSession() { + EndSession(GetFirstTabWebContents()); +} + +void WebXrBrowserTestBase::EndSessionOrFail() { + EndSessionOrFail(GetFirstTabWebContents()); +} + +} // namespace vr
diff --git a/chrome/browser/vr/test/webxr_browser_test.h b/chrome/browser/vr/test/webxr_browser_test.h new file mode 100644 index 0000000..2979b87 --- /dev/null +++ b/chrome/browser/vr/test/webxr_browser_test.h
@@ -0,0 +1,67 @@ +// Copyright 2018 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 CHROME_BROWSER_VR_TEST_WEBXR_BROWSER_TEST_H_ +#define CHROME_BROWSER_VR_TEST_WEBXR_BROWSER_TEST_H_ + +#include "chrome/browser/vr/test/xr_browser_test.h" +#include "content/public/browser/web_contents.h" + +namespace vr { + +// Base browser test class for running WebXR/WebVR-related tests. +class WebXrBrowserTestBase : public XrBrowserTestBase { + public: + // Checks whether an XRDevice was actually found. + virtual bool XrDeviceFound(content::WebContents* web_contents); + + // Convenience function for calling XrDeviceFound with the return value of + // GetFirstTabWebContents. + bool XrDeviceFound(); + + // Enters a WebXR or WebVR session of some kind. + virtual void EnterSessionWithUserGesture( + content::WebContents* web_contents) = 0; + + // Convenience function for calling EnterSessionWithUserGesture with the + // return value of GetFirstTabWebContents. + void EnterSessionWithUserGesture(); + + // Enters a WebXR or WebVR session of some kind and waits until the page + // page reports it is finished with its JavaScript step. + void EnterSessionWithUserGestureAndWait(content::WebContents* web_contents); + + // Convenience function for calling EnterSessionWithUserGestureAndWait with + // the return value of GetFirstTabWebContents. + void EnterSessionWithUserGestureAndWait(); + + // Attempts to enter a WebXR or WebVR session of some kind, failing if it is + // unable to. + virtual void EnterSessionWithUserGestureOrFail( + content::WebContents* web_contents) = 0; + + // Convenience function for calling EnterSessionWithUserGestureOrFail with the + // return value of GetFirstTabWebContents. + void EnterSessionWithUserGestureOrFail(); + + // Ends whatever type of session a subclass enters with + // EnterSessionWithUserGesture. + virtual void EndSession(content::WebContents* web_contents) = 0; + + // Convenience function for calling EndSession with the return value of + // GetFirstTabWebContents. + void EndSession(); + + // Attempts to end whatever type of session a subclass enters with + // EnterSessionWithUserGesture, failing if it is unable to. + virtual void EndSessionOrFail(content::WebContents* web_contents) = 0; + + // Convenience function for calling EndSessionOrFail with the return value of + // GetFirstTabWebContents. + void EndSessionOrFail(); +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_TEST_WEBXR_BROWSER_TEST_H_
diff --git a/chrome/browser/vr/test/webxr_vr_browser_test.cc b/chrome/browser/vr/test/webxr_vr_browser_test.cc new file mode 100644 index 0000000..72c05ce8 --- /dev/null +++ b/chrome/browser/vr/test/webxr_vr_browser_test.cc
@@ -0,0 +1,43 @@ +// Copyright 2018 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 <cstring> + +#include "chrome/browser/vr/test/webxr_vr_browser_test.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test_utils.h" + +namespace vr { + +void WebXrVrBrowserTestBase::EnterSessionWithUserGesture( + content::WebContents* web_contents) { + // ExecuteScript runs with a user gesture, so we can just directly call + // requestSession instead of having to do the hacky workaround the + // instrumentation tests use of actually sending a click event to the canvas. + EXPECT_TRUE(content::ExecuteScript(web_contents, "onRequestSession()")); +} + +void WebXrVrBrowserTestBase::EnterSessionWithUserGestureOrFail( + content::WebContents* web_contents) { + EnterSessionWithUserGesture(web_contents); + EXPECT_TRUE(PollJavaScriptBoolean( + "sessionInfos[sessionTypes.IMMERSIVE].currentSession != null", + kPollTimeoutLong, web_contents)); +} + +void WebXrVrBrowserTestBase::EndSession(content::WebContents* web_contents) { + EXPECT_TRUE(content::ExecuteScript( + web_contents, + "sessionInfos[sessionTypes.IMMERSIVE].currentSession.end()")); +} + +void WebXrVrBrowserTestBase::EndSessionOrFail( + content::WebContents* web_contents) { + EndSession(web_contents); + EXPECT_TRUE(PollJavaScriptBoolean( + "sessionInfos[sessionTypes.IMMERSIVE].currentSession == null", + kPollTimeoutLong, web_contents)); +} + +} // namespace vr
diff --git a/chrome/browser/vr/test/webxr_vr_browser_test.h b/chrome/browser/vr/test/webxr_vr_browser_test.h new file mode 100644 index 0000000..e8f47129 --- /dev/null +++ b/chrome/browser/vr/test/webxr_vr_browser_test.h
@@ -0,0 +1,61 @@ +// Copyright 2018 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 CHROME_BROWSER_VR_TEST_WEBXR_VR_BROWSER_TEST_H_ +#define CHROME_BROWSER_VR_TEST_WEBXR_VR_BROWSER_TEST_H_ + +#include "chrome/browser/vr/test/webxr_browser_test.h" +#include "chrome/browser/vr/test/xr_browser_test.h" +#include "chrome/common/chrome_features.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_features.h" + +namespace vr { + +// WebXR for VR-specific test base class. +class WebXrVrBrowserTestBase : public WebXrBrowserTestBase { + public: + void EnterSessionWithUserGesture(content::WebContents* web_contents) override; + void EnterSessionWithUserGestureOrFail( + content::WebContents* web_contents) override; + void EndSession(content::WebContents* web_contents) override; + void EndSessionOrFail(content::WebContents* web_contents) override; + + // Necessary to use the WebContents-less versions of functions. + using WebXrBrowserTestBase::XrDeviceFound; + using WebXrBrowserTestBase::EnterSessionWithUserGesture; + using WebXrBrowserTestBase::EnterSessionWithUserGestureAndWait; + using WebXrBrowserTestBase::EnterSessionWithUserGestureOrFail; + using WebXrBrowserTestBase::EndSession; + using WebXrBrowserTestBase::EndSessionOrFail; +}; + +// Test class with standard features enabled: WebXR and OpenVR. +class WebXrVrBrowserTestStandard : public WebXrVrBrowserTestBase { + public: + WebXrVrBrowserTestStandard() { + enable_features_.push_back(features::kOpenVR); + enable_features_.push_back(features::kWebXr); + } +}; + +// Test class with WebXR disabled. +class WebXrVrBrowserTestWebXrDisabled : public WebXrVrBrowserTestBase { + public: + WebXrVrBrowserTestWebXrDisabled() { + enable_features_.push_back(features::kOpenVR); + } +}; + +// Test class with OpenVR disabled. +class WebXrVrBrowserTestOpenVrDisabled : public WebXrVrBrowserTestBase { + public: + WebXrVrBrowserTestOpenVrDisabled() { + enable_features_.push_back(features::kWebXr); + } +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_TEST_WEBXR_VR_BROWSER_TEST_H_
diff --git a/chrome/browser/vr/test/xr_browser_test.cc b/chrome/browser/vr/test/xr_browser_test.cc index fbd0aff60..99b8a6d 100644 --- a/chrome/browser/vr/test/xr_browser_test.cc +++ b/chrome/browser/vr/test/xr_browser_test.cc
@@ -4,43 +4,272 @@ #include <cstring> +#include "base/bind.h" +#include "base/callback.h" +#include "base/command_line.h" +#include "base/environment.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" +#include "base/threading/platform_thread.h" +#include "base/time/time.h" +#include "build/build_config.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/vr/test/xr_browser_test.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" +#include "url/gurl.h" namespace vr { -bool XrBrowserTestBase::XrDeviceFound(content::WebContents* web_contents) { - return RunJavaScriptAndExtractBoolOrFail("xrDevice != null", web_contents); +constexpr base::TimeDelta XrBrowserTestBase::kPollCheckIntervalShort; +constexpr base::TimeDelta XrBrowserTestBase::kPollCheckIntervalLong; +constexpr base::TimeDelta XrBrowserTestBase::kPollTimeoutShort; +constexpr base::TimeDelta XrBrowserTestBase::kPollTimeoutLong; +constexpr char XrBrowserTestBase::kVrOverrideEnvVar[]; +constexpr char XrBrowserTestBase::kVrOverrideVal[]; +constexpr char XrBrowserTestBase::kVrConfigPathEnvVar[]; +constexpr char XrBrowserTestBase::kVrConfigPathVal[]; +constexpr char XrBrowserTestBase::kVrLogPathEnvVar[]; +constexpr char XrBrowserTestBase::kVrLogPathVal[]; + +XrBrowserTestBase::XrBrowserTestBase() : env_(base::Environment::Create()) {} + +XrBrowserTestBase::~XrBrowserTestBase() = default; + +// We need an std::string that is an absolute file path, which requires +// platform-specific logic since Windows uses std::wstring instead of +// std::string for FilePaths, but SetVar only accepts std::string +#ifdef OS_WIN +#define MAKE_ABSOLUTE(x) \ + base::WideToUTF8( \ + base::MakeAbsoluteFilePath(base::FilePath(base::UTF8ToWide(x))).value()) +#else +#define MAKE_ABSOLUTE(x) base::MakeAbsoluteFilePath(base::FilePath(x)).value() +#endif + +void XrBrowserTestBase::SetUp() { + // Set the environment variable to use the mock OpenVR client. + EXPECT_TRUE(env_->SetVar(kVrOverrideEnvVar, MAKE_ABSOLUTE(kVrOverrideVal))); + EXPECT_TRUE( + env_->SetVar(kVrConfigPathEnvVar, MAKE_ABSOLUTE(kVrConfigPathVal))); + EXPECT_TRUE(env_->SetVar(kVrLogPathEnvVar, MAKE_ABSOLUTE(kVrLogPathVal))); + + // Set any command line flags that subclasses have set, e.g. enabling WebVR + // and OpenVR support + for (const auto& switch_string : append_switches_) { + base::CommandLine::ForCurrentProcess()->AppendSwitch(switch_string); + } + scoped_feature_list_.InitWithFeatures(enable_features_, {}); + + InProcessBrowserTest::SetUp(); } -void XrBrowserTestBase::EnterPresentation(content::WebContents* web_contents) { - // ExecuteScript runs with a user gesture, so we can just directly call - // requestSession instead of having to do the hacky workaround the - // instrumentation tests use of actually sending a click event to the canvas. - EXPECT_TRUE(content::ExecuteScript(web_contents, "onRequestSession()")); +GURL XrBrowserTestBase::GetHtmlTestFile(const std::string& test_name) { + return ui_test_utils::GetTestUrl( + base::FilePath(FILE_PATH_LITERAL("xr/e2e_test_files/html")), +#ifdef OS_WIN + base::FilePath(base::UTF8ToWide(test_name + ".html") +#else + base::FilePath(test_name + ".html") +#endif + )); } -void XrBrowserTestBase::EnterPresentationOrFail( - content::WebContents* web_contents) { - EnterPresentation(web_contents); +content::WebContents* XrBrowserTestBase::GetFirstTabWebContents() { + return browser()->tab_strip_model()->GetWebContentsAt(0); +} + +void XrBrowserTestBase::LoadUrlAndAwaitInitialization(const GURL& url) { + ui_test_utils::NavigateToURL(browser(), url); EXPECT_TRUE(PollJavaScriptBoolean( - "sessionInfos[sessionTypes.IMMERSIVE].currentSession != null", - kPollTimeoutLong, web_contents)); + "isInitializationComplete()", kPollTimeoutShort, + browser()->tab_strip_model()->GetActiveWebContents())) + << "Timed out waiting for JavaScript test initialization."; } -void XrBrowserTestBase::ExitPresentation(content::WebContents* web_contents) { - EXPECT_TRUE(content::ExecuteScript( +XrBrowserTestBase::TestStatus XrBrowserTestBase::CheckTestStatus( + content::WebContents* web_contents) { + std::string result_string = + RunJavaScriptAndExtractStringOrFail("resultString", web_contents); + bool test_passed = + RunJavaScriptAndExtractBoolOrFail("testPassed", web_contents); + if (test_passed) { + return XrBrowserTestBase::TestStatus::STATUS_PASSED; + } else if (!test_passed && result_string == "") { + return XrBrowserTestBase::TestStatus::STATUS_RUNNING; + } + // !test_passed && result_string != "" + return XrBrowserTestBase::TestStatus::STATUS_FAILED; +} + +void XrBrowserTestBase::EndTest(content::WebContents* web_contents) { + switch (CheckTestStatus(web_contents)) { + case XrBrowserTestBase::TestStatus::STATUS_PASSED: + break; + case XrBrowserTestBase::TestStatus::STATUS_FAILED: + FAIL() << "JavaScript testharness failed with result: " + << RunJavaScriptAndExtractStringOrFail("resultString", + web_contents); + break; + case XrBrowserTestBase::TestStatus::STATUS_RUNNING: + FAIL() << "Attempted to end test in C++ without finishing in JavaScript"; + break; + default: + FAIL() << "Received unknown test status."; + } +} + +void XrBrowserTestBase::AssertNoJavaScriptErrors( + content::WebContents* web_contents) { + if (CheckTestStatus(web_contents) == + XrBrowserTestBase::TestStatus::STATUS_FAILED) { + FAIL() << "JavaScript test harness failed with result: " + << RunJavaScriptAndExtractStringOrFail("resultString", web_contents); + } +} + +bool XrBrowserTestBase::PollJavaScriptBoolean( + const std::string& bool_expression, + const base::TimeDelta& timeout, + content::WebContents* web_contents) { + // Lambda used because otherwise BindRepeating gets confused about which + // version of RunJavaScriptAndExtractBoolOrFail to use. + return BlockOnConditionUnsafe( + base::BindRepeating( + [](XrBrowserTestBase* base, std::string expression, + content::WebContents* contents) { + return base->RunJavaScriptAndExtractBoolOrFail(expression, + contents); + }, + this, bool_expression, web_contents), + timeout); +} + +void XrBrowserTestBase::WaitOnJavaScriptStep( + content::WebContents* web_contents) { + // Make sure we aren't trying to wait on a JavaScript test step without the + // code to do so. + bool code_available = RunJavaScriptAndExtractBoolOrFail( + "typeof javascriptDone !== 'undefined'", web_contents); + EXPECT_TRUE(code_available) << "Attempted to wait on a JavaScript test step " + << "without the code to do so. You either forgot " + << "to import webvr_e2e.js or " + << "are incorrectly using a C++ function."; + + // Actually wait for the step to finish + bool success = + PollJavaScriptBoolean("javascriptDone", kPollTimeoutLong, web_contents); + + // Check what state we're in to make sure javascriptDone wasn't called + // because the test failed. + XrBrowserTestBase::TestStatus test_status = CheckTestStatus(web_contents); + if (!success || test_status == XrBrowserTestBase::TestStatus::STATUS_FAILED) { + // Failure states: Either polling failed or polling succeeded, but because + // the test failed. + std::string reason; + if (!success) { + reason = "Polling JavaScript boolean javascriptDone timed out."; + } else { + reason = + "Polling JavaScript boolean javascriptDone succeeded, but test " + "failed."; + } + + std::string result_string = + RunJavaScriptAndExtractStringOrFail("resultString", web_contents); + if (result_string == "") { + reason += " Did not obtain specific reason from testharness."; + } else { + reason += " Testharness reported failure: " + result_string; + } + FAIL() << reason; + } + + // Reset the synchronization boolean + EXPECT_TRUE(content::ExecuteScript(web_contents, "javascriptDone = false")); +} + +void XrBrowserTestBase::ExecuteStepAndWait(const std::string& step_function, + content::WebContents* web_contents) { + EXPECT_TRUE(content::ExecuteScript(web_contents, step_function)); + WaitOnJavaScriptStep(web_contents); +} + +bool XrBrowserTestBase::BlockOnConditionUnsafe( + base::RepeatingCallback<bool()> condition, + const base::TimeDelta& timeout, + const base::TimeDelta& period) { + base::Time start = base::Time::Now(); + bool successful = false; + while (base::Time::Now() - start < timeout) { + successful = condition.Run(); + if (successful) { + break; + } + base::PlatformThread::Sleep(period); + } + return successful; +} + +bool XrBrowserTestBase::RunJavaScriptAndExtractBoolOrFail( + const std::string& js_expression, + content::WebContents* web_contents) { + bool result; + DLOG(ERROR) << "Run javascript: " << js_expression; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( web_contents, - "sessionInfos[sessionTypes.IMMERSIVE].currentSession.end()")); + "window.domAutomationController.send(" + js_expression + ")", &result)); + return result; } -void XrBrowserTestBase::ExitPresentationOrFail( +std::string XrBrowserTestBase::RunJavaScriptAndExtractStringOrFail( + const std::string& js_expression, content::WebContents* web_contents) { - ExitPresentation(web_contents); - EXPECT_TRUE(PollJavaScriptBoolean( - "sessionInfos[sessionTypes.IMMERSIVE].currentSession == null", - kPollTimeoutLong, web_contents)); + std::string result; + EXPECT_TRUE(content::ExecuteScriptAndExtractString( + web_contents, + "window.domAutomationController.send(" + js_expression + ")", &result)); + return result; +} + +void XrBrowserTestBase::EndTest() { + EndTest(GetFirstTabWebContents()); +} + +void XrBrowserTestBase::AssertNoJavaScriptErrors() { + AssertNoJavaScriptErrors(GetFirstTabWebContents()); +} + +bool XrBrowserTestBase::PollJavaScriptBoolean( + const std::string& bool_expression, + const base::TimeDelta& timeout) { + return PollJavaScriptBoolean(bool_expression, timeout, + GetFirstTabWebContents()); +} + +void XrBrowserTestBase::WaitOnJavaScriptStep() { + WaitOnJavaScriptStep(GetFirstTabWebContents()); +} + +void XrBrowserTestBase::ExecuteStepAndWait(const std::string& step_function) { + ExecuteStepAndWait(step_function, GetFirstTabWebContents()); +} + +bool XrBrowserTestBase::RunJavaScriptAndExtractBoolOrFail( + const std::string& js_expression) { + return RunJavaScriptAndExtractBoolOrFail(js_expression, + GetFirstTabWebContents()); +} + +std::string XrBrowserTestBase::RunJavaScriptAndExtractStringOrFail( + const std::string& js_expression) { + return RunJavaScriptAndExtractStringOrFail(js_expression, + GetFirstTabWebContents()); } } // namespace vr
diff --git a/chrome/browser/vr/test/xr_browser_test.h b/chrome/browser/vr/test/xr_browser_test.h index c9af8d1..b6571cc 100644 --- a/chrome/browser/vr/test/xr_browser_test.h +++ b/chrome/browser/vr/test/xr_browser_test.h
@@ -1,53 +1,167 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2017 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 CHROME_BROWSER_VR_TEST_XR_BROWSER_TEST_H_ #define CHROME_BROWSER_VR_TEST_XR_BROWSER_TEST_H_ -#include "chrome/browser/vr/test/vr_xr_browser_test.h" +#include "base/callback.h" +#include "base/environment.h" +#include "base/test/scoped_feature_list.h" +#include "base/time/time.h" +#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_features.h" +#include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" +#include "content/public/common/content_switches.h" +#include "url/gurl.h" + +#define REQUIRES_GPU(x) DISABLED_##x namespace vr { -// XR-specific test base class. -class XrBrowserTestBase : public VrXrBrowserTestBase { +// Base browser test class for running XR-related tests. +// This is essentially a C++ port of the way Android does similar tests in +// //chrome/android/javatests/src/.../browser/vr/XrTestFramework.java +// This must be subclassed for different XR features to handle the differences +// between APIs and different usecases of the same API. +class XrBrowserTestBase : public InProcessBrowserTest { public: - // Returns true if the JavaScript in the given WebContents has found a WebXR - // XRDevice, false otherwise - static bool XrDeviceFound(content::WebContents* web_contents); + static constexpr base::TimeDelta kPollCheckIntervalShort = + base::TimeDelta::FromMilliseconds(50); + static constexpr base::TimeDelta kPollCheckIntervalLong = + base::TimeDelta::FromMilliseconds(100); + static constexpr base::TimeDelta kPollTimeoutShort = + base::TimeDelta::FromMilliseconds(1000); + static constexpr base::TimeDelta kPollTimeoutLong = + base::TimeDelta::FromMilliseconds(10000); + static constexpr char kVrOverrideEnvVar[] = "VR_OVERRIDE"; + static constexpr char kVrOverrideVal[] = "./mock_vr_clients/"; + static constexpr char kVrConfigPathEnvVar[] = "VR_CONFIG_PATH"; + static constexpr char kVrConfigPathVal[] = "./"; + static constexpr char kVrLogPathEnvVar[] = "VR_LOG_PATH"; + static constexpr char kVrLogPathVal[] = "./"; + enum class TestStatus { + STATUS_RUNNING = 0, + STATUS_PASSED = 1, + STATUS_FAILED = 2 + }; - void EnterPresentation(content::WebContents* web_contents) override; - void EnterPresentationOrFail(content::WebContents* web_contents) override; - void ExitPresentation(content::WebContents* web_contents) override; - void ExitPresentationOrFail(content::WebContents* web_contents) override; -}; + XrBrowserTestBase(); + ~XrBrowserTestBase() override; -// Test class with standard features enabled: WebXR and OpenVR. -class XrBrowserTestStandard : public XrBrowserTestBase { - public: - XrBrowserTestStandard() { - enable_features_.push_back(features::kOpenVR); - enable_features_.push_back(features::kWebXr); - } -}; + void SetUp() override; -// Test class with WebXR disabled. -class XrBrowserTestWebXrDisabled : public XrBrowserTestBase { - public: - XrBrowserTestWebXrDisabled() { - enable_features_.push_back(features::kOpenVR); - } -}; + // Returns a GURL to the VR test HTML file of the given name, e.g. + // GetHtmlTestFile("foo") returns a GURL for the foo.html file in the VR + // test HTML directory. + GURL GetHtmlTestFile(const std::string& test_name); -// Test class with OpenVR disabled. -class XrBrowserTestOpenVrDisabled : public XrBrowserTestBase { - public: - XrBrowserTestOpenVrDisabled() { - enable_features_.push_back(features::kWebXr); - } + // Convenience function for accessing the WebContents belonging to the first + // tab open in the browser. + content::WebContents* GetFirstTabWebContents(); + + // Loads the given GURL and blocks until the JavaScript on the page has + // signalled that pre-test initialization is complete. + void LoadUrlAndAwaitInitialization(const GURL& url); + + // Retrieves the current status of the JavaScript test and returns an enum + // corresponding to it. + TestStatus CheckTestStatus(content::WebContents* web_contents); + + // Asserts that the JavaScript test code completed successfully. + void EndTest(content::WebContents* web_contents); + + // Asserts that the JavaScript test harness did not detect any failures. + // Similar to EndTest, but does not fail if the test is still detected as + // running. This is useful because not all tests make use of the test harness' + // test/assert features, but may still want to ensure that no unexpected + // JavaScript errors were encountered. + void AssertNoJavaScriptErrors(content::WebContents* web_contents); + + // Blocks until the given JavaScript expression evaluates to true or the + // timeout is reached. Returns true if the expression evaluated to true or + // false on timeout. + bool PollJavaScriptBoolean(const std::string& bool_expression, + const base::TimeDelta& timeout, + content::WebContents* web_contents); + + // Blocks until the JavaScript in the given WebContents signals that it is + // finished. + void WaitOnJavaScriptStep(content::WebContents* web_contents); + + // Executes the given step/JavaScript expression and blocks until JavaScript + // signals that it is finished. + void ExecuteStepAndWait(const std::string& step_function, + content::WebContents* web_contents); + + // Blocks until the given callback returns true or the timeout is reached. + // Returns true if the condition successfully resolved or false on timeout. + // This is unsafe because it relies on the provided callback checking a result + // from a different thread. This isn't an issue when blocking on some + // JavaScript condition to be true, but could be problematic if forced into + // use elsewhere. + bool BlockOnConditionUnsafe( + base::RepeatingCallback<bool()> condition, + const base::TimeDelta& timeout = kPollTimeoutLong, + const base::TimeDelta& period = kPollCheckIntervalLong); + + // Convenience function for ensuring ExecuteScriptAndExtractBool runs + // successfully and for directly getting the result instead of needing to pass + // a pointer to be filled. + bool RunJavaScriptAndExtractBoolOrFail(const std::string& js_expression, + content::WebContents* web_contents); + + // Convenience function for ensuring ExecuteScripteAndExtractString runs + // successfully and for directly getting the result instead of needing to pass + // a pointer to be filled. + std::string RunJavaScriptAndExtractStringOrFail( + const std::string& js_expression, + content::WebContents* web_contents); + + Browser* browser() { return InProcessBrowserTest::browser(); } + + // Convenience function for running the static EndTest with the return value + // of GetFirstTabWebContents. + void EndTest(); + + // Convenience function for running the static AssertNoJavaScriptErrors with + // the return value of GetFirstTabWebContents. + void AssertNoJavaScriptErrors(); + + // Convenience function for running the static PollJavaScriptBoolean with the + // return value of GetFirstTabWebContents. + bool PollJavaScriptBoolean(const std::string& bool_expression, + const base::TimeDelta& timeout); + + // Convenience function for running the static WaitOnJavaScriptStep with the + // return value of GetFirstTabWebContents. + void WaitOnJavaScriptStep(); + + // Convenience function for running the static ExecuteStepAndWait with the + // return value of GetFirstTabWebContents. + void ExecuteStepAndWait(const std::string& step_function); + + // Convenience function for running the static + // RunJavaScriptAndExtractBoolOrFail with the return value of + // GetFirstTabWebContents. + bool RunJavaScriptAndExtractBoolOrFail(const std::string& js_expression); + + // Convenience function for running the static + // RunJavaScriptAndExtractStringOrFail with the return value of + // GetFirstTabWebContents. + std::string RunJavaScriptAndExtractStringOrFail( + const std::string& js_expression); + + protected: + std::unique_ptr<base::Environment> env_; + std::vector<base::Feature> enable_features_; + std::vector<std::string> append_switches_; + + private: + base::test::ScopedFeatureList scoped_feature_list_; + DISALLOW_COPY_AND_ASSIGN(XrBrowserTestBase); }; } // namespace vr
diff --git a/chrome/browser/vr/webvr_frame_pose_browser_test.cc b/chrome/browser/vr/webvr_frame_pose_browser_test.cc index 62ac0845..6b3e247 100644 --- a/chrome/browser/vr/webvr_frame_pose_browser_test.cc +++ b/chrome/browser/vr/webvr_frame_pose_browser_test.cc
@@ -6,9 +6,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "chrome/browser/vr/test/mock_openvr_device_hook_base.h" -#include "chrome/browser/vr/test/vr_browser_test.h" -#include "chrome/browser/vr/test/vr_xr_browser_test.h" -#include "chrome/browser/vr/test/xr_browser_test.h" +#include "chrome/browser/vr/test/webxr_vr_browser_test.h" #include <memory> @@ -142,23 +140,24 @@ // Pixel test for WebVR/WebXR - start presentation, submit frames, get data back // out. Validates that submitted frames used expected pose. -void TestPresentationPosesImpl(VrXrBrowserTestBase* t, std::string filename) { +void TestPresentationPosesImpl(WebXrVrBrowserTestBase* t, + std::string filename) { MyOpenVRMock my_mock; // Load the test page, and enter presentation. t->LoadUrlAndAwaitInitialization(t->GetHtmlTestFile(filename)); - t->EnterPresentationOrFail(t->GetFirstTabWebContents()); + t->EnterSessionWithUserGestureOrFail(); // Wait for javascript to submit at least one frame. - EXPECT_TRUE(t->PollJavaScriptBoolean( - "hasPresentedFrame", t->kPollTimeoutShort, t->GetFirstTabWebContents())) + EXPECT_TRUE( + t->PollJavaScriptBoolean("hasPresentedFrame", t->kPollTimeoutShort)) << "No frame submitted"; // Render at least 20 frames. Make sure each has the right submitted pose. my_mock.WaitForFrames(20); // Exit presentation. - t->ExitPresentationOrFail(t->GetFirstTabWebContents()); + t->EndSessionOrFail(); // Stop hooking OpenVR, so we can safely analyze our cached data without // incoming calls (there may be leftover mojo messages queued). @@ -195,22 +194,19 @@ // Validate that the javascript-side cache of frames contains our submitted // frame. EXPECT_TRUE(t->RunJavaScriptAndExtractBoolOrFail( - base::StringPrintf("checkFrameOccurred(%d)", frame_id), - t->GetFirstTabWebContents())); + base::StringPrintf("checkFrameOccurred(%d)", frame_id))); // Validate that the javascript-side cache of frames has the correct pose. - EXPECT_TRUE(t->RunJavaScriptAndExtractBoolOrFail( - base::StringPrintf("checkFramePose(%d, %s)", frame_id, - GetPoseAsString(frame).c_str()), - t->GetFirstTabWebContents())); + EXPECT_TRUE(t->RunJavaScriptAndExtractBoolOrFail(base::StringPrintf( + "checkFramePose(%d, %s)", frame_id, GetPoseAsString(frame).c_str()))); } // Tell javascript that it is done with the test. - t->ExecuteStepAndWait("finishTest()", t->GetFirstTabWebContents()); - t->EndTest(t->GetFirstTabWebContents()); + t->ExecuteStepAndWait("finishTest()"); + t->EndTest(); } -IN_PROC_BROWSER_TEST_F(XrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, REQUIRES_GPU(TestPresentationPoses)) { TestPresentationPosesImpl(this, "test_webxr_poses"); }
diff --git a/chrome/browser/vr/webvr_input_browser_test.cc b/chrome/browser/vr/webvr_input_browser_test.cc index dd23c3f..959492e 100644 --- a/chrome/browser/vr/webvr_input_browser_test.cc +++ b/chrome/browser/vr/webvr_input_browser_test.cc
@@ -2,31 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/vr/test/vr_browser_test.h" -#include "chrome/browser/vr/test/vr_xr_browser_test.h" -#include "chrome/browser/vr/test/xr_browser_test.h" +#include "chrome/browser/vr/test/webvr_browser_test.h" +#include "chrome/browser/vr/test/webxr_vr_browser_test.h" // Browser test equivalent of -// chrome/android/javatests/src/.../browser/vr/WebVrInputTest.java. +// chrome/android/javatests/src/.../browser/vr/WebXrVrInputTest.java. // End-to-end tests for user input interaction with WebVR. namespace vr { // Test that focus is locked to the presenting display for the purposes of VR/XR // input. -void TestPresentationLocksFocusImpl(VrXrBrowserTestBase* t, +void TestPresentationLocksFocusImpl(WebXrVrBrowserTestBase* t, std::string filename) { t->LoadUrlAndAwaitInitialization(t->GetHtmlTestFile(filename)); - t->EnterPresentationOrFail(t->GetFirstTabWebContents()); - t->ExecuteStepAndWait("stepSetupFocusLoss()", t->GetFirstTabWebContents()); - t->EndTest(t->GetFirstTabWebContents()); + t->EnterSessionWithUserGestureOrFail(); + t->ExecuteStepAndWait("stepSetupFocusLoss()"); + t->EndTest(); } -IN_PROC_BROWSER_TEST_F(VrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard, REQUIRES_GPU(TestPresentationLocksFocus)) { TestPresentationLocksFocusImpl(this, "test_presentation_locks_focus"); } -IN_PROC_BROWSER_TEST_F(XrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, REQUIRES_GPU(TestPresentationLocksFocus)) { TestPresentationLocksFocusImpl(this, "webxr_test_presentation_locks_focus"); }
diff --git a/chrome/browser/vr/webvr_pixel_browser_test.cc b/chrome/browser/vr/webvr_pixel_browser_test.cc index c927c04..c68a319 100644 --- a/chrome/browser/vr/webvr_pixel_browser_test.cc +++ b/chrome/browser/vr/webvr_pixel_browser_test.cc
@@ -8,9 +8,8 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" #include "chrome/browser/vr/test/mock_openvr_device_hook_base.h" -#include "chrome/browser/vr/test/vr_browser_test.h" -#include "chrome/browser/vr/test/vr_xr_browser_test.h" -#include "chrome/browser/vr/test/xr_browser_test.h" +#include "chrome/browser/vr/test/webvr_browser_test.h" +#include "chrome/browser/vr/test/webxr_vr_browser_test.h" #include <memory> @@ -49,21 +48,22 @@ // Pixel test for WebVR/WebXR - start presentation, submit frames, get data back // out. Validates that a pixel was rendered with the expected color. -void TestPresentationPixelsImpl(VrXrBrowserTestBase* t, std::string filename) { +void TestPresentationPixelsImpl(WebXrVrBrowserTestBase* t, + std::string filename) { MyOpenVRMock my_mock; // Load the test page, and enter presentation. t->LoadUrlAndAwaitInitialization(t->GetHtmlTestFile(filename)); - t->EnterPresentationOrFail(t->GetFirstTabWebContents()); + t->EnterSessionWithUserGestureOrFail(); // Wait for javascript to submit at least one frame. - EXPECT_TRUE(t->PollJavaScriptBoolean( - "hasPresentedFrame", t->kPollTimeoutShort, t->GetFirstTabWebContents())) + EXPECT_TRUE( + t->PollJavaScriptBoolean("hasPresentedFrame", t->kPollTimeoutShort)) << "No frame submitted"; // Tell javascript that it is done with the test. - t->ExecuteStepAndWait("finishTest()", t->GetFirstTabWebContents()); - t->EndTest(t->GetFirstTabWebContents()); + t->ExecuteStepAndWait("finishTest()"); + t->EndTest(); my_mock.WaitForFrame(); @@ -74,11 +74,11 @@ EXPECT_EQ(expected.a, my_mock.last_submitted_color_.a); } -IN_PROC_BROWSER_TEST_F(VrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard, REQUIRES_GPU(TestPresentationPixels)) { TestPresentationPixelsImpl(this, "test_webvr_pixels"); } -IN_PROC_BROWSER_TEST_F(XrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, REQUIRES_GPU(TestPresentationPixels)) { TestPresentationPixelsImpl(this, "test_webxr_pixels"); }
diff --git a/chrome/browser/vr/webvr_tab_browser_test.cc b/chrome/browser/vr/webvr_tab_browser_test.cc index 6ca6494a..e5f4725 100644 --- a/chrome/browser/vr/webvr_tab_browser_test.cc +++ b/chrome/browser/vr/webvr_tab_browser_test.cc
@@ -3,36 +3,33 @@ // found in the LICENSE file. #include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/vr/test/vr_browser_test.h" -#include "chrome/browser/vr/test/vr_xr_browser_test.h" -#include "chrome/browser/vr/test/xr_browser_test.h" +#include "chrome/browser/vr/test/webvr_browser_test.h" +#include "chrome/browser/vr/test/webxr_vr_browser_test.h" #include "url/gurl.h" #include "url/url_constants.h" // Browser test equivalent of -// chrome/android/javatests/src/.../browser/vr/WebVrTabTest.java. +// chrome/android/javatests/src/.../browser/vr/WebXrVrTabTest.java. // End-to-end tests for testing WebVR's interaction with multiple tabss. namespace vr { // Tests that non-focused tabs cannot get pose information from WebVR/WebXR -void TestPoseDataUnfocusedTabImpl(VrXrBrowserTestBase* t, +void TestPoseDataUnfocusedTabImpl(WebXrVrBrowserTestBase* t, std::string filename) { t->LoadUrlAndAwaitInitialization(t->GetHtmlTestFile(filename)); - t->ExecuteStepAndWait("stepCheckFrameDataWhileFocusedTab()", - t->GetFirstTabWebContents()); + t->ExecuteStepAndWait("stepCheckFrameDataWhileFocusedTab()"); chrome::AddTabAt(t->browser(), GURL(url::kAboutBlankURL), -1 /* index, append to end */, true /* foreground */); - t->ExecuteStepAndWait("stepCheckFrameDataWhileNonFocusedTab()", - t->GetFirstTabWebContents()); - t->EndTest(t->GetFirstTabWebContents()); + t->ExecuteStepAndWait("stepCheckFrameDataWhileNonFocusedTab()"); + t->EndTest(); } -IN_PROC_BROWSER_TEST_F(VrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard, REQUIRES_GPU(TestPoseDataUnfocusedTab)) { TestPoseDataUnfocusedTabImpl(this, "test_pose_data_unfocused_tab"); } -IN_PROC_BROWSER_TEST_F(XrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, REQUIRES_GPU(TestPoseDataUnfocusedTab)) { TestPoseDataUnfocusedTabImpl(this, "webxr_test_pose_data_unfocused_tab"); }
diff --git a/chrome/browser/vr/webvr_transition_browser_test.cc b/chrome/browser/vr/webvr_transition_browser_test.cc index 97dc5b69..2ce6d77 100644 --- a/chrome/browser/vr/webvr_transition_browser_test.cc +++ b/chrome/browser/vr/webvr_transition_browser_test.cc
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/vr/test/vr_browser_test.h" -#include "chrome/browser/vr/test/vr_xr_browser_test.h" -#include "chrome/browser/vr/test/xr_browser_test.h" +#include "chrome/browser/vr/test/webvr_browser_test.h" +#include "chrome/browser/vr/test/webxr_vr_browser_test.h" #include "content/public/test/browser_test_utils.h" // Browser test equivalent of -// chrome/android/javatests/src/.../browser/vr/WebVrTransitionTest.java. +// chrome/android/javatests/src/.../browser/vr/WebXrVrTransitionTest.java. // End-to-end tests for transitioning between WebVR's magic window and // presentation modes. @@ -16,42 +15,40 @@ // Tests that a successful requestPresent or requestSession call enters // presentation. -void TestPresentationEntryImpl(VrXrBrowserTestBase* t, std::string filename) { +void TestPresentationEntryImpl(WebXrVrBrowserTestBase* t, + std::string filename) { t->LoadUrlAndAwaitInitialization(t->GetHtmlTestFile(filename)); - t->EnterPresentationOrFail(t->GetFirstTabWebContents()); + t->EnterSessionWithUserGestureOrFail(); } -IN_PROC_BROWSER_TEST_F(VrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard, REQUIRES_GPU(TestRequestPresentEntersVr)) { TestPresentationEntryImpl(this, "generic_webvr_page"); } -IN_PROC_BROWSER_TEST_F(XrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, REQUIRES_GPU(TestRequestSessionEntersVr)) { TestPresentationEntryImpl(this, "generic_webxr_page"); } // Tests that window.requestAnimationFrame continues to fire while in // WebVR/WebXR presentation since the tab is still visible. -void TestWindowRafFiresWhilePresentingImpl(VrXrBrowserTestBase* t, +void TestWindowRafFiresWhilePresentingImpl(WebXrVrBrowserTestBase* t, std::string filename) { t->LoadUrlAndAwaitInitialization(t->GetHtmlTestFile(filename)); - t->ExecuteStepAndWait("stepVerifyBeforePresent()", - t->GetFirstTabWebContents()); - t->EnterPresentationOrFail(t->GetFirstTabWebContents()); - t->ExecuteStepAndWait("stepVerifyDuringPresent()", - t->GetFirstTabWebContents()); - t->ExitPresentationOrFail(t->GetFirstTabWebContents()); - t->ExecuteStepAndWait("stepVerifyAfterPresent()", - t->GetFirstTabWebContents()); - t->EndTest(t->GetFirstTabWebContents()); + t->ExecuteStepAndWait("stepVerifyBeforePresent()"); + t->EnterSessionWithUserGestureOrFail(); + t->ExecuteStepAndWait("stepVerifyDuringPresent()"); + t->EndSessionOrFail(); + t->ExecuteStepAndWait("stepVerifyAfterPresent()"); + t->EndTest(); } -IN_PROC_BROWSER_TEST_F(VrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestStandard, REQUIRES_GPU(TestWindowRafFiresWhilePresenting)) { TestWindowRafFiresWhilePresentingImpl( this, "test_window_raf_fires_while_presenting"); } -IN_PROC_BROWSER_TEST_F(XrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, REQUIRES_GPU(TestWindowRafFiresWhilePresenting)) { TestWindowRafFiresWhilePresentingImpl( this, "webxr_test_window_raf_fires_while_presenting"); @@ -60,19 +57,19 @@ // Tests that WebVR/WebXR is not exposed if the flag is not on and the page does // not have an origin trial token. Since the API isn't actually used, we can // remove the GPU requirement. -void TestApiDisabledWithoutFlagSetImpl(VrXrBrowserTestBase* t, +void TestApiDisabledWithoutFlagSetImpl(WebXrVrBrowserTestBase* t, std::string filename) { t->LoadUrlAndAwaitInitialization(t->GetHtmlTestFile(filename)); - t->WaitOnJavaScriptStep(t->GetFirstTabWebContents()); - t->EndTest(t->GetFirstTabWebContents()); + t->WaitOnJavaScriptStep(); + t->EndTest(); } -IN_PROC_BROWSER_TEST_F(VrBrowserTestWebVrDisabled, +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestWebVrDisabled, TestWebVrDisabledWithoutFlagSet) { TestApiDisabledWithoutFlagSetImpl(this, "test_webvr_disabled_without_flag_set"); } -IN_PROC_BROWSER_TEST_F(XrBrowserTestWebXrDisabled, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestWebXrDisabled, TestWebXrDisabledWithoutFlagSet) { TestApiDisabledWithoutFlagSetImpl(this, "test_webxr_disabled_without_flag_set"); @@ -80,45 +77,46 @@ // Tests that WebVR does not return any devices if OpenVR support is disabled. // Since WebVR isn't actually used, we can remove the GPU requirement. -IN_PROC_BROWSER_TEST_F(VrBrowserTestOpenVrDisabled, +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestOpenVrDisabled, TestWebVrNoDevicesWithoutOpenVr) { LoadUrlAndAwaitInitialization(GetHtmlTestFile("generic_webvr_page")); - EXPECT_FALSE(VrDisplayFound(GetFirstTabWebContents())); + EXPECT_FALSE(XrDeviceFound()); + AssertNoJavaScriptErrors(); } // Tests that WebXR does not return any devices if OpenVR support is disabled. // Since WebXR isn't actually used, we can remove the GPU requirement. -IN_PROC_BROWSER_TEST_F(XrBrowserTestOpenVrDisabled, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestOpenVrDisabled, TestWebXrNoDevicesWithoutOpenVr) { LoadUrlAndAwaitInitialization( GetHtmlTestFile("test_webxr_does_not_return_device")); - WaitOnJavaScriptStep(GetFirstTabWebContents()); - EndTest(GetFirstTabWebContents()); + WaitOnJavaScriptStep(); + EndTest(); } // Tests that window.requestAnimationFrame continues to fire when we have a // non-immersive WebXR session IN_PROC_BROWSER_TEST_F( - XrBrowserTestStandard, + WebXrVrBrowserTestStandard, REQUIRES_GPU(TestWindowRafFiresDuringNonImmersiveSession)) { LoadUrlAndAwaitInitialization( GetHtmlTestFile("test_window_raf_fires_during_non_immersive_session")); - WaitOnJavaScriptStep(GetFirstTabWebContents()); - EndTest(GetFirstTabWebContents()); + WaitOnJavaScriptStep(); + EndTest(); } // Tests that non-immersive sessions stop receiving rAFs during an immersive // session, but resume once the immersive session ends. -IN_PROC_BROWSER_TEST_F(XrBrowserTestStandard, +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, REQUIRES_GPU(TestNonImmersiveStopsDuringImmersive)) { LoadUrlAndAwaitInitialization( GetHtmlTestFile("test_non_immersive_stops_during_immersive")); - ExecuteStepAndWait("stepBeforeImmersive()", GetFirstTabWebContents()); - EnterPresentationOrFail(GetFirstTabWebContents()); - ExecuteStepAndWait("stepDuringImmersive()", GetFirstTabWebContents()); - ExitPresentationOrFail(GetFirstTabWebContents()); - ExecuteStepAndWait("stepAfterImmersive()", GetFirstTabWebContents()); - EndTest(GetFirstTabWebContents()); + ExecuteStepAndWait("stepBeforeImmersive()"); + EnterSessionWithUserGestureOrFail(); + ExecuteStepAndWait("stepDuringImmersive()"); + EndSessionOrFail(); + ExecuteStepAndWait("stepAfterImmersive()"); + EndTest(); } } // namespace vr
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 4716327..cbcf14a 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -2,6 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +group("web_app_group") { + public_configs = [ "//build/config/compiler:wexit_time_destructors" ] +} + source_set("web_applications") { sources = [ "web_app_provider.cc", @@ -11,6 +15,7 @@ ] deps = [ + ":web_app_group", "//chrome/browser/web_applications/bookmark_apps", "//chrome/common", ] @@ -18,7 +23,9 @@ source_set("unit_tests") { testonly = true + deps = [ + ":web_app_group", "//chrome/browser/web_applications/bookmark_apps:unit_tests", "//chrome/browser/web_applications/components:unit_tests", "//chrome/browser/web_applications/extensions:unit_tests",
diff --git a/chrome/browser/web_applications/bookmark_apps/BUILD.gn b/chrome/browser/web_applications/bookmark_apps/BUILD.gn index 12dc550..9b8b940 100644 --- a/chrome/browser/web_applications/bookmark_apps/BUILD.gn +++ b/chrome/browser/web_applications/bookmark_apps/BUILD.gn
@@ -16,6 +16,7 @@ deps = [ "//chrome/browser/extensions", + "//chrome/browser/web_applications:web_app_group", "//chrome/common", "//skia", ] @@ -30,6 +31,7 @@ deps = [ ":bookmark_apps", + "//chrome/browser/web_applications:web_app_group", "//skia", "//testing/gmock", ]
diff --git a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.cc index ecac15d0..587bd0b1 100644 --- a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.cc +++ b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.h" -#include <utility> #include <vector> #include "base/values.h" @@ -15,19 +14,12 @@ namespace web_app { -WebAppPolicyManager::WebAppPolicyManager( - PrefService* pref_service, - std::unique_ptr<PendingAppManager> pending_app_manager) - : pref_service_(pref_service), - pending_app_manager_(std::move(pending_app_manager)) { +WebAppPolicyManager::WebAppPolicyManager(PrefService* pref_service, + PendingAppManager* pending_app_manager) + : pref_service_(pref_service), pending_app_manager_(pending_app_manager) { pending_app_manager_->ProcessAppOperations(GetAppsToInstall()); } -WebAppPolicyManager::WebAppPolicyManager(PrefService* pref_service) - : WebAppPolicyManager( - pref_service, - std::make_unique<extensions::PendingBookmarkAppManager>()) {} - WebAppPolicyManager::~WebAppPolicyManager() = default; std::vector<PendingAppManager::AppInfo>
diff --git a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.h b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.h index ed55b13..564e0ee 100644 --- a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.h +++ b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.h
@@ -5,7 +5,6 @@ #ifndef CHROME_BROWSER_WEB_APPLICATIONS_BOOKMARK_APPS_POLICY_WEB_APP_POLICY_MANAGER_H_ #define CHROME_BROWSER_WEB_APPLICATIONS_BOOKMARK_APPS_POLICY_WEB_APP_POLICY_MANAGER_H_ -#include <memory> #include <vector> #include "base/macros.h" @@ -22,26 +21,19 @@ class WebAppPolicyManager { public: // Constructs a WebAppPolicyManager instance that uses - // extensions::PendingBookmarkAppManager to manage apps. - explicit WebAppPolicyManager(PrefService* pref_service); - - // Constructs a WebAppPolicyManager instance that uses |pending_app_manager| - // to manage apps. - explicit WebAppPolicyManager( - PrefService* pref_service, - std::unique_ptr<PendingAppManager> pending_app_manager); - + // |pending_app_manager| to manage apps. |pending_app_manager| should outlive + // this class. + explicit WebAppPolicyManager(PrefService* pref_service, + PendingAppManager* pending_app_manager); ~WebAppPolicyManager(); - const PendingAppManager& pending_app_manager() { - return *pending_app_manager_; - } - private: std::vector<PendingAppManager::AppInfo> GetAppsToInstall(); PrefService* pref_service_; - std::unique_ptr<PendingAppManager> pending_app_manager_; + + // Used to install, uninstall, and update apps. Should outlive this class. + PendingAppManager* pending_app_manager_; DISALLOW_COPY_AND_ASSIGN(WebAppPolicyManager); };
diff --git a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc index 278ea5f6..b240ab9 100644 --- a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc +++ b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.h" +#include <memory> #include <utility> #include <vector> @@ -57,11 +58,9 @@ RegisterUserProfilePrefs(prefs->registry()); auto pending_app_manager = std::make_unique<TestPendingAppManager>(); - auto* pending_app_manager_ptr = pending_app_manager.get(); - WebAppPolicyManager web_app_policy_manager(prefs.get(), - std::move(pending_app_manager)); - const auto& apps_to_install = pending_app_manager_ptr->last_apps_to_install(); + pending_app_manager.get()); + const auto& apps_to_install = pending_app_manager->last_apps_to_install(); EXPECT_TRUE(apps_to_install.empty()); } @@ -74,11 +73,9 @@ base::Value(base::Value::Type::LIST)); auto pending_app_manager = std::make_unique<TestPendingAppManager>(); - auto* pending_app_manager_ptr = pending_app_manager.get(); - WebAppPolicyManager web_app_policy_manager(prefs.get(), - std::move(pending_app_manager)); - const auto& apps_to_install = pending_app_manager_ptr->last_apps_to_install(); + pending_app_manager.get()); + const auto& apps_to_install = pending_app_manager->last_apps_to_install(); EXPECT_TRUE(apps_to_install.empty()); } @@ -105,11 +102,9 @@ } auto pending_app_manager = std::make_unique<TestPendingAppManager>(); - auto* pending_app_manager_ptr = pending_app_manager.get(); - WebAppPolicyManager web_app_policy_manager(prefs.get(), - std::move(pending_app_manager)); - const auto& apps_to_install = pending_app_manager_ptr->last_apps_to_install(); + pending_app_manager.get()); + const auto& apps_to_install = pending_app_manager->last_apps_to_install(); std::vector<PendingAppManager::AppInfo> expected_apps_to_install; expected_apps_to_install.emplace_back(
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn index 4a873648..336f4eae0 100644 --- a/chrome/browser/web_applications/components/BUILD.gn +++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -36,9 +36,8 @@ ] } - configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + "//chrome/browser/web_applications:web_app_group", "//content/public/browser", "//skia", ] @@ -61,6 +60,8 @@ deps = [ ":components", + "//chrome/app/theme:theme_resources", + "//chrome/browser/web_applications:web_app_group", "//content/public/browser", "//skia", "//testing/gmock",
diff --git a/chrome/browser/web_applications/extensions/BUILD.gn b/chrome/browser/web_applications/extensions/BUILD.gn index 5641dae..215aa6e 100644 --- a/chrome/browser/web_applications/extensions/BUILD.gn +++ b/chrome/browser/web_applications/extensions/BUILD.gn
@@ -26,6 +26,7 @@ deps = [ "//base", + "//chrome/browser/web_applications:web_app_group", "//chrome/browser/web_applications/components", "//chrome/common", "//content/public/browser", @@ -43,6 +44,7 @@ deps = [ ":extensions", + "//chrome/browser/web_applications:web_app_group", "//chrome/browser/web_applications/components", "//content/public/browser", "//skia",
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h index dce8cdab..e599f94 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
@@ -15,7 +15,7 @@ // Implementation of web_app::PendingAppManager that manages the set of // Bookmark Apps which are being installed, uninstalled, and updated. // -// WebAppPolicyManager creates an instance of this class and manages its +// WebAppProvider creates an instance of this class and manages its // lifetime. This class should only be used from the UI thread. class PendingBookmarkAppManager final : public web_app::PendingAppManager { public:
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index 6ccec79..52b1b10 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -4,7 +4,10 @@ #include "chrome/browser/web_applications/web_app_provider.h" +#include <utility> + #include "chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager.h" +#include "chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h" #include "chrome/browser/web_applications/web_app_provider_factory.h" namespace web_app { @@ -15,8 +18,11 @@ } WebAppProvider::WebAppProvider(PrefService* pref_service) - : web_app_policy_manager_( - std::make_unique<WebAppPolicyManager>(pref_service)) { + : pending_app_manager_( + std::make_unique<extensions::PendingBookmarkAppManager>()), + web_app_policy_manager_( + std::make_unique<WebAppPolicyManager>(pref_service, + pending_app_manager_.get())) { // TODO(nigeltao): install default web apps as per http://crbug.com/855281 }
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h index f2bec23..f69f45dd 100644 --- a/chrome/browser/web_applications/web_app_provider.h +++ b/chrome/browser/web_applications/web_app_provider.h
@@ -15,6 +15,7 @@ namespace web_app { +class PendingAppManager; class WebAppPolicyManager; // Connects Web App features, such as the installation of default and @@ -26,9 +27,14 @@ explicit WebAppProvider(PrefService* pref_service); + // Clients can use PendingAppManager to install, uninstall, and update + // Web Apps. + PendingAppManager& pending_app_manager() { return *pending_app_manager_; } + ~WebAppProvider() override; private: + std::unique_ptr<PendingAppManager> pending_app_manager_; std::unique_ptr<WebAppPolicyManager> web_app_policy_manager_; DISALLOW_COPY_AND_ASSIGN(WebAppProvider);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index e710f53..e222df1e 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -915,10 +915,6 @@ // only using an account that belongs to one of the domains from this pref. const char kAllowedDomainsForApps[] = "settings.allowed_domains_for_apps"; -// Enum specifying if/how the safesites content filter should be applied. -// See the SafeSitesFilterBehavior policy for details. -const char kSafeSitesFilterBehavior[] = "settings.safe_sites_filter_behavior"; - #if defined(OS_LINUX) && !defined(OS_CHROMEOS) // Linux specific preference on whether we should match the system theme. const char kUsesSystemTheme[] = "extensions.theme.use_system";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 023f07b..da74258 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -294,7 +294,6 @@ extern const char kForceYouTubeRestrict[]; extern const char kForceSessionSync[]; extern const char kAllowedDomainsForApps[]; -extern const char kSafeSitesFilterBehavior[]; #if defined(OS_LINUX) && !defined(OS_CHROMEOS) extern const char kUsesSystemTheme[]; #endif
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index 39c631c..9731dcd 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -3284,8 +3284,7 @@ // Check only form signature attribute. The full test is in // "PasswordGenerationAgentTestForHtmlAnnotation.*". - WebString form_signature_attribute = - WebString::FromASCII(kDebugAttributeForFormSignature); + WebString form_signature_attribute = WebString::FromASCII("form_signature"); EXPECT_EQ(form_element.HasAttribute(form_signature_attribute), show_signatures); }
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc index ae3f62f..1d3f354 100644 --- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -1001,6 +1001,11 @@ blink::WebString form_signature_in_username = username_element.GetAttribute( blink::WebString::FromUTF8("form_signature")); EXPECT_EQ(kFormSignature, form_signature_in_username.Ascii()); + EXPECT_EQ( + "username_element", + username_element + .GetAttribute(blink::WebString::FromUTF8("pm_parser_annotation")) + .Ascii()); blink::WebElement password_element = document.GetElementById(blink::WebString::FromUTF8("first_password")); @@ -1012,12 +1017,31 @@ blink::WebString form_signature_in_password = password_element.GetAttribute( blink::WebString::FromUTF8("form_signature")); EXPECT_EQ(kFormSignature, form_signature_in_password.Ascii()); + // The parser annotation is based on local heuristics, but not server side + // prediction. So, the new password element is classified as the current + // password. + EXPECT_EQ( + "password_element", + password_element + .GetAttribute(blink::WebString::FromUTF8("pm_parser_annotation")) + .Ascii()); // Check the generation element is marked. blink::WebString generation_mark = password_element.GetAttribute( blink::WebString::FromUTF8("password_creation_field")); ASSERT_FALSE(generation_mark.IsNull()); EXPECT_EQ("1", generation_mark.Utf8()); + + blink::WebElement confirmation_password_element = + document.GetElementById(blink::WebString::FromUTF8("second_password")); + // The parser annotation is based on local heuristics, but not server side + // prediction. So, the confirmation password element is classified as the + // new password. + EXPECT_EQ( + "new_password_element", + confirmation_password_element + .GetAttribute(blink::WebString::FromUTF8("pm_parser_annotation")) + .Ascii()); } }
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index 5a64a9e..004f1aa4 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -170,6 +170,8 @@ .Set("thumbnailUrl", thumbnail_url) .Set("tileTitleSource", static_cast<int>(mv_item.title_source)) .Set("tileSource", static_cast<int>(mv_item.source)) + .Set("isCustomLink", + mv_item.source == ntp_tiles::TileSource::CUSTOM_LINKS) .Set("title", title) .Set("domain", mv_item.url.host()) .Set("direction", base::StringPiece(direction))
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index e2bc910..ebacc21 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1587,7 +1587,10 @@ "../browser/chromeos/file_manager/file_manager_jstest.cc", "../browser/chromeos/file_manager/file_manager_jstest_base.cc", "../browser/chromeos/file_manager/file_manager_jstest_base.h", + "../browser/chromeos/file_manager/file_manager_test_util.cc", + "../browser/chromeos/file_manager/file_manager_test_util.h", "../browser/chromeos/file_manager/file_manager_uitest.cc", + "../browser/chromeos/file_manager/file_tasks_browsertest.cc", "../browser/chromeos/file_manager/gallery_browsertest.cc", "../browser/chromeos/file_manager/gallery_jstest.cc", "../browser/chromeos/file_manager/image_loader_jstest.cc", @@ -1964,10 +1967,12 @@ "../browser/ui/views/uninstall_view_browsertest.cc", "../browser/vr/test/mock_openvr_device_hook_base.cc", "../browser/vr/test/mock_openvr_device_hook_base.h", - "../browser/vr/test/vr_browser_test.cc", - "../browser/vr/test/vr_browser_test.h", - "../browser/vr/test/vr_xr_browser_test.cc", - "../browser/vr/test/vr_xr_browser_test.h", + "../browser/vr/test/webvr_browser_test.cc", + "../browser/vr/test/webvr_browser_test.h", + "../browser/vr/test/webxr_browser_test.cc", + "../browser/vr/test/webxr_browser_test.h", + "../browser/vr/test/webxr_vr_browser_test.cc", + "../browser/vr/test/webxr_vr_browser_test.h", "../browser/vr/test/xr_browser_test.cc", "../browser/vr/test/xr_browser_test.h", "../browser/vr/webvr_frame_pose_browser_test.cc",
diff --git a/chrome/test/data/local_ntp/local_ntp_browsertest.html b/chrome/test/data/local_ntp/local_ntp_browsertest.html index 1687cfa8..0766d3b3 100644 --- a/chrome/test/data/local_ntp/local_ntp_browsertest.html +++ b/chrome/test/data/local_ntp/local_ntp_browsertest.html
@@ -73,7 +73,7 @@ <dialog div id="edit-bg-dialog"> <div id="edit-bg-title"></div> - <div id="edit-bg-google-photos" class="bg-option" tabindex="0"> + <div id="edit-bg-google-photos" class="bg-option" tabindex="0" hidden> <div class="bg-option-img"></div> <div id="edit-bg-google-photos-text" class="bg-option-text"></div> </div>
diff --git a/chrome/test/data/webui/settings/all_sites_tests.js b/chrome/test/data/webui/settings/all_sites_tests.js index 68bee0d..fe83aea 100644 --- a/chrome/test/data/webui/settings/all_sites_tests.js +++ b/chrome/test/data/webui/settings/all_sites_tests.js
@@ -2,14 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * An example pref with multiple categories and multiple allow/block - * state. - * @type {SiteSettingsPref} - */ -let prefsVarious; - suite('AllSites', function() { + const TEST_COOKIE_LIST = { + id: 'example', + children: [ + {domain: 'bar.com'}, + {domain: 'bar.com'}, + {domain: 'bar.com'}, + {domain: 'bar.com'}, + {domain: 'google.com'}, + {domain: 'google.com'}, + ] + }; + + /** + * An example pref with multiple categories and multiple allow/block + * state. + * @type {SiteSettingsPref} + */ + let prefsVarious; + /** * A site list element created before each test. * @type {SiteList} @@ -22,6 +34,12 @@ */ let browserProxy = null; + /** + * The mock local data proxy object to use during test. + * @type {TestLocalDataBrowserProxy} + */ + let localDataBrowserProxy; + suiteSetup(function() { CrSettingsPrefs.setInitialized(); }); @@ -57,7 +75,9 @@ ]); browserProxy = new TestSiteSettingsPrefsBrowserProxy(); + localDataBrowserProxy = new TestLocalDataBrowserProxy(); settings.SiteSettingsPrefsBrowserProxyImpl.instance_ = browserProxy; + settings.LocalDataBrowserProxyImpl.instance_ = localDataBrowserProxy; PolymerTest.clearBody(); testElement = document.createElement('all-sites'); assertTrue(!!testElement); @@ -76,12 +96,7 @@ */ function setUpCategory(prefs) { browserProxy.setPrefs(prefs); - // Some route is needed, but the actual route doesn't matter. - testElement.currentRoute = { - page: 'dummy', - section: 'privacy', - subpage: ['site-settings', 'site-settings-category-location'], - }; + settings.navigateTo(settings.routes.SITE_SETTINGS_ALL); } test('All sites list populated', function() { @@ -92,7 +107,7 @@ const resolver = new PromiseResolver(); testElement.async(resolver.resolve); return resolver.promise.then(() => { - assertEquals(3, testElement.siteGroupList.length); + assertEquals(3, testElement.siteGroupMap.size); // Flush to be sure list container is populated. Polymer.dom.flush(); @@ -136,23 +151,177 @@ }); }); + test('can be sorted by most visited', function() { + setUpCategory(prefsVarious); + testElement.populateList_(); + + return browserProxy.whenCalled('getAllSites').then(() => { + // Add additional origins and artificially insert fake engagement scores + // to sort. + assertEquals(3, testElement.siteGroupMap.size); + const fooSiteGroup = testElement.siteGroupMap.get('foo.com'); + fooSiteGroup.origins.push(test_util.createOriginInfo( + 'https://login.foo.com', {engagement: 20})); + assertEquals(2, fooSiteGroup.origins.length); + fooSiteGroup.origins[0].engagement = 50.4; + const googleSiteGroup = testElement.siteGroupMap.get('google.com'); + assertEquals(1, googleSiteGroup.origins.length); + googleSiteGroup.origins[0].engagement = 55.1261; + const barSiteGroup = testElement.siteGroupMap.get('bar.com'); + assertEquals(1, barSiteGroup.origins.length); + barSiteGroup.origins[0].engagement = 0.5235; + + // 'Most visited' is the default sort method, so sort by a different + // method first to ensure changing to 'Most visited' works. + testElement.root.querySelector('select').value = 'name'; + testElement.onSortMethodChanged_(); + Polymer.dom.flush(); + let siteEntries = + testElement.$.listContainer.querySelectorAll('site-entry'); + assertEquals('bar.com', siteEntries[0].$.displayName.innerText.trim()); + assertEquals('foo.com', siteEntries[1].$.displayName.innerText.trim()); + assertEquals('google.com', siteEntries[2].$.displayName.innerText.trim()); + + testElement.root.querySelector('select').value = 'most-visited'; + testElement.onSortMethodChanged_(); + Polymer.dom.flush(); + siteEntries = testElement.$.listContainer.querySelectorAll('site-entry'); + // Each site entry is sorted by its maximum engagement, so expect + // 'foo.com' to come after 'google.com'. + assertEquals('google.com', siteEntries[0].$.displayName.innerText.trim()); + assertEquals('foo.com', siteEntries[1].$.displayName.innerText.trim()); + assertEquals('bar.com', siteEntries[2].$.displayName.innerText.trim()); + }); + }); + + test('can be sorted by storage', function() { + localDataBrowserProxy.setCookieDetails(TEST_COOKIE_LIST); + setUpCategory(prefsVarious); + testElement.populateList_(); + return browserProxy.whenCalled('getAllSites') + .then(() => { + Polymer.dom.flush(); + let siteEntries = + testElement.$.listContainer.querySelectorAll('site-entry'); + // Add additional origins to SiteGroups with cookies to simulate their + // being grouped entries, plus add local storage. + siteEntries[0].siteGroup.origins[0].usage = 1000; + siteEntries[1].siteGroup.origins.push( + test_util.createOriginInfo('http://bar.com')); + siteEntries[1].siteGroup.origins[0].usage = 500; + siteEntries[1].siteGroup.origins[1].usage = 500; + siteEntries[2].siteGroup.origins.push( + test_util.createOriginInfo('http://google.com')); + + testElement.onSortMethodChanged_(); + siteEntries = + testElement.$.listContainer.querySelectorAll('site-entry'); + // Verify all sites is not sorted by storage. + assertEquals(3, siteEntries.length); + assertEquals( + 'foo.com', siteEntries[0].$.displayName.innerText.trim()); + assertEquals( + 'bar.com', siteEntries[1].$.displayName.innerText.trim()); + assertEquals( + 'google.com', siteEntries[2].$.displayName.innerText.trim()); + + // Change the sort method, then verify all sites is now sorted by + // name. + testElement.root.querySelector('select').value = 'data-stored'; + testElement.onSortMethodChanged_(); + return localDataBrowserProxy.whenCalled('getNumCookiesList'); + }) + .then(() => { + Polymer.dom.flush(); + let siteEntries = + testElement.$.listContainer.querySelectorAll('site-entry'); + assertEquals( + 'bar.com', + siteEntries[0] + .root.querySelector('#displayName .url-directionality') + .innerText.trim()); + assertEquals( + 'foo.com', + siteEntries[1] + .root.querySelector('#displayName .url-directionality') + .innerText.trim()); + assertEquals( + 'google.com', + siteEntries[2] + .root.querySelector('#displayName .url-directionality') + .innerText.trim()); + }); + }); + test('can be sorted by name', function() { setUpCategory(prefsVarious); testElement.populateList_(); return browserProxy.whenCalled('getAllSites').then(() => { Polymer.dom.flush(); - const siteEntries = + let siteEntries = testElement.$.listContainer.querySelectorAll('site-entry'); - // TODO(https://crbug.com/835712): When there is more than one sort - // method, check that the all sites list can be sorted by name from an - // existing all sites list that is out of order. Currently this is not - // possible as the all sites list will always initially be sorted by the - // default sort method, and the default sort method is by name. + // Verify all sites is not sorted by name. assertEquals(3, siteEntries.length); + assertEquals('foo.com', siteEntries[0].$.displayName.innerText.trim()); + assertEquals('bar.com', siteEntries[1].$.displayName.innerText.trim()); + assertEquals('google.com', siteEntries[2].$.displayName.innerText.trim()); + + // Change the sort method, then verify all sites is now sorted by name. + testElement.root.querySelector('select').value = 'name'; + testElement.onSortMethodChanged_(); + Polymer.dom.flush(); + siteEntries = testElement.$.listContainer.querySelectorAll('site-entry'); assertEquals('bar.com', siteEntries[0].$.displayName.innerText.trim()); assertEquals('foo.com', siteEntries[1].$.displayName.innerText.trim()); assertEquals('google.com', siteEntries[2].$.displayName.innerText.trim()); }); }); + + test('merging additional SiteGroup lists works', function() { + setUpCategory(prefsVarious); + testElement.populateList_(); + return browserProxy.whenCalled('getAllSites').then(() => { + Polymer.dom.flush(); + let siteEntries = + testElement.$.listContainer.querySelectorAll('site-entry'); + assertEquals(3, siteEntries.length); + + // Pretend an additional set of SiteGroups were added. + const fooEtldPlus1 = 'foo.com'; + const addEtldPlus1 = 'additional-site.net'; + const fooOrigin = 'https://login.foo.com'; + const addOrigin = 'http://www.additional-site.net'; + const LOCAL_STORAGE_SITE_GROUP_LIST = /** @type {!Array{!SiteGroup}} */ ([ + { + // Test merging an existing site works, with overlapping origin lists. + 'etldPlus1': fooEtldPlus1, + 'origins': [ + test_util.createOriginInfo(fooOrigin), + test_util.createOriginInfo('https://foo.com'), + ], + }, + { + // Test adding a new site entry works. + 'etldPlus1': addEtldPlus1, + 'origins': [test_util.createOriginInfo(addOrigin)], + } + ]); + testElement.onLocalStorageListFetched(LOCAL_STORAGE_SITE_GROUP_LIST); + + Polymer.dom.flush(); + siteEntries = testElement.$.listContainer.querySelectorAll('site-entry'); + assertEquals(4, siteEntries.length); + + assertEquals(fooEtldPlus1, siteEntries[0].siteGroup.etldPlus1); + assertEquals(2, siteEntries[0].siteGroup.origins.length); + assertEquals( + 'https://foo.com', siteEntries[0].siteGroup.origins[0].origin); + assertEquals(fooOrigin, siteEntries[0].siteGroup.origins[1].origin); + + assertEquals(addEtldPlus1, siteEntries[3].siteGroup.etldPlus1); + assertEquals(1, siteEntries[3].siteGroup.origins.length); + assertEquals(addOrigin, siteEntries[3].siteGroup.origins[0].origin); + }); + }); });
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 4e635502..1f839f1 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -1003,6 +1003,7 @@ /** @override */ extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ '../test_browser_proxy.js', + 'test_local_data_browser_proxy.js', 'test_util.js', 'test_site_settings_prefs_browser_proxy.js', 'all_sites_tests.js',
diff --git a/chrome/test/data/webui/settings/downloads_page_test.js b/chrome/test/data/webui/settings/downloads_page_test.js index 211e100..9f71b0b 100644 --- a/chrome/test/data/webui/settings/downloads_page_test.js +++ b/chrome/test/data/webui/settings/downloads_page_test.js
@@ -77,4 +77,39 @@ assertTrue(!button); }); }); + + if (cr.isChromeOS) { + function setDefaultDownloadPathPref(downloadPath) { + downloadsPage.prefs = { + download: { + default_directory: { + key: 'download.default_directory', + type: chrome.settingsPrivate.PrefType.STRING, + value: downloadPath, + } + } + }; + } + + function getDefaultDownloadPathString() { + const pathElement = downloadsPage.$$('#defaultDownloadPath'); + assertTrue(!!pathElement); + return pathElement.textContent.trim(); + } + + test('rewrite default download paths.', function() { + // Rewrite path for directories in Downloads volume. + setDefaultDownloadPathPref('/home/chronos/u-0123456789abcdef/Downloads'); + assertEquals('Downloads', getDefaultDownloadPathString()); + + // Rewrite path for directories in Google Drive. + setDefaultDownloadPathPref('/special/drive-0123456789abcdef/root/foo'); + assertEquals('Google Drive \u203a foo', getDefaultDownloadPathString()); + + // Rewrite path for directories in Android files volume. + setDefaultDownloadPathPref('/run/arc/sdcard/write/emulated/0/foo/bar'); + assertEquals( + 'Play files \u203a foo \u203a bar', getDefaultDownloadPathString()); + }); + } });
diff --git a/chrome/test/data/webui/settings/site_entry_tests.js b/chrome/test/data/webui/settings/site_entry_tests.js index 743cf926..0b8e4446 100644 --- a/chrome/test/data/webui/settings/site_entry_tests.js +++ b/chrome/test/data/webui/settings/site_entry_tests.js
@@ -24,10 +24,9 @@ const TEST_COOKIE_LIST = { id: 'foo', children: [ - {}, - {}, - {}, - {}, + {domain: 'example.com'}, + {domain: 'example.com'}, + {domain: 'example.com'}, ] }; @@ -130,7 +129,7 @@ settings.routes.SITE_SETTINGS_SITE_DETAILS.path, settings.getCurrentRoute().path); assertEquals( - TEST_MULTIPLE_SITE_GROUP.origins[1], + TEST_MULTIPLE_SITE_GROUP.origins[1].origin, settings.getQueryParameters().get('site')); }); @@ -202,18 +201,20 @@ testElement.siteGroup = TEST_MULTIPLE_SITE_GROUP; Polymer.dom.flush(); const cookiesLabel = testElement.$.cookies; - assertEquals('', cookiesLabel.textContent.trim()); assertTrue(cookiesLabel.hidden); // When the number of cookies is more than zero, the label appears. testElement.onSiteGroupChanged_(TEST_MULTIPLE_SITE_GROUP); - return localDataBrowserProxy.whenCalled('getNumCookiesString') + return localDataBrowserProxy.whenCalled('getNumCookiesList') .then((args) => { - assertEquals('example.com', args); + assertEquals(1, args.length); + assertEquals('example.com', args[0]); + return localDataBrowserProxy.whenCalled('getNumCookiesString'); + }) + .then((args) => { + assertEquals(3, args); assertFalse(cookiesLabel.hidden); - assertEquals( - `${TEST_COOKIE_LIST.children.length} cookies`, - cookiesLabel.textContent.trim()); + assertEquals('· 3 cookies', cookiesLabel.textContent.trim()); }); }); @@ -222,12 +223,46 @@ Polymer.dom.flush(); const cookiesLabel = testElement.$.cookies; assertTrue(cookiesLabel.hidden); - assertEquals('', cookiesLabel.textContent.trim()); testElement.onSiteGroupChanged_(TEST_SINGLE_SITE_GROUP); // Make sure there was never any call to the back end to retrieve cookies. - assertEquals(0, localDataBrowserProxy.getCallCount('getNumCookiesString')); - assertEquals('', cookiesLabel.textContent.trim()); + assertEquals(0, localDataBrowserProxy.getCallCount('getNumCookiesList')); assertTrue(cookiesLabel.hidden); }); + + test.only('data usage shown correctly for grouped entries', function() { + // Clone this object to avoid propogating changes made in this test. + const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + const numBytes1 = 74622; + const numBytes2 = 1274; + const numBytes3 = 0; + testSiteGroup.origins[0].usage = numBytes1; + testSiteGroup.origins[1].usage = numBytes2; + testSiteGroup.origins[2].usage = numBytes3; + testElement.siteGroup = testSiteGroup; + Polymer.dom.flush(); + return browserProxy.whenCalled('getFormattedBytes').then((args) => { + const sumBytes = numBytes1 + numBytes2 + numBytes3; + assertEquals( + `${sumBytes} B`, + testElement.root.querySelector('#displayName .data-unit') + .textContent.trim()); + }); + }); + + test('data usage shown correctly for ungrouped entries', function() { + // Clone this object to avoid propogating changes made in this test. + const testSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP)); + const numBytes = 74622; + testSiteGroup.origins[0].usage = numBytes; + testElement.siteGroup = testSiteGroup; + Polymer.dom.flush(); + return browserProxy.whenCalled('getFormattedBytes').then((args) => { + assertEquals( + `${numBytes} B`, + testElement.root.querySelector('#displayName .data-unit') + .textContent.trim()); + + }); + }); });
diff --git a/chrome/test/data/webui/settings/test_local_data_browser_proxy.js b/chrome/test/data/webui/settings/test_local_data_browser_proxy.js index a8d5bdd..ecf533f 100644 --- a/chrome/test/data/webui/settings/test_local_data_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_local_data_browser_proxy.js
@@ -17,6 +17,7 @@ 'removeShownItems', 'removeItem', 'getCookieDetails', + 'getNumCookiesList', 'getNumCookiesString', 'reloadCookies', 'removeCookie', @@ -82,15 +83,32 @@ } /** @override */ - getNumCookiesString(site) { - this.methodCalled('getNumCookiesString', site); + getNumCookiesList(siteList) { + this.methodCalled('getNumCookiesList', siteList); + const numCookiesMap = new Map(); if (this.cookieDetails_) { - const numCookies = this.cookieDetails_.children.length; - return Promise.resolve( - `${this.cookieDetails_.children.length} ` + - (numCookies == 1 ? 'cookie' : 'cookies')); + this.cookieDetails_.children.forEach(cookie => { + let numCookies = numCookiesMap.get(cookie.domain); + numCookies = numCookies == null ? 1 : ++numCookies; + numCookiesMap.set(cookie.domain, numCookies); + }); } - return Promise.resolve(''); + + const numCookiesList = siteList.map(site => { + const numCookies = numCookiesMap.get(site); + return { + etldPlus1: site, + numCookies: numCookies == null ? 0 : numCookies, + }; + }); + return Promise.resolve(numCookiesList); + } + + /** @override */ + getNumCookiesString(numCookies) { + this.methodCalled('getNumCookiesString', numCookies); + return Promise.resolve( + `${numCookies} ` + (numCookies == 1 ? 'cookie' : 'cookies')); } /** @override */
diff --git a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js index 4aa931d..ba9b354 100644 --- a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js
@@ -26,6 +26,7 @@ 'fetchUsbDevices', 'fetchZoomLevels', 'getAllSites', + 'getFormattedBytes', 'getDefaultValueForContentType', 'getExceptionList', 'getOriginPermissions', @@ -203,21 +204,35 @@ const origins_array = [...origins_set]; let result = []; origins_array.forEach((origin, index) => { - let entry = {}; // Functionality to get the eTLD+1 from an origin exists only on the // C++ side, so just do an (incorrect) approximate extraction here. const host = new URL(origin).host; let urlParts = host.split('.'); urlParts = urlParts.slice(Math.max(urlParts.length - 2, 0)); - entry['etldPlus1'] = urlParts.join('.'); - entry['origins'] = [origin]; - result.push(entry); + const etldPlus1Name = urlParts.join('.'); + + let existing = result.find(siteGroup => { + return siteGroup.etldPlus1 == etldPlus1Name; + }); + + if (existing) { + existing.origins.push(test_util.createOriginInfo(origin)); + } else { + const entry = test_util.createSiteGroup(etldPlus1Name, [origin]); + result.push(entry); + } }); return Promise.resolve(result); } /** @override */ + getFormattedBytes(numBytes) { + this.methodCalled('getFormattedBytes', numBytes); + return Promise.resolve(`${numBytes} B`); + } + + /** @override */ getDefaultValueForContentType(contentType) { this.methodCalled('getDefaultValueForContentType', contentType); let pref = this.prefs_.defaults[contentType];
diff --git a/chrome/test/data/webui/settings/test_util.js b/chrome/test/data/webui/settings/test_util.js index 87fa93c..649ae17 100644 --- a/chrome/test/data/webui/settings/test_util.js +++ b/chrome/test/data/webui/settings/test_util.js
@@ -192,12 +192,26 @@ * @return {SiteGroup} */ function createSiteGroup(eTLDPlus1Name, originList) { + const originInfoList = originList.map(origin => createOriginInfo(origin)); return { etldPlus1: eTLDPlus1Name, - origins: originList, + origins: originInfoList, + numCookies: 0, }; } + function createOriginInfo(origin, override) { + if (override === undefined) + override = {}; + return Object.assign( + { + origin: origin, + engagement: 0, + usage: 0, + }, + override); + } + return { eventToPromise: eventToPromise, fakeDataBind: fakeDataBind, @@ -207,6 +221,7 @@ createRawSiteException: createRawSiteException, createSiteSettingsPrefs: createSiteSettingsPrefs, createSiteGroup: createSiteGroup, + createOriginInfo: createOriginInfo, }; });
diff --git a/chrome/test/data/webui/settings/zoom_levels_tests.js b/chrome/test/data/webui/settings/zoom_levels_tests.js index abd85b9..0771b92 100644 --- a/chrome/test/data/webui/settings/zoom_levels_tests.js +++ b/chrome/test/data/webui/settings/zoom_levels_tests.js
@@ -75,7 +75,7 @@ assertEquals(0, list.items.length); assertEquals( 0, testElement.shadowRoot.querySelectorAll('.list-item').length); - assertTrue(!!testElement.$$('#empty')); + assertFalse(testElement.$.empty.hidden); }); test('non-empty zoom state', function() { @@ -86,7 +86,7 @@ const list = testElement.$.list; assertTrue(!!list); assertEquals(2, list.items.length); - assertFalse(!!testElement.$$('#empty')); + assertTrue(testElement.$.empty.hidden); assertEquals( 2, testElement.shadowRoot.querySelectorAll('.list-item').length);
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 88288395..c91b837 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -319,6 +319,8 @@ "dbus/update_engine_client.h", "dbus/upstart_client.cc", "dbus/upstart_client.h", + "dbus/util/account_identifier_operators.cc", + "dbus/util/account_identifier_operators.h", "dbus/util/tpm_util.cc", "dbus/util/tpm_util.h", "dbus/util/version_loader.cc",
diff --git a/chromeos/attestation/attestation_flow.cc b/chromeos/attestation/attestation_flow.cc index dda7001..f1c046fd 100644 --- a/chromeos/attestation/attestation_flow.cc +++ b/chromeos/attestation/attestation_flow.cc
@@ -251,7 +251,8 @@ &AttestationFlow::StartCertificateRequest, weak_factory_.GetWeakPtr(), certificate_profile, account_id, request_origin, true, callback); cryptohome_client_->TpmAttestationDoesKeyExist( - key_type, cryptohome::Identification(account_id), key_name, + key_type, cryptohome::CreateAccountIdentifierFromAccountId(account_id), + key_name, base::BindOnce( &DBusBoolRedirectCallback, on_key_exists, on_key_not_exists, base::BindRepeating(callback, ATTESTATION_UNSPECIFIED_FAILURE, ""), @@ -316,8 +317,8 @@ const std::string& key_name, const CertificateCallback& callback) { cryptohome_client_->TpmAttestationGetCertificate( - key_type, cryptohome::Identification(account_id), key_name, - base::BindOnce(&DBusCertificateMethodCallback, callback)); + key_type, cryptohome::CreateAccountIdentifierFromAccountId(account_id), + key_name, base::BindOnce(&DBusCertificateMethodCallback, callback)); } void AttestationFlow::CheckAttestationReadyAndReschedule(
diff --git a/chromeos/attestation/attestation_flow_unittest.cc b/chromeos/attestation/attestation_flow_unittest.cc index 36aae2b..ee926df 100644 --- a/chromeos/attestation/attestation_flow_unittest.cc +++ b/chromeos/attestation/attestation_flow_unittest.cc
@@ -619,7 +619,7 @@ StrictMock<cryptohome::MockAsyncMethodCaller> async_caller; chromeos::FakeCryptohomeClient client; - client.SetTpmAttestationUserCertificate(cryptohome::Identification(), + client.SetTpmAttestationUserCertificate(cryptohome::AccountIdentifier(), kEnterpriseUserKey, "fake_cert"); // We're not expecting any server calls in this case; StrictMock will verify.
diff --git a/chromeos/cryptohome/async_method_caller.cc b/chromeos/cryptohome/async_method_caller.cc index c9956d8..5e0cef0 100644 --- a/chromeos/cryptohome/async_method_caller.cc +++ b/chromeos/cryptohome/async_method_caller.cc
@@ -38,7 +38,7 @@ void AsyncRemove(const Identification& cryptohome_id, Callback callback) override { DBusThreadManager::Get()->GetCryptohomeClient()->AsyncRemove( - cryptohome_id, + CreateAccountIdentifierFromIdentification(cryptohome_id), base::BindOnce(&AsyncMethodCallerImpl::RegisterAsyncCallback, weak_ptr_factory_.GetWeakPtr(), callback, "Couldn't initiate async removal of cryptohome.")); @@ -76,7 +76,9 @@ DBusThreadManager::Get() ->GetCryptohomeClient() ->AsyncTpmAttestationCreateCertRequest( - pca_type, certificate_profile, cryptohome_id, request_origin, + pca_type, certificate_profile, + CreateAccountIdentifierFromIdentification(cryptohome_id), + request_origin, base::BindOnce( &AsyncMethodCallerImpl::RegisterAsyncDataCallback, weak_ptr_factory_.GetWeakPtr(), callback, @@ -92,7 +94,8 @@ DBusThreadManager::Get() ->GetCryptohomeClient() ->AsyncTpmAttestationFinishCertRequest( - pca_response, key_type, cryptohome_id, key_name, + pca_response, key_type, + CreateAccountIdentifierFromIdentification(cryptohome_id), key_name, base::BindOnce( &AsyncMethodCallerImpl::RegisterAsyncDataCallback, weak_ptr_factory_.GetWeakPtr(), callback, @@ -105,7 +108,8 @@ const std::string& key_name, const Callback& callback) override { DBusThreadManager::Get()->GetCryptohomeClient()->TpmAttestationRegisterKey( - key_type, cryptohome_id, key_name, + key_type, CreateAccountIdentifierFromIdentification(cryptohome_id), + key_name, base::BindOnce(&AsyncMethodCallerImpl::RegisterAsyncCallback, weak_ptr_factory_.GetWeakPtr(), callback, "Couldn't initiate async attestation register key.")); @@ -123,8 +127,8 @@ DBusThreadManager::Get() ->GetCryptohomeClient() ->TpmAttestationSignEnterpriseChallenge( - key_type, cryptohome_id, key_name, domain, device_id, options, - challenge, + key_type, CreateAccountIdentifierFromIdentification(cryptohome_id), + key_name, domain, device_id, options, challenge, base::BindOnce( &AsyncMethodCallerImpl::RegisterAsyncDataCallback, weak_ptr_factory_.GetWeakPtr(), callback, @@ -140,7 +144,8 @@ DBusThreadManager::Get() ->GetCryptohomeClient() ->TpmAttestationSignSimpleChallenge( - key_type, cryptohome_id, key_name, challenge, + key_type, CreateAccountIdentifierFromIdentification(cryptohome_id), + key_name, challenge, base::BindOnce( &AsyncMethodCallerImpl::RegisterAsyncDataCallback, weak_ptr_factory_.GetWeakPtr(), callback,
diff --git a/chromeos/cryptohome/cryptohome_parameters.cc b/chromeos/cryptohome/cryptohome_parameters.cc index b90b6d5..8e7b966c 100644 --- a/chromeos/cryptohome/cryptohome_parameters.cc +++ b/chromeos/cryptohome/cryptohome_parameters.cc
@@ -73,6 +73,19 @@ AccountType::UNKNOWN); } +AccountIdentifier CreateAccountIdentifierFromAccountId(const AccountId& id) { + AccountIdentifier out; + out.set_account_id(GetCryptohomeId(id)); + return out; +} + +AccountIdentifier CreateAccountIdentifierFromIdentification( + const Identification& id) { + AccountIdentifier out; + out.set_account_id(id.id()); + return out; +} + KeyDefinition::AuthorizationData::Secret::Secret() : encrypt(false), sign(false), wrapped(false) {
diff --git a/chromeos/cryptohome/cryptohome_parameters.h b/chromeos/cryptohome/cryptohome_parameters.h index 91457e7..e6a9340 100644 --- a/chromeos/cryptohome/cryptohome_parameters.h +++ b/chromeos/cryptohome/cryptohome_parameters.h
@@ -13,6 +13,7 @@ #include "base/containers/hash_tables.h" #include "chromeos/chromeos_export.h" +#include "chromeos/dbus/cryptohome/rpc.pb.h" #include "chromeos/login/auth/challenge_response_key.h" class AccountId; @@ -53,6 +54,14 @@ std::string id_; }; +// Creates AccountIdentifier from AccountId. +CHROMEOS_EXPORT AccountIdentifier +CreateAccountIdentifierFromAccountId(const AccountId& id); + +// Creates AccountIdentifier from Identification. +CHROMEOS_EXPORT AccountIdentifier +CreateAccountIdentifierFromIdentification(const Identification& id); + // Definition of the key (e.g. password) for the cryptohome. // It contains authorization data along with extra parameters like permissions // associated with this key.
diff --git a/chromeos/cryptohome/homedir_methods.cc b/chromeos/cryptohome/homedir_methods.cc index e5c8407f0..8b22509 100644 --- a/chromeos/cryptohome/homedir_methods.cc +++ b/chromeos/cryptohome/homedir_methods.cc
@@ -37,7 +37,7 @@ const cryptohome::CheckKeyRequest& request, const Callback& callback) override { DBusThreadManager::Get()->GetCryptohomeClient()->CheckKeyEx( - id, auth, request, + CreateAccountIdentifierFromIdentification(id), auth, request, base::BindOnce(&HomedirMethodsImpl::OnBaseReplyCallback, weak_ptr_factory_.GetWeakPtr(), callback)); } @@ -47,7 +47,7 @@ const AddKeyRequest& request, const Callback& callback) override { DBusThreadManager::Get()->GetCryptohomeClient()->AddKeyEx( - id, auth, request, + CreateAccountIdentifierFromIdentification(id), auth, request, base::BindOnce(&HomedirMethodsImpl::OnBaseReplyCallback, weak_ptr_factory_.GetWeakPtr(), callback)); } @@ -57,7 +57,7 @@ const RemoveKeyRequest& request, const Callback& callback) override { DBusThreadManager::Get()->GetCryptohomeClient()->RemoveKeyEx( - id, auth, request, + CreateAccountIdentifierFromIdentification(id), auth, request, base::BindOnce(&HomedirMethodsImpl::OnBaseReplyCallback, weak_ptr_factory_.GetWeakPtr(), callback)); } @@ -67,7 +67,7 @@ const UpdateKeyRequest& request, const Callback& callback) override { DBusThreadManager::Get()->GetCryptohomeClient()->UpdateKeyEx( - id, auth, request, + CreateAccountIdentifierFromIdentification(id), auth, request, base::BindOnce(&HomedirMethodsImpl::OnBaseReplyCallback, weak_ptr_factory_.GetWeakPtr(), callback)); }
diff --git a/chromeos/dbus/cryptohome_client.cc b/chromeos/dbus/cryptohome_client.cc index 96f91f7..b4da80937 100644 --- a/chromeos/dbus/cryptohome_client.cc +++ b/chromeos/dbus/cryptohome_client.cc
@@ -19,7 +19,6 @@ #include "base/observer_list.h" #include "base/optional.h" #include "chromeos/cryptohome/async_method_caller.h" -#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/dbus/blocking_method_caller.h" #include "chromeos/dbus/cryptohome/key.pb.h" #include "chromeos/dbus/cryptohome/rpc.pb.h" @@ -42,11 +41,6 @@ // is 2 minutes. const int kTpmDBusTimeoutMs = 2 * 60 * 1000; -void FillIdentificationProtobuf(const cryptohome::Identification& id, - cryptohome::AccountIdentifier* id_proto) { - id_proto->set_account_id(id.id()); -} - // Values for the attestation server switch. const char kAttestationServerDefault[] = "default"; const char kAttestationServerTest[] = "test"; @@ -121,12 +115,12 @@ } // CryptohomeClient override. - void AsyncRemove(const cryptohome::Identification& cryptohome_id, + void AsyncRemove(const cryptohome::AccountIdentifier& id, AsyncMethodCallback callback) override { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncRemove); dbus::MessageWriter writer(&method_call); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, base::BindOnce(&CryptohomeClientImpl::OnAsyncMethodCall, @@ -135,20 +129,15 @@ // CryptohomeClient override. void RenameCryptohome( - const cryptohome::Identification& cryptohome_id_from, - const cryptohome::Identification& cryptohome_id_to, + const cryptohome::AccountIdentifier& id_from, + const cryptohome::AccountIdentifier& id_to, DBusMethodCallback<cryptohome::BaseReply> callback) override { const char* method_name = cryptohome::kCryptohomeRenameCryptohome; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); - cryptohome::AccountIdentifier id_from_proto; - cryptohome::AccountIdentifier id_to_proto; - FillIdentificationProtobuf(cryptohome_id_from, &id_from_proto); - FillIdentificationProtobuf(cryptohome_id_to, &id_to_proto); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_from_proto); - writer.AppendProtoAsArrayOfBytes(id_to_proto); + writer.AppendProtoAsArrayOfBytes(id_from); + writer.AppendProtoAsArrayOfBytes(id_to); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, base::BindOnce(&CryptohomeClientImpl::OnBaseReplyMethod, @@ -157,15 +146,12 @@ // CryptohomeClient override. void GetAccountDiskUsage( - const cryptohome::Identification& account_id, + const cryptohome::AccountIdentifier& account_id, DBusMethodCallback<cryptohome::BaseReply> callback) override { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetAccountDiskUsage); - cryptohome::AccountIdentifier id; - FillIdentificationProtobuf(account_id, &id); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id); + writer.AppendProtoAsArrayOfBytes(account_id); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, base::BindOnce(&CryptohomeClientImpl::OnBaseReplyMethod, @@ -184,12 +170,12 @@ } // CryptohomeClient override, - void GetSanitizedUsername(const cryptohome::Identification& cryptohome_id, + void GetSanitizedUsername(const cryptohome::AccountIdentifier& id, DBusMethodCallback<std::string> callback) override { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetSanitizedUsername); dbus::MessageWriter writer(&method_call); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, base::BindOnce(&CryptohomeClientImpl::OnStringMethod, @@ -198,11 +184,11 @@ // CryptohomeClient override. std::string BlockingGetSanitizedUsername( - const cryptohome::Identification& cryptohome_id) override { + const cryptohome::AccountIdentifier& id) override { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetSanitizedUsername); dbus::MessageWriter writer(&method_call); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); std::unique_ptr<dbus::Response> response = blocking_method_caller_->CallMethodAndBlock(&method_call); @@ -337,13 +323,13 @@ // CryptohomeClient override. void Pkcs11GetTpmTokenInfoForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, DBusMethodCallback<TpmTokenInfo> callback) override { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomePkcs11GetTpmTokenInfoForUser); dbus::MessageWriter writer(&method_call); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, base::BindOnce(&CryptohomeClientImpl::OnPkcs11GetTpmTokenInfo, @@ -484,7 +470,7 @@ void AsyncTpmAttestationCreateCertRequest( attestation::PrivacyCAType pca_type, attestation::AttestationCertificateProfile certificate_profile, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& request_origin, AsyncMethodCallback callback) override { dbus::MethodCall method_call( @@ -493,7 +479,7 @@ dbus::MessageWriter writer(&method_call); writer.AppendInt32(pca_type); writer.AppendInt32(certificate_profile); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(request_origin); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, @@ -505,7 +491,7 @@ void AsyncTpmAttestationFinishCertRequest( const std::string& pca_response, attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, AsyncMethodCallback callback) override { dbus::MethodCall method_call( @@ -517,7 +503,7 @@ pca_response.size()); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, @@ -526,18 +512,17 @@ } // CryptohomeClient override. - void TpmAttestationDoesKeyExist( - attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, - const std::string& key_name, - DBusMethodCallback<bool> callback) override { + void TpmAttestationDoesKeyExist(attestation::AttestationKeyType key_type, + const cryptohome::AccountIdentifier& id, + const std::string& key_name, + DBusMethodCallback<bool> callback) override { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationDoesKeyExist); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); CallBoolMethod(&method_call, std::move(callback)); } @@ -545,7 +530,7 @@ // CryptohomeClient override. void TpmAttestationGetCertificate( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) override { dbus::MethodCall method_call( @@ -554,7 +539,7 @@ dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, @@ -565,7 +550,7 @@ // CryptohomeClient override. void TpmAttestationGetPublicKey( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) override { dbus::MethodCall method_call( @@ -574,7 +559,7 @@ dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, @@ -583,18 +568,17 @@ } // CryptohomeClient override. - void TpmAttestationRegisterKey( - attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, - const std::string& key_name, - AsyncMethodCallback callback) override { + void TpmAttestationRegisterKey(attestation::AttestationKeyType key_type, + const cryptohome::AccountIdentifier& id, + const std::string& key_name, + AsyncMethodCallback callback) override { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationRegisterKey); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, @@ -605,7 +589,7 @@ // CryptohomeClient override. void TpmAttestationSignEnterpriseChallenge( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, const std::string& domain, const std::string& device_id, @@ -619,7 +603,7 @@ writer.AppendInt32(GetVerifiedAccessType()); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); writer.AppendString(domain); writer.AppendArrayOfBytes( @@ -638,7 +622,7 @@ // CryptohomeClient override. void TpmAttestationSignSimpleChallenge( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, const std::string& challenge, AsyncMethodCallback callback) override { @@ -648,7 +632,7 @@ dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); writer.AppendArrayOfBytes( reinterpret_cast<const uint8_t*>(challenge.data()), challenge.size()); @@ -661,7 +645,7 @@ // CryptohomeClient override. void TpmAttestationGetKeyPayload( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) override { dbus::MethodCall method_call( @@ -670,7 +654,7 @@ dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs, @@ -679,19 +663,18 @@ } // CryptohomeClient override. - void TpmAttestationSetKeyPayload( - attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, - const std::string& key_name, - const std::string& payload, - DBusMethodCallback<bool> callback) override { + void TpmAttestationSetKeyPayload(attestation::AttestationKeyType key_type, + const cryptohome::AccountIdentifier& id, + const std::string& key_name, + const std::string& payload, + DBusMethodCallback<bool> callback) override { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationSetKeyPayload); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_name); writer.AppendArrayOfBytes(reinterpret_cast<const uint8_t*>(payload.data()), payload.size()); @@ -700,7 +683,7 @@ // CryptohomeClient override. void TpmAttestationDeleteKeys(attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_prefix, DBusMethodCallback<bool> callback) override { dbus::MethodCall method_call( @@ -709,7 +692,7 @@ dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(id.account_id()); writer.AppendString(key_prefix); CallBoolMethod(&method_call, std::move(callback)); } @@ -726,17 +709,14 @@ } void GetKeyDataEx( - const cryptohome::Identification& id, + const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::GetKeyDataRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override { - cryptohome::AccountIdentifier id_proto; - FillIdentificationProtobuf(id, &id_proto); - dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetKeyDataEx); dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_proto); + writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); @@ -746,19 +726,15 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void CheckKeyEx(const cryptohome::Identification& id, + void CheckKeyEx(const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::CheckKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override { const char* method_name = cryptohome::kCryptohomeCheckKeyEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); - - cryptohome::AccountIdentifier id_proto; - FillIdentificationProtobuf(id, &id_proto); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_proto); + writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); @@ -768,19 +744,15 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void MountEx(const cryptohome::Identification& id, + void MountEx(const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::MountRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override { const char* method_name = cryptohome::kCryptohomeMountEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); - - cryptohome::AccountIdentifier id_proto; - FillIdentificationProtobuf(id, &id_proto); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_proto); + writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); @@ -790,19 +762,15 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void AddKeyEx(const cryptohome::Identification& id, + void AddKeyEx(const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::AddKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override { const char* method_name = cryptohome::kCryptohomeAddKeyEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); - - cryptohome::AccountIdentifier id_proto; - FillIdentificationProtobuf(id, &id_proto); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_proto); + writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); @@ -813,19 +781,15 @@ } void UpdateKeyEx( - const cryptohome::Identification& id, + const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::UpdateKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override { const char* method_name = cryptohome::kCryptohomeUpdateKeyEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); - - cryptohome::AccountIdentifier id_proto; - FillIdentificationProtobuf(id, &id_proto); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_proto); + writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); @@ -836,18 +800,14 @@ } void RemoveKeyEx( - const cryptohome::Identification& id, + const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::RemoveKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override { const char* method_name = cryptohome::kCryptohomeRemoveKeyEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); - - cryptohome::AccountIdentifier id_proto; - FillIdentificationProtobuf(id, &id_proto); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_proto); + writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); @@ -893,17 +853,14 @@ request, std::move(callback)); } - void MigrateToDircrypto(const cryptohome::Identification& cryptohome_id, + void MigrateToDircrypto(const cryptohome::AccountIdentifier& id, const cryptohome::MigrateToDircryptoRequest& request, VoidDBusMethodCallback callback) override { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeMigrateToDircrypto); - cryptohome::AccountIdentifier id_proto; - FillIdentificationProtobuf(cryptohome_id, &id_proto); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_proto); + writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(request); // The migration progress takes unpredicatable time depending on the @@ -914,17 +871,13 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void NeedsDircryptoMigration(const cryptohome::Identification& cryptohome_id, + void NeedsDircryptoMigration(const cryptohome::AccountIdentifier& id, DBusMethodCallback<bool> callback) override { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeNeedsDircryptoMigration); - - cryptohome::AccountIdentifier id_proto; - FillIdentificationProtobuf(cryptohome_id, &id_proto); - dbus::MessageWriter writer(&method_call); - writer.AppendProtoAsArrayOfBytes(id_proto); + writer.AppendProtoAsArrayOfBytes(id); proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, @@ -1328,8 +1281,8 @@ // static std::string CryptohomeClient::GetStubSanitizedUsername( - const cryptohome::Identification& cryptohome_id) { - return cryptohome_id.id() + kUserIdStubHashSuffix; + const cryptohome::AccountIdentifier& id) { + return id.account_id() + kUserIdStubHashSuffix; } } // namespace chromeos
diff --git a/chromeos/dbus/cryptohome_client.h b/chromeos/dbus/cryptohome_client.h index c233ddd..f2434c8 100644 --- a/chromeos/dbus/cryptohome_client.h +++ b/chromeos/dbus/cryptohome_client.h
@@ -39,8 +39,6 @@ class SetFirmwareManagementParametersRequest; class UpdateKeyRequest; -class Identification; - } // namespace cryptohome namespace chromeos { @@ -132,7 +130,7 @@ // Returns the sanitized |username| that the stub implementation would return. static std::string GetStubSanitizedUsername( - const cryptohome::Identification& cryptohome_id); + const cryptohome::AccountIdentifier& id); // Adds an observer. virtual void AddObserver(Observer* observer) = 0; @@ -160,20 +158,20 @@ // Calls AsyncRemove method. |callback| is called after the method call // succeeds. - virtual void AsyncRemove(const cryptohome::Identification& cryptohome_id, + virtual void AsyncRemove(const cryptohome::AccountIdentifier& id, AsyncMethodCallback callback) = 0; // Calls RenameCryptohome method. |callback| is called after the method // call succeeds. virtual void RenameCryptohome( - const cryptohome::Identification& cryptohome_id_from, - const cryptohome::Identification& cryptohome_id_to, + const cryptohome::AccountIdentifier& id_from, + const cryptohome::AccountIdentifier& id_to, DBusMethodCallback<cryptohome::BaseReply> callback) = 0; // Calls GetAccountDiskUsage method. |callback| is called after the method // call succeeds virtual void GetAccountDiskUsage( - const cryptohome::Identification& account_id, + const cryptohome::AccountIdentifier& account_id, DBusMethodCallback<cryptohome::BaseReply> callback) = 0; // Calls GetSystemSalt method. |callback| is called after the method call @@ -184,7 +182,7 @@ // Calls GetSanitizedUsername method. |callback| is called after the method // call succeeds. virtual void GetSanitizedUsername( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, DBusMethodCallback<std::string> callback) = 0; // Same as GetSanitizedUsername() but blocks until a reply is received, and @@ -194,7 +192,7 @@ // considered acceptable (e.g. restarting the browser after a crash or after // a flag change). virtual std::string BlockingGetSanitizedUsername( - const cryptohome::Identification& cryptohome_id) = 0; + const cryptohome::AccountIdentifier& id) = 0; // Calls MountGuestEx method. |callback| is called after the method call // succeeds. @@ -255,10 +253,9 @@ DBusMethodCallback<TpmTokenInfo> callback) = 0; // Calls Pkcs11GetTpmTokenInfoForUser method. On success |callback| will - // receive PKCS #11 token information for the user identified by - // |cryptohome_id|. + // receive PKCS #11 token information for the user identified by |id|. virtual void Pkcs11GetTpmTokenInfoForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, DBusMethodCallback<TpmTokenInfo> callback) = 0; // Calls InstallAttributesGet method and returns true when the call succeeds. @@ -325,19 +322,18 @@ AsyncMethodCallback callback) = 0; // Asynchronously creates an attestation certificate request according to - // |certificate_profile|. Some profiles require that the |cryptohome_id| of + // |certificate_profile|. Some profiles require that the |id| of // the currently active user and an identifier of the |request_origin| be // provided. |callback| will be called when the dbus call completes. When // the operation completes, the AsyncCallStatusWithDataHandler signal handler // is called. The data that is sent with the signal is a certificate request // to be sent to the Privacy CA of type |pca_type|. The certificate request // is completed by calling AsyncTpmAttestationFinishCertRequest. The - // |cryptohome_id| will not be included in the certificate request for the - // Privacy CA. + // |id| will not be included in the certificate request for the Privacy CA. virtual void AsyncTpmAttestationCreateCertRequest( chromeos::attestation::PrivacyCAType pca_type, attestation::AttestationCertificateProfile certificate_profile, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& request_origin, AsyncMethodCallback callback) = 0; @@ -348,45 +344,42 @@ // is the response to the certificate request emitted by the Privacy CA. // |key_type| determines whether the certified key is to be associated with // the current user. |key_name| is a name for the key. If |key_type| is - // KEY_USER, a |cryptohome_id| must be provided. Otherwise |cryptohome_id| - // is ignored. + // KEY_USER, a |id| must be provided. Otherwise |id| is ignored. virtual void AsyncTpmAttestationFinishCertRequest( const std::string& pca_response, attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, AsyncMethodCallback callback) = 0; // Checks if an attestation key already exists. If the key specified by // |key_type| and |key_name| exists, then the result sent to the callback will - // be true. If |key_type| is KEY_USER, a |cryptohome_id| must be provided. - // Otherwise |cryptohome_id| is ignored. + // be true. If |key_type| is KEY_USER, a |id| must be provided. + // Otherwise |id| is ignored. virtual void TpmAttestationDoesKeyExist( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, DBusMethodCallback<bool> callback) = 0; // Gets the attestation certificate for the key specified by |key_type| and // |key_name|. |callback| will be called when the operation completes. If // the key does not exist the callback |result| parameter will be false. If - // |key_type| is KEY_USER, a |cryptohome_id| must be provided. Otherwise - // |cryptohome_id| - // is ignored. + // |key_type| is KEY_USER, a |id| must be provided. Otherwise |id| is + // ignored. virtual void TpmAttestationGetCertificate( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) = 0; // Gets the public key for the key specified by |key_type| and |key_name|. // |callback| will be called when the operation completes. If the key does // not exist the callback |result| parameter will be false. If |key_type| is - // KEY_USER, a |cryptohome_id| must be provided. Otherwise |cryptohome_id| - // is ignored. + // KEY_USER, a |id| must be provided. Otherwise |id| is ignored. virtual void TpmAttestationGetPublicKey( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) = 0; @@ -394,11 +387,11 @@ // PKCS #11 token. The |callback| will be called when the dbus call // completes. When the operation completes, the AsyncCallStatusHandler signal // handler is called. |key_type| and |key_name| specify the key to register. - // If |key_type| is KEY_USER, a |cryptohome_id| must be provided. Otherwise - // |cryptohome_id| is ignored. + // If |key_type| is KEY_USER, a |id| must be provided. Otherwise |id| is + // ignored. virtual void TpmAttestationRegisterKey( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, AsyncMethodCallback callback) = 0; @@ -408,11 +401,11 @@ // generated. |challenge| must be a valid enterprise attestation challenge. // The |callback| will be called when the dbus call completes. When the // operation completes, the AsyncCallStatusWithDataHandler signal handler is - // called. If |key_type| is KEY_USER, a |cryptohome_id| must be provided. - // Otherwise |cryptohome_id| is ignored. + // called. If |key_type| is KEY_USER, a |id| must be provided. + // Otherwise |id| is ignored. virtual void TpmAttestationSignEnterpriseChallenge( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, const std::string& domain, const std::string& device_id, @@ -426,11 +419,10 @@ // cannot be used to sign arbitrary data. The |callback| will be called when // the dbus call completes. When the operation completes, the // AsyncCallStatusWithDataHandler signal handler is called. If |key_type| is - // KEY_USER, a |cryptohome_id| must be provided. Otherwise |cryptohome_id| - // is ignored. + // KEY_USER, a |id| must be provided. Otherwise |id| is ignored. virtual void TpmAttestationSignSimpleChallenge( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, const std::string& challenge, AsyncMethodCallback callback) = 0; @@ -440,22 +432,21 @@ // If the key does not exist the callback |result| parameter will be false. // If no payload has been set for the key the callback |result| parameter will // be true and the |data| parameter will be empty. If |key_type| is - // KEY_USER, a |cryptohome_id| must be provided. Otherwise |cryptohome_id| - // is ignored. + // KEY_USER, a |id| must be provided. Otherwise |id| is ignored. virtual void TpmAttestationGetKeyPayload( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) = 0; // Sets the |payload| associated with the key specified by |key_type| and // |key_name|. The |callback| will be called when the operation completes. // If the operation succeeds, the callback |result| parameter will be true. - // If |key_type| is KEY_USER, a |cryptohome_id| must be provided. Otherwise - // |cryptohome_id| is ignored. + // If |key_type| is KEY_USER, a |id| must be provided. Otherwise |id| is + // ignored. virtual void TpmAttestationSetKeyPayload( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_name, const std::string& payload, DBusMethodCallback<bool> callback) = 0; @@ -463,14 +454,13 @@ // Deletes certified keys as specified by |key_type| and |key_prefix|. The // |callback| will be called when the operation completes. If the operation // succeeds, the callback |result| parameter will be true. If |key_type| is - // KEY_USER, a |cryptohome_id| must be provided. Otherwise |cryptohome_id| - // is ignored. + // KEY_USER, a |id| must be provided. Otherwise |id| is ignored. // All keys where the key name has a prefix matching |key_prefix| will be // deleted. All meta-data associated with the key, including certificates, // will also be deleted. virtual void TpmAttestationDeleteKeys( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const std::string& key_prefix, DBusMethodCallback<bool> callback) = 0; @@ -484,7 +474,7 @@ // present, this does not include any secret information and the call should // not be authenticated (|auth| should be empty). virtual void GetKeyDataEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::GetKeyDataRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) = 0; @@ -493,7 +483,7 @@ // call, and with reply protobuf. // CheckKeyEx just checks if authorization information is valid. virtual void CheckKeyEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::CheckKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) = 0; @@ -502,7 +492,7 @@ // the reply. // MountEx attempts to mount home dir using given authorization, // and can create new home dir if necessary values are specified in |request|. - virtual void MountEx(const cryptohome::Identification& cryptohome_id, + virtual void MountEx(const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::MountRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) = 0; @@ -511,7 +501,7 @@ // call, and with reply protobuf. // AddKeyEx adds another key to the given key set. |request| also defines // behavior in case when key with specified label already exist. - virtual void AddKeyEx(const cryptohome::Identification& cryptohome_id, + virtual void AddKeyEx(const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::AddKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) = 0; @@ -522,7 +512,7 @@ // other keys. If specified at home dir creation time, new key may have // to be signed and/or encrypted. virtual void UpdateKeyEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::UpdateKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) = 0; @@ -531,7 +521,7 @@ // call, and with reply protobuf. // RemoveKeyEx removes key from the given key set. virtual void RemoveKeyEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::RemoveKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) = 0; @@ -569,7 +559,7 @@ // |request| contains additional parameters, such as specifying if a full // migration or a minimal migration should be performed. virtual void MigrateToDircrypto( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& id, const cryptohome::MigrateToDircryptoRequest& request, VoidDBusMethodCallback callback) = 0; @@ -589,9 +579,8 @@ // Calls NeedsDircryptoMigration to find out whether the given user needs // dircrypto migration. - virtual void NeedsDircryptoMigration( - const cryptohome::Identification& cryptohome_id, - DBusMethodCallback<bool> callback) = 0; + virtual void NeedsDircryptoMigration(const cryptohome::AccountIdentifier& id, + DBusMethodCallback<bool> callback) = 0; // Calls GetSupportedKeyPolicies to determine which type of keys can be added. virtual void GetSupportedKeyPolicies(
diff --git a/chromeos/dbus/fake_auth_policy_client.cc b/chromeos/dbus/fake_auth_policy_client.cc index c78d952..84b2ce73 100644 --- a/chromeos/dbus/fake_auth_policy_client.cc +++ b/chromeos/dbus/fake_auth_policy_client.cc
@@ -248,7 +248,8 @@ policy_data.set_policy_value(payload); response.set_policy_data(policy_data.SerializeAsString()); session_manager_client->StorePolicyForUser( - cryptohome::Identification(account_id), response.SerializeAsString(), + cryptohome::CreateAccountIdentifierFromAccountId(account_id), + response.SerializeAsString(), base::BindOnce(&OnStorePolicy, std::move(callback))); }
diff --git a/chromeos/dbus/fake_cryptohome_client.cc b/chromeos/dbus/fake_cryptohome_client.cc index a9335a8..fe1cc36 100644 --- a/chromeos/dbus/fake_cryptohome_client.cc +++ b/chromeos/dbus/fake_cryptohome_client.cc
@@ -22,6 +22,7 @@ #include "chromeos/dbus/attestation/attestation.pb.h" #include "chromeos/dbus/cryptohome/key.pb.h" #include "chromeos/dbus/cryptohome/rpc.pb.h" +#include "chromeos/dbus/util/account_identifier_operators.h" #include "components/policy/proto/install_attributes.pb.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -97,20 +98,20 @@ } void FakeCryptohomeClient::AsyncRemove( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, AsyncMethodCallback callback) { ReturnAsyncMethodResult(std::move(callback)); } void FakeCryptohomeClient::RenameCryptohome( - const cryptohome::Identification& cryptohome_id_from, - const cryptohome::Identification& cryptohome_id_to, + const cryptohome::AccountIdentifier& cryptohome_id_from, + const cryptohome::AccountIdentifier& cryptohome_id_to, DBusMethodCallback<cryptohome::BaseReply> callback) { ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback)); } void FakeCryptohomeClient::GetAccountDiskUsage( - const cryptohome::Identification& account_id, + const cryptohome::AccountIdentifier& account_id, DBusMethodCallback<cryptohome::BaseReply> callback) { cryptohome::BaseReply reply; cryptohome::GetAccountDiskUsageReply* get_account_disk_usage_reply = @@ -127,7 +128,7 @@ } void FakeCryptohomeClient::GetSanitizedUsername( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, DBusMethodCallback<std::string> callback) { // Even for stub implementation we have to return different values so that // multi-profiles would work. @@ -139,7 +140,7 @@ } std::string FakeCryptohomeClient::BlockingGetSanitizedUsername( - const cryptohome::Identification& cryptohome_id) { + const cryptohome::AccountIdentifier& cryptohome_id) { return service_is_available_ ? GetStubSanitizedUsername(cryptohome_id) : std::string(); } @@ -227,7 +228,7 @@ } void FakeCryptohomeClient::Pkcs11GetTpmTokenInfoForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, DBusMethodCallback<TpmTokenInfo> callback) { Pkcs11GetTpmTokenInfo(std::move(callback)); } @@ -350,7 +351,7 @@ void FakeCryptohomeClient::AsyncTpmAttestationCreateCertRequest( chromeos::attestation::PrivacyCAType pca_type, attestation::AttestationCertificateProfile certificate_profile, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& request_origin, AsyncMethodCallback callback) { ReturnAsyncMethodData(std::move(callback), std::string()); @@ -359,7 +360,7 @@ void FakeCryptohomeClient::AsyncTpmAttestationFinishCertRequest( const std::string& pca_response, attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, AsyncMethodCallback callback) { ReturnAsyncMethodData(std::move(callback), std::string()); @@ -367,7 +368,7 @@ void FakeCryptohomeClient::TpmAttestationDoesKeyExist( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, DBusMethodCallback<bool> callback) { if (!service_is_available_ || @@ -394,7 +395,7 @@ void FakeCryptohomeClient::TpmAttestationGetCertificate( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) { TpmAttestationDataResult result; @@ -423,7 +424,7 @@ void FakeCryptohomeClient::TpmAttestationGetPublicKey( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -433,7 +434,7 @@ void FakeCryptohomeClient::TpmAttestationRegisterKey( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, AsyncMethodCallback callback) { ReturnAsyncMethodData(std::move(callback), std::string()); @@ -441,7 +442,7 @@ void FakeCryptohomeClient::TpmAttestationSignEnterpriseChallenge( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, const std::string& domain, const std::string& device_id, @@ -453,7 +454,7 @@ void FakeCryptohomeClient::TpmAttestationSignSimpleChallenge( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, const std::string& challenge, AsyncMethodCallback callback) { @@ -465,7 +466,7 @@ void FakeCryptohomeClient::TpmAttestationGetKeyPayload( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) { TpmAttestationDataResult result; @@ -483,7 +484,7 @@ void FakeCryptohomeClient::TpmAttestationSetKeyPayload( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, const std::string& payload, DBusMethodCallback<bool> callback) { @@ -500,7 +501,7 @@ void FakeCryptohomeClient::TpmAttestationDeleteKeys( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_prefix, DBusMethodCallback<bool> callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -514,7 +515,7 @@ } void FakeCryptohomeClient::GetKeyDataEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::GetKeyDataRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) { @@ -538,7 +539,7 @@ } void FakeCryptohomeClient::CheckKeyEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::CheckKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) { @@ -564,7 +565,7 @@ } void FakeCryptohomeClient::MountEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::MountRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) { @@ -584,7 +585,7 @@ } void FakeCryptohomeClient::AddKeyEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::AddKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) { @@ -593,7 +594,7 @@ } void FakeCryptohomeClient::RemoveKeyEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::RemoveKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) { @@ -607,7 +608,7 @@ } void FakeCryptohomeClient::UpdateKeyEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::UpdateKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) { @@ -637,7 +638,7 @@ } void FakeCryptohomeClient::MigrateToDircrypto( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::MigrateToDircryptoRequest& request, VoidDBusMethodCallback callback) { id_for_disk_migrated_to_dircrypto_ = cryptohome_id; @@ -664,7 +665,7 @@ } void FakeCryptohomeClient::NeedsDircryptoMigration( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, DBusMethodCallback<bool> callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -704,7 +705,7 @@ } void FakeCryptohomeClient::SetTpmAttestationUserCertificate( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, const std::string& certificate) { user_certificate_map_[std::make_pair(cryptohome_id, key_name)] = certificate;
diff --git a/chromeos/dbus/fake_cryptohome_client.h b/chromeos/dbus/fake_cryptohome_client.h index 9ab6b6f..c266973 100644 --- a/chromeos/dbus/fake_cryptohome_client.h +++ b/chromeos/dbus/fake_cryptohome_client.h
@@ -42,21 +42,21 @@ const cryptohome::AuthorizationRequest& auth_request, const cryptohome::MigrateKeyRequest& migrate_request, DBusMethodCallback<cryptohome::BaseReply> callback) override; - void AsyncRemove(const cryptohome::Identification& cryptohome_id, + void AsyncRemove(const cryptohome::AccountIdentifier& cryptohome_id, AsyncMethodCallback callback) override; void RenameCryptohome( - const cryptohome::Identification& cryptohome_id_from, - const cryptohome::Identification& cryptohome_id_to, + const cryptohome::AccountIdentifier& cryptohome_id_from, + const cryptohome::AccountIdentifier& cryptohome_id_to, DBusMethodCallback<cryptohome::BaseReply> callback) override; void GetAccountDiskUsage( - const cryptohome::Identification& account_id, + const cryptohome::AccountIdentifier& account_id, DBusMethodCallback<cryptohome::BaseReply> callback) override; void GetSystemSalt( DBusMethodCallback<std::vector<uint8_t>> callback) override; - void GetSanitizedUsername(const cryptohome::Identification& cryptohome_id, + void GetSanitizedUsername(const cryptohome::AccountIdentifier& cryptohome_id, DBusMethodCallback<std::string> callback) override; std::string BlockingGetSanitizedUsername( - const cryptohome::Identification& cryptohome_id) override; + const cryptohome::AccountIdentifier& cryptohome_id) override; void MountGuestEx( const cryptohome::MountGuestRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; @@ -75,7 +75,7 @@ void Pkcs11GetTpmTokenInfo( DBusMethodCallback<TpmTokenInfo> callback) override; void Pkcs11GetTpmTokenInfoForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, DBusMethodCallback<TpmTokenInfo> callback) override; bool InstallAttributesGet(const std::string& name, std::vector<uint8_t>* value, @@ -101,38 +101,38 @@ void AsyncTpmAttestationCreateCertRequest( chromeos::attestation::PrivacyCAType pca_type, attestation::AttestationCertificateProfile certificate_profile, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& request_origin, AsyncMethodCallback callback) override; void AsyncTpmAttestationFinishCertRequest( const std::string& pca_response, attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, AsyncMethodCallback callback) override; void TpmAttestationDoesKeyExist( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, DBusMethodCallback<bool> callback) override; void TpmAttestationGetCertificate( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) override; void TpmAttestationGetPublicKey( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) override; void TpmAttestationRegisterKey( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, AsyncMethodCallback callback) override; void TpmAttestationSignEnterpriseChallenge( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, const std::string& domain, const std::string& device_id, @@ -141,48 +141,49 @@ AsyncMethodCallback callback) override; void TpmAttestationSignSimpleChallenge( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, const std::string& challenge, AsyncMethodCallback callback) override; void TpmAttestationGetKeyPayload( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, DBusMethodCallback<TpmAttestationDataResult> callback) override; void TpmAttestationSetKeyPayload( attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, const std::string& payload, DBusMethodCallback<bool> callback) override; - void TpmAttestationDeleteKeys(attestation::AttestationKeyType key_type, - const cryptohome::Identification& cryptohome_id, - const std::string& key_prefix, - DBusMethodCallback<bool> callback) override; + void TpmAttestationDeleteKeys( + attestation::AttestationKeyType key_type, + const cryptohome::AccountIdentifier& cryptohome_id, + const std::string& key_prefix, + DBusMethodCallback<bool> callback) override; void TpmGetVersion(DBusMethodCallback<TpmVersionInfo> callback) override; void GetKeyDataEx( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::GetKeyDataRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; - void CheckKeyEx(const cryptohome::Identification& cryptohome_id, + void CheckKeyEx(const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::CheckKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; - void MountEx(const cryptohome::Identification& cryptohome_id, + void MountEx(const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::MountRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; - void AddKeyEx(const cryptohome::Identification& cryptohome_id, + void AddKeyEx(const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::AddKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; - void UpdateKeyEx(const cryptohome::Identification& cryptohome_id, + void UpdateKeyEx(const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::UpdateKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; - void RemoveKeyEx(const cryptohome::Identification& cryptohome_id, + void RemoveKeyEx(const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::AuthorizationRequest& auth, const cryptohome::RemoveKeyRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; @@ -195,7 +196,7 @@ void FlushAndSignBootAttributes( const cryptohome::FlushAndSignBootAttributesRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; - void MigrateToDircrypto(const cryptohome::Identification& cryptohome_id, + void MigrateToDircrypto(const cryptohome::AccountIdentifier& cryptohome_id, const cryptohome::MigrateToDircryptoRequest& request, VoidDBusMethodCallback callback) override; void RemoveFirmwareManagementParametersFromTpm( @@ -204,8 +205,9 @@ void SetFirmwareManagementParametersInTpm( const cryptohome::SetFirmwareManagementParametersRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; - void NeedsDircryptoMigration(const cryptohome::Identification& cryptohome_id, - DBusMethodCallback<bool> callback) override; + void NeedsDircryptoMigration( + const cryptohome::AccountIdentifier& cryptohome_id, + DBusMethodCallback<bool> callback) override; void GetSupportedKeyPolicies( const cryptohome::GetSupportedKeyPoliciesRequest& request, DBusMethodCallback<cryptohome::BaseReply> callback) override; @@ -277,7 +279,7 @@ } void SetTpmAttestationUserCertificate( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& key_name, const std::string& certificate); @@ -307,7 +309,7 @@ } // MigrateToDircrypto getters. - const cryptohome::Identification& get_id_for_disk_migrated_to_dircrypto() + const cryptohome::AccountIdentifier& get_id_for_disk_migrated_to_dircrypto() const { return id_for_disk_migrated_to_dircrypto_; } @@ -372,11 +374,12 @@ std::map<std::string, std::vector<uint8_t>> install_attrs_; bool locked_; - std::map<cryptohome::Identification, std::map<std::string, cryptohome::Key>> + std::map<cryptohome::AccountIdentifier, + std::map<std::string, cryptohome::Key>> key_data_map_; // User attestation certificate mapped by cryptohome_id and key_name. - std::map<std::pair<cryptohome::Identification, std::string>, std::string> + std::map<std::pair<cryptohome::AccountIdentifier, std::string>, std::string> user_certificate_map_; // Device attestation certificate mapped by key_name. @@ -407,7 +410,7 @@ cryptohome::AuthorizationRequest last_mount_auth_request_; // MigrateToDircrypto fields. - cryptohome::Identification id_for_disk_migrated_to_dircrypto_; + cryptohome::AccountIdentifier id_for_disk_migrated_to_dircrypto_; cryptohome::MigrateToDircryptoRequest last_migrate_to_dircrypto_request_; base::WeakPtrFactory<FakeCryptohomeClient> weak_ptr_factory_;
diff --git a/chromeos/dbus/fake_cryptohome_client_unittest.cc b/chromeos/dbus/fake_cryptohome_client_unittest.cc index 6f2aa280..b19958e 100644 --- a/chromeos/dbus/fake_cryptohome_client_unittest.cc +++ b/chromeos/dbus/fake_cryptohome_client_unittest.cc
@@ -61,7 +61,7 @@ ScopedObserver<CryptohomeClient, TestObserver> scoped_observer(&observer); scoped_observer.Add(&fake_cryptohome_client_); - cryptohome::Identification cryptohome_id; + cryptohome::AccountIdentifier cryptohome_id; bool called = false; fake_cryptohome_client_.TpmAttestationSignSimpleChallenge( attestation::AttestationKeyType::KEY_DEVICE, cryptohome_id, "key_name",
diff --git a/chromeos/dbus/fake_session_manager_client.cc b/chromeos/dbus/fake_session_manager_client.cc index 35bca46..23c8c3f 100644 --- a/chromeos/dbus/fake_session_manager_client.cc +++ b/chromeos/dbus/fake_session_manager_client.cc
@@ -22,6 +22,7 @@ #include "chromeos/chromeos_paths.h" #include "chromeos/dbus/cryptohome_client.h" #include "chromeos/dbus/login_manager/policy_descriptor.pb.h" +#include "chromeos/dbus/util/account_identifier_operators.h" #include "components/policy/proto/device_management_backend.pb.h" #include "crypto/sha2.h" @@ -145,8 +146,8 @@ case login_manager::ACCOUNT_TYPE_SESSIONLESS_USER: case login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT: { DCHECK(descriptor.has_account_id()); - cryptohome::Identification cryptohome_id = - cryptohome::Identification::FromString(descriptor.account_id()); + cryptohome::AccountIdentifier cryptohome_id; + cryptohome_id.set_account_id(descriptor.account_id()); const std::string sanitized_id = CryptohomeClient::GetStubSanitizedUsername(cryptohome_id); return base::FilePath(sanitized_id) @@ -273,11 +274,11 @@ void FakeSessionManagerClient::SaveLoginPassword(const std::string& password) {} void FakeSessionManagerClient::StartSession( - const cryptohome::Identification& cryptohome_id) { - DCHECK_EQ(0UL, user_sessions_.count(cryptohome_id)); + const cryptohome::AccountIdentifier& cryptohome_id) { + DCHECK_EQ(0UL, user_sessions_.count(cryptohome_id.account_id())); std::string user_id_hash = CryptohomeClient::GetStubSanitizedUsername(cryptohome_id); - user_sessions_[cryptohome_id] = user_id_hash; + user_sessions_[cryptohome_id.account_id()] = user_id_hash; } void FakeSessionManagerClient::StopSession() {} @@ -330,27 +331,27 @@ } void FakeSessionManagerClient::RetrievePolicyForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, RetrievePolicyCallback callback) { login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id()); RetrievePolicy(descriptor, std::move(callback)); } RetrievePolicyResponseType FakeSessionManagerClient::BlockingRetrievePolicyForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, std::string* policy_out) { login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id()); return BlockingRetrievePolicy(descriptor, policy_out); } void FakeSessionManagerClient::RetrievePolicyForUserWithoutSession( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, RetrievePolicyCallback callback) { login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_SESSIONLESS_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_SESSIONLESS_USER, cryptohome_id.account_id()); RetrievePolicy(descriptor, std::move(callback)); } @@ -415,11 +416,11 @@ } void FakeSessionManagerClient::StorePolicyForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob, VoidDBusMethodCallback callback) { login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id()); StorePolicy(descriptor, policy_blob, std::move(callback)); } @@ -493,7 +494,7 @@ } void FakeSessionManagerClient::SetFlagsForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::vector<std::string>& flags) { flags_for_user_[cryptohome_id] = flags; } @@ -575,7 +576,7 @@ } void FakeSessionManagerClient::EmitArcBooted( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, VoidDBusMethodCallback callback) { PostReply(FROM_HERE, std::move(callback), arc_available_); } @@ -588,7 +589,7 @@ } void FakeSessionManagerClient::RemoveArcData( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, VoidDBusMethodCallback callback) { if (!callback.is_null()) PostReply(FROM_HERE, std::move(callback), arc_available_); @@ -602,7 +603,7 @@ } bool FakeSessionManagerClient::GetFlagsForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, std::vector<std::string>* out_flags_for_user) const { auto iter = flags_for_user_.find(cryptohome_id); if (iter == flags_for_user_.end()) @@ -629,29 +630,29 @@ } const std::string& FakeSessionManagerClient::user_policy( - const cryptohome::Identification& cryptohome_id) const { + const cryptohome::AccountIdentifier& cryptohome_id) const { DCHECK(policy_storage_ == PolicyStorageType::kInMemory); login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id()); auto it = policy_.find(GetMemoryStorageKey(descriptor)); return it != policy_.end() ? it->second : base::EmptyString(); } void FakeSessionManagerClient::set_user_policy( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob) { DCHECK(policy_storage_ == PolicyStorageType::kInMemory); login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id()); policy_[GetMemoryStorageKey(descriptor)] = policy_blob; } void FakeSessionManagerClient::set_user_policy_without_session( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob) { DCHECK(policy_storage_ == PolicyStorageType::kInMemory); login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_SESSIONLESS_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_SESSIONLESS_USER, cryptohome_id.account_id()); policy_[GetMemoryStorageKey(descriptor)] = policy_blob; }
diff --git a/chromeos/dbus/fake_session_manager_client.h b/chromeos/dbus/fake_session_manager_client.h index 4849317f..fdf281b 100644 --- a/chromeos/dbus/fake_session_manager_client.h +++ b/chromeos/dbus/fake_session_manager_client.h
@@ -47,7 +47,8 @@ const std::vector<std::string>& argv, VoidDBusMethodCallback callback) override; void SaveLoginPassword(const std::string& password) override; - void StartSession(const cryptohome::Identification& cryptohome_id) override; + void StartSession( + const cryptohome::AccountIdentifier& cryptohome_id) override; void StopSession() override; void NotifySupervisedUserCreationStarted() override; void NotifySupervisedUserCreationFinished() override; @@ -60,13 +61,13 @@ void RetrieveDevicePolicy(RetrievePolicyCallback callback) override; RetrievePolicyResponseType BlockingRetrieveDevicePolicy( std::string* policy_out) override; - void RetrievePolicyForUser(const cryptohome::Identification& cryptohome_id, + void RetrievePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id, RetrievePolicyCallback callback) override; RetrievePolicyResponseType BlockingRetrievePolicyForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, std::string* policy_out) override; void RetrievePolicyForUserWithoutSession( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, RetrievePolicyCallback callback) override; void RetrieveDeviceLocalAccountPolicy( const std::string& account_id, @@ -81,7 +82,7 @@ std::string* policy_out) override; void StoreDevicePolicy(const std::string& policy_blob, VoidDBusMethodCallback callback) override; - void StorePolicyForUser(const cryptohome::Identification& cryptohome_id, + void StorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob, VoidDBusMethodCallback callback) override; void StoreDeviceLocalAccountPolicy(const std::string& account_id, @@ -91,7 +92,7 @@ const std::string& policy_blob, VoidDBusMethodCallback callback) override; bool SupportsRestartToApplyUserFlags() const override; - void SetFlagsForUser(const cryptohome::Identification& cryptohome_id, + void SetFlagsForUser(const cryptohome::AccountIdentifier& cryptohome_id, const std::vector<std::string>& flags) override; void GetServerBackedStateKeys(StateKeysCallback callback) override; @@ -106,10 +107,10 @@ void SetArcCpuRestriction( login_manager::ContainerCpuRestrictionState restriction_state, VoidDBusMethodCallback callback) override; - void EmitArcBooted(const cryptohome::Identification& cryptohome_id, + void EmitArcBooted(const cryptohome::AccountIdentifier& cryptohome_id, VoidDBusMethodCallback callback) override; void GetArcStartTime(DBusMethodCallback<base::TimeTicks> callback) override; - void RemoveArcData(const cryptohome::Identification& cryptohome_id, + void RemoveArcData(const cryptohome::AccountIdentifier& cryptohome_id, VoidDBusMethodCallback callback) override; // Notifies observers as if ArcInstanceStopped signal is received. @@ -119,7 +120,7 @@ // Returns true if flags for |cryptohome_id| have been set. If the return // value is |true|, |*out_flags_for_user| is filled with the flags passed to // |SetFlagsForUser|. - bool GetFlagsForUser(const cryptohome::Identification& cryptohome_id, + bool GetFlagsForUser(const cryptohome::AccountIdentifier& cryptohome_id, std::vector<std::string>* out_flags_for_user) const; // Sets whether FakeSessionManagerClient should advertise (through @@ -141,11 +142,11 @@ // Accessors for user policy. Only available for PolicyStorageType::kInMemory. const std::string& user_policy( - const cryptohome::Identification& cryptohome_id) const; - void set_user_policy(const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id) const; + void set_user_policy(const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob); void set_user_policy_without_session( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob); // Accessors for device local account policy. Only available for @@ -234,7 +235,7 @@ StubDelegate* delegate_; // The last-set flags for user set through |SetFlagsForUser|. - std::map<cryptohome::Identification, std::vector<std::string>> + std::map<cryptohome::AccountIdentifier, std::vector<std::string>> flags_for_user_; base::WeakPtrFactory<FakeSessionManagerClient> weak_ptr_factory_;
diff --git a/chromeos/dbus/session_manager_client.cc b/chromeos/dbus/session_manager_client.cc index ebf8efe..990dc5a 100644 --- a/chromeos/dbus/session_manager_client.cc +++ b/chromeos/dbus/session_manager_client.cc
@@ -192,11 +192,12 @@ base::DoNothing()); } - void StartSession(const cryptohome::Identification& cryptohome_id) override { + void StartSession( + const cryptohome::AccountIdentifier& cryptohome_id) override { dbus::MethodCall method_call(login_manager::kSessionManagerInterface, login_manager::kSessionManagerStartSession); dbus::MessageWriter writer(&method_call); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(cryptohome_id.account_id()); writer.AppendString(""); // Unique ID is deprecated session_manager_proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, @@ -279,26 +280,27 @@ return BlockingRetrievePolicy(descriptor, policy_out); } - void RetrievePolicyForUser(const cryptohome::Identification& cryptohome_id, + void RetrievePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id, RetrievePolicyCallback callback) override { login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id()); CallRetrievePolicy(descriptor, std::move(callback)); } RetrievePolicyResponseType BlockingRetrievePolicyForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, std::string* policy_out) override { login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id()); return BlockingRetrievePolicy(descriptor, policy_out); } void RetrievePolicyForUserWithoutSession( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, RetrievePolicyCallback callback) override { - login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_SESSIONLESS_USER, cryptohome_id.id()); + login_manager::PolicyDescriptor descriptor = + MakeChromePolicyDescriptor(login_manager::ACCOUNT_TYPE_SESSIONLESS_USER, + cryptohome_id.account_id()); CallRetrievePolicy(descriptor, std::move(callback)); } @@ -336,11 +338,11 @@ CallStorePolicy(descriptor, policy_blob, std::move(callback)); } - void StorePolicyForUser(const cryptohome::Identification& cryptohome_id, + void StorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob, VoidDBusMethodCallback callback) override { login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor( - login_manager::ACCOUNT_TYPE_USER, cryptohome_id.id()); + login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id()); CallStorePolicy(descriptor, policy_blob, std::move(callback)); } @@ -360,12 +362,12 @@ bool SupportsRestartToApplyUserFlags() const override { return true; } - void SetFlagsForUser(const cryptohome::Identification& cryptohome_id, + void SetFlagsForUser(const cryptohome::AccountIdentifier& cryptohome_id, const std::vector<std::string>& flags) override { dbus::MethodCall method_call(login_manager::kSessionManagerInterface, login_manager::kSessionManagerSetFlagsForUser); dbus::MessageWriter writer(&method_call); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(cryptohome_id.account_id()); writer.AppendArrayOfStrings(flags); session_manager_proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, @@ -449,12 +451,12 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void EmitArcBooted(const cryptohome::Identification& cryptohome_id, + void EmitArcBooted(const cryptohome::AccountIdentifier& cryptohome_id, VoidDBusMethodCallback callback) override { dbus::MethodCall method_call(login_manager::kSessionManagerInterface, login_manager::kSessionManagerEmitArcBooted); dbus::MessageWriter writer(&method_call); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(cryptohome_id.account_id()); session_manager_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&SessionManagerClientImpl::OnVoidMethod, @@ -472,12 +474,12 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void RemoveArcData(const cryptohome::Identification& cryptohome_id, + void RemoveArcData(const cryptohome::AccountIdentifier& cryptohome_id, VoidDBusMethodCallback callback) override { dbus::MethodCall method_call(login_manager::kSessionManagerInterface, login_manager::kSessionManagerRemoveArcData); dbus::MessageWriter writer(&method_call); - writer.AppendString(cryptohome_id.id()); + writer.AppendString(cryptohome_id.account_id()); session_manager_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&SessionManagerClientImpl::OnVoidMethod, @@ -645,7 +647,7 @@ LOG(ERROR) << method_name << " response is incorrect: " << response->ToString(); } else { - sessions[cryptohome::Identification::FromString(key)] = value; + sessions[key] = value; } } std::move(callback).Run(std::move(sessions));
diff --git a/chromeos/dbus/session_manager_client.h b/chromeos/dbus/session_manager_client.h index 875d2048..cdebd66e 100644 --- a/chromeos/dbus/session_manager_client.h +++ b/chromeos/dbus/session_manager_client.h
@@ -21,7 +21,7 @@ #include "third_party/cros_system_api/dbus/login_manager/dbus-constants.h" namespace cryptohome { -class Identification; +class AccountIdentifier; } namespace login_manager { @@ -129,7 +129,7 @@ // Starts the session for the user. virtual void StartSession( - const cryptohome::Identification& cryptohome_id) = 0; + const cryptohome::AccountIdentifier& cryptohome_id) = 0; // Stops the current session. virtual void StopSession() = 0; @@ -158,7 +158,7 @@ // Map that is used to describe the set of active user sessions where |key| // is cryptohome id and |value| is user_id_hash. - using ActiveSessionsMap = std::map<cryptohome::Identification, std::string>; + using ActiveSessionsMap = std::map<std::string, std::string>; // The ActiveSessionsCallback is used for the RetrieveActiveSessions() // method. It receives |sessions| argument where the keys are cryptohome_ids @@ -207,7 +207,7 @@ // provided callback. // DEPRECATED, use RetrievePolicy() instead. virtual void RetrievePolicyForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, RetrievePolicyCallback callback) = 0; // Same as RetrievePolicyForUser() but blocks until a reply is received, and @@ -219,14 +219,14 @@ // TODO(crbug.com/160522): Get rid of blocking calls. // DEPRECATED, use BlockingRetrievePolicy() instead. virtual RetrievePolicyResponseType BlockingRetrievePolicyForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, std::string* policy_out) = 0; // Fetches the user policy blob for a hidden user home mount. |callback| is // invoked upon completition. // DEPRECATED, use RetrievePolicy() instead. virtual void RetrievePolicyForUserWithoutSession( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, RetrievePolicyCallback callback) = 0; // Fetches the policy blob associated with the specified device-local account @@ -273,7 +273,7 @@ // given |cryptohome_id|. Upon completion of the store attempt, we will call // callback. virtual void StorePolicyForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, const std::string& policy_blob, VoidDBusMethodCallback callback) = 0; @@ -297,8 +297,9 @@ // Sets the flags to be applied next time by the session manager when Chrome // is restarted inside an already started session for a particular user. - virtual void SetFlagsForUser(const cryptohome::Identification& cryptohome_id, - const std::vector<std::string>& flags) = 0; + virtual void SetFlagsForUser( + const cryptohome::AccountIdentifier& cryptohome_id, + const std::vector<std::string>& flags) = 0; using StateKeysCallback = base::OnceCallback<void(const std::vector<std::string>& state_keys)>; @@ -356,7 +357,7 @@ VoidDBusMethodCallback callback) = 0; // Emits the "arc-booted" upstart signal. - virtual void EmitArcBooted(const cryptohome::Identification& cryptohome_id, + virtual void EmitArcBooted(const cryptohome::AccountIdentifier& cryptohome_id, VoidDBusMethodCallback callback) = 0; // Asynchronously retrieves the timestamp which ARC instance is invoked. @@ -368,7 +369,7 @@ // located by |cryptohome_id|. Upon completion, invokes |callback| with the // result; true on success, false on failure (either session manager failed // to remove user data or session manager can not be reached). - virtual void RemoveArcData(const cryptohome::Identification& cryptohome_id, + virtual void RemoveArcData(const cryptohome::AccountIdentifier& cryptohome_id, VoidDBusMethodCallback callback) = 0; // Creates the instance.
diff --git a/chromeos/dbus/util/account_identifier_operators.cc b/chromeos/dbus/util/account_identifier_operators.cc new file mode 100644 index 0000000..d942471 --- /dev/null +++ b/chromeos/dbus/util/account_identifier_operators.cc
@@ -0,0 +1,17 @@ +// Copyright 2018 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 "chromeos/dbus/util/account_identifier_operators.h" + +namespace cryptohome { + +bool operator<(const AccountIdentifier& l, const AccountIdentifier& r) { + return l.account_id() < r.account_id(); +} + +bool operator==(const AccountIdentifier& l, const AccountIdentifier& r) { + return l.account_id() == r.account_id(); +} + +} // namespace cryptohome
diff --git a/chromeos/dbus/util/account_identifier_operators.h b/chromeos/dbus/util/account_identifier_operators.h new file mode 100644 index 0000000..1c1a066 --- /dev/null +++ b/chromeos/dbus/util/account_identifier_operators.h
@@ -0,0 +1,23 @@ +// Copyright 2018 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 CHROMEOS_DBUS_UTIL_ACCOUNT_IDENTIFIER_OPERATORS_H_ +#define CHROMEOS_DBUS_UTIL_ACCOUNT_IDENTIFIER_OPERATORS_H_ + +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/cryptohome/rpc.pb.h" + +namespace cryptohome { + +// operator< to use AccountIdentifier in STL containers. +CHROMEOS_EXPORT bool operator<(const AccountIdentifier& l, + const AccountIdentifier& r); + +// operator== to use AccountIdentifier in tests. +CHROMEOS_EXPORT bool operator==(const AccountIdentifier& l, + const AccountIdentifier& r); + +} // namespace cryptohome + +#endif // CHROMEOS_DBUS_UTIL_ACCOUNT_IDENTIFIER_OPERATORS_H_
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc index f9eddf9..f8a80e07 100644 --- a/chromeos/login/auth/cryptohome_authenticator.cc +++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -205,8 +205,9 @@ auth_key->mutable_data()->set_label(key->GetLabel()); auth_key->set_secret(key->GetSecret()); DBusThreadManager::Get()->GetCryptohomeClient()->MountEx( - cryptohome::Identification(attempt->user_context.GetAccountId()), auth, - mount, base::BindOnce(&OnMount, attempt, resolver)); + cryptohome::CreateAccountIdentifierFromAccountId( + attempt->user_context.GetAccountId()), + auth, mount, base::BindOnce(&OnMount, attempt, resolver)); } // Handle cryptohome migration status. @@ -269,14 +270,15 @@ if (need_migration) { chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( "CryptohomeRename-Start", false); - const std::string& cryptohome_id_from = - attempt->user_context.GetAccountId().GetUserEmail(); // Migrated - const std::string cryptohome_id_to = - attempt->user_context.GetAccountId().GetAccountIdKey(); + cryptohome::AccountIdentifier cryptohome_id_from; + cryptohome_id_from.set_account_id( + attempt->user_context.GetAccountId().GetUserEmail()); // Migrated + cryptohome::AccountIdentifier cryptohome_id_to; + cryptohome_id_to.set_account_id( + attempt->user_context.GetAccountId().GetAccountIdKey()); DBusThreadManager::Get()->GetCryptohomeClient()->RenameCryptohome( - cryptohome::Identification::FromString(cryptohome_id_from), - cryptohome::Identification::FromString(cryptohome_id_to), + cryptohome_id_from, cryptohome_id_to, base::BindOnce(&OnCryptohomeRenamed, attempt, resolver, ephemeral, create_if_nonexistent)); return; @@ -411,7 +413,8 @@ cryptohome::GetKeyDataRequest request; request.mutable_key()->mutable_data()->set_label(kCryptohomeGAIAKeyLabel); DBusThreadManager::Get()->GetCryptohomeClient()->GetKeyDataEx( - cryptohome::Identification(attempt->user_context.GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId( + attempt->user_context.GetAccountId()), cryptohome::AuthorizationRequest(), request, base::BindOnce(&OnGetKeyDataEx, attempt, resolver, ephemeral, create_if_nonexistent)); @@ -431,7 +434,8 @@ "CryptohomeMountGuest-End")); DBusThreadManager::Get()->GetCryptohomeClient()->GetSanitizedUsername( - cryptohome::Identification(attempt->user_context.GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId( + attempt->user_context.GetAccountId()), base::BindOnce(&OnGetSanitizedUsername, base::BindOnce(&TriggerResolveHash, attempt, resolver))); } @@ -456,7 +460,8 @@ // which is a wildcard allowing any key to match to allow cryptohomes created // in a legacy way. (See comments in DoMount.) DBusThreadManager::Get()->GetCryptohomeClient()->MountEx( - cryptohome::Identification(attempt->user_context.GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId( + attempt->user_context.GetAccountId()), cryptohome::AuthorizationRequest(), mount, base::BindOnce(&OnMount, attempt, resolver)); } @@ -470,9 +475,9 @@ chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( "CryptohomeMigrate-Start", false); - cryptohome::AccountIdentifier account_id; - account_id.set_account_id( - cryptohome::Identification(attempt->user_context.GetAccountId()).id()); + cryptohome::AccountIdentifier account_id = + cryptohome::CreateAccountIdentifierFromAccountId( + attempt->user_context.GetAccountId()); cryptohome::AuthorizationRequest auth_request; cryptohome::MigrateKeyRequest migrate_request; @@ -523,8 +528,9 @@ cryptohome::AuthorizationRequest auth; auth.mutable_key()->set_secret(key->GetSecret()); DBusThreadManager::Get()->GetCryptohomeClient()->CheckKeyEx( - cryptohome::Identification(attempt->user_context.GetAccountId()), auth, - cryptohome::CheckKeyRequest(), + cryptohome::CreateAccountIdentifierFromAccountId( + attempt->user_context.GetAccountId()), + auth, cryptohome::CheckKeyRequest(), base::BindOnce(&OnKeyChecked, attempt, resolver)); }
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc index 9f46e8c..e166eb2c 100644 --- a/chromeos/login/auth/extended_authenticator_impl.cc +++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -174,7 +174,8 @@ RecordStartMarker("MountEx"); const Key* const key = user_context.GetKey(); DBusThreadManager::Get()->GetCryptohomeClient()->MountEx( - cryptohome::Identification(user_context.GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId( + user_context.GetAccountId()), cryptohome::CreateAuthorizationRequest(key->GetLabel(), key->GetSecret()), cryptohome::MountRequest(), base::BindOnce(&ExtendedAuthenticatorImpl::OnMountComplete, this,
diff --git a/chromeos/tpm/tpm_token_info_getter.cc b/chromeos/tpm/tpm_token_info_getter.cc index 9107a80..7bf6b70 100644 --- a/chromeos/tpm/tpm_token_info_getter.cc +++ b/chromeos/tpm/tpm_token_info_getter.cc
@@ -98,7 +98,7 @@ weak_factory_.GetWeakPtr())); } else { // if (type_ == TYPE_USER) cryptohome_client_->Pkcs11GetTpmTokenInfoForUser( - cryptohome::Identification(account_id_), + cryptohome::CreateAccountIdentifierFromAccountId(account_id_), base::BindOnce(&TPMTokenInfoGetter::OnPkcs11GetTpmTokenInfo, weak_factory_.GetWeakPtr())); }
diff --git a/chromeos/tpm/tpm_token_info_getter_unittest.cc b/chromeos/tpm/tpm_token_info_getter_unittest.cc index 8dfab79e..d48a907 100644 --- a/chromeos/tpm/tpm_token_info_getter_unittest.cc +++ b/chromeos/tpm/tpm_token_info_getter_unittest.cc
@@ -141,10 +141,12 @@ } void Pkcs11GetTpmTokenInfoForUser( - const cryptohome::Identification& cryptohome_id, + const cryptohome::AccountIdentifier& cryptohome_id, chromeos::DBusMethodCallback<TpmTokenInfo> callback) override { - ASSERT_FALSE(cryptohome_id.id().empty()); - ASSERT_EQ(account_id_, cryptohome_id.GetAccountId()); + ASSERT_FALSE(cryptohome_id.account_id().empty()); + ASSERT_EQ(cryptohome::CreateAccountIdentifierFromAccountId(account_id_) + .account_id(), + cryptohome_id.account_id()); HandleGetTpmTokenInfo(std::move(callback)); }
diff --git a/components/arc/arc_data_remover.cc b/components/arc/arc_data_remover.cc index dad2343..23e0633 100644 --- a/components/arc/arc_data_remover.cc +++ b/components/arc/arc_data_remover.cc
@@ -46,9 +46,10 @@ chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); DCHECK(session_manager_client); session_manager_client->RemoveArcData( - cryptohome_id_, base::AdaptCallbackForRepeating(base::BindOnce( - &ArcDataRemover::OnDataRemoved, - weak_factory_.GetWeakPtr(), std::move(callback)))); + cryptohome::CreateAccountIdentifierFromIdentification(cryptohome_id_), + base::AdaptCallbackForRepeating( + base::BindOnce(&ArcDataRemover::OnDataRemoved, + weak_factory_.GetWeakPtr(), std::move(callback)))); } void ArcDataRemover::OnDataRemoved(RunCallback callback, bool success) {
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index 7b1ad84..0b261d5 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -79,6 +79,11 @@ const char kDummyUsernameField[] = "anonymous_username"; const char kDummyPasswordField[] = "anonymous_password"; +// Names of HTML attributes to show form and field signatures for debugging. +const char kDebugAttributeForFormSignature[] = "form_signature"; +const char kDebugAttributeForFieldSignature[] = "field_signature"; +const char kDebugAttributeForParserAnnotations[] = "pm_parser_annotation"; + // Maps element names to the actual elements to simplify form filling. typedef std::map<base::string16, WebInputElement> FormInputElementMap; @@ -524,11 +529,33 @@ base::NumberToString(CalculateFormSignature(password_form.form_data))); } +// Add parser annotations saved in |password_form| to |element|. +void AddParserAnnotations(PasswordForm* password_form, + blink::WebFormControlElement* element) { + base::string16 element_name = element->NameForAutofill().Utf16(); + std::string attribute_value; + if (password_form->username_element == element_name) { + attribute_value = "username_element"; + } else if (password_form->password_element == element_name) { + attribute_value = "password_element"; + } else if (password_form->new_password_element == element_name) { + attribute_value = "new_password_element"; + } else if (password_form->confirmation_password_element == element_name) { + attribute_value = "confirmation_password_element"; + } + element->SetAttribute( + blink::WebString::FromASCII(kDebugAttributeForParserAnnotations), + attribute_value.empty() ? blink::WebString() + : blink::WebString::FromASCII(attribute_value)); +} + // Annotate |fields| with field signatures and form signature as HTML // attributes. -void AnnotateFieldsWithSignatures(std::vector<WebFormControlElement>* fields, - const WebString& form_signature) { - for (WebFormControlElement& control_element : *fields) { +void AnnotateFieldsWithSignatures( + std::vector<blink::WebFormControlElement>* fields, + const blink::WebString& form_signature, + PasswordForm* password_form) { + for (blink::WebFormControlElement& control_element : *fields) { FieldSignature field_signature = CalculateFieldSignatureByNameAndType( control_element.NameForAutofill().Utf16(), control_element.FormControlTypeForAutofill().Utf8()); @@ -536,7 +563,10 @@ WebString::FromASCII(kDebugAttributeForFieldSignature), WebString::FromUTF8(base::NumberToString(field_signature))); control_element.SetAttribute( - WebString::FromASCII(kDebugAttributeForFormSignature), form_signature); + blink::WebString::FromASCII(kDebugAttributeForFormSignature), + form_signature); + if (password_form) + AddParserAnnotations(password_form, &control_element); } } @@ -555,7 +585,8 @@ } std::vector<WebFormControlElement> form_fields = form_util::ExtractAutofillableElementsInForm(form); - AnnotateFieldsWithSignatures(&form_fields, form_signature); + AnnotateFieldsWithSignatures(&form_fields, form_signature, + password_form ? password_form.get() : nullptr); } std::vector<WebFormControlElement> unowned_elements = @@ -567,7 +598,8 @@ WebString form_signature; if (password_form) form_signature = GetFormSignatureAsWebString(*password_form); - AnnotateFieldsWithSignatures(&unowned_elements, form_signature); + AnnotateFieldsWithSignatures(&unowned_elements, form_signature, + password_form ? password_form.get() : nullptr); } // Returns true iff there is a password field in |frame|. @@ -650,9 +682,6 @@ //////////////////////////////////////////////////////////////////////////////// // PasswordAutofillAgent, public: -const char kDebugAttributeForFormSignature[] = "form_signature"; -const char kDebugAttributeForFieldSignature[] = "field_signature"; - PasswordAutofillAgent::PasswordAutofillAgent( content::RenderFrame* render_frame, service_manager::BinderRegistry* registry)
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h index a284a03..c68572a 100644 --- a/components/autofill/content/renderer/password_autofill_agent.h +++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -59,10 +59,6 @@ kMaxValue = kPrefilledUsernameNotOverridden, }; -// Names of HTML attributes to show form and field signatures for debugging. -extern const char kDebugAttributeForFormSignature[]; -extern const char kDebugAttributeForFieldSignature[]; - class RendererSavePasswordProgressLogger; class PasswordGenerationAgent;
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index 6175978..1dc35bf6 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -348,6 +348,7 @@ if (base::FeatureList::IsEnabled( switches::kSyncClearDataOnPassphraseEncryption) && sync_prefs_.GetPassphraseEncryptionTransitionInProgress()) { + DCHECK(CanConfigureDataTypes()); // We are restarting catchup configuration after browser restart. UMA_HISTOGRAM_ENUMERATION("Sync.ClearServerDataEvents", syncer::CLEAR_SERVER_DATA_RETRIED, @@ -458,9 +459,7 @@ crypto_ = std::make_unique<syncer::SyncServiceCrypto>( base::BindRepeating(&ProfileSyncService::NotifyObservers, base::Unretained(this)), - base::BindRepeating(&ProfileSyncService::GetPreferredDataTypes, - base::Unretained(this)), - base::BindRepeating(&ProfileSyncService::CanConfigureDataTypes, + base::BindRepeating(&ProfileSyncService::ReconfigureDueToPassphrase, base::Unretained(this)), &sync_prefs_); } @@ -991,14 +990,18 @@ engine_.get(), this); crypto_->SetSyncEngine(engine_.get()); - crypto_->SetDataTypeManager(data_type_manager_.get()); // Auto-start means IsFirstSetupComplete gets set automatically. if (start_behavior_ == AUTO_START && !IsFirstSetupComplete()) { // This will trigger a configure if it completes setup. SetFirstSetupComplete(); } else if (CanConfigureDataTypes()) { - ConfigureDataTypeManager(); + // Datatype downloads on restart are generally due to newly supported + // datatypes (although it's also possible we're picking up where a failed + // previous configuration left off). + // TODO(sync): consider detecting configuration recovery and setting + // the reason here appropriately. + ConfigureDataTypeManager(syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE); } // Check for a cookie jar mismatch. @@ -1525,48 +1528,30 @@ platform_sync_allowed_provider_ = platform_sync_allowed_provider; } -void ProfileSyncService::ConfigureDataTypeManager() { - // Don't configure datatypes if the setup UI is still on the screen - this - // is to help multi-screen setting UIs (like iOS) where they don't want to - // start syncing data until the user is done configuring encryption options, - // etc. ReconfigureDatatypeManager() will get called again once the UI calls - // SetSetupInProgress(false). - if (!CanConfigureDataTypes()) { - // If we can't configure the data type manager yet, we should still notify - // observers. This is to support multiple setup UIs being open at once. - NotifyObservers(); - return; - } +void ProfileSyncService::ConfigureDataTypeManager( + syncer::ConfigureReason reason) { + DCHECK_NE(reason, syncer::CONFIGURE_REASON_UNKNOWN); + DCHECK(CanConfigureDataTypes() || + reason == syncer::CONFIGURE_REASON_MIGRATION); - bool restart = false; if (!migrator_) { - restart = true; - // We create the migrator at the same time. migrator_ = std::make_unique<syncer::BackendMigrator>( - debug_identifier_, GetUserShare(), this, data_type_manager_.get(), + debug_identifier_, GetUserShare(), data_type_manager_.get(), + base::BindRepeating(&ProfileSyncService::ConfigureDataTypeManager, + base::Unretained(this), + syncer::CONFIGURE_REASON_MIGRATION), base::BindRepeating(&ProfileSyncService::StartSyncingWithServer, base::Unretained(this))); + + // Override reason if no configuration has completed ever. + if (is_first_time_sync_configure_ && + reason != syncer::CONFIGURE_REASON_CATCH_UP) { + reason = syncer::CONFIGURE_REASON_NEW_CLIENT; + } } - syncer::ModelTypeSet types; - syncer::ConfigureReason reason = syncer::CONFIGURE_REASON_UNKNOWN; - types = GetPreferredDataTypes(); - if (restart) { - // Datatype downloads on restart are generally due to newly supported - // datatypes (although it's also possible we're picking up where a failed - // previous configuration left off). - // TODO(sync): consider detecting configuration recovery and setting - // the reason here appropriately. - reason = is_first_time_sync_configure_ - ? syncer::CONFIGURE_REASON_NEW_CLIENT - : syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE; - } else { - // The user initiated a reconfiguration (either to add or remove types). - reason = syncer::CONFIGURE_REASON_RECONFIGURATION; - } - - data_type_manager_->Configure(types, reason); + data_type_manager_->Configure(GetPreferredDataTypes(), reason); } syncer::UserShare* ProfileSyncService::GetUserShare() const { @@ -1682,6 +1667,8 @@ void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase, PassphraseType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(data_type_manager_); + DCHECK(data_type_manager_->IsNigoriEnabled()); crypto_->SetEncryptionPassphrase(passphrase, type == EXPLICIT); } @@ -1689,7 +1676,11 @@ const std::string& passphrase) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (IsPassphraseRequired()) { + DCHECK(data_type_manager_); + DCHECK(data_type_manager_->IsNigoriEnabled()); + DVLOG(1) << "Setting passphrase for decryption."; + bool result = crypto_->SetDecryptionPassphrase(passphrase); UMA_HISTOGRAM_BOOLEAN("Sync.PassphraseDecryptionSucceeded", result); return result; @@ -1988,7 +1979,20 @@ // association to start before a Directory has even been created. if (engine_initialized_) { DCHECK(engine_); - ConfigureDataTypeManager(); + // Don't configure datatypes if the setup UI is still on the screen - this + // is to help multi-screen setting UIs (like iOS) where they don't want to + // start syncing data until the user is done configuring encryption options, + // etc. ReconfigureDatatypeManager() will get called again once the last + // SyncSetupInProgressHandle is released. + if (CanConfigureDataTypes()) { + ConfigureDataTypeManager(syncer::CONFIGURE_REASON_RECONFIGURATION); + } else { + DVLOG(0) << "ConfigureDataTypeManager not invoked because datatypes " + << "cannot be configured now"; + // If we can't configure the data type manager yet, we should still notify + // observers. This is to support multiple setup UIs being open at once. + NotifyObservers(); + } } else if (HasDisableReason(DISABLE_REASON_UNRECOVERABLE_ERROR)) { // There is nothing more to configure. So inform the listeners, NotifyObservers(); @@ -2192,6 +2196,18 @@ if (engine_initialized_) ReconfigureDatatypeManager(); + + NotifyObservers(); +} + +void ProfileSyncService::ReconfigureDueToPassphrase( + syncer::ConfigureReason reason) { + if (!CanConfigureDataTypes()) { + return; + } + DCHECK(data_type_manager_->IsNigoriEnabled()); + ConfigureDataTypeManager(reason); + // Notify observers that the passphrase status may have changed. NotifyObservers(); }
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h index d2af80f..cc208e9 100644 --- a/components/browser_sync/profile_sync_service.h +++ b/components/browser_sync/profile_sync_service.h
@@ -34,6 +34,7 @@ #include "components/sync/driver/sync_service.h" #include "components/sync/driver/sync_service_crypto.h" #include "components/sync/driver/sync_stopped_reporter.h" +#include "components/sync/engine/configure_reason.h" #include "components/sync/engine/events/protocol_event_observer.h" #include "components/sync/engine/model_safe_worker.h" #include "components/sync/engine/net/network_time_update_callback.h" @@ -505,7 +506,7 @@ bool IsSyncAllowedByPlatform() const; // Helper to install and configure a data type manager. - void ConfigureDataTypeManager(); + void ConfigureDataTypeManager(syncer::ConfigureReason reason); // Shuts down the engine sync components. // |reason| dictates if syncing is being disabled or not, and whether @@ -604,6 +605,9 @@ // Called when a SetupInProgressHandle issued by this instance is destroyed. virtual void OnSetupInProgressHandleDestroyed(); + // Called by SyncServiceCrypto when a passphrase is required or accepted. + void ReconfigureDueToPassphrase(syncer::ConfigureReason reason); + // This profile's SyncClient, which abstracts away non-Sync dependencies and // the Sync API component factory. const std::unique_ptr<syncer::SyncClient> sync_client_;
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/browser_sync/profile_sync_service_unittest.cc index e153e62..5840b231 100644 --- a/components/browser_sync/profile_sync_service_unittest.cc +++ b/components/browser_sync/profile_sync_service_unittest.cc
@@ -60,8 +60,7 @@ void ReenableType(syncer::ModelType type) override {} void ResetDataTypeErrors() override {} - void PurgeForMigration(syncer::ModelTypeSet undesired_types, - syncer::ConfigureReason reason) override {} + void PurgeForMigration(syncer::ModelTypeSet undesired_types) override {} void Stop(syncer::ShutdownReason reason) override {} syncer::ModelTypeSet GetActiveDataTypes() const override { return syncer::ModelTypeSet();
diff --git a/components/metrics/call_stack_profile_collector.cc b/components/metrics/call_stack_profile_collector.cc index dc16a0f..7395f3cb 100644 --- a/components/metrics/call_stack_profile_collector.cc +++ b/components/metrics/call_stack_profile_collector.cc
@@ -4,9 +4,8 @@ #include "components/metrics/call_stack_profile_collector.h" -#include <utility> - #include <memory> +#include <utility> #include "components/metrics/call_stack_profile_metrics_provider.h" #include "mojo/public/cpp/bindings/interface_request.h"
diff --git a/components/nux_google_apps/resources/nux_google_apps.html b/components/nux_google_apps/resources/nux_google_apps.html index 0dcd72f..56f427a 100644 --- a/components/nux_google_apps/resources/nux_google_apps.html +++ b/components/nux_google_apps/resources/nux_google_apps.html
@@ -1,4 +1,5 @@ <!DOCTYPE html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <meta charset="utf-8"> <title>$i18n{headerText}</title> @@ -84,4 +85,4 @@ <nux-google-apps></nux-google-apps> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> -</html> +</html> \ No newline at end of file
diff --git a/components/policy/core/common/policy_pref_names.cc b/components/policy/core/common/policy_pref_names.cc index 6daa439..f0429e19 100644 --- a/components/policy/core/common/policy_pref_names.cc +++ b/components/policy/core/common/policy_pref_names.cc
@@ -11,6 +11,14 @@ // by UMA_HISTOGRAM_ENUMERATION. const char kLastPolicyStatisticsUpdate[] = "policy.last_statistics_update"; +// The enrollment token of machine level user cloud policy. +const char kMachineLevelUserCloudPolicyEnrollmentToken[] = + "policy.machine_level_user_cloud_policy_enrollment_token"; + +// Enum specifying if/how the SafeSites content filter should be applied. +// See the SafeSitesFilterBehavior policy for details. +const char kSafeSitesFilterBehavior[] = "policy.safe_sites_filter_behavior"; + // Blocks access to the listed host patterns. const char kUrlBlacklist[] = "policy.url_blacklist"; @@ -22,9 +30,5 @@ // by the cloud policy subsystem. const char kUserPolicyRefreshRate[] = "policy.user_refresh_rate"; -// The enrollment token of machine level user cloud policy -const char kMachineLevelUserCloudPolicyEnrollmentToken[] = - "policy.machine_level_user_cloud_policy_enrollment_token"; - } // namespace policy_prefs } // namespace policy
diff --git a/components/policy/core/common/policy_pref_names.h b/components/policy/core/common/policy_pref_names.h index 31a8211..44feb56 100644 --- a/components/policy/core/common/policy_pref_names.h +++ b/components/policy/core/common/policy_pref_names.h
@@ -11,10 +11,12 @@ namespace policy_prefs { POLICY_EXPORT extern const char kLastPolicyStatisticsUpdate[]; +POLICY_EXPORT extern const char kMachineLevelUserCloudPolicyEnrollmentToken[]; +POLICY_EXPORT extern const char kSafeSitesFilterBehavior[]; POLICY_EXPORT extern const char kUrlBlacklist[]; POLICY_EXPORT extern const char kUrlWhitelist[]; POLICY_EXPORT extern const char kUserPolicyRefreshRate[]; -POLICY_EXPORT extern const char kMachineLevelUserCloudPolicyEnrollmentToken[]; + } // namespace policy_prefs } // namespace policy
diff --git a/components/signin/core/browser/fake_profile_oauth2_token_service.cc b/components/signin/core/browser/fake_profile_oauth2_token_service.cc index bdbf33bc..7f9963a 100644 --- a/components/signin/core/browser/fake_profile_oauth2_token_service.cc +++ b/components/signin/core/browser/fake_profile_oauth2_token_service.cc
@@ -119,6 +119,21 @@ return valid_requests; } +void FakeProfileOAuth2TokenService::CancelAllRequests() { + CompleteRequests( + "", true, ScopeSet(), + GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED), + std::string(), base::Time()); +} + +void FakeProfileOAuth2TokenService::CancelRequestsForAccount( + const std::string& account_id) { + CompleteRequests( + account_id, true, ScopeSet(), + GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED), + std::string(), base::Time()); +} + void FakeProfileOAuth2TokenService::FetchOAuth2Token( RequestImpl* request, const std::string& account_id,
diff --git a/components/signin/core/browser/fake_profile_oauth2_token_service.h b/components/signin/core/browser/fake_profile_oauth2_token_service.h index ea6feaf..face6db4 100644 --- a/components/signin/core/browser/fake_profile_oauth2_token_service.h +++ b/components/signin/core/browser/fake_profile_oauth2_token_service.h
@@ -87,6 +87,10 @@ protected: // OAuth2TokenService overrides. + void CancelAllRequests() override; + + void CancelRequestsForAccount(const std::string& account_id) override; + void FetchOAuth2Token( RequestImpl* request, const std::string& account_id,
diff --git a/components/sync/driver/backend_migrator.cc b/components/sync/driver/backend_migrator.cc index a65f15e45..731c0d6 100644 --- a/components/sync/driver/backend_migrator.cc +++ b/components/sync/driver/backend_migrator.cc
@@ -8,8 +8,6 @@ #include "base/sequenced_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "components/sync/driver/sync_service.h" -#include "components/sync/engine/configure_reason.h" #include "components/sync/protocol/sync.pb.h" #include "components/sync/syncable/directory.h" #include "components/sync/syncable/read_transaction.h" @@ -18,18 +16,22 @@ MigrationObserver::~MigrationObserver() {} -BackendMigrator::BackendMigrator(const std::string& name, - UserShare* user_share, - SyncService* service, - DataTypeManager* manager, - const base::Closure& migration_done_callback) +BackendMigrator::BackendMigrator( + const std::string& name, + UserShare* user_share, + DataTypeManager* manager, + const base::RepeatingClosure& reconfigure_callback, + const base::RepeatingClosure& migration_done_callback) : name_(name), user_share_(user_share), - service_(service), manager_(manager), - state_(IDLE), + reconfigure_callback_(reconfigure_callback), migration_done_callback_(migration_done_callback), - weak_ptr_factory_(this) {} + state_(IDLE), + weak_ptr_factory_(this) { + DCHECK(!reconfigure_callback_.is_null()); + DCHECK(!migration_done_callback_.is_null()); +} BackendMigrator::~BackendMigrator() {} @@ -94,7 +96,7 @@ SDVLOG(1) << "BackendMigrator disabling types " << ModelTypeSetToString(to_migrate_); - manager_->PurgeForMigration(to_migrate_, CONFIGURE_REASON_MIGRATION); + manager_->PurgeForMigration(to_migrate_); } void BackendMigrator::OnConfigureDone( @@ -178,12 +180,8 @@ } ChangeState(REENABLING_TYPES); - // Don't use |to_migrate_| for the re-enabling because the user - // may have chosen to disable types during the migration. - const ModelTypeSet full_set = service_->GetPreferredDataTypes(); - SDVLOG(1) << "BackendMigrator re-enabling types: " - << ModelTypeSetToString(full_set); - manager_->Configure(full_set, CONFIGURE_REASON_MIGRATION); + SDVLOG(1) << "BackendMigrator triggering reconfiguration"; + reconfigure_callback_.Run(); } else if (state_ == REENABLING_TYPES) { // We're done! ChangeState(IDLE); @@ -191,9 +189,7 @@ SDVLOG(1) << "BackendMigrator: Migration complete for: " << ModelTypeSetToString(to_migrate_); to_migrate_.Clear(); - - if (!migration_done_callback_.is_null()) - migration_done_callback_.Run(); + migration_done_callback_.Run(); } }
diff --git a/components/sync/driver/backend_migrator.h b/components/sync/driver/backend_migrator.h index ab68e762..cf3e1121 100644 --- a/components/sync/driver/backend_migrator.h +++ b/components/sync/driver/backend_migrator.h
@@ -16,7 +16,6 @@ namespace syncer { -class SyncService; struct UserShare; // Interface for anything that wants to know when the migrator's state @@ -45,9 +44,9 @@ // TODO(akalin): Remove the dependency on |user_share|. BackendMigrator(const std::string& name, UserShare* user_share, - SyncService* service, DataTypeManager* manager, - const base::Closure& migration_done_callback); + const base::RepeatingClosure& reconfigure_callback, + const base::RepeatingClosure& migration_done_callback); virtual ~BackendMigrator(); // Starts a sequence of events that will disable and reenable |types|. @@ -82,17 +81,17 @@ const std::string name_; UserShare* user_share_; - SyncService* service_; DataTypeManager* manager_; + const base::RepeatingClosure reconfigure_callback_; + const base::RepeatingClosure migration_done_callback_; + State state_; base::ObserverList<MigrationObserver> migration_observers_; ModelTypeSet to_migrate_; - base::Closure migration_done_callback_; - base::WeakPtrFactory<BackendMigrator> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BackendMigrator);
diff --git a/components/sync/driver/backend_migrator_unittest.cc b/components/sync/driver/backend_migrator_unittest.cc index 22d29f6e..0773f1a 100644 --- a/components/sync/driver/backend_migrator_unittest.cc +++ b/components/sync/driver/backend_migrator_unittest.cc
@@ -8,9 +8,9 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/mock_callback.h" #include "components/sync/base/model_type_test_util.h" #include "components/sync/driver/data_type_manager_mock.h" -#include "components/sync/driver/fake_sync_service.h" #include "components/sync/protocol/sync.pb.h" #include "components/sync/syncable/directory.h" #include "components/sync/syncable/test_user_share.h" @@ -39,8 +39,8 @@ preferred_types_.Put(AUTOFILL); migrator_ = std::make_unique<BackendMigrator>( - "Profile0", test_user_share_.user_share(), service(), manager(), - base::Closure()); + "Profile0", test_user_share_.user_share(), manager(), + reconfigure_callback()->Get(), migration_done_callback()->Get()); SetUnsyncedTypes(ModelTypeSet()); } @@ -76,17 +76,22 @@ run_loop.RunUntilIdle(); } - SyncService* service() { return &service_; } DataTypeManagerMock* manager() { return &manager_; } ModelTypeSet preferred_types() { return preferred_types_; } + base::MockCallback<base::RepeatingClosure>* reconfigure_callback() { + return &reconfigure_callback_; + } + base::MockCallback<base::RepeatingClosure>* migration_done_callback() { + return &migration_done_callback_; + } BackendMigrator* migrator() { return migrator_.get(); } - void RemovePreferredType(ModelType type) { preferred_types_.Remove(type); } private: base::MessageLoop message_loop_; ModelTypeSet preferred_types_; - FakeSyncService service_; NiceMock<DataTypeManagerMock> manager_; + NiceMock<base::MockCallback<base::RepeatingClosure>> reconfigure_callback_; + NiceMock<base::MockCallback<base::RepeatingClosure>> migration_done_callback_; TestUserShare test_user_share_; std::unique_ptr<BackendMigrator> migrator_; }; @@ -101,6 +106,8 @@ // Test that in the normal case a migration does transition through each state // and wind up back in IDLE. TEST_F(SyncBackendMigratorTest, Sanity) { + EXPECT_CALL(*migration_done_callback(), Run()).Times(0); + MockMigrationObserver migration_observer; migrator()->AddMigrationObserver(&migration_observer); EXPECT_CALL(migration_observer, OnMigrationStateChange()).Times(4); @@ -112,9 +119,8 @@ EXPECT_CALL(*manager(), state()) .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*manager(), PurgeForMigration(_, CONFIGURE_REASON_MIGRATION)) - .Times(1); - EXPECT_CALL(*manager(), Configure(_, CONFIGURE_REASON_MIGRATION)).Times(1); + EXPECT_CALL(*manager(), PurgeForMigration(_)); + EXPECT_CALL(*reconfigure_callback(), Run()); migrator()->MigrateTypes(to_migrate); EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state()); @@ -123,6 +129,7 @@ SendConfigureDone(DataTypeManager::OK, difference); EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state()); + EXPECT_CALL(*migration_done_callback(), Run()); SetUnsyncedTypes(ModelTypeSet()); SendConfigureDone(DataTypeManager::OK, preferred_types()); EXPECT_EQ(BackendMigrator::IDLE, migrator()->state()); @@ -133,6 +140,8 @@ // Test that in the normal case with Nigori a migration transitions through // each state and wind up back in IDLE. TEST_F(SyncBackendMigratorTest, MigrateNigori) { + EXPECT_CALL(*migration_done_callback(), Run()).Times(0); + ModelTypeSet to_migrate, difference; to_migrate.Put(NIGORI); difference.Put(AUTOFILL); @@ -141,15 +150,17 @@ EXPECT_CALL(*manager(), state()) .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*manager(), PurgeForMigration(_, CONFIGURE_REASON_MIGRATION)); + EXPECT_CALL(*manager(), PurgeForMigration(_)); migrator()->MigrateTypes(to_migrate); EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state()); + EXPECT_CALL(*reconfigure_callback(), Run()); SetUnsyncedTypes(to_migrate); SendConfigureDone(DataTypeManager::OK, difference); EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state()); + EXPECT_CALL(*migration_done_callback(), Run()); SetUnsyncedTypes(ModelTypeSet()); SendConfigureDone(DataTypeManager::OK, preferred_types()); EXPECT_EQ(BackendMigrator::IDLE, migrator()->state()); @@ -163,14 +174,14 @@ EXPECT_CALL(*manager(), state()) .WillOnce(Return(DataTypeManager::CONFIGURING)); - EXPECT_CALL(*manager(), Configure(_, _)).Times(0); + EXPECT_CALL(*reconfigure_callback(), Run()).Times(0); migrator()->MigrateTypes(to_migrate); EXPECT_EQ(BackendMigrator::WAITING_TO_START, migrator()->state()); Mock::VerifyAndClearExpectations(manager()); EXPECT_CALL(*manager(), state()) .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*manager(), PurgeForMigration(_, CONFIGURE_REASON_MIGRATION)); + EXPECT_CALL(*manager(), PurgeForMigration(_)); SetUnsyncedTypes(ModelTypeSet()); SendConfigureDone(DataTypeManager::OK, ModelTypeSet()); @@ -189,8 +200,7 @@ EXPECT_CALL(*manager(), state()) .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*manager(), PurgeForMigration(_, CONFIGURE_REASON_MIGRATION)) - .Times(2); + EXPECT_CALL(*manager(), PurgeForMigration(_)).Times(2); migrator()->MigrateTypes(to_migrate1); EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state()); @@ -199,9 +209,8 @@ const ModelTypeSet difference1 = Difference(preferred_types(), to_migrate1); Mock::VerifyAndClearExpectations(manager()); - EXPECT_CALL(*manager(), PurgeForMigration(_, CONFIGURE_REASON_MIGRATION)) - .Times(1); - EXPECT_CALL(*manager(), Configure(_, CONFIGURE_REASON_MIGRATION)).Times(1); + EXPECT_CALL(*manager(), PurgeForMigration(_)); + EXPECT_CALL(*reconfigure_callback(), Run()); SetUnsyncedTypes(to_migrate1); SendConfigureDone(DataTypeManager::OK, difference1); EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state()); @@ -222,14 +231,12 @@ EXPECT_CALL(*manager(), state()) .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*manager(), PurgeForMigration(HasModelTypes(to_migrate), - CONFIGURE_REASON_MIGRATION)); + EXPECT_CALL(*manager(), PurgeForMigration(HasModelTypes(to_migrate))); migrator()->MigrateTypes(to_migrate); EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state()); Mock::VerifyAndClearExpectations(manager()); - EXPECT_CALL(*manager(), PurgeForMigration(HasModelTypes(to_migrate), - CONFIGURE_REASON_MIGRATION)); + EXPECT_CALL(*manager(), PurgeForMigration(HasModelTypes(to_migrate))); SetUnsyncedTypes(ModelTypeSet()); SendConfigureDone(DataTypeManager::OK, preferred_types()); @@ -247,9 +254,8 @@ EXPECT_CALL(*manager(), state()) .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*manager(), PurgeForMigration(_, CONFIGURE_REASON_MIGRATION)) - .Times(1); - EXPECT_CALL(*manager(), Configure(_, CONFIGURE_REASON_MIGRATION)).Times(1); + EXPECT_CALL(*manager(), PurgeForMigration(_)); + EXPECT_CALL(*reconfigure_callback(), Run()); migrator()->MigrateTypes(to_migrate); EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state()); @@ -268,34 +274,13 @@ EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state()); } -TEST_F(SyncBackendMigratorTest, MigratedTypeDisabledByUserDuringMigration) { - ModelTypeSet to_migrate; - to_migrate.Put(PREFERENCES); - - EXPECT_CALL(*manager(), state()) - .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*manager(), PurgeForMigration(_, CONFIGURE_REASON_MIGRATION)) - .Times(1); - EXPECT_CALL(*manager(), Configure(_, CONFIGURE_REASON_MIGRATION)).Times(1); - migrator()->MigrateTypes(to_migrate); - - RemovePreferredType(PREFERENCES); - SetUnsyncedTypes(to_migrate); - SendConfigureDone(DataTypeManager::OK, preferred_types()); - EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state()); - SetUnsyncedTypes(ModelTypeSet()); - SendConfigureDone(DataTypeManager::OK, preferred_types()); - EXPECT_EQ(BackendMigrator::IDLE, migrator()->state()); -} - TEST_F(SyncBackendMigratorTest, ConfigureFailure) { ModelTypeSet to_migrate; to_migrate.Put(PREFERENCES); EXPECT_CALL(*manager(), state()) .WillOnce(Return(DataTypeManager::CONFIGURED)); - EXPECT_CALL(*manager(), PurgeForMigration(_, CONFIGURE_REASON_MIGRATION)) - .Times(1); + EXPECT_CALL(*manager(), PurgeForMigration(_)); migrator()->MigrateTypes(to_migrate); SetUnsyncedTypes(ModelTypeSet()); SendConfigureDone(DataTypeManager::ABORTED, ModelTypeSet());
diff --git a/components/sync/driver/data_type_manager.h b/components/sync/driver/data_type_manager.h index c7975a0..d1358d0 100644 --- a/components/sync/driver/data_type_manager.h +++ b/components/sync/driver/data_type_manager.h
@@ -78,8 +78,7 @@ // Resets all data type error state. virtual void ResetDataTypeErrors() = 0; - virtual void PurgeForMigration(ModelTypeSet undesired_types, - ConfigureReason reason) = 0; + virtual void PurgeForMigration(ModelTypeSet undesired_types) = 0; // Synchronously stops all registered data types. If called after // Configure() is called but before it finishes, it will abort the
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc index 338bd4e..42dc14f1 100644 --- a/components/sync/driver/data_type_manager_impl.cc +++ b/components/sync/driver/data_type_manager_impl.cc
@@ -122,10 +122,9 @@ data_type_status_table_.Reset(); } -void DataTypeManagerImpl::PurgeForMigration(ModelTypeSet undesired_types, - ConfigureReason reason) { +void DataTypeManagerImpl::PurgeForMigration(ModelTypeSet undesired_types) { ModelTypeSet remainder = Difference(last_requested_types_, undesired_types); - ConfigureImpl(remainder, reason); + ConfigureImpl(remainder, CONFIGURE_REASON_MIGRATION); } void DataTypeManagerImpl::ConfigureImpl(ModelTypeSet desired_types, @@ -153,7 +152,7 @@ return; } - Restart(reason); + Restart(); } void DataTypeManagerImpl::RegisterTypesWithBackend() { @@ -244,8 +243,9 @@ return config_state_map; } -void DataTypeManagerImpl::Restart(ConfigureReason reason) { +void DataTypeManagerImpl::Restart() { DVLOG(1) << "Restarting..."; + const ConfigureReason reason = last_configure_reason_; // Only record the type histograms for user-triggered configurations or // restarts.
diff --git a/components/sync/driver/data_type_manager_impl.h b/components/sync/driver/data_type_manager_impl.h index 8e25be24..4d88f52 100644 --- a/components/sync/driver/data_type_manager_impl.h +++ b/components/sync/driver/data_type_manager_impl.h
@@ -52,8 +52,7 @@ void ResetDataTypeErrors() override; // Needed only for backend migration. - void PurgeForMigration(ModelTypeSet undesired_types, - ConfigureReason reason) override; + void PurgeForMigration(ModelTypeSet undesired_types) override; void Stop(ShutdownReason reason) override; ModelTypeSet GetActiveDataTypes() const override; @@ -144,7 +143,7 @@ // Post a task to reconfigure when no downloading or association are running. void ProcessReconfigure(); - void Restart(ConfigureReason reason); + void Restart(); void DownloadReady(ModelTypeSet types_to_download, ModelTypeSet first_sync_types, ModelTypeSet failed_configuration_types);
diff --git a/components/sync/driver/data_type_manager_impl_unittest.cc b/components/sync/driver/data_type_manager_impl_unittest.cc index 8f5bbabe..2bf098c 100644 --- a/components/sync/driver/data_type_manager_impl_unittest.cc +++ b/components/sync/driver/data_type_manager_impl_unittest.cc
@@ -923,7 +923,7 @@ EXPECT_EQ(0, GetController(BOOKMARKS)->clear_metadata_call_count()); SetConfigureStartExpectation(); SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable()); - dtm_->PurgeForMigration(to_migrate, CONFIGURE_REASON_MIGRATION); + dtm_->PurgeForMigration(to_migrate); EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); EXPECT_EQ(1, GetController(BOOKMARKS)->clear_metadata_call_count()); @@ -959,7 +959,7 @@ // Purge the Nigori type. SetConfigureStartExpectation(); - dtm_->PurgeForMigration(ModelTypeSet(NIGORI), CONFIGURE_REASON_MIGRATION); + dtm_->PurgeForMigration(ModelTypeSet(NIGORI)); EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); observer_.ResetExpectations();
diff --git a/components/sync/driver/data_type_manager_mock.h b/components/sync/driver/data_type_manager_mock.h index 8752a52..2873e4f 100644 --- a/components/sync/driver/data_type_manager_mock.h +++ b/components/sync/driver/data_type_manager_mock.h
@@ -19,7 +19,7 @@ MOCK_METHOD2(Configure, void(ModelTypeSet, ConfigureReason)); MOCK_METHOD1(ReenableType, void(ModelType)); MOCK_METHOD0(ResetDataTypeErrors, void()); - MOCK_METHOD2(PurgeForMigration, void(ModelTypeSet, ConfigureReason)); + MOCK_METHOD1(PurgeForMigration, void(ModelTypeSet)); MOCK_METHOD1(Stop, void(ShutdownReason)); MOCK_METHOD0(controllers, const DataTypeController::TypeMap&()); MOCK_CONST_METHOD0(GetActiveDataTypes, ModelTypeSet());
diff --git a/components/sync/driver/sync_service_crypto.cc b/components/sync/driver/sync_service_crypto.cc index 83ff6cf..fc75d96 100644 --- a/components/sync/driver/sync_service_crypto.cc +++ b/components/sync/driver/sync_service_crypto.cc
@@ -13,7 +13,6 @@ #include "components/sync/base/nigori.h" #include "components/sync/base/sync_prefs.h" #include "components/sync/driver/clear_server_data_events.h" -#include "components/sync/driver/data_type_manager.h" #include "components/sync/driver/sync_driver_switches.h" #include "components/sync/driver/sync_service.h" #include "components/sync/engine/sync_string_conversions.h" @@ -103,18 +102,15 @@ } // namespace SyncServiceCrypto::SyncServiceCrypto( - base::RepeatingClosure notify_observers, - base::RepeatingCallback<ModelTypeSet()> get_preferred_types, - base::RepeatingCallback<bool()> can_configure_data_types, + const base::RepeatingClosure& notify_observers, + const base::RepeatingCallback<void(ConfigureReason)>& reconfigure, CryptoSyncPrefs* sync_prefs) - : notify_observers_(std::move(notify_observers)), - get_preferred_types_(std::move(get_preferred_types)), - can_configure_data_types_(std::move(can_configure_data_types)), + : notify_observers_(notify_observers), + reconfigure_(reconfigure), sync_prefs_(sync_prefs), weak_factory_(this) { DCHECK(notify_observers_); - DCHECK(get_preferred_types_); - DCHECK(can_configure_data_types_); + DCHECK(reconfigure_); DCHECK(sync_prefs_); } @@ -154,7 +150,6 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // This should only be called when the engine has been initialized. DCHECK(engine_); - DCHECK(data_type_manager_); DCHECK(!(!is_explicit && IsUsingSecondaryPassphrase())) << "Data is already encrypted using an explicit passphrase"; DCHECK(!(is_explicit && passphrase_required_reason_ == REASON_DECRYPTION)) @@ -172,12 +167,6 @@ notify_observers_.Run(); } - if (!data_type_manager_->IsNigoriEnabled()) { - NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori" - " is disabled."; - return; - } - // We should never be called with an empty passphrase. DCHECK(!passphrase.empty()); @@ -191,13 +180,6 @@ bool SyncServiceCrypto::SetDecryptionPassphrase(const std::string& passphrase) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(data_type_manager_); - - if (!data_type_manager_->IsNigoriEnabled()) { - NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori" - " is disabled."; - return false; - } // We should never be called with an empty passphrase. DCHECK(!passphrase.empty()); @@ -262,16 +244,9 @@ << PassphraseRequiredReasonToString(reason); passphrase_required_reason_ = reason; - const ModelTypeSet types = get_preferred_types_.Run(); - if (data_type_manager_ && can_configure_data_types_.Run()) { - DCHECK(data_type_manager_->IsNigoriEnabled()); - // Reconfigure without the encrypted types (excluded implicitly via the - // failed datatypes handler). - data_type_manager_->Configure(types, CONFIGURE_REASON_CRYPTO); - } - - // Notify observers that the passphrase status may have changed. - notify_observers_.Run(); + // Reconfigure without the encrypted types (excluded implicitly via the + // failed datatypes handler). + reconfigure_.Run(CONFIGURE_REASON_CRYPTO); } void SyncServiceCrypto::OnPassphraseAccepted() { @@ -286,13 +261,7 @@ // Make sure the data types that depend on the passphrase are started at // this time. - const ModelTypeSet types = get_preferred_types_.Run(); - if (data_type_manager_ && can_configure_data_types_.Run()) { - // Re-enable any encrypted types if necessary. - data_type_manager_->Configure(types, CONFIGURE_REASON_CRYPTO); - } - - notify_observers_.Run(); + reconfigure_.Run(CONFIGURE_REASON_CRYPTO); } void SyncServiceCrypto::OnBootstrapTokenUpdated( @@ -369,14 +338,11 @@ void SyncServiceCrypto::BeginConfigureCatchUpBeforeClear() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(data_type_manager_); DCHECK(!saved_nigori_state_); - DCHECK(can_configure_data_types_.Run()); saved_nigori_state_ = std::make_unique<SyncEncryptionHandler::NigoriState>(); sync_prefs_->GetNigoriSpecificsForPassphraseTransition( &saved_nigori_state_->nigori_specifics); - const ModelTypeSet types = data_type_manager_->GetActiveDataTypes(); - data_type_manager_->Configure(types, CONFIGURE_REASON_CATCH_UP); + reconfigure_.Run(CONFIGURE_REASON_CATCH_UP); } std::unique_ptr<SyncEncryptionHandler::Observer>
diff --git a/components/sync/driver/sync_service_crypto.h b/components/sync/driver/sync_service_crypto.h index 066ea6e3..357e4d2 100644 --- a/components/sync/driver/sync_service_crypto.h +++ b/components/sync/driver/sync_service_crypto.h
@@ -12,12 +12,12 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "components/sync/base/model_type.h" +#include "components/sync/engine/configure_reason.h" #include "components/sync/engine/sync_encryption_handler.h" #include "components/sync/engine/sync_engine.h" namespace syncer { -class DataTypeManager; class CryptoSyncPrefs; // This class functions as mostly independent component of SyncServiceBase that @@ -25,10 +25,10 @@ // encryption communications with the sync thread. class SyncServiceCrypto : public SyncEncryptionHandler::Observer { public: - SyncServiceCrypto(base::RepeatingClosure notify_observers, - base::RepeatingCallback<ModelTypeSet()> get_preferred_types, - base::RepeatingCallback<bool()> can_configure_data_types, - CryptoSyncPrefs* sync_prefs); + SyncServiceCrypto( + const base::RepeatingClosure& notify_observers, + const base::RepeatingCallback<void(ConfigureReason)>& reconfigure, + CryptoSyncPrefs* sync_prefs); ~SyncServiceCrypto() override; // See the SyncService header. @@ -71,9 +71,8 @@ // Calls data type manager to start catch up configure. void BeginConfigureCatchUpBeforeClear(); - // Used to provide the engine and DTM when the engine is initialized. + // Used to provide the engine when it is initialized. void SetSyncEngine(SyncEngine* engine) { engine_ = engine; } - void SetDataTypeManager(DataTypeManager* dtm) { data_type_manager_ = dtm; } // Creates a proxy observer object that will post calls to this thread. std::unique_ptr<SyncEncryptionHandler::Observer> GetEncryptionObserverProxy(); @@ -97,20 +96,14 @@ // Calls SyncServiceBase::NotifyObservers(). Never null. const base::RepeatingClosure notify_observers_; - // Calls SyncService::GetPreferredDataTypes(). Never null. - const base::RepeatingCallback<ModelTypeSet()> get_preferred_types_; - - // Returns true if data types can be configured and false otherwise (e.g. if - // setup has not been completed). Never null. - const base::RepeatingCallback<bool()> can_configure_data_types_; + const base::RepeatingCallback<void(ConfigureReason)> reconfigure_; // A pointer to the crypto-relevant sync prefs. Never null and guaranteed to // outlive us. CryptoSyncPrefs* const sync_prefs_; - // These are only not-null when the engine is initialized. + // Not-null when the engine is initialized. SyncEngine* engine_ = nullptr; - DataTypeManager* data_type_manager_ = nullptr; // Was the last SYNC_PASSPHRASE_REQUIRED notification sent because it // was required for encryption, decryption with a cached passphrase, or
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 9f20f83..3d341b7 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -2168,8 +2168,6 @@ "android/synchronous_compositor_host.h", "android/synchronous_compositor_sync_call_bridge.cc", "android/synchronous_compositor_sync_call_bridge.h", - "android/tap_disambiguator.cc", - "android/tap_disambiguator.h", "android/tracing_controller_android.cc", "android/tracing_controller_android.h", "android/web_contents_observer_proxy.cc",
diff --git a/content/browser/OWNERS b/content/browser/OWNERS index 223a5fa2d..61804ae 100644 --- a/content/browser/OWNERS +++ b/content/browser/OWNERS
@@ -1,6 +1,10 @@ # For Android boliu@chromium.org +# These are for the common case of adding or renaming files. If you're doing +# structural changes, please get a review from a reviewer in this file. +per-file BUILD.gn=* + # For security review. per-file child_process_security_policy_impl.*=set noparent per-file child_process_security_policy_impl.*=creis@chromium.org
diff --git a/content/browser/android/select_popup.cc b/content/browser/android/select_popup.cc index 1c40ca4..44d187ce 100644 --- a/content/browser/android/select_popup.cc +++ b/content/browser/android/select_popup.cc
@@ -40,27 +40,14 @@ } // namespace -jlong JNI_SelectPopup_Init(JNIEnv* env, - const JavaParamRef<jobject>& obj, - const JavaParamRef<jobject>& jweb_contents) { - WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents); - DCHECK(web_contents); - - auto* wc_impl = static_cast<WebContentsImpl*>(web_contents); - auto* wcv = static_cast<WebContentsViewAndroid*>(wc_impl->GetView()); - - // Owned by |WebContentsViewAndroid|. - auto select_popup = std::make_unique<SelectPopup>(env, obj, wc_impl); - SelectPopup* select_popup_ptr = select_popup.get(); - wcv->SetSelectPopup(std::move(select_popup)); - return reinterpret_cast<intptr_t>(select_popup_ptr); +SelectPopup::SelectPopup(WebContentsImpl* web_contents) + : web_contents_(web_contents) { + JNIEnv* env = AttachCurrentThread(); + java_obj_ = JavaObjectWeakGlobalRef( + env, Java_SelectPopup_create(env, web_contents_->GetJavaWebContents(), + reinterpret_cast<intptr_t>(this))); } -SelectPopup::SelectPopup(JNIEnv* env, - const JavaParamRef<jobject>& obj, - WebContentsImpl* web_contents) - : web_contents_(web_contents), java_obj_(env, obj) {} - SelectPopup::~SelectPopup() { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> j_obj = java_obj_.get(env);
diff --git a/content/browser/android/select_popup.h b/content/browser/android/select_popup.h index 41839b3..3ef5def 100644 --- a/content/browser/android/select_popup.h +++ b/content/browser/android/select_popup.h
@@ -23,9 +23,7 @@ class SelectPopup { public: - SelectPopup(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - WebContentsImpl* web_contents); + explicit SelectPopup(WebContentsImpl* web_contents); ~SelectPopup(); // Creates a popup menu with |items|.
diff --git a/content/browser/android/tap_disambiguator.cc b/content/browser/android/tap_disambiguator.cc deleted file mode 100644 index 875c128..0000000 --- a/content/browser/android/tap_disambiguator.cc +++ /dev/null
@@ -1,109 +0,0 @@ -// Copyright 2017 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/browser/android/tap_disambiguator.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/android/scoped_java_ref.h" -#include "content/browser/renderer_host/render_widget_host_view_android.h" -#include "content/public/browser/web_contents.h" -#include "jni/TapDisambiguator_jni.h" -#include "ui/gfx/android/java_bitmap.h" - -using base::android::AttachCurrentThread; -using base::android::ConvertUTF8ToJavaString; -using base::android::JavaParamRef; -using base::android::ScopedJavaLocalRef; - -namespace content { - -namespace { - -ScopedJavaLocalRef<jobject> JNI_TapDisambiguator_CreateJavaRect( - JNIEnv* env, - const gfx::Rect& rect) { - return ScopedJavaLocalRef<jobject>(Java_TapDisambiguator_createRect( - env, rect.x(), rect.y(), rect.right(), rect.bottom())); -} - -} // namespace - -jlong JNI_TapDisambiguator_Init(JNIEnv* env, - const JavaParamRef<jobject>& obj, - const JavaParamRef<jobject>& jweb_contents) { - WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents); - DCHECK(web_contents); - - // Owns itself and gets destroyed when |WebContentsDestroyed| is called. - auto* tap_disambiguator = new TapDisambiguator(env, obj, web_contents); - tap_disambiguator->Initialize(); - return reinterpret_cast<intptr_t>(tap_disambiguator); -} - -TapDisambiguator::TapDisambiguator(JNIEnv* env, - const JavaParamRef<jobject>& obj, - WebContents* web_contents) - : RenderWidgetHostConnector(web_contents), rwhva_(nullptr) { - java_obj_ = JavaObjectWeakGlobalRef(env, obj); -} - -TapDisambiguator::~TapDisambiguator() { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_obj_.get(env); - if (!obj.is_null()) - Java_TapDisambiguator_destroy(env, obj); -} - -void TapDisambiguator::UpdateRenderProcessConnection( - RenderWidgetHostViewAndroid* old_rwhva, - RenderWidgetHostViewAndroid* new_rwhva) { - if (old_rwhva) - old_rwhva->set_tap_disambiguator(nullptr); - if (new_rwhva) - new_rwhva->set_tap_disambiguator(this); - rwhva_ = new_rwhva; -} - -void TapDisambiguator::ShowPopup(const gfx::Rect& rect_pixels, - const SkBitmap& zoomed_bitmap) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_obj_.get(env); - if (obj.is_null()) - return; - - ScopedJavaLocalRef<jobject> rect_object( - JNI_TapDisambiguator_CreateJavaRect(env, rect_pixels)); - - ScopedJavaLocalRef<jobject> java_bitmap = - gfx::ConvertToJavaBitmap(&zoomed_bitmap); - DCHECK(!java_bitmap.is_null()); - - Java_TapDisambiguator_showPopup(env, obj, rect_object, java_bitmap); -} - -void TapDisambiguator::HidePopup() { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_obj_.get(env); - if (obj.is_null()) - return; - Java_TapDisambiguator_hidePopup(env, obj); -} - -void TapDisambiguator::ResolveTapDisambiguation( - JNIEnv* env, - const JavaParamRef<jobject>& obj, - jlong time_ms, - jfloat x, - jfloat y, - jboolean is_long_press) { - if (!rwhva_) - return; - - float dip_scale = rwhva_->GetNativeView()->GetDipScale(); - rwhva_->ResolveTapDisambiguation( - time_ms / 1000, gfx::Point(x / dip_scale, y / dip_scale), is_long_press); -} - -} // namespace content
diff --git a/content/browser/android/tap_disambiguator.h b/content/browser/android/tap_disambiguator.h deleted file mode 100644 index 849c5b78..0000000 --- a/content/browser/android/tap_disambiguator.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2017 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_BROWSER_ANDROID_TAP_DISAMBIGUATOR_H_ -#define CONTENT_BROWSER_ANDROID_TAP_DISAMBIGUATOR_H_ - -#include <jni.h> - -#include "base/android/jni_weak_ref.h" -#include "content/browser/android/render_widget_host_connector.h" -#include "ui/gfx/geometry/rect_f.h" - -namespace content { - -class RenderWidgetHostViewAndroid; - -class TapDisambiguator : public RenderWidgetHostConnector { - public: - TapDisambiguator(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - WebContents* web_contents); - - // RendetWidgetHostConnector implementation. - void UpdateRenderProcessConnection( - RenderWidgetHostViewAndroid* old_rwhva, - RenderWidgetHostViewAndroid* new_rhwva) override; - - // Shows the disambiguation popup - // |rect_pixels| --> window coordinates which |zoomed_bitmap| represents - // |zoomed_bitmap| --> magnified image of potential touch targets - void ResolveTapDisambiguation(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - jlong time_ms, - jfloat x, - jfloat y, - jboolean is_long_press); - - // Called from native -> java - - // Shows the disambiguator popup - // |rect_pixels| --> window coordinates which |zoomed_bitmap| represents - // |zoomed_bitmap| --> magnified image of potential touch targets - void ShowPopup(const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap); - void HidePopup(); - - private: - ~TapDisambiguator() override; - - // Current RenderWidgetHostView connected to this instance. Can be null. - RenderWidgetHostViewAndroid* rwhva_; - JavaObjectWeakGlobalRef java_obj_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_ANDROID_TAP_DISAMBIGUATOR_H_
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index be66cc2..1f3e2b3 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -681,8 +681,6 @@ OnTextInputStateChanged) IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse) IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse) - IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup, - OnShowDisambiguationPopup) IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged, OnSelectionBoundsChanged) IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched) @@ -2428,35 +2426,6 @@ return view_->GetKeyboardLayoutMap(); } -void RenderWidgetHostImpl::OnShowDisambiguationPopup( - const gfx::Rect& rect_pixels, - const gfx::Size& size, - base::SharedMemoryHandle handle) { - DCHECK(!rect_pixels.IsEmpty()); - DCHECK(!size.IsEmpty()); - - SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); - size_t shm_size = info.computeMinByteSize(); - - base::SharedMemory shm(handle, false /* read_only */); - if (shm_size == 0 || !shm.Map(shm_size)) { - bad_message::ReceivedBadMessage(GetProcess(), - bad_message::RWH_SHARED_BITMAP); - return; - } - - SkBitmap zoomed_bitmap; - zoomed_bitmap.installPixels(info, shm.memory(), info.minRowBytes()); - - // Note that |rect| is in coordinates of pixels relative to the window origin. - // Aura-based systems will want to convert this to DIPs. - if (view_) - view_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap); - - // It is assumed that the disambiguation popup will make a copy of the - // provided zoomed image, so we delete |zoomed_bitmap| and free shared memory. -} - void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) { ignore_input_events_ = ignore_input_events; }
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 89e3ced..0d347cb 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -822,9 +822,6 @@ void OnLockMouse(bool user_gesture, bool privileged); void OnUnlockMouse(); - void OnShowDisambiguationPopup(const gfx::Rect& rect_pixels, - const gfx::Size& size, - base::SharedMemoryHandle handle); void OnSelectionBoundsChanged( const ViewHostMsg_SelectionBounds_Params& params); void OnSetNeedsBeginFrames(bool needs_begin_frames);
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 3d10664..71942db 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -40,7 +40,6 @@ #include "content/browser/android/overscroll_controller_android.h" #include "content/browser/android/selection/selection_popup_controller.h" #include "content/browser/android/synchronous_compositor_host.h" -#include "content/browser/android/tap_disambiguator.h" #include "content/browser/android/text_suggestion_host_android.h" #include "content/browser/bad_message.h" #include "content/browser/compositor/surface_utils.h" @@ -171,7 +170,6 @@ is_window_activity_started_(true), is_in_vr_(false), ime_adapter_android_(nullptr), - tap_disambiguator_(nullptr), selection_popup_controller_(nullptr), text_suggestion_host_(nullptr), gesture_listener_manager_(nullptr), @@ -915,14 +913,6 @@ return latest_capture_sequence_number_; } -void RenderWidgetHostViewAndroid::ShowDisambiguationPopup( - const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) { - if (!tap_disambiguator_) - return; - - tap_disambiguator_->ShowPopup(rect_pixels, zoomed_bitmap); -} - void RenderWidgetHostViewAndroid::OnInterstitialPageGoingAway() { sync_compositor_.reset(); } @@ -1848,17 +1838,6 @@ GetTouchHandleHeight()); } -void RenderWidgetHostViewAndroid::ResolveTapDisambiguation( - double timestamp_seconds, - gfx::Point tap_viewport_offset, - bool is_long_press) { - DCHECK(host()); - host()->Send(new ViewMsg_ResolveTapDisambiguation( - host()->GetRoutingID(), - base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp_seconds), - tap_viewport_offset, is_long_press)); -} - void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) { if (host() && host()->delegate()) host()->delegate()->MoveCaret(point); @@ -2076,8 +2055,6 @@ void RenderWidgetHostViewAndroid::OnSizeChanged() { if (ime_adapter_android_) ime_adapter_android_->UpdateAfterViewSizeChanged(); - if (tap_disambiguator_) - tap_disambiguator_->HidePopup(); } void RenderWidgetHostViewAndroid::OnPhysicalBackingSizeChanged() {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index c5d40f6..8d3c70cd 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -53,7 +53,6 @@ class SelectionPopupController; class SynchronousCompositorHost; class SynchronousCompositorClient; -class TapDisambiguator; class TextSuggestionHostAndroid; class TouchSelectionControllerClientManagerAndroid; class WebContentsAccessibilityAndroid; @@ -161,8 +160,6 @@ bool IsInVR() const override; void DidOverscroll(const ui::DidOverscrollParams& params) override; void DidStopFlinging() override; - void ShowDisambiguationPopup(const gfx::Rect& rect_pixels, - const SkBitmap& zoomed_bitmap) override; void OnInterstitialPageGoingAway() override; std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget() override; @@ -264,15 +261,9 @@ void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event); void SendGestureEvent(const blink::WebGestureEvent& event); bool ShowSelectionMenu(const ContextMenuParams& params); - void ResolveTapDisambiguation(double timestamp_seconds, - gfx::Point tap_viewport_offset, - bool is_long_press); void set_ime_adapter(ImeAdapterAndroid* ime_adapter) { ime_adapter_android_ = ime_adapter; } - void set_tap_disambiguator(TapDisambiguator* tap_disambiguator) { - tap_disambiguator_ = tap_disambiguator; - } void set_selection_popup_controller(SelectionPopupController* controller) { selection_popup_controller_ = controller; } @@ -449,7 +440,6 @@ bool handles_hidden_by_selection_ui_ = false; ImeAdapterAndroid* ime_adapter_android_; - TapDisambiguator* tap_disambiguator_; SelectionPopupController* selection_popup_controller_; TextSuggestionHostAndroid* text_suggestion_host_; GestureListenerManager* gesture_listener_manager_;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index c61199d..0b2eed0 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -488,12 +488,6 @@ ++renderer_frame_number_; } -void RenderWidgetHostViewBase::ShowDisambiguationPopup( - const gfx::Rect& rect_pixels, - const SkBitmap& zoomed_bitmap) { - NOTIMPLEMENTED_LOG_ONCE(); -} - void RenderWidgetHostViewBase::OnAutoscrollStart() { if (!GetMouseWheelPhaseHandler()) return;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 8ed6ffd..922f7897 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -48,7 +48,6 @@ #include "content/common/render_widget_window_tree_client_factory.mojom.h" #include "services/ui/public/interfaces/window_tree.mojom.h" #endif -class SkBitmap; struct ViewHostMsg_SelectionBounds_Params; @@ -495,11 +494,6 @@ // Gets the bounds of the top-level window, in screen coordinates. virtual gfx::Rect GetBoundsInRootWindow() = 0; - // Called by the RenderWidgetHost when an ambiguous gesture is detected to - // show the disambiguation popup bubble. - virtual void ShowDisambiguationPopup(const gfx::Rect& rect_pixels, - const SkBitmap& zoomed_bitmap); - // Called by the WebContentsImpl when a user tries to navigate a new page on // main frame. virtual void OnDidNavigateMainFrameToNewPage();
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc index 8990bc7..fe977804 100644 --- a/content/browser/web_contents/web_contents_view_android.cc +++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -107,11 +107,6 @@ content_ui_event_handler_ = std::move(handler); } -void WebContentsViewAndroid::SetSelectPopup( - std::unique_ptr<SelectPopup> select_popup) { - select_popup_ = std::move(select_popup); -} - void WebContentsViewAndroid::SetOverscrollRefreshHandler( std::unique_ptr<ui::OverscrollRefreshHandler> overscroll_refresh_handler) { overscroll_refresh_handler_ = std::move(overscroll_refresh_handler); @@ -323,6 +318,12 @@ delegate_->ShowContextMenu(render_frame_host, params); } +SelectPopup* WebContentsViewAndroid::GetSelectPopup() { + if (!select_popup_) + select_popup_ = std::make_unique<SelectPopup>(web_contents_); + return select_popup_.get(); +} + void WebContentsViewAndroid::ShowPopupMenu( RenderFrameHost* render_frame_host, const gfx::Rect& bounds, @@ -332,15 +333,12 @@ const std::vector<MenuItem>& items, bool right_aligned, bool allow_multiple_selection) { - if (select_popup_) { - select_popup_->ShowMenu(render_frame_host, bounds, items, selected_item, - allow_multiple_selection, right_aligned); - } + GetSelectPopup()->ShowMenu(render_frame_host, bounds, items, selected_item, + allow_multiple_selection, right_aligned); } void WebContentsViewAndroid::HidePopupMenu() { - if (select_popup_) - select_popup_->HideMenu(); + GetSelectPopup()->HideMenu(); } void WebContentsViewAndroid::StartDragging(
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h index 088fedea..53d1898 100644 --- a/content/browser/web_contents/web_contents_view_android.h +++ b/content/browser/web_contents/web_contents_view_android.h
@@ -38,9 +38,6 @@ void SetContentUiEventHandler(std::unique_ptr<ContentUiEventHandler> handler); - // Sets the object that show/hide popup view for <select> tag. - void SetSelectPopup(std::unique_ptr<SelectPopup> select_popup); - void set_synchronous_compositor_client(SynchronousCompositorClient* client) { synchronous_compositor_client_ = client; } @@ -142,6 +139,8 @@ void OnDragEnded(); void OnSystemDragEnded(); + SelectPopup* GetSelectPopup(); + // The WebContents whose contents we display. WebContentsImpl* web_contents_;
diff --git a/content/common/DEPS b/content/common/DEPS index 03fa018..be1b08af 100644 --- a/content/common/DEPS +++ b/content/common/DEPS
@@ -55,7 +55,6 @@ "+third_party/blink/public/platform/modules/device_orientation/WebDeviceMotionData.h", "+third_party/blink/public/platform/modules/device_orientation/WebDeviceOrientationData.h", "+third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h", - "+third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom.h", "+third_party/blink/public/platform/modules/indexeddb/web_idb_types.h", "+third_party/blink/public/platform/modules/mediasession/media_session.mojom.h", "+third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h",
diff --git a/content/common/service_worker/service_worker_types_unittest.cc b/content/common/service_worker/service_worker_types_unittest.cc index 87db85c..3de9f20e 100644 --- a/content/common/service_worker/service_worker_types_unittest.cc +++ b/content/common/service_worker/service_worker_types_unittest.cc
@@ -7,7 +7,7 @@ #include "mojo/public/cpp/base/time_mojom_traits.h" #include "mojo/public/cpp/test_support/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom.h" +#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h" #include "url/mojom/url_gurl_mojom_traits.h" #include "net/base/load_flags.h"
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 1c1cd39..7098391 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -103,8 +103,6 @@ gfx::FontRenderParams::SUBPIXEL_RENDERING_MAX) IPC_ENUM_TRAITS_MAX_VALUE(content::ScreenOrientationValues, content::SCREEN_ORIENTATION_VALUES_LAST) -IPC_ENUM_TRAITS_MAX_VALUE(content::TapMultipleTargetsStrategy, - content::TAP_MULTIPLE_TARGETS_STRATEGY_MAX) IPC_ENUM_TRAITS_MAX_VALUE(content::ThreeDAPIType, content::THREE_D_API_TYPE_LAST) IPC_ENUM_TRAITS_MAX_VALUE(ui::TextInputMode, ui::TEXT_INPUT_MODE_MAX) @@ -217,7 +215,6 @@ IPC_STRUCT_TRAITS_MEMBER(webrtc_udp_max_port) IPC_STRUCT_TRAITS_MEMBER(user_agent_override) IPC_STRUCT_TRAITS_MEMBER(accept_languages) - IPC_STRUCT_TRAITS_MEMBER(tap_multiple_targets_strategy) IPC_STRUCT_TRAITS_MEMBER(disable_client_blocked_error_page) IPC_STRUCT_TRAITS_MEMBER(plugin_fullscreen_allowed) IPC_STRUCT_TRAITS_MEMBER(network_contry_iso) @@ -455,14 +452,6 @@ bool /* result */) #endif -// If the ViewHostMsg_ShowDisambiguationPopup resulted in the user tapping -// inside the popup, instruct the renderer to generate a synthetic tap at that -// offset. -IPC_MESSAGE_ROUTED3(ViewMsg_ResolveTapDisambiguation, - base::TimeTicks /* timestamp */, - gfx::Point /* tap_viewport_offset */, - bool /* is_long_press */) - IPC_MESSAGE_ROUTED0(ViewMsg_SelectWordAroundCaret) // Sent by the browser to ask the renderer to redraw. Robust to events that can @@ -669,13 +658,6 @@ // ViewHostMsg_UnlockMouse). IPC_MESSAGE_ROUTED0(ViewHostMsg_UnlockMouse) -// Notifies that multiple touch targets may have been pressed, and to show -// the disambiguation popup. -IPC_MESSAGE_ROUTED3(ViewHostMsg_ShowDisambiguationPopup, - gfx::Rect, /* Border of touched targets */ - gfx::Size, /* Size of zoomed image */ - base::SharedMemoryHandle /* Bitmap pixels */) - // Message sent from renderer to the browser when the element that is focused // has been touched. A bool is passed in this message which indicates if the // node is editable.
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 632b3a0..8135b93 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -133,13 +133,11 @@ "java/src/org/chromium/content/browser/MotionEventSynthesizerImpl.java", "java/src/org/chromium/content/browser/NfcHost.java", "java/src/org/chromium/content/browser/PopupController.java", - "java/src/org/chromium/content/browser/PopupZoomer.java", "java/src/org/chromium/content/browser/RenderCoordinatesImpl.java", "java/src/org/chromium/content/browser/ScreenOrientationProviderImpl.java", "java/src/org/chromium/content/browser/SpareChildConnection.java", "java/src/org/chromium/content/browser/SpeechRecognitionImpl.java", "java/src/org/chromium/content/browser/SyntheticGestureTarget.java", - "java/src/org/chromium/content/browser/TapDisambiguator.java", "java/src/org/chromium/content/browser/TracingControllerAndroid.java", "java/src/org/chromium/content/browser/ViewEventSinkImpl.java", "java/src/org/chromium/content/browser/WindowEventObserver.java", @@ -374,7 +372,6 @@ "java/src/org/chromium/content/browser/ScreenOrientationProviderImpl.java", "java/src/org/chromium/content/browser/SpeechRecognitionImpl.java", "java/src/org/chromium/content/browser/SyntheticGestureTarget.java", - "java/src/org/chromium/content/browser/TapDisambiguator.java", "java/src/org/chromium/content/browser/TracingControllerAndroid.java", "java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java", "java/src/org/chromium/content/browser/accessibility/captioning/CaptioningController.java", @@ -459,7 +456,6 @@ "javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java", "javatests/src/org/chromium/content/browser/ContentViewLocationTest.java", "javatests/src/org/chromium/content/browser/ContentViewPointerTypeTest.java", - "javatests/src/org/chromium/content/browser/ContentViewPopupZoomerTest.java", "javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java", "javatests/src/org/chromium/content/browser/EncodeHtmlDataUriTest.java", "javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java", @@ -476,7 +472,6 @@ "javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java", "javatests/src/org/chromium/content/browser/MediaSessionTest.java", "javatests/src/org/chromium/content/browser/NavigationTest.java", - "javatests/src/org/chromium/content/browser/PopupZoomerTest.java", "javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java", "javatests/src/org/chromium/content/browser/TestsJavaScriptEvalTest.java", "javatests/src/org/chromium/content/browser/TracingControllerAndroidTest.java",
diff --git a/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png b/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png deleted file mode 100644 index bf355b1..0000000 --- a/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png +++ /dev/null Binary files differ
diff --git a/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png b/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png deleted file mode 100644 index dec3281..0000000 --- a/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png +++ /dev/null Binary files differ
diff --git a/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png b/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png deleted file mode 100644 index 4a5079bc..0000000 --- a/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png +++ /dev/null Binary files differ
diff --git a/content/public/android/java/res/values/dimens.xml b/content/public/android/java/res/values/dimens.xml index f86b30d3..ad91cdf7 100644 --- a/content/public/android/java/res/values/dimens.xml +++ b/content/public/android/java/res/values/dimens.xml
@@ -7,7 +7,6 @@ <resources> <!-- Link Preview dimensions --> - <dimen name="link_preview_overlay_radius">7dp</dimen> <dimen name="text_edit_suggestion_item_layout_height">48dp</dimen> <dimen name="text_suggestion_popup_elevation">2dp</dimen> <dimen name="text_suggestion_popup_vertical_margin">20dp</dimen>
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java b/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java index fed9ec2b..5886047 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java
@@ -111,11 +111,6 @@ @CalledByNative private boolean onKeyUp(int keyCode, KeyEvent event) { - TapDisambiguator tapDisambiguator = TapDisambiguator.fromWebContents(mWebContents); - if (tapDisambiguator.isShowing() && keyCode == KeyEvent.KEYCODE_BACK) { - tapDisambiguator.backButtonPressed(); - return true; - } return mEventDelegate.super_onKeyUp(keyCode, event); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java index 38339bac..9538d032 100644 --- a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
@@ -274,9 +274,6 @@ return true; } - TapDisambiguator tapDisambiguator = TapDisambiguator.fromWebContents(mWebContents); - if (!tapDisambiguator.isShowing()) tapDisambiguator.setLastTouch(x, y); - return false; } @@ -298,17 +295,12 @@ contentHeight = Math.max( contentHeight, containerView.getHeight() / (deviceScale * pageScaleFactor)); - final boolean contentSizeChanged = contentWidth != rc.getContentWidthCss() - || contentHeight != rc.getContentHeightCss(); final boolean scaleLimitsChanged = minPageScaleFactor != rc.getMinPageScaleFactor() || maxPageScaleFactor != rc.getMaxPageScaleFactor(); final boolean pageScaleChanged = pageScaleFactor != rc.getPageScaleFactor(); final boolean scrollChanged = pageScaleChanged || scrollOffsetX != rc.getScrollX() || scrollOffsetY != rc.getScrollY(); - if (contentSizeChanged || scrollChanged) - TapDisambiguator.fromWebContents(mWebContents).hidePopup(true); - if (scrollChanged) { mScrollDelegate.onScrollChanged((int) rc.fromLocalCssToPix(scrollOffsetX), (int) rc.fromLocalCssToPix(scrollOffsetY), (int) rc.getScrollXPix(),
diff --git a/content/public/android/java/src/org/chromium/content/browser/PopupZoomer.java b/content/public/android/java/src/org/chromium/content/browser/PopupZoomer.java deleted file mode 100644 index 7270ccf..0000000 --- a/content/public/android/java/src/org/chromium/content/browser/PopupZoomer.java +++ /dev/null
@@ -1,598 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.content.browser; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Path.Direction; -import android.graphics.PointF; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Region.Op; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.os.SystemClock; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.Interpolator; -import android.view.animation.OvershootInterpolator; - -import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.Log; -import org.chromium.base.VisibleForTesting; -import org.chromium.base.metrics.RecordHistogram; -import org.chromium.content.R; - -/** - * {@link View} class that implements tap disambiguation UI. - */ -public class PopupZoomer extends View { - private static final String TAG = "cr.PopupZoomer"; - - // The padding between the edges of the view and the popup. Note that there is a mirror - // constant in content/renderer/render_view_impl.cc which should be kept in sync if - // this is changed. - private static final int ZOOM_BOUNDS_MARGIN = 25; - // Time it takes for the animation to finish in ms. - private static final long ANIMATION_DURATION = 300; - - // Note that these values should be cross-checked against - // tools/metrics/histograms/histograms.xml. Values should only be appended, - // not changed or removed. - private static final String UMA_TAPDISAMBIGUATION = "Touchscreen.TapDisambiguation"; - private static final int UMA_TAPDISAMBIGUATION_OTHER = 0; - private static final int UMA_TAPDISAMBIGUATION_BACKBUTTON = 1; - private static final int UMA_TAPDISAMBIGUATION_TAPPEDOUTSIDE = 2; - private static final int UMA_TAPDISAMBIGUATION_TAPPEDINSIDE_DEPRECATED = 3; - private static final int UMA_TAPDISAMBIGUATION_TAPPEDINSIDE_SAMENODE = 4; - private static final int UMA_TAPDISAMBIGUATION_TAPPEDINSIDE_DIFFERENTNODE = 5; - private static final int UMA_TAPDISAMBIGUATION_COUNT = 6; - - private void recordHistogram(int value) { - RecordHistogram.recordEnumeratedHistogram( - UMA_TAPDISAMBIGUATION, value, UMA_TAPDISAMBIGUATION_COUNT); - } - - /** - * Interface to be implemented to listen for touch events inside the zoomed area. - */ - public static interface OnTapListener { - public void onResolveTapDisambiguation(long timeMs, float x, float y, boolean isLongPress); - } - - private final OnTapListener mOnTapListener; - - /** - * Interface to be implemented to add and remove PopupZoomer to/from the view hierarchy. - */ - public static interface OnVisibilityChangedListener { - public void onPopupZoomerShown(PopupZoomer zoomer); - public void onPopupZoomerHidden(PopupZoomer zoomer); - } - - private final OnVisibilityChangedListener mOnVisibilityChangedListener; - - // Cached drawable used to frame the zooming popup. - // TODO(tonyg): This should be marked purgeable so that if the system wants to recover this - // memory, we can just reload it from the resource ID next time it is needed. - // See android.graphics.BitmapFactory.Options#inPurgeable - private static Drawable sOverlayDrawable; - // The padding used for drawing the overlay around the content, instead of directly above it. - private static Rect sOverlayPadding; - // The radius of the overlay bubble, used for rounding the bitmap to draw underneath it. - private static float sOverlayCornerRadius; - - private final Interpolator mShowInterpolator = new OvershootInterpolator(); - private final Interpolator mHideInterpolator = new ReverseInterpolator(mShowInterpolator); - - private boolean mAnimating; - private boolean mShowing; - private long mAnimationStartTime; - - // The time that was left for the outwards animation to finish. - // This is used in the case that the zoomer is cancelled while it is still animating outwards, - // to avoid having it jump to full size then animate closed. - private long mTimeLeft; - - // initDimensions() needs to be called in onDraw(). - private boolean mNeedsToInitDimensions; - - // Available view area after accounting for ZOOM_BOUNDS_MARGIN. - private RectF mViewClipRect; - - // The target rect to be zoomed. - private Rect mTargetBounds; - - // The bitmap to hold the zoomed view. - private Bitmap mZoomedBitmap; - - // How far to shift the canvas after all zooming is done, to keep it inside the bounds of the - // view (including margin). - private float mShiftX, mShiftY; - // The magnification factor of the popup. It is recomputed once we have mTargetBounds and - // mZoomedBitmap. - private float mScale = 1.0f; - // The bounds representing the actual zoomed popup. - private RectF mClipRect; - // The extrusion values are how far the zoomed area (mClipRect) extends from the touch point. - // These values to used to animate the popup. - private float mLeftExtrusion, mTopExtrusion, mRightExtrusion, mBottomExtrusion; - // The last touch point, where the animation will start from. - private final PointF mTouch = new PointF(); - - // Since we sometimes overflow the bounds of the mViewClipRect, we need to allow scrolling. - // Current scroll position. - private float mPopupScrollX, mPopupScrollY; - // Scroll bounds. - private float mMinScrollX, mMaxScrollX; - private float mMinScrollY, mMaxScrollY; - - private final GestureDetector mGestureDetector; - - // These bounds are computed and valid for one execution of onDraw. - // Extracted to a member variable to save unnecessary allocations on each invocation. - private RectF mDrawRect; - - private static float getOverlayCornerRadius(Context context) { - if (sOverlayCornerRadius == 0) { - try { - sOverlayCornerRadius = context.getResources().getDimension( - R.dimen.link_preview_overlay_radius); - } catch (Resources.NotFoundException e) { - Log.w(TAG, "No corner radius resource for PopupZoomer overlay found."); - sOverlayCornerRadius = 1.0f; - } - } - return sOverlayCornerRadius; - } - - /** - * Gets the drawable that should be used to frame the zooming popup, loading - * it from the resource bundle if not already cached. - */ - private static Drawable getOverlayDrawable(Context context) { - if (sOverlayDrawable == null) { - try { - sOverlayDrawable = ApiCompatibilityUtils.getDrawable(context.getResources(), - R.drawable.ondemand_overlay); - } catch (Resources.NotFoundException e) { - Log.w(TAG, "No drawable resource for PopupZoomer overlay found."); - sOverlayDrawable = new ColorDrawable(); - } - sOverlayPadding = new Rect(); - sOverlayDrawable.getPadding(sOverlayPadding); - } - return sOverlayDrawable; - } - - private static float constrain(float amount, float low, float high) { - return amount < low ? low : (amount > high ? high : amount); - } - - private static int constrain(int amount, int low, int high) { - return amount < low ? low : (amount > high ? high : amount); - } - - /** - * Creates Popupzoomer. - * @param context Context to be used. - * @param containerView view that popup zoomer gets added to. - * @param visibilityListener {@link OnVisibilityChangedListener} listener. - * @param tapListener {@link OnTapListener} listener. - */ - public PopupZoomer(Context context, ViewGroup containerView, - OnVisibilityChangedListener visibilityListener, OnTapListener tapListener) { - super(context); - - mOnVisibilityChangedListener = visibilityListener; - mOnTapListener = tapListener; - - setVisibility(INVISIBLE); - setFocusable(true); - setFocusableInTouchMode(true); - - GestureDetector.SimpleOnGestureListener listener = - new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { - if (mAnimating) return true; - - if (isTouchOutsideArea(e1.getX(), e1.getY())) { - tappedOutside(); - } else { - scroll(distanceX, distanceY); - } - return true; - } - - @Override - public boolean onSingleTapUp(MotionEvent e) { - return handleTapOrPress(e, false); - } - - @Override - public void onLongPress(MotionEvent e) { - handleTapOrPress(e, true); - } - - private boolean handleTapOrPress(MotionEvent e, boolean isLongPress) { - if (mAnimating) return true; - - float x = e.getX(); - float y = e.getY(); - if (isTouchOutsideArea(x, y)) { - tappedOutside(); - } else if (mOnTapListener != null) { - PointF converted = convertTouchPoint(x, y); - mOnTapListener.onResolveTapDisambiguation( - e.getEventTime(), converted.x, converted.y, isLongPress); - tappedInside(); - } - return true; - } - }; - mGestureDetector = new GestureDetector(context, listener); - } - - /** - * Sets the bitmap to be used for the zoomed view. - */ - @VisibleForTesting - void setBitmap(Bitmap bitmap) { - if (mZoomedBitmap != null) { - mZoomedBitmap.recycle(); - mZoomedBitmap = null; - } - mZoomedBitmap = bitmap; - - // Round the corners of the bitmap so it doesn't stick out around the overlay. - Canvas canvas = new Canvas(mZoomedBitmap); - Path path = new Path(); - RectF canvasRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight()); - float overlayCornerRadius = getOverlayCornerRadius(getContext()); - path.addRoundRect(canvasRect, overlayCornerRadius, overlayCornerRadius, Direction.CCW); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - canvas.clipOutPath(path); - } else { - canvas.clipPath(path, Op.DIFFERENCE); - } - Paint clearPaint = new Paint(); - clearPaint.setXfermode(new PorterDuffXfermode(Mode.SRC)); - clearPaint.setColor(Color.TRANSPARENT); - canvas.drawPaint(clearPaint); - } - - private void scroll(float x, float y) { - mPopupScrollX = constrain(mPopupScrollX - x, mMinScrollX, mMaxScrollX); - mPopupScrollY = constrain(mPopupScrollY - y, mMinScrollY, mMaxScrollY); - invalidate(); - } - - private void startAnimation(boolean show) { - mAnimating = true; - mShowing = show; - mTimeLeft = 0; - if (show) { - setVisibility(VISIBLE); - mNeedsToInitDimensions = true; - if (mOnVisibilityChangedListener != null) { - mOnVisibilityChangedListener.onPopupZoomerShown(this); - } - } else { - long endTime = mAnimationStartTime + ANIMATION_DURATION; - mTimeLeft = endTime - SystemClock.uptimeMillis(); - if (mTimeLeft < 0) mTimeLeft = 0; - } - mAnimationStartTime = SystemClock.uptimeMillis(); - invalidate(); - } - - private void hideImmediately() { - mAnimating = false; - mShowing = false; - mTimeLeft = 0; - if (mOnVisibilityChangedListener != null) { - mOnVisibilityChangedListener.onPopupZoomerHidden(this); - } - setVisibility(INVISIBLE); - mZoomedBitmap.recycle(); - mZoomedBitmap = null; - } - - /** - * Returns true if the view is currently being shown (or is animating). - */ - public boolean isShowing() { - return mShowing || mAnimating; - } - - /** - * Sets the last touch point (on the unzoomed view). - */ - public void setLastTouch(float x, float y) { - mTouch.x = x; - mTouch.y = y; - } - - private void setTargetBounds(Rect rect) { - mTargetBounds = rect; - } - - private void initDimensions() { - if (mTargetBounds == null || mTouch == null) return; - - // Compute the final zoom scale. - mScale = (float) mZoomedBitmap.getWidth() / mTargetBounds.width(); - - float l = mTouch.x - mScale * (mTouch.x - mTargetBounds.left); - float t = mTouch.y - mScale * (mTouch.y - mTargetBounds.top); - float r = l + mZoomedBitmap.getWidth(); - float b = t + mZoomedBitmap.getHeight(); - mClipRect = new RectF(l, t, r, b); - int width = getWidth(); - int height = getHeight(); - - mViewClipRect = new RectF(ZOOM_BOUNDS_MARGIN, - ZOOM_BOUNDS_MARGIN, - width - ZOOM_BOUNDS_MARGIN, - height - ZOOM_BOUNDS_MARGIN); - - // Ensure it stays inside the bounds of the view. First shift it around to see if it - // can fully fit in the view, then clip it to the padding section of the view to - // ensure no overflow. - mShiftX = 0; - mShiftY = 0; - - // Right now this has the happy coincidence of showing the leftmost portion - // of a scaled up bitmap, which usually has the text in it. When we want to support - // RTL languages, we can conditionally switch the order of this check to push it - // to the left instead of right. - if (mClipRect.left < ZOOM_BOUNDS_MARGIN) { - mShiftX = ZOOM_BOUNDS_MARGIN - mClipRect.left; - mClipRect.left += mShiftX; - mClipRect.right += mShiftX; - } else if (mClipRect.right > width - ZOOM_BOUNDS_MARGIN) { - mShiftX = (width - ZOOM_BOUNDS_MARGIN - mClipRect.right); - mClipRect.right += mShiftX; - mClipRect.left += mShiftX; - } - if (mClipRect.top < ZOOM_BOUNDS_MARGIN) { - mShiftY = ZOOM_BOUNDS_MARGIN - mClipRect.top; - mClipRect.top += mShiftY; - mClipRect.bottom += mShiftY; - } else if (mClipRect.bottom > height - ZOOM_BOUNDS_MARGIN) { - mShiftY = height - ZOOM_BOUNDS_MARGIN - mClipRect.bottom; - mClipRect.bottom += mShiftY; - mClipRect.top += mShiftY; - } - - // Allow enough scrolling to get to the entire bitmap that may be clipped inside the - // bounds of the view. - mMinScrollX = mMaxScrollX = mMinScrollY = mMaxScrollY = 0; - if (mViewClipRect.right + mShiftX < mClipRect.right) { - mMinScrollX = mViewClipRect.right - mClipRect.right; - } - if (mViewClipRect.left + mShiftX > mClipRect.left) { - mMaxScrollX = mViewClipRect.left - mClipRect.left; - } - if (mViewClipRect.top + mShiftY > mClipRect.top) { - mMaxScrollY = mViewClipRect.top - mClipRect.top; - } - if (mViewClipRect.bottom + mShiftY < mClipRect.bottom) { - mMinScrollY = mViewClipRect.bottom - mClipRect.bottom; - } - // Now that we know how much we need to scroll, we can intersect with mViewClipRect. - mClipRect.intersect(mViewClipRect); - - mLeftExtrusion = mTouch.x - mClipRect.left; - mRightExtrusion = mClipRect.right - mTouch.x; - mTopExtrusion = mTouch.y - mClipRect.top; - mBottomExtrusion = mClipRect.bottom - mTouch.y; - - // Set an initial scroll position to take touch point into account. - float percentX = - (mTouch.x - mTargetBounds.centerX()) / (mTargetBounds.width() / 2.f) + .5f; - float percentY = - (mTouch.y - mTargetBounds.centerY()) / (mTargetBounds.height() / 2.f) + .5f; - - float scrollWidth = mMaxScrollX - mMinScrollX; - float scrollHeight = mMaxScrollY - mMinScrollY; - mPopupScrollX = scrollWidth * percentX * -1f; - mPopupScrollY = scrollHeight * percentY * -1f; - // Constrain initial scroll position within allowed bounds. - mPopupScrollX = constrain(mPopupScrollX, mMinScrollX, mMaxScrollX); - mPopupScrollY = constrain(mPopupScrollY, mMinScrollY, mMaxScrollY); - - // Compute the bounds in onDraw() - mDrawRect = new RectF(); - } - - /* - * Tests override it as the PopupZoomer is never attached to the view hierarchy. - */ - protected boolean acceptZeroSizeView() { - return false; - } - - @Override - protected void onDraw(Canvas canvas) { - if (!isShowing() || mZoomedBitmap == null) return; - if (!acceptZeroSizeView() && (getWidth() == 0 || getHeight() == 0)) return; - - if (mNeedsToInitDimensions) { - mNeedsToInitDimensions = false; - initDimensions(); - } - - canvas.save(); - // Calculate the elapsed fraction of animation. - float time = (SystemClock.uptimeMillis() - mAnimationStartTime + mTimeLeft) - / ((float) ANIMATION_DURATION); - time = constrain(time, 0, 1); - if (time >= 1) { - mAnimating = false; - if (!isShowing()) { - hideImmediately(); - return; - } - } else { - invalidate(); - } - - // Fraction of the animation to actally show. - float fractionAnimation; - if (mShowing) { - fractionAnimation = mShowInterpolator.getInterpolation(time); - } else { - fractionAnimation = mHideInterpolator.getInterpolation(time); - } - - // Draw a faded color over the entire view to fade out the original content, increasing - // the alpha value as fractionAnimation increases. - // TODO(nileshagrawal): We should use time here instead of fractionAnimation - // as fractionAnimaton is interpolated and can go over 1. - canvas.drawARGB((int) (80 * fractionAnimation), 0, 0, 0); - canvas.save(); - - // Since we want the content to appear directly above its counterpart we need to make - // sure that it starts out at exactly the same size as it appears in the page, - // i.e. scale grows from 1/mScale to 1. Note that extrusion values are already zoomed - // with mScale. - float scale = fractionAnimation * (mScale - 1.0f) / mScale + 1.0f / mScale; - - // Since we want the content to appear directly above its counterpart on the - // page, we need to remove the mShiftX/Y effect at the beginning of the animation. - // The unshifting decreases with the animation. - float unshiftX = -mShiftX * (1.0f - fractionAnimation) / mScale; - float unshiftY = -mShiftY * (1.0f - fractionAnimation) / mScale; - - // Compute the |mDrawRect| to show. - mDrawRect.left = mTouch.x - mLeftExtrusion * scale + unshiftX; - mDrawRect.top = mTouch.y - mTopExtrusion * scale + unshiftY; - mDrawRect.right = mTouch.x + mRightExtrusion * scale + unshiftX; - mDrawRect.bottom = mTouch.y + mBottomExtrusion * scale + unshiftY; - canvas.clipRect(mDrawRect); - - // Since the canvas transform APIs all pre-concat the transformations, this is done in - // reverse order. The canvas is first scaled up, then shifted the appropriate amount of - // pixels. - canvas.scale(scale, scale, mDrawRect.left, mDrawRect.top); - canvas.translate(mPopupScrollX, mPopupScrollY); - canvas.drawBitmap(mZoomedBitmap, mDrawRect.left, mDrawRect.top, null); - canvas.restore(); - Drawable overlayNineTile = getOverlayDrawable(getContext()); - overlayNineTile.setBounds((int) mDrawRect.left - sOverlayPadding.left, - (int) mDrawRect.top - sOverlayPadding.top, - (int) mDrawRect.right + sOverlayPadding.right, - (int) mDrawRect.bottom + sOverlayPadding.bottom); - // TODO(nileshagrawal): We should use time here instead of fractionAnimation - // as fractionAnimaton is interpolated and can go over 1. - int alpha = constrain((int) (fractionAnimation * 255), 0, 255); - overlayNineTile.setAlpha(alpha); - overlayNineTile.draw(canvas); - canvas.restore(); - } - - /** - * Show the PopupZoomer view with given target bounds. - */ - @VisibleForTesting - void show(Rect rect) { - if (mShowing || mZoomedBitmap == null) return; - - setTargetBounds(rect); - startAnimation(true); - } - - /** - * Hide the PopupZoomer view because of some external event such as focus - * change, JS-originating scroll, etc. - * @param animation true if hide with animation. - */ - public void hide(boolean animation) { - if (!mShowing) return; - recordHistogram(UMA_TAPDISAMBIGUATION_OTHER); - - if (animation) { - startAnimation(false); - } else { - hideImmediately(); - } - } - - private void tappedInside() { - if (!mShowing) return; - // Tapped-inside histogram value is recorded on the renderer side, - // not here. - - startAnimation(false); - } - - private void tappedOutside() { - if (!mShowing) return; - recordHistogram(UMA_TAPDISAMBIGUATION_TAPPEDOUTSIDE); - - startAnimation(false); - } - - public void backButtonPressed() { - if (!mShowing) return; - recordHistogram(UMA_TAPDISAMBIGUATION_BACKBUTTON); - - startAnimation(false); - } - - /** - * Converts the coordinates to a point on the original un-zoomed view. - */ - private PointF convertTouchPoint(float x, float y) { - x -= mShiftX; - y -= mShiftY; - x = mTouch.x + (x - mTouch.x - mPopupScrollX) / mScale; - y = mTouch.y + (y - mTouch.y - mPopupScrollY) / mScale; - return new PointF(x, y); - } - - /** - * Returns true if the point is inside the final drawable area for this popup zoomer. - */ - private boolean isTouchOutsideArea(float x, float y) { - return !mClipRect.contains(x, y); - } - - @SuppressLint("ClickableViewAccessibility") - @Override - public boolean onTouchEvent(MotionEvent event) { - mGestureDetector.onTouchEvent(event); - return true; - } - - private static class ReverseInterpolator implements Interpolator { - private final Interpolator mInterpolator; - - public ReverseInterpolator(Interpolator i) { - mInterpolator = i; - } - - @Override - public float getInterpolation(float input) { - input = 1.0f - input; - if (mInterpolator == null) return input; - return mInterpolator.getInterpolation(input); - } - } -}
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopup.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopup.java index 0304ece3..75ba6ac2 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopup.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopup.java
@@ -64,6 +64,13 @@ return webContents.getOrSetUserData(SelectPopup.class, UserDataFactoryLazyHolder.INSTANCE); } + @CalledByNative + private static SelectPopup create(WebContents webContents, long nativePtr) { + SelectPopup selectPopup = fromWebContents(webContents); + selectPopup.mNativeSelectPopup = nativePtr; + return selectPopup; + } + /** * Create {@link SelectPopup} instance. * @param webContents WebContents instance. @@ -74,7 +81,6 @@ assert viewDelegate != null; mContainerView = viewDelegate.getContainerView(); viewDelegate.addObserver(this); - mNativeSelectPopup = nativeInit(mWebContents); PopupController.register(mWebContents, this); WindowEventObserverManager.from(mWebContents).addObserver(this); } @@ -188,7 +194,6 @@ mPopupView = null; } - private native long nativeInit(WebContents webContents); private native void nativeSelectMenuItems( long nativeSelectPopup, long nativeSelectPopupSourceFrame, int[] indices); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java index 306a085..048edab 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -205,9 +205,6 @@ setViewAndroidDelegate(viewDelegate); setTopLevelNativeWindow(windowAndroid); - // Internally registers the handler that controls showing <select> HTML elements. - SelectPopup.fromWebContents(this); - ViewEventSinkImpl.from(this).setAccessDelegate(accessDelegate); getRenderCoordinates().setDeviceScaleFactor(windowAndroid.getDisplay().getDipScale()); }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewPopupZoomerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewPopupZoomerTest.java deleted file mode 100644 index 9c155e82..0000000 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewPopupZoomerTest.java +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.content.browser; - -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.MediumTest; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.RetryOnFailure; -import org.chromium.base.test.util.UrlUtils; -import org.chromium.content.browser.test.util.Criteria; -import org.chromium.content.browser.test.util.CriteriaHelper; -import org.chromium.content.browser.test.util.DOMUtils; -import org.chromium.content_public.browser.WebContents; -import org.chromium.content_shell_apk.ContentShellActivityTestRule; - -import java.util.concurrent.TimeoutException; - -/** - * Class which provides test coverage for Popup Zoomer. - */ -@RunWith(BaseJUnit4ClassRunner.class) -@RetryOnFailure -public class ContentViewPopupZoomerTest { - private static final String TARGET_NODE_ID = "target"; - - @Rule - public ContentShellActivityTestRule mActivityTestRule = new ContentShellActivityTestRule(); - - private static PopupZoomer findPopupZoomer(ViewGroup view) { - assert view != null; - for (int i = 0; i < view.getChildCount(); i++) { - View child = view.getChildAt(i); - if (child instanceof PopupZoomer) return (PopupZoomer) child; - } - return null; - } - - private static class PopupShowingCriteria extends Criteria { - private final ViewGroup mView; - private final boolean mShouldBeShown; - public PopupShowingCriteria(ViewGroup view, boolean shouldBeShown) { - super(shouldBeShown ? "Popup did not get shown." : "Popup shown incorrectly."); - mView = view; - mShouldBeShown = shouldBeShown; - } - @Override - public boolean isSatisfied() { - PopupZoomer popup = findPopupZoomer(mView); - boolean isVisibilitySet = popup == null ? false : popup.getVisibility() == View.VISIBLE; - return isVisibilitySet ? mShouldBeShown : !mShouldBeShown; - } - } - - private static class PopupHasNonZeroDimensionsCriteria extends Criteria { - private final ViewGroup mView; - public PopupHasNonZeroDimensionsCriteria(ViewGroup view) { - super("The zoomer popup has zero dimensions."); - mView = view; - } - @Override - public boolean isSatisfied() { - PopupZoomer popup = findPopupZoomer(mView); - if (popup == null) return false; - return popup.getWidth() != 0 && popup.getHeight() != 0; - } - } - - /** - * Creates a webpage that has a couple links next to one another with a zero-width node between - * them. Clicking on the zero-width node should trigger the popup zoomer to appear. - */ - private String generateTestUrl() { - final StringBuilder testUrl = new StringBuilder(); - testUrl.append("<html><body>"); - testUrl.append("<a href=\"javascript:void(0);\">A</a>"); - testUrl.append("<a id=\"" + TARGET_NODE_ID + "\"></a>"); - testUrl.append("<a href=\"javascript:void(0);\">Z</a>"); - testUrl.append("</body></html>"); - return UrlUtils.encodeHtmlDataUri(testUrl.toString()); - } - - public ContentViewPopupZoomerTest() { - } - - /** - * Tests that shows a zoomer popup and makes sure it has valid dimensions. - */ - @Test - @MediumTest - @Feature({"Browser"}) - public void testPopupZoomerShowsUp() throws InterruptedException, TimeoutException { - mActivityTestRule.launchContentShellWithUrl(generateTestUrl()); - mActivityTestRule.waitForActiveShellToBeDoneLoading(); - - final WebContents webContents = mActivityTestRule.getWebContents(); - final ViewGroup view = webContents.getViewAndroidDelegate().getContainerView(); - - // The popup should be hidden before the click. - CriteriaHelper.pollInstrumentationThread(new PopupShowingCriteria(view, false)); - - // Once clicked, the popup should show up. - DOMUtils.clickNode(webContents, TARGET_NODE_ID); - CriteriaHelper.pollInstrumentationThread(new PopupShowingCriteria(view, true)); - - // The shown popup should have valid dimensions eventually. - CriteriaHelper.pollInstrumentationThread(new PopupHasNonZeroDimensionsCriteria(view)); - } - - /** - * Tests Popup zoomer hides when device back key is pressed. - */ - @Test - @MediumTest - @Feature({"Browser"}) - @RetryOnFailure - public void testBackKeyDismissesPopupZoomer() throws InterruptedException, TimeoutException { - mActivityTestRule.launchContentShellWithUrl(generateTestUrl()); - mActivityTestRule.waitForActiveShellToBeDoneLoading(); - - final WebContents webContents = mActivityTestRule.getWebContents(); - final ViewGroup view = webContents.getViewAndroidDelegate().getContainerView(); - - CriteriaHelper.pollInstrumentationThread(new PopupShowingCriteria(view, false)); - DOMUtils.clickNode(webContents, TARGET_NODE_ID); - CriteriaHelper.pollInstrumentationThread(new PopupShowingCriteria(view, true)); - InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); - // When device key is pressed, popup zoomer should hide if already showing. - CriteriaHelper.pollInstrumentationThread(new PopupShowingCriteria(view, false)); - } -}
diff --git a/content/public/common/renderer_preferences.cc b/content/public/common/renderer_preferences.cc index 3e4683a..2f5c823d 100644 --- a/content/public/common/renderer_preferences.cc +++ b/content/public/common/renderer_preferences.cc
@@ -34,7 +34,6 @@ enable_encrypted_media(true), webrtc_udp_min_port(0), webrtc_udp_max_port(0), - tap_multiple_targets_strategy(TAP_MULTIPLE_TARGETS_STRATEGY_POPUP), disable_client_blocked_error_page(false), plugin_fullscreen_allowed(true) #if defined(OS_WIN)
diff --git a/content/public/common/renderer_preferences.h b/content/public/common/renderer_preferences.h index 688fc6b..0f823c50 100644 --- a/content/public/common/renderer_preferences.h +++ b/content/public/common/renderer_preferences.h
@@ -25,14 +25,6 @@ namespace content { -enum TapMultipleTargetsStrategy { - TAP_MULTIPLE_TARGETS_STRATEGY_ZOOM = 0, - TAP_MULTIPLE_TARGETS_STRATEGY_POPUP, - TAP_MULTIPLE_TARGETS_STRATEGY_NONE, - - TAP_MULTIPLE_TARGETS_STRATEGY_MAX = TAP_MULTIPLE_TARGETS_STRATEGY_NONE, -}; - struct CONTENT_EXPORT RendererPreferences { RendererPreferences(); RendererPreferences(const RendererPreferences& other); @@ -119,9 +111,6 @@ // The accept-languages of the browser, comma-separated. std::string accept_languages; - // How to handle a tap gesture touching multiple targets - TapMultipleTargetsStrategy tap_multiple_targets_strategy; - // Disables rendering default error page when client choses to block a page. // Corresponds to net::ERR_BLOCKED_BY_CLIENT. bool disable_client_blocked_error_page;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index bce0c21..02fdaef6 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -39,8 +39,6 @@ "accessibility/blink_ax_tree_source.h", "accessibility/render_accessibility_impl.cc", "accessibility/render_accessibility_impl.h", - "android/disambiguation_popup_helper.cc", - "android/disambiguation_popup_helper.h", "android/renderer_date_time_picker.cc", "android/renderer_date_time_picker.h", "android/synchronous_compositor_proxy.cc", @@ -756,6 +754,9 @@ "//third_party/webrtc/pc:rtc_pc_base", "//third_party/webrtc/rtc_base:rtc_base", "//third_party/webrtc/rtc_base:rtc_task_queue", + + # TODO(titovartem) remove dependency on WebRTC internals. + "//third_party/webrtc/rtc_base/third_party/sigslot:sigslot", "//third_party/webrtc/stats", "//third_party/webrtc/system_wrappers", "//third_party/webrtc_overrides:init_webrtc",
diff --git a/content/renderer/OWNERS b/content/renderer/OWNERS index d646d43c..63dda49 100644 --- a/content/renderer/OWNERS +++ b/content/renderer/OWNERS
@@ -1,5 +1,9 @@ haraken@chromium.org +# These are for the common case of adding or renaming files. If you're doing +# structural changes, please get a review from a reviewer in this file. +per-file BUILD.gn=* + # Mac Sandbox profiles. per-file *.sb=set noparent per-file *.sb=rsesek@chromium.org
diff --git a/content/renderer/android/disambiguation_popup_helper.cc b/content/renderer/android/disambiguation_popup_helper.cc deleted file mode 100644 index 485732f..0000000 --- a/content/renderer/android/disambiguation_popup_helper.cc +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/android/disambiguation_popup_helper.h" - -#include <stddef.h> - -#include <algorithm> - -#include "third_party/blink/public/platform/web_rect.h" -#include "ui/gfx/geometry/size_conversions.h" - -using blink::WebRect; -using blink::WebVector; - -namespace { - -// The amount of padding to add to the disambiguation popup to show -// content around the possible elements, adding some context. -const int kDisambiguationPopupPadding = 8; - -// Constants used for fitting the disambiguation popup inside the bounds of -// the view. Note that there are mirror constants in PopupZoomer.java. -const int kDisambiguationPopupBoundsMargin = 25; - -// The smallest allowable touch target used for disambiguation popup. -// This value is used to determine the minimum amount we need to scale to -// make all targets touchable. -const int kDisambiguationPopupMinimumTouchSize = 40; -const float kDisambiguationPopupMaxScale = 5.0; -const float kDisambiguationPopupMinScale = 2.0; - -// Compute the scaling factor to ensure the smallest touch candidate reaches -// a certain clickable size after zooming -float FindOptimalScaleFactor(const WebVector<WebRect>& target_rects, - float total_scale) { - DCHECK_GT(total_scale, 0.0f); - if (!target_rects.size()) { - NOTREACHED(); - return kDisambiguationPopupMinScale; - } - int smallest_target = std::min(target_rects[0].width, target_rects[0].height); - for (size_t i = 1; i < target_rects.size(); i++) { - smallest_target = std::min( - {smallest_target, target_rects[i].width, target_rects[i].height}); - } - const float smallest_target_f = std::max(smallest_target * total_scale, 1.0f); - return std::min(kDisambiguationPopupMaxScale, - std::max(kDisambiguationPopupMinScale, - kDisambiguationPopupMinimumTouchSize / - smallest_target_f)) * - total_scale; -} - -void TrimEdges(int* e1, int* e2, int max_combined) { - if (*e1 + *e2 <= max_combined) - return; - - if (std::min(*e1, *e2) * 2 >= max_combined) - *e1 = *e2 = max_combined / 2; - else if (*e1 > *e2) - *e1 = max_combined - *e2; - else - *e2 = max_combined - *e1; -} - -// Ensure the disambiguation popup fits inside the screen, -// clip the edges farthest to the touch point if needed. -gfx::Rect CropZoomArea(const gfx::Rect& zoom_rect, - const gfx::Size& viewport_size, - const gfx::Point& touch_point, - float scale) { - gfx::Size max_size = viewport_size; - max_size.Enlarge(-2 * kDisambiguationPopupBoundsMargin, - -2 * kDisambiguationPopupBoundsMargin); - max_size = gfx::ScaleToCeiledSize(max_size, 1.0 / scale); - - int left = touch_point.x() - zoom_rect.x(); - int right = zoom_rect.right() - touch_point.x(); - int top = touch_point.y() - zoom_rect.y(); - int bottom = zoom_rect.bottom() - touch_point.y(); - TrimEdges(&left, &right, max_size.width()); - TrimEdges(&top, &bottom, max_size.height()); - - return gfx::Rect(touch_point.x() - left, - touch_point.y() - top, - left + right, - top + bottom); -} - -} // namespace - -namespace content { - -// static -float DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor( - const gfx::Rect& tap_rect, - const WebVector<WebRect>& target_rects, - const gfx::Size& screen_size, - const gfx::Size& visible_content_size, - float total_scale, - gfx::Rect* zoom_rect) { - *zoom_rect = tap_rect; - for (size_t i = 0; i < target_rects.size(); i++) - zoom_rect->Union(gfx::Rect(target_rects[i])); - zoom_rect->Inset(-kDisambiguationPopupPadding, -kDisambiguationPopupPadding); - - zoom_rect->Intersect(gfx::Rect(visible_content_size)); - - float new_total_scale = - FindOptimalScaleFactor(target_rects, total_scale); - *zoom_rect = CropZoomArea( - *zoom_rect, screen_size, tap_rect.CenterPoint(), new_total_scale); - - return new_total_scale; -} - -} // namespace content
diff --git a/content/renderer/android/disambiguation_popup_helper.h b/content/renderer/android/disambiguation_popup_helper.h deleted file mode 100644 index e2824bd4..0000000 --- a/content/renderer/android/disambiguation_popup_helper.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_ANDROID_DISAMBIGUATION_POPUP_HELPER_H_ -#define CONTENT_RENDERER_ANDROID_DISAMBIGUATION_POPUP_HELPER_H_ - -#include "content/common/content_export.h" -#include "third_party/blink/public/platform/web_vector.h" - -namespace gfx { -class Rect; -class Size; -} - -namespace blink { -struct WebRect; -} - -namespace content { - -// Contains functions to calculate proper scaling factor and popup size -class DisambiguationPopupHelper { - public: - CONTENT_EXPORT static float ComputeZoomAreaAndScaleFactor( - const gfx::Rect& tap_rect, - const blink::WebVector<blink::WebRect>& target_rects, - const gfx::Size& screen_size, - const gfx::Size& visible_content_size, - float total_scale, - gfx::Rect* zoom_rect); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_ANDROID_DISAMBIGUATION_POPUP_HELPER_H_
diff --git a/content/renderer/android/disambiguation_popup_helper_unittest.cc b/content/renderer/android/disambiguation_popup_helper_unittest.cc deleted file mode 100644 index 679a8e2..0000000 --- a/content/renderer/android/disambiguation_popup_helper_unittest.cc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/android/disambiguation_popup_helper.h" - -#include <stddef.h> - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/web_rect.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/geometry/size_conversions.h" - -// these constants are copied from the implementation class -namespace { -const float kDisambiguationPopupMaxScale = 5.0; -const float kDisambiguationPopupMinScale = 2.0; -} // unnamed namespace - -namespace content { - -class DisambiguationPopupHelperUnittest : public testing::Test { - public: - DisambiguationPopupHelperUnittest() - : kScreenSize_(640, 480) - , kVisibleContentSize_(640, 480) - , kImplScale_(1) { } - protected: - const gfx::Size kScreenSize_; - const gfx::Size kVisibleContentSize_; - const float kImplScale_; -}; - -TEST_F(DisambiguationPopupHelperUnittest, ClipByViewport) { - gfx::Rect tap_rect(1000, 1000, 10, 10); - blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(1)); - target_rects[0] = gfx::Rect(-20, -20, 10, 10); - - gfx::Rect zoom_rect; - float scale = DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor( - tap_rect, target_rects, kScreenSize_, kVisibleContentSize_, kImplScale_, - &zoom_rect); - - EXPECT_TRUE(gfx::Rect(kVisibleContentSize_).Contains(zoom_rect)); - EXPECT_LE(kDisambiguationPopupMinScale, scale); - - gfx::Size scaled_size = gfx::ScaleToCeiledSize(zoom_rect.size(), scale); - EXPECT_TRUE(gfx::Rect(kScreenSize_).Contains(gfx::Rect(scaled_size))); -} - -TEST_F(DisambiguationPopupHelperUnittest, MiniTarget) { - gfx::Rect tap_rect(-5, -5, 20, 20); - blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(1)); - target_rects[0] = gfx::Rect(10, 10, 1, 1); - - gfx::Rect zoom_rect; - float scale = DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor( - tap_rect, target_rects, kScreenSize_, kVisibleContentSize_, kImplScale_, - &zoom_rect); - - EXPECT_TRUE(gfx::Rect(kVisibleContentSize_).Contains(zoom_rect)); - EXPECT_EQ(kDisambiguationPopupMaxScale, scale); - EXPECT_TRUE(zoom_rect.Contains(target_rects[0])); - - gfx::Size scaled_size = gfx::ScaleToCeiledSize(zoom_rect.size(), scale); - EXPECT_TRUE(gfx::Rect(kScreenSize_).Contains(gfx::Rect(scaled_size))); -} - -TEST_F(DisambiguationPopupHelperUnittest, LongLinks) { - gfx::Rect tap_rect(10, 10, 20, 20); - blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(2)); - target_rects[0] = gfx::Rect(15, 15, 1000, 5); - target_rects[1] = gfx::Rect(15, 25, 1000, 5); - - gfx::Rect zoom_rect; - float scale = DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor( - tap_rect, target_rects, kScreenSize_, kVisibleContentSize_, kImplScale_, - &zoom_rect); - - EXPECT_TRUE(gfx::Rect(kVisibleContentSize_).Contains(zoom_rect)); - EXPECT_EQ(kDisambiguationPopupMaxScale, scale); - EXPECT_TRUE(zoom_rect.Contains(tap_rect)); - - gfx::Size scaled_size = gfx::ScaleToCeiledSize(zoom_rect.size(), scale); - EXPECT_TRUE(gfx::Rect(kScreenSize_).Contains(gfx::Rect(scaled_size))); -} - -} // namespace content
diff --git a/content/renderer/media/webrtc/stun_field_trial.h b/content/renderer/media/webrtc/stun_field_trial.h index 24c6dfc..5843731 100644 --- a/content/renderer/media/webrtc/stun_field_trial.h +++ b/content/renderer/media/webrtc/stun_field_trial.h
@@ -18,7 +18,7 @@ #include "content/renderer/p2p/network_list_observer.h" #include "third_party/webrtc/p2p/stunprober/stunprober.h" #include "third_party/webrtc/rtc_base/network.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace rtc { class PacketSocketFactory;
diff --git a/content/renderer/p2p/empty_network_manager.h b/content/renderer/p2p/empty_network_manager.h index 1ecb6a8..35df4d1 100644 --- a/content/renderer/p2p/empty_network_manager.h +++ b/content/renderer/p2p/empty_network_manager.h
@@ -10,7 +10,7 @@ #include "base/threading/thread_checker.h" #include "content/common/content_export.h" #include "third_party/webrtc/rtc_base/network.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace rtc { class IPAddress;
diff --git a/content/renderer/p2p/filtering_network_manager.h b/content/renderer/p2p/filtering_network_manager.h index 99d5ef5..16ef60d 100644 --- a/content/renderer/p2p/filtering_network_manager.h +++ b/content/renderer/p2p/filtering_network_manager.h
@@ -12,7 +12,7 @@ #include "content/common/content_export.h" #include "content/renderer/p2p/network_manager_uma.h" #include "third_party/webrtc/rtc_base/network.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" #include "url/gurl.h" namespace media {
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index ef00a76b..f94856c7 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -542,80 +542,6 @@ } }; -#if defined(OS_ANDROID) -class TapCallbackFilter : public IPC::Listener { - public: - explicit TapCallbackFilter( - base::RepeatingCallback<void(const gfx::Rect&, const gfx::Size&)> - callback) - : callback_(callback) {} - - bool OnMessageReceived(const IPC::Message& msg) override { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(TapCallbackFilter, msg) - IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup, - OnShowDisambiguationPopup) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; - } - - void OnShowDisambiguationPopup(const gfx::Rect& rect_pixels, - const gfx::Size& size, - base::SharedMemoryHandle handle) { - callback_.Run(rect_pixels, size); - } - - private: - base::RepeatingCallback<void(const gfx::Rect&, const gfx::Size&)> callback_; -}; - -static blink::WebCoalescedInputEvent FatTap(int x, - int y, - int width, - int height) { - blink::WebGestureEvent event( - blink::WebInputEvent::kGestureTap, blink::WebInputEvent::kNoModifiers, - blink::WebInputEvent::GetStaticTimeStampForTests(), - blink::kWebGestureDeviceTouchscreen); - event.SetPositionInWidget(gfx::PointF(x, y)); - event.data.tap.width = width; - event.data.tap.height = height; - return blink::WebCoalescedInputEvent(event); -} - -TEST_F(RenderViewImplScaleFactorTest, TapDisambiguatorSize) { - // TODO(oshima): This test tried in the past to enable UseZoomForDSF but - // didn't actually do so for the compositor, and fails with it enabled. - const float device_scale = 2.625f; - SetDeviceScaleFactor(device_scale); - EXPECT_EQ(device_scale, view()->GetDeviceScaleFactor()); - - LoadHTML( - "<style type=\"text/css\">" - " a {" - " display: block;" - " width: 40px;" - " height: 40px;" - " background-color:#ccccff;" - " }" - "</style>" - "<body style=\"margin: 0px\">" - "<a href=\"#\">link </a>" - "<a href=\"#\">link </a>" - "</body>"); - std::unique_ptr<TapCallbackFilter> callback_filter( - new TapCallbackFilter(base::BindRepeating( - [](const gfx::Rect& rect_pixels, const gfx::Size& canvas_size) { - EXPECT_EQ(rect_pixels, gfx::Rect(28, 68, 24, 24)); - EXPECT_EQ(canvas_size, gfx::Size(48, 48)); - }))); - render_thread_->sink().AddFilter(callback_filter.get()); - view()->webview()->HandleInputEvent(FatTap(40, 80, 200, 200)); - render_thread_->sink().RemoveFilter(callback_filter.get()); -} -#endif - // Ensure that the main RenderFrame is deleted and cleared from the RenderView // after closing it. TEST_F(RenderViewImplTest, RenderFrameClearedAfterClose) { @@ -2563,19 +2489,8 @@ TEST_F(RenderViewImplBlinkSettingsTest, CommandLine) { base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kBlinkSettings, - "multiTargetTapNotificationEnabled=true,viewportEnabled=true"); + switches::kBlinkSettings, "viewportEnabled=true"); DoSetUp(); - EXPECT_TRUE(settings()->MultiTargetTapNotificationEnabled()); - EXPECT_TRUE(settings()->ViewportEnabled()); -} - -TEST_F(RenderViewImplBlinkSettingsTest, Negative) { - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kBlinkSettings, - "multiTargetTapNotificationEnabled=false,viewportEnabled=true"); - DoSetUp(); - EXPECT_FALSE(settings()->MultiTargetTapNotificationEnabled()); EXPECT_TRUE(settings()->ViewportEnabled()); }
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index f268c830..5583a22 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -183,7 +183,6 @@ #include "base/android/build_info.h" #include "base/memory/shared_memory.h" #include "content/child/child_thread_impl.h" -#include "content/renderer/android/disambiguation_popup_helper.h" #include "ui/gfx/geometry/rect_f.h" #elif defined(OS_MACOSX) @@ -1305,8 +1304,6 @@ OnDisableScrollbarsForSmallWindows) IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs) IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt) - IPC_MESSAGE_HANDLER(ViewMsg_ResolveTapDisambiguation, - OnResolveTapDisambiguation) IPC_MESSAGE_HANDLER(ViewMsg_SelectWordAroundCaret, OnSelectWordAroundCaret) // Page messages. @@ -2074,96 +2071,6 @@ date_time_picker_client_.reset(); } -bool RenderViewImpl::DidTapMultipleTargets( - const WebSize& inner_viewport_offset, - const WebRect& touch_rect, - const WebVector<WebRect>& target_rects) { - // Never show a disambiguation popup when accessibility is enabled, - // as this interferes with "touch exploration". - ui::AXMode accessibility_mode = GetMainRenderFrame()->accessibility_mode(); - if (accessibility_mode == ui::kAXModeComplete) - return false; - - // The touch_rect, target_rects and zoom_rect are in the outer viewport - // reference frame. - float to_pix = - IsUseZoomForDSFEnabled() ? 1 : GetWebScreenInfo().device_scale_factor; - gfx::Rect zoom_rect; - float new_total_scale = - DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor( - touch_rect, target_rects, GetSize(), - gfx::Rect(webview()->MainFrame()->VisibleContentRect()).size(), - to_pix * webview()->PageScaleFactor(), &zoom_rect); - if (!new_total_scale || zoom_rect.IsEmpty()) - return false; - - bool handled = false; - switch (renderer_preferences_.tap_multiple_targets_strategy) { - case TAP_MULTIPLE_TARGETS_STRATEGY_ZOOM: - handled = webview()->ZoomToMultipleTargetsRect(zoom_rect); - break; - case TAP_MULTIPLE_TARGETS_STRATEGY_POPUP: { - gfx::Size canvas_size = - gfx::ScaleToCeiledSize(zoom_rect.size(), new_total_scale); - - SkImageInfo info = - SkImageInfo::MakeN32Premul(canvas_size.width(), canvas_size.height()); - size_t shm_size = info.computeMinByteSize(); - - if (shm_size == 0) { - DLOG(ERROR) << "Invalid size for SharedMemory"; - return false; - } - - auto shm = ChildThreadImpl::AllocateSharedMemory(shm_size); - if (!shm || !shm->Map(shm_size)) { - DLOG(ERROR) << "SharedMemory allocate/map failed"; - return false; - } - - { - SkBitmap bitmap; - bitmap.installPixels(info, shm->memory(), info.minRowBytes()); - cc::SkiaPaintCanvas canvas(bitmap); - - // TODO(trchen): Cleanup the device scale factor mess. - // device scale will be applied in WebKit - // --> zoom_rect doesn't include device scale, - // but WebKit will still draw on zoom_rect * - // GetWebScreenInfo().device_scale_factor - canvas.scale(new_total_scale / to_pix, new_total_scale / to_pix); - canvas.translate(-zoom_rect.x() * to_pix, -zoom_rect.y() * to_pix); - - DCHECK(webview_->IsAcceleratedCompositingActive()); - webview_->UpdateAllLifecyclePhases(); - webview_->PaintContentIgnoringCompositing(&canvas, zoom_rect); - } - - gfx::Rect zoom_rect_in_screen = - zoom_rect - gfx::Vector2d(inner_viewport_offset.width, - inner_viewport_offset.height); - - gfx::Rect physical_window_zoom_rect = gfx::ToEnclosingRect( - gfx::ScaleRect(gfx::RectF(zoom_rect_in_screen), - to_pix * webview()->PageScaleFactor())); - - // A SharedMemoryHandle is sent to the browser process, which is - // responsible for freeing the shared memory when no longer needed. - Send(new ViewHostMsg_ShowDisambiguationPopup( - GetWidget()->routing_id(), physical_window_zoom_rect, canvas_size, - shm->TakeHandle())); - - handled = true; - break; - } - case TAP_MULTIPLE_TARGETS_STRATEGY_NONE: - // No-op. - break; - } - - return handled; -} - void RenderViewImpl::SuspendVideoCaptureDevices(bool suspend) { if (!main_render_frame_) return; @@ -2205,12 +2112,4 @@ } } -void RenderViewImpl::OnResolveTapDisambiguation( - base::TimeTicks timestamp, - const gfx::Point& tap_viewport_offset, - bool is_long_press) { - webview()->ResolveTapDisambiguation(timestamp, tap_viewport_offset, - is_long_press); -} - } // namespace content
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 4f6eef8..5614c1270 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -240,14 +240,6 @@ const blink::WebNode& toNode) override; bool CanUpdateLayout() override; void DidUpdateLayout() override; -#if defined(OS_ANDROID) - // |touch_rect| is in physical pixels if --use-zoom-for-dsf is enabled. - // Otherwise, it is in DIPs. - bool DidTapMultipleTargets( - const blink::WebSize& inner_viewport_offset, - const blink::WebRect& touch_rect, - const blink::WebVector<blink::WebRect>& target_rects) override; -#endif blink::WebString AcceptLanguages() override; void NavigateBackForwardSoon(int offset) override; int HistoryBackListCount() override; @@ -464,9 +456,6 @@ void OnPluginActionAt(const gfx::Point& location, const blink::WebPluginAction& action); void OnMoveOrResizeStarted(); - void OnResolveTapDisambiguation(base::TimeTicks timestamp, - const gfx::Point& tap_viewport_offset, - bool is_long_press); void OnExitFullscreen(); void OnSetHistoryOffsetAndLength(int history_offset, int history_length); void OnSetInitialFocus(bool reverse);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index e754e7e..db6d5241 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1627,7 +1627,6 @@ "../public/common/url_utils_unittest.cc", "../public/test/referrer_unittest.cc", "../public/test/test_browser_thread_bundle_unittest.cc", - "../renderer/android/disambiguation_popup_helper_unittest.cc", "../renderer/bmp_image_decoder_unittest.cc", "../renderer/categorized_worker_pool_unittest.cc", "../renderer/child_frame_compositing_helper_unittest.cc",
diff --git a/device/BUILD.gn b/device/BUILD.gn index 30667c5..31f7702 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -303,6 +303,10 @@ "bluetooth/test/fake_gatt_characteristic_winrt.h", "bluetooth/test/fake_gatt_characteristics_result_winrt.cc", "bluetooth/test/fake_gatt_characteristics_result_winrt.h", + "bluetooth/test/fake_gatt_descriptor_winrt.cc", + "bluetooth/test/fake_gatt_descriptor_winrt.h", + "bluetooth/test/fake_gatt_descriptors_result_winrt.cc", + "bluetooth/test/fake_gatt_descriptors_result_winrt.h", "bluetooth/test/fake_gatt_device_service_winrt.cc", "bluetooth/test/fake_gatt_device_service_winrt.h", "bluetooth/test/fake_gatt_device_services_result_winrt.cc",
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index 4fd41efe..2541d15 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -248,6 +248,8 @@ "bluetooth_gatt_discoverer_winrt.h", "bluetooth_remote_gatt_characteristic_winrt.cc", "bluetooth_remote_gatt_characteristic_winrt.h", + "bluetooth_remote_gatt_descriptor_winrt.cc", + "bluetooth_remote_gatt_descriptor_winrt.h", "bluetooth_remote_gatt_service_winrt.cc", "bluetooth_remote_gatt_service_winrt.h", "event_utils_winrt.h",
diff --git a/device/bluetooth/bluetooth_device_winrt.cc b/device/bluetooth/bluetooth_device_winrt.cc index 9bfe79e..e248c43 100644 --- a/device/bluetooth/bluetooth_device_winrt.cc +++ b/device/bluetooth/bluetooth_device_winrt.cc
@@ -344,6 +344,13 @@ base::BindRepeating(&BluetoothDeviceWinrt::OnConnectionStatusChanged, weak_ptr_factory_.GetWeakPtr())); + // For paired devices the OS immediately establishes a GATT connection after + // the first advertisement. In this case our handler is registered too late to + // catch the initial connection changed event, and we need to perform an + // explicit check ourselves. + if (IsGattConnected()) + DidConnectGatt(); + if (gatt_services_changed_token_) { RemoveGattServicesChangedHandler(ble_device_.Get(), *gatt_services_changed_token_);
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.cc b/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.cc new file mode 100644 index 0000000..049a71aa --- /dev/null +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.cc
@@ -0,0 +1,58 @@ +// Copyright 2018 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 "device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.h" + +#include "base/logging.h" +#include "device/bluetooth/bluetooth_uuid.h" + +namespace device { + +BluetoothRemoteGattDescriptorWinrt::BluetoothRemoteGattDescriptorWinrt() = + default; + +BluetoothRemoteGattDescriptorWinrt::~BluetoothRemoteGattDescriptorWinrt() = + default; + +std::string BluetoothRemoteGattDescriptorWinrt::GetIdentifier() const { + NOTIMPLEMENTED(); + return std::string(); +} + +BluetoothUUID BluetoothRemoteGattDescriptorWinrt::GetUUID() const { + NOTIMPLEMENTED(); + return BluetoothUUID(); +} + +BluetoothGattCharacteristic::Permissions +BluetoothRemoteGattDescriptorWinrt::GetPermissions() const { + NOTIMPLEMENTED(); + return BluetoothGattCharacteristic::Permissions(); +} + +const std::vector<uint8_t>& BluetoothRemoteGattDescriptorWinrt::GetValue() + const { + return value_; +} + +BluetoothRemoteGattCharacteristic* +BluetoothRemoteGattDescriptorWinrt::GetCharacteristic() const { + NOTIMPLEMENTED(); + return nullptr; +} + +void BluetoothRemoteGattDescriptorWinrt::ReadRemoteDescriptor( + const ValueCallback& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothRemoteGattDescriptorWinrt::WriteRemoteDescriptor( + const std::vector<uint8_t>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +} // namespace device
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.h b/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.h new file mode 100644 index 0000000..9e0fecb --- /dev/null +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.h
@@ -0,0 +1,51 @@ +// Copyright 2018 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 DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_DESCRIPTOR_WINRT_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_DESCRIPTOR_WINRT_H_ + +#include <stdint.h> + +#include <string> +#include <vector> + +#include "base/callback_forward.h" +#include "base/macros.h" +#include "device/bluetooth/bluetooth_export.h" +#include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" +#include "device/bluetooth/bluetooth_remote_gatt_descriptor.h" + +namespace device { + +class BluetoothUUID; + +class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattDescriptorWinrt + : public BluetoothRemoteGattDescriptor { + public: + BluetoothRemoteGattDescriptorWinrt(); + ~BluetoothRemoteGattDescriptorWinrt() override; + + // BluetoothGattDescriptor: + std::string GetIdentifier() const override; + BluetoothUUID GetUUID() const override; + BluetoothGattCharacteristic::Permissions GetPermissions() const override; + + // BluetoothRemoteGattDescriptor: + const std::vector<uint8_t>& GetValue() const override; + BluetoothRemoteGattCharacteristic* GetCharacteristic() const override; + void ReadRemoteDescriptor(const ValueCallback& callback, + const ErrorCallback& error_callback) override; + void WriteRemoteDescriptor(const std::vector<uint8_t>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + private: + std::vector<uint8_t> value_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattDescriptorWinrt); +}; + +} // namespace device + +#endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_DESCRIPTOR_WINRT_H_
diff --git a/device/bluetooth/test/fake_gatt_descriptor_winrt.cc b/device/bluetooth/test/fake_gatt_descriptor_winrt.cc new file mode 100644 index 0000000..25e1223 --- /dev/null +++ b/device/bluetooth/test/fake_gatt_descriptor_winrt.cc
@@ -0,0 +1,69 @@ +// Copyright 2018 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 "device/bluetooth/test/fake_gatt_descriptor_winrt.h" + +namespace device { + +namespace { + +using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode; +using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattCommunicationStatus; +using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattProtectionLevel; +using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattReadResult; +using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattWriteResult; +using ABI::Windows::Foundation::IAsyncOperation; +using ABI::Windows::Storage::Streams::IBuffer; + +} // namespace + +FakeGattDescriptorWinrt::FakeGattDescriptorWinrt() = default; + +FakeGattDescriptorWinrt::~FakeGattDescriptorWinrt() = default; + +HRESULT FakeGattDescriptorWinrt::get_ProtectionLevel( + GattProtectionLevel* value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorWinrt::put_ProtectionLevel( + GattProtectionLevel value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorWinrt::get_Uuid(GUID* value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorWinrt::get_AttributeHandle(uint16_t* value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorWinrt::ReadValueAsync( + IAsyncOperation<GattReadResult*>** value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorWinrt::ReadValueWithCacheModeAsync( + BluetoothCacheMode cache_mode, + IAsyncOperation<GattReadResult*>** value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorWinrt::WriteValueAsync( + IBuffer* value, + IAsyncOperation<GattCommunicationStatus>** async_op) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorWinrt::WriteValueWithResultAsync( + IBuffer* value, + IAsyncOperation<GattWriteResult*>** operation) { + return E_NOTIMPL; +} + +} // namespace device
diff --git a/device/bluetooth/test/fake_gatt_descriptor_winrt.h b/device/bluetooth/test/fake_gatt_descriptor_winrt.h new file mode 100644 index 0000000..8cd7185b --- /dev/null +++ b/device/bluetooth/test/fake_gatt_descriptor_winrt.h
@@ -0,0 +1,66 @@ +// Copyright 2018 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 DEVICE_BLUETOOTH_TEST_FAKE_GATT_DESCRIPTOR_WINRT_H_ +#define DEVICE_BLUETOOTH_TEST_FAKE_GATT_DESCRIPTOR_WINRT_H_ + +#include <windows.devices.bluetooth.genericattributeprofile.h> +#include <wrl/implements.h> + +#include <stdint.h> + +#include "base/macros.h" + +namespace device { + +class FakeGattDescriptorWinrt + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags< + Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>, + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + IGattDescriptor, + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + IGattDescriptor2> { + public: + FakeGattDescriptorWinrt(); + ~FakeGattDescriptorWinrt() override; + + // IGattDescriptor: + IFACEMETHODIMP get_ProtectionLevel( + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattProtectionLevel* value) override; + IFACEMETHODIMP put_ProtectionLevel( + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattProtectionLevel value) override; + IFACEMETHODIMP get_Uuid(GUID* value) override; + IFACEMETHODIMP get_AttributeHandle(uint16_t* value) override; + IFACEMETHODIMP ReadValueAsync( + ABI::Windows::Foundation::IAsyncOperation< + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattReadResult*>** value) override; + IFACEMETHODIMP ReadValueWithCacheModeAsync( + ABI::Windows::Devices::Bluetooth::BluetoothCacheMode cache_mode, + ABI::Windows::Foundation::IAsyncOperation< + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattReadResult*>** value) override; + IFACEMETHODIMP WriteValueAsync( + ABI::Windows::Storage::Streams::IBuffer* value, + ABI::Windows::Foundation::IAsyncOperation< + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattCommunicationStatus>** action) override; + + // IGattDescriptor2: + IFACEMETHODIMP WriteValueWithResultAsync( + ABI::Windows::Storage::Streams::IBuffer* value, + ABI::Windows::Foundation::IAsyncOperation< + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattWriteResult*>** operation) override; + + private: + DISALLOW_COPY_AND_ASSIGN(FakeGattDescriptorWinrt); +}; + +} // namespace device + +#endif // DEVICE_BLUETOOTH_TEST_FAKE_GATT_DESCRIPTOR_WINRT_H_
diff --git a/device/bluetooth/test/fake_gatt_descriptors_result_winrt.cc b/device/bluetooth/test/fake_gatt_descriptors_result_winrt.cc new file mode 100644 index 0000000..e8cbb0d5 --- /dev/null +++ b/device/bluetooth/test/fake_gatt_descriptors_result_winrt.cc
@@ -0,0 +1,38 @@ +// Copyright 2018 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 "device/bluetooth/test/fake_gatt_descriptors_result_winrt.h" + +namespace device { + +namespace { + +using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattCommunicationStatus; +using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDescriptor; +using ABI::Windows::Foundation::Collections::IVectorView; +using ABI::Windows::Foundation::IReference; + +} // namespace + +FakeGattDescriptorsResultWinrt::FakeGattDescriptorsResultWinrt() = default; + +FakeGattDescriptorsResultWinrt::~FakeGattDescriptorsResultWinrt() = default; + +HRESULT FakeGattDescriptorsResultWinrt::get_Status( + GattCommunicationStatus* value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorsResultWinrt::get_ProtocolError( + IReference<uint8_t>** value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorsResultWinrt::get_Descriptors( + IVectorView<GattDescriptor*>** value) { + return E_NOTIMPL; +} + +} // namespace device
diff --git a/device/bluetooth/test/fake_gatt_descriptors_result_winrt.h b/device/bluetooth/test/fake_gatt_descriptors_result_winrt.h new file mode 100644 index 0000000..0ec624ff --- /dev/null +++ b/device/bluetooth/test/fake_gatt_descriptors_result_winrt.h
@@ -0,0 +1,46 @@ +// Copyright 2018 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 DEVICE_BLUETOOTH_TEST_FAKE_GATT_DESCRIPTORS_RESULT_WINRT_H_ +#define DEVICE_BLUETOOTH_TEST_FAKE_GATT_DESCRIPTORS_RESULT_WINRT_H_ + +#include <windows.devices.bluetooth.genericattributeprofile.h> +#include <windows.foundation.collections.h> +#include <windows.foundation.h> +#include <wrl/implements.h> + +#include <stdint.h> + +#include "base/macros.h" + +namespace device { + +class FakeGattDescriptorsResultWinrt + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags< + Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>, + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + IGattDescriptorsResult> { + public: + FakeGattDescriptorsResultWinrt(); + ~FakeGattDescriptorsResultWinrt() override; + + // IGattDescriptorsResult: + IFACEMETHODIMP get_Status( + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattCommunicationStatus* value) override; + IFACEMETHODIMP get_ProtocolError( + ABI::Windows::Foundation::IReference<uint8_t>** value) override; + IFACEMETHODIMP get_Descriptors( + ABI::Windows::Foundation::Collections::IVectorView< + ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattDescriptor*>** value) override; + + private: + DISALLOW_COPY_AND_ASSIGN(FakeGattDescriptorsResultWinrt); +}; + +} // namespace device + +#endif // DEVICE_BLUETOOTH_TEST_FAKE_GATT_DESCRIPTORS_RESULT_WINRT_H_
diff --git a/docs/android_build_instructions.md b/docs/android_build_instructions.md index e5de463..71eee04 100644 --- a/docs/android_build_instructions.md +++ b/docs/android_build_instructions.md
@@ -228,6 +228,19 @@ Which prints a list of connected devices. If not connected, try unplugging and reattaching your device. +### Enable apps from unknown sources + +Allow Android to run APKs that haven't been signed through the Play Store: + +* Enable 'Unknown sources' under Settings \> Security + +In case that setting isn't present, it may be possible to configure it via +`adb shell` instead: + +```shell +third_party/android_tools/sdk/platform-tools/adb shell settings put global verifier_verify_adb_installs 0 +``` + ### Build the full browser ```shell
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index f142a31e..7c2d281 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -648,6 +648,9 @@ event->event_args.get(), event->user_gesture, event->filter_info); + for (TestObserver& observer : test_observers_) + observer.OnDidDispatchEventToProcess(*event); + // TODO(lazyboy): This is wrong for extensions SW events. We need to: // 1. Increment worker ref count // 2. Add EventAck IPC to decrement that ref count.
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h index 387d99f4..a0294ba4 100644 --- a/extensions/browser/event_router.h +++ b/extensions/browser/event_router.h
@@ -88,6 +88,7 @@ public: virtual ~TestObserver() = default; virtual void OnWillDispatchEvent(const Event& event) = 0; + virtual void OnDidDispatchEventToProcess(const Event& event) = 0; }; // Gets the EventRouter for |browser_context|.
diff --git a/extensions/browser/test_event_router_observer.cc b/extensions/browser/test_event_router_observer.cc index b7f623eb..0837566c 100644 --- a/extensions/browser/test_event_router_observer.cc +++ b/extensions/browser/test_event_router_observer.cc
@@ -21,6 +21,7 @@ void TestEventRouterObserver::ClearEvents() { events_.clear(); + dispatched_events_.clear(); } void TestEventRouterObserver::OnWillDispatchEvent(const Event& event) { @@ -28,4 +29,9 @@ events_[event.event_name] = base::WrapUnique(event.DeepCopy()); } +void TestEventRouterObserver::OnDidDispatchEventToProcess(const Event& event) { + DCHECK(!event.event_name.empty()); + dispatched_events_[event.event_name] = base::WrapUnique(event.DeepCopy()); +} + } // namespace extensions
diff --git a/extensions/browser/test_event_router_observer.h b/extensions/browser/test_event_router_observer.h index 19926835..7ccd595 100644 --- a/extensions/browser/test_event_router_observer.h +++ b/extensions/browser/test_event_router_observer.h
@@ -24,12 +24,15 @@ void ClearEvents(); const EventMap& events() { return events_; } + const EventMap& dispatched_events() { return dispatched_events_; } private: // EventRouter::TestObserver: void OnWillDispatchEvent(const Event& event) override; + void OnDidDispatchEventToProcess(const Event& event) override; EventMap events_; + EventMap dispatched_events_; EventRouter* event_router_; DISALLOW_COPY_AND_ASSIGN(TestEventRouterObserver);
diff --git a/google_apis/gaia/oauth2_token_service.h b/google_apis/gaia/oauth2_token_service.h index c1c31929..1d4aab8 100644 --- a/google_apis/gaia/oauth2_token_service.h +++ b/google_apis/gaia/oauth2_token_service.h
@@ -284,11 +284,13 @@ // used to request the tokens. void ClearCacheForAccount(const std::string& account_id); - // Cancels all requests that are currently in progress. - void CancelAllRequests(); + // Cancels all requests that are currently in progress. Virtual so it can be + // overridden for tests. + virtual void CancelAllRequests(); - // Cancels all requests related to a given |account_id|. - void CancelRequestsForAccount(const std::string& account_id); + // Cancels all requests related to a given |account_id|. Virtual so it can be + // overridden for tests. + virtual void CancelRequestsForAccount(const std::string& account_id); // Fetches an OAuth token for the specified client/scopes. Virtual so it can // be overridden for tests and for platform-specific behavior.
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index e08f169..714a1d6 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -267,6 +267,7 @@ #define glIsVertexArrayOES GLES2_GET_FUN(IsVertexArrayOES) #define glBindVertexArrayOES GLES2_GET_FUN(BindVertexArrayOES) #define glFramebufferParameteri GLES2_GET_FUN(FramebufferParameteri) +#define glBindImageTexture GLES2_GET_FUN(BindImageTexture) #define glDispatchCompute GLES2_GET_FUN(DispatchCompute) #define glSwapBuffers GLES2_GET_FUN(SwapBuffers) #define glGetMaxValueInBufferCHROMIUM GLES2_GET_FUN(GetMaxValueInBufferCHROMIUM)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index c3335a3e..a64c3ac1 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1806,6 +1806,13 @@ 'gen_func': 'GenFramebuffersEXT', 'trace_level': 1, }, + 'BindImageTexture':{ + 'cmd_args': 'GLuint unit, GLuint texture, GLint level, GLboolean layered, ' + 'GLint layer, GLenum access, GLenum format', + 'unit_test': False, + 'trace_level': 2, + 'es31': True, + }, 'BindRenderbuffer': { 'type': 'Bind', 'decoder_func': 'DoBindRenderbuffer',
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index ad2a5fcc..0fbd05b 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1213,6 +1213,16 @@ GLint param) { gles2::GetGLContext()->FramebufferParameteri(target, pname, param); } +void GL_APIENTRY GLES2BindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) { + gles2::GetGLContext()->BindImageTexture(unit, texture, level, layered, layer, + access, format); +} void GL_APIENTRY GLES2DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) { @@ -2741,6 +2751,10 @@ reinterpret_cast<GLES2FunctionPointer>(glFramebufferParameteri), }, { + "glBindImageTexture", + reinterpret_cast<GLES2FunctionPointer>(glBindImageTexture), + }, + { "glDispatchCompute", reinterpret_cast<GLES2FunctionPointer>(glDispatchCompute), },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index ec080df..ee2c9899 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2370,6 +2370,20 @@ } } +void BindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) { + gles2::cmds::BindImageTexture* c = + GetCmdSpace<gles2::cmds::BindImageTexture>(); + if (c) { + c->Init(unit, texture, level, layered, layer, access, format); + } +} + void DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) {
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 74f3f996..19fe921 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -847,6 +847,14 @@ void FramebufferParameteri(GLenum target, GLenum pname, GLint param) override; +void BindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) override; + void DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) override;
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 284e0b2..41a8477 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -3038,6 +3038,24 @@ CheckGLError(); } +void GLES2Implementation::BindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindImageTexture(" << unit + << ", " << texture << ", " << level << ", " + << GLES2Util::GetStringBool(layered) << ", " << layer + << ", " << GLES2Util::GetStringEnum(access) << ", " + << GLES2Util::GetStringEnum(format) << ")"); + helper_->BindImageTexture(unit, texture, level, layered, layer, access, + format); + CheckGLError(); +} + void GLES2Implementation::DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) {
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 99a7913..66ec1bd8 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -2690,6 +2690,17 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, BindImageTexture) { + struct Cmds { + cmds::BindImageTexture cmd; + }; + Cmds expected; + expected.cmd.Init(1, 2, 3, true, 5, 6, 7); + + gl_->BindImageTexture(1, 2, 3, true, 5, 6, 7); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, DispatchCompute) { struct Cmds { cmds::DispatchCompute cmd;
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index ddae5af..4b1cb655 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -620,6 +620,13 @@ virtual void FramebufferParameteri(GLenum target, GLenum pname, GLint param) = 0; +virtual void BindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) = 0; virtual void DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) = 0;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 857859f..60dec34 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -597,6 +597,13 @@ GLboolean IsVertexArrayOES(GLuint array) override; void BindVertexArrayOES(GLuint array) override; void FramebufferParameteri(GLenum target, GLenum pname, GLint param) override; +void BindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) override; void DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) override;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 1795549..17865d76 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -820,6 +820,13 @@ void GLES2InterfaceStub::FramebufferParameteri(GLenum /* target */, GLenum /* pname */, GLint /* param */) {} +void GLES2InterfaceStub::BindImageTexture(GLuint /* unit */, + GLuint /* texture */, + GLint /* level */, + GLboolean /* layered */, + GLint /* layer */, + GLenum /* access */, + GLenum /* format */) {} void GLES2InterfaceStub::DispatchCompute(GLuint /* num_groups_x */, GLuint /* num_groups_y */, GLuint /* num_groups_z */) {}
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 506b208..e61cdd1 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -597,6 +597,13 @@ GLboolean IsVertexArrayOES(GLuint array) override; void BindVertexArrayOES(GLuint array) override; void FramebufferParameteri(GLenum target, GLenum pname, GLint param) override; +void BindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) override; void DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) override;
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index d87e56e..3ce147b 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -1770,6 +1770,17 @@ gl_->FramebufferParameteri(target, pname, param); } +void GLES2TraceImplementation::BindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BindImageTexture"); + gl_->BindImageTexture(unit, texture, level, layered, layer, access, format); +} + void GLES2TraceImplementation::DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) {
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index cc2f79d..fae918e 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -11777,6 +11777,77 @@ static_assert(offsetof(FramebufferParameteri, param) == 12, "offset of FramebufferParameteri param should be 12"); +struct BindImageTexture { + typedef BindImageTexture ValueType; + static const CommandId kCmdId = kBindImageTexture; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(2); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLuint _unit, + GLuint _texture, + GLint _level, + GLboolean _layered, + GLint _layer, + GLenum _access, + GLenum _format) { + SetHeader(); + unit = _unit; + texture = _texture; + level = _level; + layered = _layered; + layer = _layer; + access = _access; + format = _format; + } + + void* Set(void* cmd, + GLuint _unit, + GLuint _texture, + GLint _level, + GLboolean _layered, + GLint _layer, + GLenum _access, + GLenum _format) { + static_cast<ValueType*>(cmd)->Init(_unit, _texture, _level, _layered, + _layer, _access, _format); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t unit; + uint32_t texture; + int32_t level; + uint32_t layered; + int32_t layer; + uint32_t access; + uint32_t format; +}; + +static_assert(sizeof(BindImageTexture) == 32, + "size of BindImageTexture should be 32"); +static_assert(offsetof(BindImageTexture, header) == 0, + "offset of BindImageTexture header should be 0"); +static_assert(offsetof(BindImageTexture, unit) == 4, + "offset of BindImageTexture unit should be 4"); +static_assert(offsetof(BindImageTexture, texture) == 8, + "offset of BindImageTexture texture should be 8"); +static_assert(offsetof(BindImageTexture, level) == 12, + "offset of BindImageTexture level should be 12"); +static_assert(offsetof(BindImageTexture, layered) == 16, + "offset of BindImageTexture layered should be 16"); +static_assert(offsetof(BindImageTexture, layer) == 20, + "offset of BindImageTexture layer should be 20"); +static_assert(offsetof(BindImageTexture, access) == 24, + "offset of BindImageTexture access should be 24"); +static_assert(offsetof(BindImageTexture, format) == 28, + "offset of BindImageTexture format should be 28"); + struct DispatchCompute { typedef DispatchCompute ValueType; static const CommandId kCmdId = kDispatchCompute;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 0b85079..4ae468d 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3952,6 +3952,25 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, BindImageTexture) { + cmds::BindImageTexture& cmd = *GetBufferAs<cmds::BindImageTexture>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11), + static_cast<GLuint>(12), static_cast<GLint>(13), + static_cast<GLboolean>(14), static_cast<GLint>(15), + static_cast<GLenum>(16), static_cast<GLenum>(17)); + EXPECT_EQ(static_cast<uint32_t>(cmds::BindImageTexture::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.unit); + EXPECT_EQ(static_cast<GLuint>(12), cmd.texture); + EXPECT_EQ(static_cast<GLint>(13), cmd.level); + EXPECT_EQ(static_cast<GLboolean>(14), cmd.layered); + EXPECT_EQ(static_cast<GLint>(15), cmd.layer); + EXPECT_EQ(static_cast<GLenum>(16), cmd.access); + EXPECT_EQ(static_cast<GLenum>(17), cmd.format); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, DispatchCompute) { cmds::DispatchCompute& cmd = *GetBufferAs<cmds::DispatchCompute>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 0a719dae..10b5db5 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -254,97 +254,98 @@ OP(IsVertexArrayOES) /* 495 */ \ OP(BindVertexArrayOES) /* 496 */ \ OP(FramebufferParameteri) /* 497 */ \ - OP(DispatchCompute) /* 498 */ \ - OP(SwapBuffers) /* 499 */ \ - OP(GetMaxValueInBufferCHROMIUM) /* 500 */ \ - OP(EnableFeatureCHROMIUM) /* 501 */ \ - OP(MapBufferRange) /* 502 */ \ - OP(UnmapBuffer) /* 503 */ \ - OP(FlushMappedBufferRange) /* 504 */ \ - OP(ResizeCHROMIUM) /* 505 */ \ - OP(GetRequestableExtensionsCHROMIUM) /* 506 */ \ - OP(RequestExtensionCHROMIUM) /* 507 */ \ - OP(GetProgramInfoCHROMIUM) /* 508 */ \ - OP(GetUniformBlocksCHROMIUM) /* 509 */ \ - OP(GetTransformFeedbackVaryingsCHROMIUM) /* 510 */ \ - OP(GetUniformsES3CHROMIUM) /* 511 */ \ - OP(DescheduleUntilFinishedCHROMIUM) /* 512 */ \ - OP(GetTranslatedShaderSourceANGLE) /* 513 */ \ - OP(PostSubBufferCHROMIUM) /* 514 */ \ - OP(CopyTextureCHROMIUM) /* 515 */ \ - OP(CopySubTextureCHROMIUM) /* 516 */ \ - OP(CompressedCopyTextureCHROMIUM) /* 517 */ \ - OP(DrawArraysInstancedANGLE) /* 518 */ \ - OP(DrawElementsInstancedANGLE) /* 519 */ \ - OP(VertexAttribDivisorANGLE) /* 520 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 521 */ \ - OP(CreateAndConsumeTextureINTERNALImmediate) /* 522 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 523 */ \ - OP(BindTexImage2DCHROMIUM) /* 524 */ \ - OP(BindTexImage2DWithInternalformatCHROMIUM) /* 525 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 526 */ \ - OP(TraceBeginCHROMIUM) /* 527 */ \ - OP(TraceEndCHROMIUM) /* 528 */ \ - OP(DiscardFramebufferEXTImmediate) /* 529 */ \ - OP(LoseContextCHROMIUM) /* 530 */ \ - OP(InsertFenceSyncCHROMIUM) /* 531 */ \ - OP(WaitSyncTokenCHROMIUM) /* 532 */ \ - OP(UnpremultiplyAndDitherCopyCHROMIUM) /* 533 */ \ - OP(DrawBuffersEXTImmediate) /* 534 */ \ - OP(DiscardBackbufferCHROMIUM) /* 535 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 536 */ \ - OP(ScheduleCALayerSharedStateCHROMIUM) /* 537 */ \ - OP(ScheduleCALayerCHROMIUM) /* 538 */ \ - OP(ScheduleCALayerInUseQueryCHROMIUMImmediate) /* 539 */ \ - OP(CommitOverlayPlanesCHROMIUM) /* 540 */ \ - OP(FlushDriverCachesCHROMIUM) /* 541 */ \ - OP(ScheduleDCLayerSharedStateCHROMIUM) /* 542 */ \ - OP(ScheduleDCLayerCHROMIUM) /* 543 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 544 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 545 */ \ - OP(GenPathsCHROMIUM) /* 546 */ \ - OP(DeletePathsCHROMIUM) /* 547 */ \ - OP(IsPathCHROMIUM) /* 548 */ \ - OP(PathCommandsCHROMIUM) /* 549 */ \ - OP(PathParameterfCHROMIUM) /* 550 */ \ - OP(PathParameteriCHROMIUM) /* 551 */ \ - OP(PathStencilFuncCHROMIUM) /* 552 */ \ - OP(StencilFillPathCHROMIUM) /* 553 */ \ - OP(StencilStrokePathCHROMIUM) /* 554 */ \ - OP(CoverFillPathCHROMIUM) /* 555 */ \ - OP(CoverStrokePathCHROMIUM) /* 556 */ \ - OP(StencilThenCoverFillPathCHROMIUM) /* 557 */ \ - OP(StencilThenCoverStrokePathCHROMIUM) /* 558 */ \ - OP(StencilFillPathInstancedCHROMIUM) /* 559 */ \ - OP(StencilStrokePathInstancedCHROMIUM) /* 560 */ \ - OP(CoverFillPathInstancedCHROMIUM) /* 561 */ \ - OP(CoverStrokePathInstancedCHROMIUM) /* 562 */ \ - OP(StencilThenCoverFillPathInstancedCHROMIUM) /* 563 */ \ - OP(StencilThenCoverStrokePathInstancedCHROMIUM) /* 564 */ \ - OP(BindFragmentInputLocationCHROMIUMBucket) /* 565 */ \ - OP(ProgramPathFragmentInputGenCHROMIUM) /* 566 */ \ - OP(CoverageModulationCHROMIUM) /* 567 */ \ - OP(BlendBarrierKHR) /* 568 */ \ - OP(ApplyScreenSpaceAntialiasingCHROMIUM) /* 569 */ \ - OP(BindFragDataLocationIndexedEXTBucket) /* 570 */ \ - OP(BindFragDataLocationEXTBucket) /* 571 */ \ - OP(GetFragDataIndexEXT) /* 572 */ \ - OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 573 */ \ - OP(OverlayPromotionHintCHROMIUM) /* 574 */ \ - OP(SwapBuffersWithBoundsCHROMIUMImmediate) /* 575 */ \ - OP(SetDrawRectangleCHROMIUM) /* 576 */ \ - OP(SetEnableDCLayersCHROMIUM) /* 577 */ \ - OP(InitializeDiscardableTextureCHROMIUM) /* 578 */ \ - OP(UnlockDiscardableTextureCHROMIUM) /* 579 */ \ - OP(LockDiscardableTextureCHROMIUM) /* 580 */ \ - OP(TexStorage2DImageCHROMIUM) /* 581 */ \ - OP(SetColorSpaceMetadataCHROMIUM) /* 582 */ \ - OP(WindowRectanglesEXTImmediate) /* 583 */ \ - OP(CreateGpuFenceINTERNAL) /* 584 */ \ - OP(WaitGpuFenceCHROMIUM) /* 585 */ \ - OP(DestroyGpuFenceCHROMIUM) /* 586 */ \ - OP(SetReadbackBufferShadowAllocationINTERNAL) /* 587 */ \ - OP(FramebufferTextureMultiviewLayeredANGLE) /* 588 */ + OP(BindImageTexture) /* 498 */ \ + OP(DispatchCompute) /* 499 */ \ + OP(SwapBuffers) /* 500 */ \ + OP(GetMaxValueInBufferCHROMIUM) /* 501 */ \ + OP(EnableFeatureCHROMIUM) /* 502 */ \ + OP(MapBufferRange) /* 503 */ \ + OP(UnmapBuffer) /* 504 */ \ + OP(FlushMappedBufferRange) /* 505 */ \ + OP(ResizeCHROMIUM) /* 506 */ \ + OP(GetRequestableExtensionsCHROMIUM) /* 507 */ \ + OP(RequestExtensionCHROMIUM) /* 508 */ \ + OP(GetProgramInfoCHROMIUM) /* 509 */ \ + OP(GetUniformBlocksCHROMIUM) /* 510 */ \ + OP(GetTransformFeedbackVaryingsCHROMIUM) /* 511 */ \ + OP(GetUniformsES3CHROMIUM) /* 512 */ \ + OP(DescheduleUntilFinishedCHROMIUM) /* 513 */ \ + OP(GetTranslatedShaderSourceANGLE) /* 514 */ \ + OP(PostSubBufferCHROMIUM) /* 515 */ \ + OP(CopyTextureCHROMIUM) /* 516 */ \ + OP(CopySubTextureCHROMIUM) /* 517 */ \ + OP(CompressedCopyTextureCHROMIUM) /* 518 */ \ + OP(DrawArraysInstancedANGLE) /* 519 */ \ + OP(DrawElementsInstancedANGLE) /* 520 */ \ + OP(VertexAttribDivisorANGLE) /* 521 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 522 */ \ + OP(CreateAndConsumeTextureINTERNALImmediate) /* 523 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 524 */ \ + OP(BindTexImage2DCHROMIUM) /* 525 */ \ + OP(BindTexImage2DWithInternalformatCHROMIUM) /* 526 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 527 */ \ + OP(TraceBeginCHROMIUM) /* 528 */ \ + OP(TraceEndCHROMIUM) /* 529 */ \ + OP(DiscardFramebufferEXTImmediate) /* 530 */ \ + OP(LoseContextCHROMIUM) /* 531 */ \ + OP(InsertFenceSyncCHROMIUM) /* 532 */ \ + OP(WaitSyncTokenCHROMIUM) /* 533 */ \ + OP(UnpremultiplyAndDitherCopyCHROMIUM) /* 534 */ \ + OP(DrawBuffersEXTImmediate) /* 535 */ \ + OP(DiscardBackbufferCHROMIUM) /* 536 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 537 */ \ + OP(ScheduleCALayerSharedStateCHROMIUM) /* 538 */ \ + OP(ScheduleCALayerCHROMIUM) /* 539 */ \ + OP(ScheduleCALayerInUseQueryCHROMIUMImmediate) /* 540 */ \ + OP(CommitOverlayPlanesCHROMIUM) /* 541 */ \ + OP(FlushDriverCachesCHROMIUM) /* 542 */ \ + OP(ScheduleDCLayerSharedStateCHROMIUM) /* 543 */ \ + OP(ScheduleDCLayerCHROMIUM) /* 544 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 545 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 546 */ \ + OP(GenPathsCHROMIUM) /* 547 */ \ + OP(DeletePathsCHROMIUM) /* 548 */ \ + OP(IsPathCHROMIUM) /* 549 */ \ + OP(PathCommandsCHROMIUM) /* 550 */ \ + OP(PathParameterfCHROMIUM) /* 551 */ \ + OP(PathParameteriCHROMIUM) /* 552 */ \ + OP(PathStencilFuncCHROMIUM) /* 553 */ \ + OP(StencilFillPathCHROMIUM) /* 554 */ \ + OP(StencilStrokePathCHROMIUM) /* 555 */ \ + OP(CoverFillPathCHROMIUM) /* 556 */ \ + OP(CoverStrokePathCHROMIUM) /* 557 */ \ + OP(StencilThenCoverFillPathCHROMIUM) /* 558 */ \ + OP(StencilThenCoverStrokePathCHROMIUM) /* 559 */ \ + OP(StencilFillPathInstancedCHROMIUM) /* 560 */ \ + OP(StencilStrokePathInstancedCHROMIUM) /* 561 */ \ + OP(CoverFillPathInstancedCHROMIUM) /* 562 */ \ + OP(CoverStrokePathInstancedCHROMIUM) /* 563 */ \ + OP(StencilThenCoverFillPathInstancedCHROMIUM) /* 564 */ \ + OP(StencilThenCoverStrokePathInstancedCHROMIUM) /* 565 */ \ + OP(BindFragmentInputLocationCHROMIUMBucket) /* 566 */ \ + OP(ProgramPathFragmentInputGenCHROMIUM) /* 567 */ \ + OP(CoverageModulationCHROMIUM) /* 568 */ \ + OP(BlendBarrierKHR) /* 569 */ \ + OP(ApplyScreenSpaceAntialiasingCHROMIUM) /* 570 */ \ + OP(BindFragDataLocationIndexedEXTBucket) /* 571 */ \ + OP(BindFragDataLocationEXTBucket) /* 572 */ \ + OP(GetFragDataIndexEXT) /* 573 */ \ + OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 574 */ \ + OP(OverlayPromotionHintCHROMIUM) /* 575 */ \ + OP(SwapBuffersWithBoundsCHROMIUMImmediate) /* 576 */ \ + OP(SetDrawRectangleCHROMIUM) /* 577 */ \ + OP(SetEnableDCLayersCHROMIUM) /* 578 */ \ + OP(InitializeDiscardableTextureCHROMIUM) /* 579 */ \ + OP(UnlockDiscardableTextureCHROMIUM) /* 580 */ \ + OP(LockDiscardableTextureCHROMIUM) /* 581 */ \ + OP(TexStorage2DImageCHROMIUM) /* 582 */ \ + OP(SetColorSpaceMetadataCHROMIUM) /* 583 */ \ + OP(WindowRectanglesEXTImmediate) /* 584 */ \ + OP(CreateGpuFenceINTERNAL) /* 585 */ \ + OP(WaitGpuFenceCHROMIUM) /* 586 */ \ + OP(DestroyGpuFenceCHROMIUM) /* 587 */ \ + OP(SetReadbackBufferShadowAllocationINTERNAL) /* 588 */ \ + OP(FramebufferTextureMultiviewLayeredANGLE) /* 589 */ enum CommandId { kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/gles2_cmd_buffer_functions.txt b/gpu/command_buffer/gles2_cmd_buffer_functions.txt index cadd57a..39428c7 100644 --- a/gpu/command_buffer/gles2_cmd_buffer_functions.txt +++ b/gpu/command_buffer/gles2_cmd_buffer_functions.txt
@@ -255,6 +255,7 @@ GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLidBindVertexArray array); GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenumFramebufferTarget target, GLenumFramebufferParameter pname, GLint param); +GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); // Non-GL commands.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 4c60d17..f049df3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -4525,6 +4525,12 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleBindImageTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + return error::kUnknownCommand; +} + error::Error GLES2DecoderImpl::HandleDispatchCompute( uint32_t immediate_data_size, const volatile void* cmd_data) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h index 5148d3b..3e91162 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
@@ -18,6 +18,13 @@ GLintptr offset, GLsizeiptr size); error::Error DoBindFramebuffer(GLenum target, GLuint framebuffer); +error::Error DoBindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format); error::Error DoBindRenderbuffer(GLenum target, GLuint renderbuffer); error::Error DoBindSampler(GLuint unit, GLuint sampler); error::Error DoBindTexture(GLenum target, GLuint texture);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index ae2fcec..4c2755b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -435,6 +435,20 @@ return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::DoBindImageTexture(GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) { + api()->glBindImageTextureEXTFn( + unit, + GetTextureServiceID(api(), texture, resources_, bind_generates_resource_), + level, layered, layer, access, format); + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::DoBindRenderbuffer( GLenum target, GLuint renderbuffer) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc index e91d86d8..8847c4b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
@@ -3925,6 +3925,28 @@ return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::HandleBindImageTexture( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + if (!feature_info_->IsWebGL2ComputeContext()) + return error::kUnknownCommand; + const volatile gles2::cmds::BindImageTexture& c = + *static_cast<const volatile gles2::cmds::BindImageTexture*>(cmd_data); + GLuint unit = static_cast<GLuint>(c.unit); + GLuint texture = static_cast<GLuint>(c.texture); + GLint level = static_cast<GLint>(c.level); + GLboolean layered = static_cast<GLboolean>(c.layered); + GLint layer = static_cast<GLint>(c.layer); + GLenum access = static_cast<GLenum>(c.access); + GLenum format = static_cast<GLenum>(c.format); + error::Error error = + DoBindImageTexture(unit, texture, level, layered, layer, access, format); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::HandleDispatchCompute( uint32_t immediate_data_size, const volatile void* cmd_data) {
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index dd5aed3..3e357ff 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -104,6 +104,18 @@ } } +# This is for tryservers becoming very slow and critical path of patch landing. +builder_mixins { + name: "goma-j300" + recipe { + properties_j: <<END + $build/goma: { + "jobs": 300 + } + END + } +} + builder_mixins { name: "android" dimensions: "os:Android" @@ -2351,7 +2363,7 @@ } builders { mixins: "android-try" - mixins: "goma-j150" + mixins: "goma-j300" name: "android_arm64_dbg_recipe" dimensions: "os:Ubuntu-14.04" }
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd index 02356401..58edb88 100644 --- a/ios/chrome/app/strings/ios_chromium_strings.grd +++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -156,6 +156,9 @@ Chromium has features that help you manage your internet data and how quickly you're able to load webpages. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph> </message> + <message name="IDS_IOS_BOTTOM_TOOLBAR_IPH_PROMOTION_VOICE_OVER" desc="Text to be read by VoiceOver when the Bottom Toolbar Tip is presented to the user, explaining that the bottom toolbar can be used to reach some controls. Read by Text-to-Speech. [iOS only]"> + Chromium tip. Some buttons are now at the bottom of your screen, like Back, Forward, and Search. + </message> <message name="IDS_IOS_CLEAR_BROWSING_DATA_HISTORY_NOTICE_DESCRIPTION" desc="Description of the dialog informing the user that their Chromium browsing history was deleted, but other forms of history can still be found on Google My Activity."> The selected data has been removed from Chromium and synced devices. Your Google Account may have other forms of browsing history like searches and activity from other Google services at history.google.com. </message> @@ -195,6 +198,9 @@ <message name="IDS_IOS_LOGIN_ERROR_AUTHENTICATING_HOSTED" desc="Couldn't sign in because hosted account is used."> Your account does not work on Chromium. Please contact your domain administrator or use a regular Google Account to sign in. </message> + <message name="IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_VOICE_OVER" desc="Text to be read by VoiceOver when the LongPress Toolbar Tip is presented to the user. Read by Text-to-Speech."> + Chromium tip. For more tab options, press and hold the Show Tabs button in the toolbar, which is at the bottom or top of your screen. + </message> <message name="IDS_IOS_MANAGED_DISCONNECT_DIALOG_INFO" desc="Message explaini ng that signing out of a managed account will clear all the Chromium data.[Length: 200em, may be line wrapped to multiple lines at run time.]."> You are signing out of an account managed by <ph name="SIGNOUT_MANAGED_DOMAIN">$1<ex>google.com</ex></ph>. This will delete your Chromium data from this device, but your data will remain in your Google account. </message>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd index 3b25b44f..11dab723b 100644 --- a/ios/chrome/app/strings/ios_google_chrome_strings.grd +++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -156,6 +156,9 @@ Google Chrome has features that help you manage your internet data and how quickly you're able to load webpages. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph> </message> + <message name="IDS_IOS_BOTTOM_TOOLBAR_IPH_PROMOTION_VOICE_OVER" desc="Text to be read by VoiceOver when the Bottom Toolbar Tip is presented to the user, explaining that the bottom toolbar can be used to reach some controls. Read by Text-to-Speech. [iOS only]"> + Chrome tip. Some buttons are now at the bottom of your screen, like Back, Forward, and Search. + </message> <message name="IDS_IOS_CLEAR_BROWSING_DATA_HISTORY_NOTICE_DESCRIPTION" desc="Description of the dialog informing the user that their Chrome browsing history was deleted, but other forms of history can still be found on Google My Activity."> The selected data has been removed from Chrome and synced devices. Your Google Account may have other forms of browsing history like searches and activity from other Google services at history.google.com. </message> @@ -195,6 +198,9 @@ <message name="IDS_IOS_LOGIN_ERROR_AUTHENTICATING_HOSTED" desc="Couldn't sign in because hosted account is used."> Your account does not work on Google Chrome. Please contact your domain administrator or use a regular Google Account to sign in. </message> + <message name="IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_VOICE_OVER" desc="Text to be read by VoiceOver when the LongPress Toolbar Tip is presented to the user. Read by Text-to-Speech."> + Chrome tip. For more tab options, press and hold the Show Tabs button in the toolbar, which is at the bottom or top of your screen. + </message> <message name="IDS_IOS_MANAGED_DISCONNECT_DIALOG_INFO" desc="Message explaini ng that signing out of a managed account will clear all the Chrome data.[Length: 200em, may be line wrapped to multiple lines at run time.]."> You are signing out of an account managed by <ph name="SIGNOUT_MANAGED_DOMAIN">$1<ex>google.com</ex></ph>. This will delete your Chrome data from this device, but your data will remain in your Google account. </message>
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_presenter.mm index 680e39d..907a747 100644 --- a/ios/chrome/browser/ui/bubble/bubble_presenter.mm +++ b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
@@ -21,6 +21,7 @@ #import "ios/chrome/browser/ui/uikit_ui_util.h" #import "ios/chrome/browser/ui/util/named_guide.h" #import "ios/chrome/browser/ui/util/named_guide_util.h" +#include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/web/public/web_state/ui/crw_web_view_proxy.h" #import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" @@ -193,6 +194,9 @@ direction:arrowDirection alignment:BubbleAlignmentTrailing text:text + voiceOverAnnouncement: + l10n_util::GetNSString( + IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_VOICE_OVER) anchorPoint:searchButtonAnchor]; if (!presenter) return; @@ -207,6 +211,7 @@ direction:(BubbleArrowDirection)direction alignment:(BubbleAlignment)alignment text:(NSString*)text + voiceOverAnnouncement:(NSString*)voiceOverAnnouncement anchorPoint:(CGPoint)anchorPoint { BubbleViewControllerPresenter* presenter = [self bubblePresenterForFeature:feature @@ -214,6 +219,8 @@ alignment:alignment text:text]; + presenter.voiceOverAnnouncement = voiceOverAnnouncement; + [presenter presentInViewController:self.rootViewController view:self.rootViewController.view anchorPoint:anchorPoint]; @@ -244,6 +251,9 @@ direction:arrowDirection alignment:BubbleAlignmentCenter text:text + voiceOverAnnouncement: + l10n_util::GetNSString( + IDS_IOS_BOTTOM_TOOLBAR_IPH_PROMOTION_VOICE_OVER) anchorPoint:searchButtonAnchor]; if (!presenter) return; @@ -290,6 +300,7 @@ direction:arrowDirection alignment:BubbleAlignmentTrailing text:text + voiceOverAnnouncement:nil anchorPoint:tabSwitcherAnchor]; if (!presenter) return; @@ -321,6 +332,7 @@ direction:arrowDirection alignment:BubbleAlignmentTrailing text:text + voiceOverAnnouncement:nil anchorPoint:toolsButtonAnchor]; if (!presenter) return;
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h index 911f1c6..e7838a6 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h +++ b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h
@@ -37,6 +37,9 @@ // triggered the follow-up action. @property(nonatomic, assign) BOOL triggerFollowUpAction; +// Text to be announced with Voice Over when the bubble is presented. +@property(nonatomic, copy) NSString* voiceOverAnnouncement; + // Initializes the presenter. |text| is the text displayed by the bubble. // |arrowDirection| is the direction the bubble's arrow is pointing. |alignment| // is the position of the arrow on the bubble. |dismissalCallback| is a block
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm index da3ced4..266a902 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm +++ b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
@@ -104,6 +104,7 @@ @synthesize arrowDirection = _arrowDirection; @synthesize alignment = _alignment; @synthesize dismissalCallback = _dismissalCallback; +@synthesize voiceOverAnnouncement = _voiceOverAnnouncement; - (instancetype)initWithText:(NSString*)text arrowDirection:(BubbleArrowDirection)arrowDirection @@ -180,6 +181,11 @@ selector:@selector(engagementTimerFired:) userInfo:nil repeats:NO]; + + if (self.voiceOverAnnouncement) { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, + self.voiceOverAnnouncement); + } } - (void)dismissAnimated:(BOOL)animated {
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm index 1cf7ecc..1a94409 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm +++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
@@ -584,6 +584,11 @@ // switched off and the correct button indicating that the torch is off is shown // when the scanner is opened again. - (void)testTorchButtonIsResetWhenQRScannerIsReopened { + // TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad. + if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10."); + } + id cameraControllerMock = [self getCameraControllerMockWithAuthorizationStatus: AVAuthorizationStatusAuthorized]; @@ -727,6 +732,11 @@ // Tests that an error dialog is dismissed if the camera becomes available. - (void)testDialogDismissedIfCameraBecomesAvailable { + // TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad. + if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10."); + } + id cameraControllerMock = [self getCameraControllerMockWithAuthorizationStatus: AVAuthorizationStatusAuthorized]; @@ -805,6 +815,10 @@ // Test that the correct page is loaded if the scanner result is a URL which is // then manually edited. - (void)testReceivingQRScannerURLResultAndEditingTheURL { + // TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad. + if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10."); + } // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once // grey_typeText works on iOS 11. if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { @@ -825,6 +839,10 @@ // Test that the correct page is loaded if the scanner result is a search query // which is then manually edited. - (void)testReceivingQRScannerSearchQueryResultAndEditingTheQuery { + // TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad. + if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10."); + } // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once // grey_typeText works on iOS 11. if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) {
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h index e79414f..6f05b9c 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h
@@ -31,7 +31,7 @@ @property(nonatomic, weak) UIImage* icon; @property(nonatomic, weak) UIImage* snapshot; @property(nonatomic, copy) NSString* title; - +@property(nonatomic, assign) BOOL titleHidden; @end // A GridCell for use in animated transitions that only shows selection state
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm index ff66980..7daf519 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
@@ -62,6 +62,7 @@ @synthesize icon = _icon; @synthesize snapshot = _snapshot; @synthesize title = _title; +@synthesize titleHidden = _titleHidden; // Private properties. @synthesize topBarHeight = _topBarHeight; @synthesize topBar = _topBar; @@ -141,6 +142,7 @@ [super prepareForReuse]; self.itemIdentifier = nil; self.title = nil; + self.titleHidden = NO; self.icon = nil; self.snapshot = nil; self.selected = NO; @@ -216,6 +218,11 @@ _title = title; } +- (void)setTitleHidden:(BOOL)titleHidden { + self.titleLabel.hidden = titleHidden; + _titleHidden = titleHidden; +} + #pragma mark - Private // Sets up the top bar with icon, title, and close button. @@ -350,6 +357,7 @@ proxy.icon = cell.icon; proxy.snapshot = cell.snapshot; proxy.title = cell.title; + proxy.titleHidden = cell.titleHidden; return proxy; } #pragma mark - GridToTabTransitionView properties.
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_item.h b/ios/chrome/browser/ui/tab_grid/grid/grid_item.h index 65d276d..59219ac 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_item.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_item.h
@@ -18,6 +18,7 @@ @property(nonatomic, readonly) NSString* identifier; @property(nonatomic, copy) NSString* title; +@property(nonatomic, assign) BOOL hidesTitle; @end #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_ITEM_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_item.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_item.mm index 8a1004bc..a0dec09 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_item.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_item.mm
@@ -13,6 +13,7 @@ @implementation GridItem @synthesize identifier = _identifier; @synthesize title = _title; +@synthesize hidesTitle = _hidesTitle; - (instancetype)initWithIdentifier:(NSString*)identifier { DCHECK(identifier);
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm index a35ea49..ee68337e 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm
@@ -502,6 +502,7 @@ cell.theme = self.theme; cell.itemIdentifier = item.identifier; cell.title = item.title; + cell.titleHidden = item.hidesTitle; cell.snapshot = nil; cell.icon = nil; NSString* itemIdentifier = item.identifier;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h index ea8765f9..d660e420 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h
@@ -11,6 +11,7 @@ #import "ios/chrome/browser/ui/tab_switcher/tab_switcher.h" @protocol TabGridPaging; +@class TabGridURLLoader; // An opque adaptor for the TabSwitcher protocol into the TabGrid. // Consuming objects should be passed instances of this object as an @@ -28,6 +29,8 @@ @property(nonatomic, weak) id<TabGridPaging> tabGridPager; // The mediator for the incognito grid. @property(nonatomic, weak) TabGridMediator* incognitoMediator; +// Specialized URL loader for tab grid. +@property(nonatomic, weak) TabGridURLLoader* loader; @end #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_ADAPTOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm index 74382d8..1579300 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
@@ -7,6 +7,7 @@ #import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/ui/main/view_controller_swapping.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h" +#import "ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h" #import "ios/web/public/navigation_manager.h" @@ -25,6 +26,7 @@ @synthesize adaptedDispatcher = _adaptedDispatcher; @synthesize tabGridPager = _tabGridPager; @synthesize incognitoMediator = _incognitoMediator; +@synthesize loader = _loader; #pragma mark - TabSwitcher @@ -95,6 +97,8 @@ - (void)setOtrTabModel:(TabModel*)otrModel { DCHECK(self.incognitoMediator); self.incognitoMediator.tabModel = otrModel; + self.loader.incognitoWebStateList = otrModel.webStateList; + self.loader.incognitoBrowserState = otrModel.browserState; } - (void)setTransitionContext:(TabSwitcherTransitionContext*)transitionContext {
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index a8cf93c..ecdea424 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -206,6 +206,7 @@ incognitoWebStateList:self.incognitoTabModel.webStateList regularBrowserState:self.regularTabModel.browserState incognitoBrowserState:self.incognitoTabModel.browserState]; + self.adaptor.loader = self.URLLoader; mainViewController.remoteTabsViewController.loader = self.URLLoader; mainViewController.remoteTabsViewController.presentationDelegate = self;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm index 8a57dfd..ee6b5c7 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
@@ -38,9 +38,10 @@ TabIdTabHelper* tab_helper = TabIdTabHelper::FromWebState(web_state); GridItem* item = [[GridItem alloc] initWithIdentifier:tab_helper->tab_id()]; // chrome://newtab (NTP) tabs have no title. - if (!IsURLNtp(web_state->GetVisibleURL())) { - item.title = base::SysUTF16ToNSString(web_state->GetTitle()); + if (IsURLNtp(web_state->GetVisibleURL())) { + item.hidesTitle = YES; } + item.title = base::SysUTF16ToNSString(web_state->GetTitle()); return item; }
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h index 96bc3af..95503743 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h
@@ -28,6 +28,11 @@ incognitoBrowserState:(ios::ChromeBrowserState*)incognitoBrowserState NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; + +// The incognito WebStateList this loader manages. +@property(nonatomic, assign) WebStateList* incognitoWebStateList; +// The incognito BrowserState this loader manages. +@property(nonatomic, assign) ios::ChromeBrowserState* incognitoBrowserState; @end #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_URL_LOADER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm index 3c01334..5564d0f 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm
@@ -32,9 +32,7 @@ @interface TabGridURLLoader () @property(nonatomic, assign) WebStateList* regularWebStateList; -@property(nonatomic, assign) WebStateList* incognitoWebStateList; @property(nonatomic, assign) ios::ChromeBrowserState* regularBrowserState; -@property(nonatomic, assign) ios::ChromeBrowserState* incognitoBrowserState; @end @implementation TabGridURLLoader
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn b/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn index 6cd0825..cc44e605 100644 --- a/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn +++ b/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn
@@ -115,6 +115,25 @@ libs = [ "XCTest.framework" ] } +source_set("unit_tests") { + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true + sources = [ + "adaptive_toolbar_view_controller_unittest.mm", + ] + deps = [ + ":adaptive_ui", + "//base", + "//base/test:test_support", + "//ios/chrome/browser/ui:ui_util", + "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/popup_menu/public", + "//ios/chrome/browser/ui/toolbar/buttons", + "//testing/gtest", + "//third_party/ocmock", + ] +} + source_set("hooks") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller_unittest.mm b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller_unittest.mm new file mode 100644 index 0000000..7ad3bfd --- /dev/null +++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller_unittest.mm
@@ -0,0 +1,120 @@ +// Copyright 2018 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. + +#import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h" + +#import <UIKit/UIGestureRecognizerSubclass.h> + +#include "base/run_loop.h" +#import "base/test/ios/wait_util.h" +#include "base/test/scoped_task_environment.h" +#import "ios/chrome/browser/ui/commands/popup_menu_commands.h" +#import "ios/chrome/browser/ui/popup_menu/public/popup_menu_long_press_delegate.h" +#import "ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h" +#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button.h" +#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.h" +#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h" +#include "ios/chrome/browser/ui/ui_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#include "third_party/ocmock/gtest_support.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +UIView* GetTabGridToolbarButton(UIView* parentView) { + if (parentView.accessibilityIdentifier == kToolbarStackButtonIdentifier) + return parentView; + + for (UIView* subview in parentView.subviews) { + UIView* buttonSubview = GetTabGridToolbarButton(subview); + if (buttonSubview) + return buttonSubview; + } + return nil; +} + +class AdaptiveToolbarViewControllerTest : public PlatformTest { + protected: + AdaptiveToolbarViewControllerTest() + : scopedTaskEnvironment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI) {} + + base::test::ScopedTaskEnvironment scopedTaskEnvironment_; +}; + +TEST_F(AdaptiveToolbarViewControllerTest, DetectForceTouch) { + if (!IsUIRefreshPhase1Enabled()) + return; + + id dispatcher = OCMProtocolMock(@protocol(PopupMenuCommands)); + id longPressDelegate = OCMProtocolMock(@protocol(PopupMenuLongPressDelegate)); + ToolbarButtonFactory* factory = + [[ToolbarButtonFactory alloc] initWithStyle:NORMAL]; + + AdaptiveToolbarViewController* toolbar = + [[PrimaryToolbarViewController alloc] init]; + toolbar.buttonFactory = factory; + toolbar.longPressDelegate = longPressDelegate; + toolbar.dispatcher = dispatcher; + + UIView* buttonView = GetTabGridToolbarButton(toolbar.view); + + ASSERT_NE(buttonView, nil); + ASSERT_GE(buttonView.gestureRecognizers.count, 1UL); + + UIGestureRecognizer* gestureRecognizer = buttonView.gestureRecognizers[0]; + + id event = OCMClassMock([UIEvent class]); + + CGFloat maximumForce = 1; + CGFloat currentForce = 0.7; + id touch = OCMClassMock([UITouch class]); + OCMStub([touch maximumPossibleForce]).andReturn(maximumForce); + OCMStub([touch force]).andReturn(currentForce); + [gestureRecognizer touchesBegan:[NSSet setWithObject:touch] withEvent:event]; + [gestureRecognizer touchesMoved:[NSSet setWithObject:touch] withEvent:event]; + + // Check that the dispatcher is called when the force touch is detected. + OCMExpect([dispatcher showTabGridButtonPopup]); + + currentForce = 0.9; + + touch = OCMClassMock([UITouch class]); + OCMStub([touch maximumPossibleForce]).andReturn(maximumForce); + OCMStub([touch force]).andReturn(currentForce); + [gestureRecognizer touchesMoved:[NSSet setWithObject:touch] withEvent:event]; + + base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSecondsD(0.05)); + + EXPECT_OCMOCK_VERIFY(dispatcher); + + // Check that the longPressDelegate is notified when the gesture recognizer + // changes, even with lower force. + [[[longPressDelegate expect] ignoringNonObjectArgs] + longPressFocusPointChangedTo:CGPointZero]; + + touch = OCMClassMock([UITouch class]); + OCMStub([touch maximumPossibleForce]).andReturn(maximumForce); + OCMStub([touch force]).andReturn(currentForce); + [gestureRecognizer touchesMoved:[NSSet setWithObject:touch] withEvent:event]; + + base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSecondsD(0.05)); + + EXPECT_OCMOCK_VERIFY(longPressDelegate); + + // Change the state to Ended here, as the long press gesture recognizer isn't + // working on unit test (the state is cancelled). + gestureRecognizer.state = UIGestureRecognizerStateEnded; + + base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSecondsD(0.05)); + + EXPECT_OCMOCK_VERIFY(longPressDelegate); +} + +} // namespace
diff --git a/ios/chrome/browser/ui/util/BUILD.gn b/ios/chrome/browser/ui/util/BUILD.gn index be0c9bf..6abd6cb 100644 --- a/ios/chrome/browser/ui/util/BUILD.gn +++ b/ios/chrome/browser/ui/util/BUILD.gn
@@ -63,6 +63,7 @@ sources = [ "CRUILabel+AttributeUtils_unittest.mm", "core_text_util_unittest.mm", + "force_touch_long_press_gesture_recognizer_unittest.mm", "label_link_controller_unittest.mm", "label_observer_unittest.mm", "manual_text_framer_unittest.mm", @@ -76,6 +77,7 @@ "//ios/third_party/material_components_ios", "//ios/third_party/material_roboto_font_loader_ios", "//testing/gtest", + "//third_party/ocmock", "//url", ] }
diff --git a/ios/chrome/browser/ui/util/force_touch_long_press_gesture_recognizer_unittest.mm b/ios/chrome/browser/ui/util/force_touch_long_press_gesture_recognizer_unittest.mm new file mode 100644 index 0000000..67289194 --- /dev/null +++ b/ios/chrome/browser/ui/util/force_touch_long_press_gesture_recognizer_unittest.mm
@@ -0,0 +1,73 @@ +// Copyright 2018 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. + +#import "ios/chrome/browser/ui/util/force_touch_long_press_gesture_recognizer.h" + +#import <UIKit/UIGestureRecognizerSubclass.h> + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface ForceTouchLongPressGestureRecognizerReceiverForTest : NSObject + +@end + +@implementation ForceTouchLongPressGestureRecognizerReceiverForTest + +- (void)handleGestureRecognizer:(UIGestureRecognizer*)gesture { +} + +@end + +namespace { + +using ForceTouchLongPressGestureRecognizerTest = PlatformTest; + +TEST_F(ForceTouchLongPressGestureRecognizerTest, DetectForceTouch) { + ForceTouchLongPressGestureRecognizerReceiverForTest* testReceiver = + [[ForceTouchLongPressGestureRecognizerReceiverForTest alloc] init]; + + ForceTouchLongPressGestureRecognizer* gestureRecognizer = + [[ForceTouchLongPressGestureRecognizer alloc] + initWithTarget:testReceiver + action:@selector(handleGestureRecognizer:)]; + gestureRecognizer.forceThreshold = 0.6; + + ASSERT_EQ(UIGestureRecognizerStatePossible, gestureRecognizer.state); + + id event = OCMClassMock([UIEvent class]); + + CGFloat maximumForce = 1; + CGFloat currentForce = 0.5; + id touch = OCMClassMock([UITouch class]); + OCMStub([touch maximumPossibleForce]).andReturn(maximumForce); + OCMStub([touch force]).andReturn(currentForce); + [gestureRecognizer touchesBegan:[NSSet setWithObject:touch] withEvent:event]; + [gestureRecognizer touchesMoved:[NSSet setWithObject:touch] withEvent:event]; + + EXPECT_EQ(UIGestureRecognizerStatePossible, gestureRecognizer.state); + + currentForce = 0.7; + + touch = OCMClassMock([UITouch class]); + OCMStub([touch maximumPossibleForce]).andReturn(maximumForce); + OCMStub([touch force]).andReturn(currentForce); + [gestureRecognizer touchesMoved:[NSSet setWithObject:touch] withEvent:event]; + + EXPECT_EQ(UIGestureRecognizerStateBegan, gestureRecognizer.state); + + touch = OCMClassMock([UITouch class]); + OCMStub([touch maximumPossibleForce]).andReturn(maximumForce); + OCMStub([touch force]).andReturn(currentForce); + [gestureRecognizer touchesEnded:[NSSet setWithObject:touch] withEvent:event]; + + EXPECT_EQ(UIGestureRecognizerStateCancelled, gestureRecognizer.state); +} + +} // namespace
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index a4facee..12ea7a3 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -235,6 +235,7 @@ "//ios/chrome/browser/ui/table_view/cells:unit_tests", "//ios/chrome/browser/ui/tabs:unit_tests", "//ios/chrome/browser/ui/toolbar:unit_tests", + "//ios/chrome/browser/ui/toolbar/adaptive:unit_tests", "//ios/chrome/browser/ui/toolbar/clean:unit_tests", "//ios/chrome/browser/ui/toolbar/legacy:unit_tests", "//ios/chrome/browser/ui/tools_menu:unit_tests",
diff --git a/ios/web/public/test/http_server/http_server.mm b/ios/web/public/test/http_server/http_server.mm index d59145d..486e431f 100644 --- a/ios/web/public/test/http_server/http_server.mm +++ b/ios/web/public/test/http_server/http_server.mm
@@ -56,6 +56,7 @@ static dispatch_once_t once; dispatch_once(&once, ^{ shared_instance = new HttpServer(); + shared_instance->AddRef(); }); return *shared_instance; }
diff --git a/jingle/glue/chrome_async_socket_unittest.cc b/jingle/glue/chrome_async_socket_unittest.cc index f8b369c..65b9d9a7 100644 --- a/jingle/glue/chrome_async_socket_unittest.cc +++ b/jingle/glue/chrome_async_socket_unittest.cc
@@ -30,8 +30,8 @@ #include "net/url_request/url_request_context_getter.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/webrtc/rtc_base/ipaddress.h" -#include "third_party/webrtc/rtc_base/sigslot.h" #include "third_party/webrtc/rtc_base/socketaddress.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace jingle_glue {
diff --git a/jingle/notifier/base/weak_xmpp_client_unittest.cc b/jingle/notifier/base/weak_xmpp_client_unittest.cc index 80c0de8..e67b572 100644 --- a/jingle/notifier/base/weak_xmpp_client_unittest.cc +++ b/jingle/notifier/base/weak_xmpp_client_unittest.cc
@@ -12,7 +12,7 @@ #include "jingle/glue/task_pump.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace notifier {
diff --git a/jingle/notifier/base/xmpp_connection.h b/jingle/notifier/base/xmpp_connection.h index 78189c7..a00dd39 100644 --- a/jingle/notifier/base/xmpp_connection.h +++ b/jingle/notifier/base/xmpp_connection.h
@@ -17,7 +17,7 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context_getter.h" #include "third_party/libjingle_xmpp/xmpp/xmppengine.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace buzz { class PreXmppAuth;
diff --git a/remoting/protocol/channel_socket_adapter.h b/remoting/protocol/channel_socket_adapter.h index 30e3c5db..1a68d69 100644 --- a/remoting/protocol/channel_socket_adapter.h +++ b/remoting/protocol/channel_socket_adapter.h
@@ -21,8 +21,8 @@ // cricket::TransportChannel. #include "third_party/webrtc/p2p/base/packettransportinterface.h" #include "third_party/webrtc/rtc_base/asyncpacketsocket.h" -#include "third_party/webrtc/rtc_base/sigslot.h" #include "third_party/webrtc/rtc_base/socketaddress.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace remoting { namespace protocol {
diff --git a/remoting/protocol/ice_transport_channel.h b/remoting/protocol/ice_transport_channel.h index d41cc79..bbe337b5a 100644 --- a/remoting/protocol/ice_transport_channel.h +++ b/remoting/protocol/ice_transport_channel.h
@@ -20,7 +20,7 @@ // TODO(johan): Replace #include by forward declaration once proper inheritance // is defined for rtc::PacketTransportInterface and cricket::TransportChannel. #include "third_party/webrtc/p2p/base/packettransportinterface.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace cricket { class Candidate;
diff --git a/services/identity/public/cpp/access_token_fetcher_unittest.cc b/services/identity/public/cpp/access_token_fetcher_unittest.cc index d6219f5..42c2a74 100644 --- a/services/identity/public/cpp/access_token_fetcher_unittest.cc +++ b/services/identity/public/cpp/access_token_fetcher_unittest.cc
@@ -228,16 +228,13 @@ run_loop.Run(); - // Simulate the refresh token getting invalidated. In this case, pending - // access token requests get canceled, and the fetcher should *not* retry. - token_service()->RevokeCredentials(account_id); + // Revoke the refresh token, which should cancel all pending requests. The + // fetcher should *not* retry. EXPECT_CALL( callback, Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED), AccessTokenInfo())); - token_service()->IssueErrorForAllPendingRequestsForAccount( - account_id, - GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED)); + token_service()->RevokeCredentials(account_id); } TEST_F(AccessTokenFetcherTest, FailedAccessTokenRequest) {
diff --git a/services/identity/public/cpp/primary_account_access_token_fetcher_unittest.cc b/services/identity/public/cpp/primary_account_access_token_fetcher_unittest.cc index 3f0ed86..c597a94 100644 --- a/services/identity/public/cpp/primary_account_access_token_fetcher_unittest.cc +++ b/services/identity/public/cpp/primary_account_access_token_fetcher_unittest.cc
@@ -334,13 +334,12 @@ // Simulate the user signing out while the access token request is pending. // In this case, the pending request gets canceled, and the fetcher should // *not* retry. - identity_test_env()->ClearPrimaryAccount(); EXPECT_CALL( callback, Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED), AccessTokenInfo())); - identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( - GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED)); + + identity_test_env()->ClearPrimaryAccount(); } #endif // !OS_CHROMEOS @@ -357,15 +356,13 @@ callback.Get(), PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable); - // Simulate the refresh token getting invalidated. In this case, pending + // Simulate the refresh token getting removed. In this case, pending // access token requests get canceled, and the fetcher should *not* retry. - identity_test_env()->RemoveRefreshTokenForPrimaryAccount(); EXPECT_CALL( callback, Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED), AccessTokenInfo())); - identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( - GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED)); + identity_test_env()->RemoveRefreshTokenForPrimaryAccount(); } TEST_F(PrimaryAccountAccessTokenFetcherTest,
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index fe9ec4f..5341726 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -10820,7 +10820,7 @@ "--enable-gpu", "--test-launcher-bot-mode", "--test-launcher-jobs=1", - "--gtest_filter=VrBrowserTest*:XrBrowserTest*", + "--gtest_filter=WebVrBrowserTest*:WebXrVrBrowserTest*", "--enable-pixel-output-in-tests", "--gtest_also_run_disabled_tests" ], @@ -11183,7 +11183,7 @@ "--enable-gpu", "--test-launcher-bot-mode", "--test-launcher-jobs=1", - "--gtest_filter=VrBrowserTest*:XrBrowserTest*", + "--gtest_filter=WebVrBrowserTest*:WebXrVrBrowserTest*", "--enable-pixel-output-in-tests", "--gtest_also_run_disabled_tests" ], @@ -11773,7 +11773,7 @@ "--enable-gpu", "--test-launcher-bot-mode", "--test-launcher-jobs=1", - "--gtest_filter=VrBrowserTest*:XrBrowserTest*", + "--gtest_filter=WebVrBrowserTest*:WebXrVrBrowserTest*", "--enable-pixel-output-in-tests", "--gtest_also_run_disabled_tests" ], @@ -13065,7 +13065,7 @@ "--enable-gpu", "--test-launcher-bot-mode", "--test-launcher-jobs=1", - "--gtest_filter=VrBrowserTest*:XrBrowserTest*", + "--gtest_filter=WebVrBrowserTest*:WebXrVrBrowserTest*", "--enable-pixel-output-in-tests", "--gtest_also_run_disabled_tests" ], @@ -13780,7 +13780,7 @@ "--enable-gpu", "--test-launcher-bot-mode", "--test-launcher-jobs=1", - "--gtest_filter=VrBrowserTest*:XrBrowserTest*", + "--gtest_filter=WebVrBrowserTest*:WebXrVrBrowserTest*", "--enable-pixel-output-in-tests", "--gtest_also_run_disabled_tests" ],
diff --git a/testing/buildbot/chromium.gpu.json b/testing/buildbot/chromium.gpu.json index 7e441b26..2ebb3ce 100644 --- a/testing/buildbot/chromium.gpu.json +++ b/testing/buildbot/chromium.gpu.json
@@ -2219,7 +2219,7 @@ "--enable-gpu", "--test-launcher-bot-mode", "--test-launcher-jobs=1", - "--gtest_filter=VrBrowserTest*:XrBrowserTest*", + "--gtest_filter=WebVrBrowserTest*:WebXrVrBrowserTest*", "--enable-pixel-output-in-tests", "--gtest_also_run_disabled_tests" ], @@ -2643,7 +2643,7 @@ "--enable-gpu", "--test-launcher-bot-mode", "--test-launcher-jobs=1", - "--gtest_filter=VrBrowserTest*:XrBrowserTest*", + "--gtest_filter=WebVrBrowserTest*:WebXrVrBrowserTest*", "--enable-pixel-output-in-tests", "--gtest_also_run_disabled_tests" ],
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 61414b2..5908e7b 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -2865,7 +2865,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "webkit_layout_tests_exparchive", "merge": { "args": [
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter index b54b6ed9..c67b47a 100644 --- a/testing/buildbot/filters/mash.browser_tests.filter +++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -292,6 +292,7 @@ # disabled. # https://crbug.com/827327 -PictureInPictureWindowControllerBrowserTest.* +-ControlPictureInPictureWindowControllerBrowserTest.* # These started failing with the switch to ws2. # https:://crbug.com/855767
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 04f381d..e6f1dd2 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1719,8 +1719,6 @@ ], 'shards': 12, }, - - 'experiment_percentage': 100, # crbug.com/868180 }, 'Mac10.13 Tests (dbg)': { 'args': [
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 94e6ec2..59072ccf4 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -1227,7 +1227,7 @@ '--enable-gpu', '--test-launcher-bot-mode', '--test-launcher-jobs=1', - '--gtest_filter=VrBrowserTest*:XrBrowserTest*', + '--gtest_filter=WebVrBrowserTest*:WebXrVrBrowserTest*', '--enable-pixel-output-in-tests', '--gtest_also_run_disabled_tests', ],
diff --git a/testing/libfuzzer/getting_started.md b/testing/libfuzzer/getting_started.md index fc6adc0..0eeb2a1d 100644 --- a/testing/libfuzzer/getting_started.md +++ b/testing/libfuzzer/getting_started.md
@@ -33,9 +33,8 @@ | `is_ubsan_security=true` | enables [Undefined Behavior Sanitizer] to catch<sup>\[[*](reference.md#UBSan)\]</sup> undefined behavior like integer overflow. | | | it is possible to run libfuzzer without any sanitizers; *probably not what you want*.| -Fuzz targets are built with minimal symbols by default, regardless of the value -of `is_debug` and `symbol_level`. However if you want to run fuzz target under a -debugger you can re-enable them by setting `sanitizer_keep_symbols=true`. +Fuzz targets are built with minimal symbols by default. The symbol level +can be adjusted in the usual way by setting `symbol_level`. To get the exact GN configuration that are used on our builders, see [Build Config].
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 6bc35c4..b67a0fe 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -22,7 +22,7 @@ crbug.com/591099 fast/block/marquee-width-shrinks-to-fit-in-fixed-size-container.html [ Failure ] # Whitespace differences only -crbug.com/854889 accessibility/canvas-fallback-content-2.html [ Timeout ] +crbug.com/854889 accessibility/canvas-fallback-content-2.html [ Failure Timeout ] # Wrong quirks mode line height for pattern <div><a><img></a></div> crbug.com/854840 fast/table/backgr_border-table-quirks-collapsed-border.html [ Failure ] @@ -61,14 +61,14 @@ # New failures are appended below by the script. crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ] crbug.com/728378 compositing/culling/tile-occlusion-boundaries.html [ Failure ] -crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure ] -crbug.com/591099 compositing/layer-creation/stacking-context-overlap-nested.html [ Failure ] -crbug.com/591099 compositing/perpendicular-layer-sorting.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-above-fixed-3.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-same-transform-ancestor.html [ Failure ] -crbug.com/591099 compositing/squashing/squashing-inside-perspective.html [ Failure ] -crbug.com/591099 css3/blending/mix-blend-mode-composited-reason-children.html [ Failure ] -crbug.com/591099 css3/blending/mix-blend-mode-isolation-2-stacking-contexts.html [ Failure ] +crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure Pass ] +crbug.com/869265 compositing/layer-creation/stacking-context-overlap-nested.html [ Failure ] +crbug.com/591099 compositing/perpendicular-layer-sorting.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squash-above-fixed-3.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squash-same-transform-ancestor.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squashing-inside-perspective.html [ Failure Pass ] +crbug.com/591099 css3/blending/mix-blend-mode-composited-reason-children.html [ Failure Pass ] +crbug.com/591099 css3/blending/mix-blend-mode-isolation-2-stacking-contexts.html [ Failure Pass ] crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ] crbug.com/591099 css3/flexbox/bug646288.html [ Failure ] crbug.com/591099 css3/flexbox/flex-flow-margins-auto-size.html [ Failure ] @@ -352,7 +352,7 @@ crbug.com/591099 external/wpt/fetch/cross-origin-resource-policy/fetch.any.html [ Timeout ] crbug.com/591099 external/wpt/fetch/http-cache/basic-auth-cache-test.html [ Timeout ] crbug.com/591099 external/wpt/fullscreen/api/document-exit-fullscreen-nested-in-iframe-manual.html [ Pass ] -crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ] +crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ] crbug.com/591099 external/wpt/html-media-capture/capture_audio_cancel-manual.html [ Failure ] crbug.com/591099 external/wpt/html-media-capture/capture_image_cancel-manual.html [ Failure ] crbug.com/591099 external/wpt/html-media-capture/capture_video_cancel-manual.html [ Failure ] @@ -360,7 +360,6 @@ crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_parent [ Timeout ] crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_self [ Timeout ] crbug.com/591099 external/wpt/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive.html [ Timeout ] -crbug.com/863040 external/wpt/html/editing/focus/tabindex-focus-flag.html [ Crash ] crbug.com/591099 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.worker.html [ Failure ] crbug.com/591099 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ Failure ] crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/color.html [ Failure ] @@ -376,7 +375,7 @@ crbug.com/591099 external/wpt/html/user-activation/activation-api-iframe.tenative.html [ Failure ] crbug.com/591099 external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html [ Failure ] crbug.com/591099 external/wpt/infrastructure/reftest/reftest_ref_timeout.html [ Timeout ] -crbug.com/714962 external/wpt/intersection-observer/text-target.html [ Failure ] +crbug.com/714962 external/wpt/intersection-observer/text-target.html [ Failure Pass ] crbug.com/591099 external/wpt/media-source/mediasource-avtracks.html [ Failure ] crbug.com/591099 external/wpt/media-source/mediasource-config-change-mp4-av-audio-bitrate.html [ Failure ] crbug.com/591099 external/wpt/media-source/mediasource-config-change-mp4-av-video-bitrate.html [ Failure ] @@ -464,7 +463,6 @@ crbug.com/591099 external/wpt/workers/baseurl/alpha/worker-in-worker.html [ Pass ] crbug.com/591099 external/wpt/workers/constructors/Worker/same-origin.html [ Timeout ] crbug.com/591099 external/wpt/workers/semantics/interface-objects/004.html [ Failure ] -crbug.com/591099 external/wpt/xhr/open-url-redirected-worker-origin.htm [ Failure Pass ] crbug.com/591099 external/wpt/xhr/send-authentication-prompt-2-manual.htm [ Failure ] crbug.com/591099 fast/backgrounds/background-clip-text.html [ Failure ] crbug.com/591099 fast/backgrounds/background-leakage-transforms.html [ Failure ] @@ -512,7 +510,7 @@ crbug.com/591099 fast/encoding/utf-16-little-endian.html [ Failure ] crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ] crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ] -crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Failure Pass ] +crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ] crbug.com/591099 fast/forms/text-control-intrinsic-widths.html [ Timeout ] crbug.com/591099 fast/inline-block/vertical-align-top-and-bottom-2.html [ Failure ] crbug.com/714962 fast/inline/continuation-outlines-with-layers-2.html [ Failure ] @@ -528,7 +526,7 @@ crbug.com/591099 fast/ruby/position-after.html [ Failure ] crbug.com/591099 fast/scrolling/content-box-smaller-than-scrollbar.html [ Failure ] crbug.com/591099 fast/scrolling/jquery-rtl-scroll-type.html [ Failure ] -crbug.com/591099 fast/scrolling/scrollbar-tickmarks-hittest.html [ Failure Pass ] +crbug.com/591099 fast/scrolling/scrollbar-tickmarks-hittest.html [ Pass ] crbug.com/591099 fast/sub-pixel/sub-pixel-border-2.html [ Failure ] crbug.com/591099 fast/table/border-collapsing/004-vertical.html [ Failure ] crbug.com/591099 fast/table/border-collapsing/composited-cell-collapsed-border.html [ Failure ] @@ -536,8 +534,8 @@ crbug.com/591099 fast/table/dynamic-descendant-percentage-height.html [ Failure ] crbug.com/591099 fast/table/empty-table-percent-height.html [ Failure ] crbug.com/591099 fast/table/height-percent-test-vertical.html [ Failure ] -crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure Pass ] -crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure ] +crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure ] +crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure Pass ] crbug.com/591099 fast/table/percent-height-replaced-content-in-cell.html [ Failure ] crbug.com/858998 fast/table/table-continuation-outline-paint-crash.html [ Failure ] crbug.com/591099 fast/table/table-display-types-vertical.html [ Failure ] @@ -585,13 +583,13 @@ crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ] crbug.com/591099 http/tests/websocket/invalid-subprotocol-characters.html [ Pass Timeout ] -crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Pass ] +crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass ] crbug.com/714962 images/color-profile-background-clip-text.html [ Failure ] crbug.com/591099 images/color-profile-image-filter-all.html [ Failure ] crbug.com/714962 inspector-protocol/css/css-get-platform-fonts.js [ Failure ] crbug.com/714962 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-viewport.js [ Failure ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Failure ] -crbug.com/591099 inspector-protocol/layers/get-layers.js [ Failure ] +crbug.com/591099 inspector-protocol/layers/get-layers.js [ Failure Pass ] crbug.com/714962 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ] crbug.com/591099 inspector-protocol/timeline/page-frames.js [ Failure Pass ] crbug.com/591099 paint/inline/focus-ring-under-absolute-with-relative-continuation.html [ Failure ] @@ -664,12 +662,12 @@ crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ] crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ] crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ] -crbug.com/591099 storage/indexeddb/cursor-continue-validity.html [ Timeout ] +crbug.com/591099 storage/indexeddb/cursor-continue-validity.html [ Pass Timeout ] crbug.com/591099 storage/indexeddb/index-cursor.html [ Pass Timeout ] crbug.com/591099 storage/indexeddb/mozilla/indexes.html [ Timeout ] crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Timeout ] crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ] -crbug.com/591099 storage/indexeddb/objectstore-keycursor.html [ Pass Timeout ] +crbug.com/591099 storage/indexeddb/objectstore-keycursor.html [ Timeout ] crbug.com/591099 svg/custom/object-sizing-no-width-height.xhtml [ Failure ] crbug.com/591099 svg/filters/feTurbulence-bad-seeds.html [ Failure ] crbug.com/591099 svg/in-html/sizing/svg-inline.html [ Failure ] @@ -700,7 +698,7 @@ crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Pass ] crbug.com/591099 virtual/layout_ng/ [ Skip ] crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ] -crbug.com/591099 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass Timeout ] +crbug.com/591099 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ] @@ -713,7 +711,7 @@ crbug.com/591099 virtual/paint-touchaction-rects/fast/events/touch/touch-rect-assert-first-layer-special.html [ Failure ] crbug.com/591099 virtual/paint-touchaction-rects/fast/events/touch/touch-rect-crash-on-unpromote-layer.html [ Failure ] crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ] -crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass ] +crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass Timeout ] crbug.com/591099 virtual/scroll_customization/ [ Skip ] crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] crbug.com/591099 virtual/spv2/paint/invalidation/box/margin.html [ Failure Pass ] @@ -721,4 +719,4 @@ crbug.com/591099 virtual/threaded/ [ Skip ] crbug.com/591099 virtual/user-activation-v2/fast/events/mouse-cursor.html [ Failure ] crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] -crbug.com/591099 virtual/user-activation-v2/fullscreen/full-screen-with-flex-item.html [ Failure Timeout ] +crbug.com/591099 virtual/user-activation-v2/fullscreen/full-screen-with-flex-item.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 21341b4d..fa6ce33 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -4875,3 +4875,4 @@ # Sheriff 2018-07-30 crbug.com/866166 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Pass Timeout ] +crbug.com/868706 external/wpt/css/css-layout-api/auto-block-size-inflow.https.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 88376bf8..6e964bf 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -175699,6 +175699,11 @@ {} ] ], + "xhr/responsetype.any.worker-expected.txt": [ + [ + {} + ] + ], "xhr/responsexml-media-type-expected.txt": [ [ {} @@ -255527,12 +255532,6 @@ {} ] ], - "webmessaging/with-options/invalid-args.tentative.html": [ - [ - "/webmessaging/with-options/invalid-args.tentative.html", - {} - ] - ], "webmessaging/with-options/message-channel-transferable.tentative.html": [ [ "/webmessaging/with-options/message-channel-transferable.tentative.html", @@ -255545,9 +255544,9 @@ {} ] ], - "webmessaging/with-options/null-arg-two.tentative.html": [ + "webmessaging/with-options/null-transfer.tentative.html": [ [ - "/webmessaging/with-options/null-arg-two.tentative.html", + "/webmessaging/with-options/null-transfer.tentative.html", {} ] ], @@ -255563,12 +255562,6 @@ {} ] ], - "webmessaging/with-options/two-arg.tentative.html": [ - [ - "/webmessaging/with-options/two-arg.tentative.html", - {} - ] - ], "webmessaging/with-options/undefined-transferable.tentative.html": [ [ "/webmessaging/with-options/undefined-transferable.tentative.html", @@ -261615,9 +261608,13 @@ {} ] ], - "xhr/overridemimetype-done-state.htm": [ + "xhr/overridemimetype-done-state.any.js": [ [ - "/xhr/overridemimetype-done-state.htm", + "/xhr/overridemimetype-done-state.any.html", + {} + ], + [ + "/xhr/overridemimetype-done-state.any.worker.html", {} ] ], @@ -261767,9 +261764,13 @@ {} ] ], - "xhr/responsetype.html": [ + "xhr/responsetype.any.js": [ [ - "/xhr/responsetype.html", + "/xhr/responsetype.any.html", + {} + ], + [ + "/xhr/responsetype.any.worker.html", {} ] ], @@ -409395,27 +409396,23 @@ "support" ], "webmessaging/with-options/broken-origin.tentative.html": [ - "4cd25fa136ea0d934893baa94cbb02f9225283b4", + "c58b905cf4247f401f89e6c8c3922c5c732254fc", "testharness" ], "webmessaging/with-options/host-specific-origin.tentative.html": [ - "3629058f06adc6e087fdb0541290ff3b2f0bd193", - "testharness" - ], - "webmessaging/with-options/invalid-args.tentative.html": [ - "fd58b92f5031a7c853752ada170c0243de3390ce", + "9a9cccf99db02b3f5121eb021950319dc79aa3c2", "testharness" ], "webmessaging/with-options/message-channel-transferable.tentative.html": [ - "bb6befea5b1d6ecaaccf0c91e0667e2162211e61", + "2ab1bff00f16b3786d139248e69dede14c511e03", "testharness" ], "webmessaging/with-options/no-target-origin.tentative.html": [ - "4488ff7e67cbb21a61c4bc10a86ce8db635381a3", + "01cba7e85d9e2e07a4a38ae7b3ccf16a93ae7561", "testharness" ], - "webmessaging/with-options/null-arg-two.tentative.html": [ - "e267e7d0434187d68183519e771b49fb5f7e8cf0", + "webmessaging/with-options/null-transfer.tentative.html": [ + "b3f2cd81654f770dde61e2958ed94d9d0928f807", "testharness" ], "webmessaging/with-options/one-arg.tentative.html": [ @@ -409423,19 +409420,15 @@ "testharness" ], "webmessaging/with-options/slash-origin.tentative.html": [ - "dc13f33233bcff9b45574cd82e58587bed4e8145", - "testharness" - ], - "webmessaging/with-options/two-arg.tentative.html": [ - "466c251aaa926ce739acd758d2b44104d8165501", + "d727e94b51d9fa379ff3726159aa51429230c888", "testharness" ], "webmessaging/with-options/undefined-transferable.tentative.html": [ - "bd0c1bde34600a11350b50e3030997d908276aef", + "696c547a2b3ec910ab1198565762b51d31a41ab4", "testharness" ], "webmessaging/with-options/unknown-parameter.tentative.html": [ - "0a80a8467e9bcfdd7f44f3e7f6884e64d785509c", + "3aa6d67a00ca6a155cce943fc295a73fe5a33972", "testharness" ], "webmessaging/with-ports/001.html": [ @@ -417086,8 +417079,8 @@ "38a7f6e2871ac0def651e5b82bb8a43b061633bb", "testharness" ], - "xhr/overridemimetype-done-state.htm": [ - "167f34f8dfc1312a9124c12ee4f8de808fa41680", + "xhr/overridemimetype-done-state.any.js": [ + "5924cec26f0bf551a7d37969a62941fc88c177f1", "testharness" ], "xhr/overridemimetype-edge-cases.window-expected.txt": [ @@ -417598,10 +417591,14 @@ "d08dd5c1d0b21b639389dfc1deec65215b3334dc", "testharness" ], - "xhr/responsetype.html": [ - "090ae5981aed9e0ed5e5f8a2f5615d57df0c366b", + "xhr/responsetype.any.js": [ + "eda46254f0b786635b91fdd7f2b63992f2f9ad5d", "testharness" ], + "xhr/responsetype.any.worker-expected.txt": [ + "982fa891fcb2318d26f8e99c59adc40c6d9024fa", + "support" + ], "xhr/responseurl.html": [ "b7ac10fed9c8a07afcd13f1d4906e10996ae56c6", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-transceivers.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-transceivers.https.html index 49f6839..c89737c9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-transceivers.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-transceivers.https.html
@@ -321,7 +321,7 @@ promise_test(async t => { const pc1 = createPeerConnectionWithCleanup(t); const pc2 = createPeerConnectionWithCleanup(t); - const [track, stream] = await createTrackAndStreamWithCleanup(t); + const [track] = await createTrackAndStreamWithCleanup(t); pc1.addTransceiver(track, {streams:[]}); const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2); assert_equals(trackEvent.streams.length, 0, 'trackEvent.streams.length == 0'); @@ -330,7 +330,8 @@ promise_test(async t => { const pc1 = createPeerConnectionWithCleanup(t); const pc2 = createPeerConnectionWithCleanup(t); - const [track, stream] = await createTrackAndStreamWithCleanup(t); + const [track] = await createTrackAndStreamWithCleanup(t); + const stream = new MediaStream(); pc1.addTransceiver(track, {streams:[stream]}); const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2); assert_equals(trackEvent.streams.length, 1, 'trackEvent.streams.length == 1'); @@ -341,7 +342,7 @@ promise_test(async t => { const pc1 = createPeerConnectionWithCleanup(t); const pc2 = createPeerConnectionWithCleanup(t); - const [track, stream] = await createTrackAndStreamWithCleanup(t); + const [track] = await createTrackAndStreamWithCleanup(t); const stream0 = new MediaStream(); const stream1 = new MediaStream(); pc1.addTransceiver(track, {streams:[stream0, stream1]}); @@ -356,8 +357,8 @@ promise_test(async t => { const pc1 = createPeerConnectionWithCleanup(t); const pc2 = createPeerConnectionWithCleanup(t); - const [track, stream] = await createTrackAndStreamWithCleanup(t); - pc1.addTrack(track, stream); + const [track] = await createTrackAndStreamWithCleanup(t); + pc1.addTrack(track); const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2); assert_equals(trackEvent.streams.length, 0, 'trackEvent.streams.length == 0'); }, 'addTrack(0 streams): ontrack fires with no stream'); @@ -365,7 +366,8 @@ promise_test(async t => { const pc1 = createPeerConnectionWithCleanup(t); const pc2 = createPeerConnectionWithCleanup(t); - const [track, stream] = await createTrackAndStreamWithCleanup(t); + const [track] = await createTrackAndStreamWithCleanup(t); + const stream = new MediaStream(); pc1.addTrack(track, stream); const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2); assert_equals(trackEvent.streams.length, 1, 'trackEvent.streams.length == 1'); @@ -376,7 +378,7 @@ promise_test(async t => { const pc1 = createPeerConnectionWithCleanup(t); const pc2 = createPeerConnectionWithCleanup(t); - const [track, stream] = await createTrackAndStreamWithCleanup(t); + const [track] = await createTrackAndStreamWithCleanup(t); const stream0 = new MediaStream(); const stream1 = new MediaStream(); pc1.addTrack(track, stream0, stream1);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/overridemimetype-done-state.any.js b/third_party/WebKit/LayoutTests/external/wpt/xhr/overridemimetype-done-state.any.js new file mode 100644 index 0000000..bdf49e1c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/xhr/overridemimetype-done-state.any.js
@@ -0,0 +1,20 @@ +// META title= XMLHttpRequest: overrideMimeType() in DONE state</title> + +/** + * Spec: <https://xhr.spec.whatwg.org/#the-overridemimetype()-method>; data-tested-assertations="/following::ol/li[1]" + */ +var test = async_test(); +var client = new XMLHttpRequest(); +client.onreadystatechange = test.step_func( function() { + if (client.readyState !== 4) return; + var text = client.responseText; + assert_not_equals(text, ""); + assert_throws("InvalidStateError", function() { client.overrideMimeType('application/xml;charset=Shift-JIS'); }); + if (GLOBAL.isWindow()) { + assert_equals(client.responseXML, null); + } + assert_equals(client.responseText, text); + test.done(); +}); +client.open("GET", "resources/status.py?type="+encodeURIComponent('text/plain;charset=iso-8859-1')+'&content=%3Cmsg%3E%83%65%83%58%83%67%3C%2Fmsg%3E'); +client.send();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/overridemimetype-done-state.htm b/third_party/WebKit/LayoutTests/external/wpt/xhr/overridemimetype-done-state.htm deleted file mode 100644 index a1711e6..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/xhr/overridemimetype-done-state.htm +++ /dev/null
@@ -1,26 +0,0 @@ -<!doctype html> -<html> - <head> - <title>XMLHttpRequest: overrideMimeType() in DONE state</title> - <meta charset="utf-8"> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <link rel="help" href="https://xhr.spec.whatwg.org/#the-overridemimetype()-method" data-tested-assertations="/following::ol/li[1]" /> - </head> - <body> - <div id="log"></div> - <script> - var test = async_test(); - var client = new XMLHttpRequest(); - client.onreadystatechange = test.step_func( function() { - if (client.readyState !== 4) return; - assert_throws("InvalidStateError", function() { client.overrideMimeType('application/xml;charset=Shift-JIS'); }); - assert_equals(client.responseXML, null); - test.done(); - }); - client.open("GET", "resources/status.py?type="+encodeURIComponent('text/plain;charset=iso-8859-1')+'&content=%3Cmsg%3E%83%65%83%58%83%67%3C%2Fmsg%3E'); - client.send(); - </script> - - </body> -</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.html b/third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.any.js similarity index 60% rename from third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.html rename to third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.any.js index ade6044..88bd9189 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.html +++ b/third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.any.js
@@ -1,31 +1,51 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>XMLHttpRequest.responseType</title> -<link rel="author" title="Mathias Bynens" href="http://mathiasbynens.be/"> -<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"> -<link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetype-attribute"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> +// META: title=XMLHttpRequest.responseType + +/** + * Author: Mathias Bynens <http://mathiasbynens.be/> + * Author: Ms2ger <mailto:Ms2ger@gmail.com> + * + * Spec: <https://xhr.spec.whatwg.org/#the-responsetype-attribute> + */ test(function() { var xhr = new XMLHttpRequest(); assert_equals(xhr.responseType, ''); }, 'Initial value of responseType'); -var types = ['', 'json', 'document', 'arraybuffer', 'blob', 'text']; +var types = ['', 'json', 'document', 'arraybuffer', 'blob', 'text', "nosuchtype"]; + +function isIgnoredType(type) { + if (type == "nosuchtype") { + return true; + } + + if (type != "document") { + return false; + } + + // "document" is ignored only on workers. + return GLOBAL.isWorker(); +} + +function expectedType(type) { + if (!isIgnoredType(type)) { + return type; + } + + return ""; +} + types.forEach(function(type) { test(function() { var xhr = new XMLHttpRequest(); xhr.responseType = type; - assert_equals(xhr.responseType, type); + assert_equals(xhr.responseType, expectedType(type)); }, 'Set responseType to ' + format_value(type) + ' when readyState is UNSENT.'); test(function() { var xhr = new XMLHttpRequest(); xhr.open('get', '/'); xhr.responseType = type; - assert_equals(xhr.responseType, type); + assert_equals(xhr.responseType, expectedType(type)); }, 'Set responseType to ' + format_value(type) + ' when readyState is OPENED.'); async_test(function() { @@ -34,7 +54,7 @@ xhr.onreadystatechange = this.step_func(function() { if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) { xhr.responseType = type; - assert_equals(xhr.responseType, type); + assert_equals(xhr.responseType, expectedType(type)); this.done(); } }); @@ -46,9 +66,13 @@ xhr.open('get', '/'); xhr.onreadystatechange = this.step_func(function() { if (xhr.readyState === XMLHttpRequest.LOADING) { - assert_throws("InvalidStateError", function() { + if (isIgnoredType(type)) { xhr.responseType = type; - }); + } else { + assert_throws("InvalidStateError", function() { + xhr.responseType = type; + }); + } assert_equals(xhr.responseType, ""); this.done(); } @@ -61,10 +85,17 @@ xhr.open('get', '/'); xhr.onreadystatechange = this.step_func(function() { if (xhr.readyState === XMLHttpRequest.DONE) { - assert_throws("InvalidStateError", function() { + var text = xhr.responseText; + assert_not_equals(text, ""); + if (isIgnoredType(type)) { xhr.responseType = type; - }); + } else { + assert_throws("InvalidStateError", function() { + xhr.responseType = type; + }); + } assert_equals(xhr.responseType, ""); + assert_equals(xhr.responseText, text); this.done(); } }); @@ -76,10 +107,15 @@ test(function() { var xhr = new XMLHttpRequest(); xhr.open('get', '/', false); - assert_throws("InvalidAccessError", function() { + if (GLOBAL.isWorker() || isIgnoredType(type)) { + // Setting responseType on workers is valid even for a sync XHR. xhr.responseType = type; - }); - assert_equals(xhr.responseType, ""); + assert_equals(xhr.responseType, expectedType(type)); + } else { + assert_throws("InvalidAccessError", function() { + xhr.responseType = type; + }); + } }, 'Set responseType to ' + format_value(type) + ' when readyState is OPENED and the sync flag is set.'); test(function() { @@ -87,10 +123,13 @@ xhr.open('get', '/', false); xhr.send(); assert_equals(xhr.readyState, XMLHttpRequest.DONE); - assert_throws("InvalidStateError", function() { + if (isIgnoredType(type)) { xhr.responseType = type; - }); + } else { + assert_throws("InvalidStateError", function() { + xhr.responseType = type; + }); + } assert_equals(xhr.responseType, ""); }, 'Set responseType to ' + format_value(type) + ' when readyState is DONE and the sync flag is set.'); }); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.any.worker-expected.txt new file mode 100644 index 0000000..970e94bb --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/xhr/responsetype.any.worker-expected.txt
@@ -0,0 +1,54 @@ +This is a testharness.js-based test. +Found 50 tests; 43 PASS, 7 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS Initial value of responseType +PASS Set responseType to "" when readyState is UNSENT. +PASS Set responseType to "" when readyState is OPENED. +PASS Set responseType to "" when readyState is HEADERS_RECEIVED. +PASS Set responseType to "" when readyState is LOADING. +PASS Set responseType to "" when readyState is DONE. +PASS Set responseType to "" when readyState is OPENED and the sync flag is set. +PASS Set responseType to "" when readyState is DONE and the sync flag is set. +PASS Set responseType to "json" when readyState is UNSENT. +PASS Set responseType to "json" when readyState is OPENED. +PASS Set responseType to "json" when readyState is HEADERS_RECEIVED. +PASS Set responseType to "json" when readyState is LOADING. +PASS Set responseType to "json" when readyState is DONE. +PASS Set responseType to "json" when readyState is OPENED and the sync flag is set. +PASS Set responseType to "json" when readyState is DONE and the sync flag is set. +FAIL Set responseType to "document" when readyState is UNSENT. assert_equals: expected "" but got "document" +FAIL Set responseType to "document" when readyState is OPENED. assert_equals: expected "" but got "document" +FAIL Set responseType to "document" when readyState is HEADERS_RECEIVED. assert_equals: expected "" but got "document" +FAIL Set responseType to "document" when readyState is LOADING. Failed to set the 'responseType' property on 'XMLHttpRequest': The response type cannot be set if the object's state is LOADING or DONE. +FAIL Set responseType to "document" when readyState is DONE. Failed to set the 'responseType' property on 'XMLHttpRequest': The response type cannot be set if the object's state is LOADING or DONE. +FAIL Set responseType to "document" when readyState is OPENED and the sync flag is set. assert_equals: expected "" but got "document" +FAIL Set responseType to "document" when readyState is DONE and the sync flag is set. Failed to set the 'responseType' property on 'XMLHttpRequest': The response type cannot be set if the object's state is LOADING or DONE. +PASS Set responseType to "arraybuffer" when readyState is UNSENT. +PASS Set responseType to "arraybuffer" when readyState is OPENED. +PASS Set responseType to "arraybuffer" when readyState is HEADERS_RECEIVED. +PASS Set responseType to "arraybuffer" when readyState is LOADING. +PASS Set responseType to "arraybuffer" when readyState is DONE. +PASS Set responseType to "arraybuffer" when readyState is OPENED and the sync flag is set. +PASS Set responseType to "arraybuffer" when readyState is DONE and the sync flag is set. +PASS Set responseType to "blob" when readyState is UNSENT. +PASS Set responseType to "blob" when readyState is OPENED. +PASS Set responseType to "blob" when readyState is HEADERS_RECEIVED. +PASS Set responseType to "blob" when readyState is LOADING. +PASS Set responseType to "blob" when readyState is DONE. +PASS Set responseType to "blob" when readyState is OPENED and the sync flag is set. +PASS Set responseType to "blob" when readyState is DONE and the sync flag is set. +PASS Set responseType to "text" when readyState is UNSENT. +PASS Set responseType to "text" when readyState is OPENED. +PASS Set responseType to "text" when readyState is HEADERS_RECEIVED. +PASS Set responseType to "text" when readyState is LOADING. +PASS Set responseType to "text" when readyState is DONE. +PASS Set responseType to "text" when readyState is OPENED and the sync flag is set. +PASS Set responseType to "text" when readyState is DONE and the sync flag is set. +PASS Set responseType to "nosuchtype" when readyState is UNSENT. +PASS Set responseType to "nosuchtype" when readyState is OPENED. +PASS Set responseType to "nosuchtype" when readyState is HEADERS_RECEIVED. +PASS Set responseType to "nosuchtype" when readyState is LOADING. +PASS Set responseType to "nosuchtype" when readyState is DONE. +PASS Set responseType to "nosuchtype" when readyState is OPENED and the sync flag is set. +PASS Set responseType to "nosuchtype" when readyState is DONE and the sync flag is set. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/fast/block/margin-collapse/display-contents-contenteditable.html b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/display-contents-contenteditable.html new file mode 100644 index 0000000..883df1b --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/display-contents-contenteditable.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<p>There should be a green square below.</p> +<div id="container" style="overflow:hidden; width:100px; background:green;" data-expected-height="100"> + <div style="display:contents;"> + <div id="initiallyNone" style="display:none; margin:100px 0;"> + <div style="margin:100px 0;"></div> + </div> + </div> + <div style="margin:100px 0;"> + <div style="margin:100px 0;"></div> + </div> + <div contenteditable="true" style="height:0;"></div> +</div> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/check-layout-th.js"></script> +<script> + document.body.offsetTop; + document.getElementById("initiallyNone").style.display = "block"; + checkLayout("#container"); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/hit-test-counts-expected.txt b/third_party/WebKit/LayoutTests/fast/events/hit-test-counts-expected.txt index 7b8a411..617de2c 100644 --- a/third_party/WebKit/LayoutTests/fast/events/hit-test-counts-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/events/hit-test-counts-expected.txt
@@ -78,7 +78,7 @@ TouchEnd: 0+0 GestureTapDown: 0+1 GestureShowPress: 0+1 -GestureTap: 0+3 [with multiTargetTapNotification: 1+3] +GestureTap: 0+3 GestureScrollBegin: 0+1 GestureTapCancel: 0+1 GestureScrollUpdate: 0+0
diff --git a/third_party/WebKit/LayoutTests/fast/events/hit-test-counts.html b/third_party/WebKit/LayoutTests/fast/events/hit-test-counts.html index ab83525..f782d70 100644 --- a/third_party/WebKit/LayoutTests/fast/events/hit-test-counts.html +++ b/third_party/WebKit/LayoutTests/fast/events/hit-test-counts.html
@@ -170,12 +170,10 @@ { clearCounts(documents); sendEvents(targetX, targetY, documents, false); - internals.settings.setMultiTargetTapNotificationEnabled(true); for(var i = 0; i < documents.length; i++) { internals.clearHitTestCache(documents[i]); } sendEvents(targetX, targetY, documents, true); - internals.settings.setMultiTargetTapNotificationEnabled(false); } function centerOf(element) { @@ -189,8 +187,6 @@ eventCounts = {}; onload = function() { - internals.settings.setMultiTargetTapNotificationEnabled(false); - debug('Event on a simple div'); debug('---------------------'); var point = centerOf(document.getElementById('target'));
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/modules-load-initial-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/modules-load-initial-expected.txt index f64ef05..0d01d5a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/modules-load-initial-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/modules-load-initial-expected.txt
@@ -2,7 +2,6 @@ Loaded modules: bindings - browser_components browser_sdk common components
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/download.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/download.js index 01af4f0..1a0b9f3 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/download.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/download.js
@@ -23,7 +23,7 @@ TestRunner.addIframe('resources/download.zzz'); function responseReceived(requestId, time, resourceType, response) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/download\.zzz/.exec(request.url())) { TestRunner.addResult('Received response for download.zzz'); @@ -33,13 +33,13 @@ } function loadingFinished(requestId, finishTime) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/download\.zzz/.exec(request.url())) TestRunner.completeTest(); } function loadingFailed(requestId, time, localizedDescription, canceled) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/download\.zzz/.exec(request.url())) TestRunner.completeTest(); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-datareceived.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-datareceived.js index 9377df4e..3080675 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-datareceived.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-datareceived.js
@@ -23,7 +23,7 @@ var encodedBytesReceived = 0; function responseReceived(requestId, loaderId, time, resourceType, response, frameId) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/resource\.php/.exec(request.url())) { TestRunner.addResult('Received response.'); encodedBytesReceived += response.encodedDataLength; @@ -31,7 +31,7 @@ } function loadingFinished(requestId, finishTime, encodedDataLength) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/resource\.php/.exec(request.url())) { TestRunner.assertEquals(encodedBytesReceived, encodedDataLength, 'Data length mismatch'); TestRunner.addResult('SUCCESS'); @@ -40,7 +40,7 @@ } function loadingFailed(requestId, time, localizedDescription, canceled) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/resource\.php/.exec(request.url())) { TestRunner.addResult('Loading failed!'); TestRunner.completeTest(); @@ -49,7 +49,7 @@ function dataReceived(requestId, time, dataLength, encodedDataLength) { TestRunner.addSniffer(SDK.NetworkDispatcher.prototype, 'dataReceived', dataReceived); - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/resource\.php/.exec(request.url())) encodedBytesReceived += encodedDataLength; }
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain.js index 9745993..5c580015 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain.js
@@ -15,7 +15,7 @@ var requests = NetworkTestRunner.networkRequests(); requests.forEach((request) => { TestRunner.addResult('\n' + request.url()); - var graph = BrowserSDK.networkLog.initiatorGraphForRequest(request); + var graph = SDK.networkLog.initiatorGraphForRequest(request); TestRunner.addResult('Initiators ' + Array.from(graph.initiators).map(request => request._url)); TestRunner.addResult('Initiated ' + Array.from(graph.initiated).map(request => request._url)); });
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http.js index 64dc3f2b..03a180c2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http.js
@@ -36,7 +36,7 @@ '//tbody/tr/td[position()=1]/@title', dataGrid, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var outputStrings = []; - for (var request of BrowserSDK.networkLog.requests()) { + for (var request of SDK.networkLog.requests()) { var line = request.displayName + ':' + request.statusCode + ' ' + request.statusText; if (request.failed) line += '(failed)';
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xhr-data-received-async-response-type-blob.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xhr-data-received-async-response-type-blob.js index c556ff15..ce1827b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xhr-data-received-async-response-type-blob.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xhr-data-received-async-response-type-blob.js
@@ -14,7 +14,7 @@ 'GET', 'resources/resource.php', true, undefined, undefined, [], false, undefined, 'blob', function() {}); function dataReceived(requestId, time, dataLength, encodedDataLength) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/resource\.php/.exec(request.url())) { TestRunner.addResult('Received data for resource.php'); TestRunner.addResult('SUCCESS');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xhr-replay.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xhr-replay.js index d63c50f..4a80b0a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xhr-replay.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xhr-replay.js
@@ -34,11 +34,11 @@ NetworkTestRunner.makeXHR(method, url, async, user, password, headers, withCredentials, payload, type); var originalRequest = - await TestRunner.waitForEvent(BrowserSDK.NetworkLog.Events.RequestAdded, BrowserSDK.networkLog); + await TestRunner.waitForEvent(SDK.NetworkLog.Events.RequestAdded, SDK.networkLog); await dumpRequest(originalRequest); TestRunner.NetworkAgent.replayXHR(originalRequest.requestId()); var replayedRequest = - await TestRunner.waitForEvent(BrowserSDK.NetworkLog.Events.RequestAdded, BrowserSDK.networkLog); + await TestRunner.waitForEvent(SDK.NetworkLog.Events.RequestAdded, SDK.networkLog); assertRequestEqual(originalRequest, replayedRequest); callback();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xsl-content.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xsl-content.js index d12db6af..a8ea471 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xsl-content.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-xsl-content.js
@@ -23,7 +23,7 @@ TestRunner.addSniffer(SDK.NetworkDispatcher.prototype, 'loadingFinished', loadingFinished, true); function loadingFinished(requestId) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); request.requestContent().then(contentReceived.bind(this, request)); } function contentReceived(request, content) {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-conversion.js b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-conversion.js index 0d82a2175..9628887 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-conversion.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-conversion.js
@@ -35,7 +35,7 @@ } addCookieHeadersToRequest(findRequestByURL(/inspected-page\.html$/)); - var log = await BrowserSDK.HARLog.build(NetworkTestRunner.networkRequests()); + var log = await SDK.HARLog.build(NetworkTestRunner.networkRequests()); // Filter out favicon.ico requests that only appear on certain platforms. log.entries = log.entries.filter(function(entry) { return !/favicon\.ico$/.test(entry.request.url);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers.js b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers.js index 627af4f..bf0bb43 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers.js
@@ -53,7 +53,7 @@ '_transferSize': 'formatAsTypeName', '_error': 'skip' }; - var har = await BrowserSDK.HAREntry.build(testRequest); + var har = await SDK.HARLog.Entry.build(testRequest); TestRunner.addObject(har, stillNondeterministic, '', 'HAR:'); TestRunner.completeTest(); })();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6.js b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6.js index 8d20fe6..532342c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6.js
@@ -29,7 +29,7 @@ if (!/post-target\.cgi/.test(request.url())) return; TestRunner.addResult(request.url()); - TestRunner.addObject(await BrowserSDK.HAREntry.build(request), NetworkTestRunner.HARPropertyFormattersWithSize); + TestRunner.addObject(await SDK.HARLog.Entry.build(request), NetworkTestRunner.HARPropertyFormattersWithSize); TestRunner.completeTest(); } })();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters.js b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters.js index 7055301..d0a3bd7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters.js
@@ -26,7 +26,7 @@ async function onRequestFinished(event) { var request = event.data; TestRunner.addResult(request.url()); - TestRunner.addObject(await BrowserSDK.HAREntry.build(request), NetworkTestRunner.HARPropertyFormattersWithSize); + TestRunner.addObject(await SDK.HARLog.Entry.build(request), NetworkTestRunner.HARPropertyFormattersWithSize); TestRunner.completeTest(); } })();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/reveal-objects.js b/third_party/WebKit/LayoutTests/http/tests/devtools/reveal-objects.js index 4f5df1e..72f95bb 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/reveal-objects.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/reveal-objects.js
@@ -52,7 +52,7 @@ } function firstXhrCallback() { - requestWithResource = BrowserSDK.networkLog.requestForURL(resource.url); + requestWithResource = SDK.networkLog.requestForURL(resource.url); TestRunner.evaluateInPage('loadResource(\'missing.js\')', secondXhrCallback); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/async-callstack-network-initiator-image.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/async-callstack-network-initiator-image.js index db8e6272..52527b5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/async-callstack-network-initiator-image.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/async-callstack-network-initiator-image.js
@@ -23,7 +23,7 @@ if (!event.data.url().endsWith('resources/image.png')) return; - var initiatorInfo = BrowserSDK.networkLog.initiatorInfoForRequest(event.data); + var initiatorInfo = SDK.networkLog.initiatorInfoForRequest(event.data); var element = new Components.Linkifier().linkifyScriptLocation( TestRunner.mainTarget, initiatorInfo.scriptId, initiatorInfo.url, initiatorInfo.lineNumber, initiatorInfo.columnNumber - 1);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-cert-not-found.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-cert-not-found.js index 50366cb..6230c2d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-cert-not-found.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-cert-not-found.js
@@ -11,7 +11,7 @@ // until "Apr 8 2018 00:00 UTC". await TestRunner.evaluateInPageAsync( 'setSignedExchangeVerificationTime(new Date("Apr 1 2018 00:01 UTC"))'); - BrowserSDK.networkLog.reset(); + SDK.networkLog.reset(); await TestRunner.addIframe('/loading/sxg/resources/sxg-cert-not-found.sxg'); ConsoleTestRunner.dumpConsoleMessages(); NetworkTestRunner.dumpNetworkRequestsWithSignedExchangeInfo();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-disable-cache.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-disable-cache.js index d1f11f8..64017e83 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-disable-cache.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-disable-cache.js
@@ -23,7 +23,7 @@ // Load the test signed exchange first, to cache the certificate file. await TestRunner.addIframe(outerUrl); - BrowserSDK.networkLog.reset(); + SDK.networkLog.reset(); await TestRunner.NetworkAgent.setCacheDisabled(true); await TestRunner.addIframe(outerUrl + '?iframe-1'); @@ -33,7 +33,7 @@ await TestRunner.addIframe(outerUrl + '?iframe-2'); await addPrefetchAndWait(outerUrl + '?prefetch-2', innerUrl); - for (var request of BrowserSDK.networkLog.requests()) { + for (var request of SDK.networkLog.requests()) { if (request.url() != certUrl) continue; TestRunner.addResult(`* ${request.url()}`); @@ -45,7 +45,7 @@ const promise = new Promise(resolve => { TestRunner.addSniffer(SDK.NetworkDispatcher.prototype, 'loadingFinished', loadingFinished); function loadingFinished(requestId, finishTime, encodedDataLength) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (request.url() == waitUrl) { resolve(); } else {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-navigation-expired.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-navigation-expired.js index f4dcfad..96f3d9b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-navigation-expired.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-navigation-expired.js
@@ -11,7 +11,7 @@ // until "Apr 8 2018 00:00 UTC". So in Apr 10, the page load should fail. await TestRunner.evaluateInPageAsync( 'setSignedExchangeVerificationTime(new Date("Apr 10 2018 00:01 UTC"))'); - BrowserSDK.networkLog.reset(); + SDK.networkLog.reset(); await TestRunner.addIframe('/loading/sxg/resources/sxg-location.sxg'); ConsoleTestRunner.dumpConsoleMessages(); NetworkTestRunner.dumpNetworkRequestsWithSignedExchangeInfo();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-navigation.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-navigation.js index 1e64c84..4ffc82a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-navigation.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-navigation.js
@@ -11,7 +11,7 @@ // until "Apr 8 2018 00:00 UTC". await TestRunner.evaluateInPageAsync( 'setSignedExchangeVerificationTime(new Date("Apr 1 2018 00:01 UTC"))'); - BrowserSDK.networkLog.reset(); + SDK.networkLog.reset(); await TestRunner.addIframe('/loading/sxg/resources/sxg-location.sxg'); ConsoleTestRunner.dumpConsoleMessages(); NetworkTestRunner.dumpNetworkRequestsWithSignedExchangeInfo();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-prefetch-expired.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-prefetch-expired.js index ade9cb83..e45fd566 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-prefetch-expired.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-prefetch-expired.js
@@ -11,12 +11,12 @@ // until "Apr 8 2018 00:00 UTC". So in Apr 10, the prefetch should fail. await TestRunner.evaluateInPageAsync( 'setSignedExchangeVerificationTime(new Date("Apr 10 2018 00:01 UTC"))'); - BrowserSDK.networkLog.reset(); + SDK.networkLog.reset(); const promise = new Promise(resolve => { TestRunner.addSniffer(SDK.NetworkDispatcher.prototype, 'loadingFailed', loadingFailed, true); function loadingFailed(requestId, time, localizedDescription, canceled) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/sxg-location\.sxg/.exec(request.url())) resolve(); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-prefetch.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-prefetch.js index e9c56f4b..1239c889 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-prefetch.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sxg/sxg-prefetch.js
@@ -11,12 +11,12 @@ // until "Apr 8 2018 00:00 UTC". await TestRunner.evaluateInPageAsync( 'setSignedExchangeVerificationTime(new Date("Apr 1 2018 00:01 UTC"))'); - BrowserSDK.networkLog.reset(); + SDK.networkLog.reset(); const promise = new Promise(resolve => { TestRunner.addSniffer(SDK.NetworkDispatcher.prototype, 'loadingFinished', loadingFinished, true); function loadingFinished(requestId, finishTime, encodedDataLength) { - var request = BrowserSDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); + var request = SDK.networkLog.requestByManagerAndId(TestRunner.networkManager, requestId); if (/test\.html/.exec(request.url())) resolve(); }
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-transceivers.https-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-transceivers.https-expected.txt index 9d5709a..8570ecba 100644 --- a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-transceivers.https-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-transceivers.https-expected.txt
@@ -27,7 +27,7 @@ PASS addTransceiver(0 streams): ontrack fires with no stream PASS addTransceiver(1 stream): ontrack fires with corresponding stream PASS addTransceiver(2 streams): ontrack fires with corresponding two streams -FAIL addTrack(0 streams): ontrack fires with no stream assert_equals: trackEvent.streams.length == 0 expected 0 but got 1 +PASS addTrack(0 streams): ontrack fires with no stream PASS addTrack(1 stream): ontrack fires with corresponding stream PASS addTrack(2 streams): ontrack fires with corresponding two streams PASS addTransceiver('audio'): creates a transceiver with direction sendrecv
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index db71ce3..746011cd 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -10023,7 +10023,7 @@ attribute @@toStringTag getter emulatedPosition getter gripMatrix - getter pointerMatrix + getter targetRay method constructor interface XRInputSource attribute @@toStringTag @@ -10042,6 +10042,12 @@ attribute @@toStringTag getter canvas method constructor +interface XRRay + attribute @@toStringTag + getter direction + getter origin + getter transformMatrix + method constructor interface XRSession : EventTarget attribute @@toStringTag getter baseLayer
diff --git a/third_party/WebKit/LayoutTests/xr/getInputPose_hand.html b/third_party/WebKit/LayoutTests/xr/getInputPose_hand.html index 8444877..a44188a 100644 --- a/third_party/WebKit/LayoutTests/xr/getInputPose_hand.html +++ b/third_party/WebKit/LayoutTests/xr/getInputPose_hand.html
@@ -11,8 +11,8 @@ <script> -let testName = "XRInputSources with a pointer origin of 'hand' properly " - + "communicate their poses"; +let testName = "XRInputSources with a target ray mode of 'tracked-pointer' " + + "properly communicate their poses"; let fakeDeviceInitParams = { supportsImmersive: true }; @@ -72,9 +72,9 @@ // the grip and pointer matrices should be the same. assert_matrices_approx_equal(input_pose.gripMatrix, VALID_GRIP, FLOAT_EPSILON, "Grip matrix is not equal to input."); - assert_matrices_approx_equal(input_pose.pointerMatrix, + assert_matrices_approx_equal(input_pose.targetRay.transformMatrix, input_pose.gripMatrix, FLOAT_EPSILON, - "Grip matrix is not equal to pointer matrix."); + "Grip matrix is not equal to target ray matrix."); }); input_source.pointerOffset = VALID_POINTER_OFFSET; @@ -93,7 +93,7 @@ // offset. assert_matrices_approx_equal(input_pose.gripMatrix, VALID_GRIP, FLOAT_EPSILON, "Grip matrix is not equal to input valid grip."); - assert_matrices_approx_equal(input_pose.pointerMatrix, + assert_matrices_approx_equal(input_pose.targetRay.transformMatrix, VALID_GRIP_WITH_POINTER_OFFSET, FLOAT_EPSILON, "Grip matrix not multipled properly."); });
diff --git a/third_party/WebKit/LayoutTests/xr/getInputPose_ray.html b/third_party/WebKit/LayoutTests/xr/getInputPose_ray.html new file mode 100644 index 0000000..42988fb --- /dev/null +++ b/third_party/WebKit/LayoutTests/xr/getInputPose_ray.html
@@ -0,0 +1,105 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> +<script src="../external/wpt/resources/chromium/webxr-test.js"></script> +<script src="../xr/resources/xr-internal-device-mocking.js"></script> +<script src="../xr/resources/xr-test-utils.js"></script> +<script src="../xr/resources/test-constants.js"></script> +<canvas id="webgl-canvas"></canvas> + +<script> + +let testName = "XRInputSources produce valid target rays"; + +let fakeDeviceInitParams = { supportsImmersive: true }; + +let requestSessionOptions = [{ immersive: true }]; + +let testFunction = + (session, t, fakeDeviceController) => new Promise((resolve) => { + // Session must have a baseLayer or frame requests will be ignored. + session.baseLayer = new XRWebGLLayer(session, gl); + + // Need to have a valid pose or input events don't process. + fakeDeviceController.setXRPresentationFrameData(VALID_POSE_MATRIX, [{ + eye:"left", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewMatrix: VALID_VIEW_MATRIX + }, { + eye:"right", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewMatrix: VALID_VIEW_MATRIX + }]); + + let input_source = new MockXRInputSource(); + input_source.targetRayMode = "tracked-pointer"; + input_source.handedness = "right"; + input_source.grip = VALID_GRIP; + + fakeDeviceController.addInputSource(input_source); + + // Must have a frameOfReference to get input poses. eye-level doesn't apply + // any transforms to the given matrix. + session.requestFrameOfReference("eye-level").then( (frameOfRef) => { + + function CheckTargetRayNoOffset(time, xrFrame) { + let source = session.getInputSources()[0]; + + let input_pose = xrFrame.getInputPose(source, frameOfRef); + + t.step( () => { + assert_matrices_approx_equal(input_pose.targetRay.transformMatrix, + input_pose.gripMatrix, FLOAT_EPSILON, + "Target ray matrix is incorrect."); + + assert_equals(input_pose.targetRay.origin.x, 4.0); + assert_equals(input_pose.targetRay.origin.y, 3.0); + assert_equals(input_pose.targetRay.origin.z, 2.0); + assert_equals(input_pose.targetRay.origin.w, 1.0); + + assert_equals(input_pose.targetRay.direction.x, 0.0); + assert_equals(input_pose.targetRay.direction.y, 0.0); + assert_equals(input_pose.targetRay.direction.z, -1.0); + assert_equals(input_pose.targetRay.direction.w, 0.0); + }, "Target ray computed properly with no pointer offset"); + + input_source.pointerOffset = VALID_POINTER_OFFSET; + + session.requestAnimationFrame(CheckTargetRayOffset); + } + + function CheckTargetRayOffset(time, xrFrame) { + let source = session.getInputSources()[0]; + + let input_pose = xrFrame.getInputPose(source, frameOfRef); + + t.step( () => { + assert_matrices_approx_equal(input_pose.targetRay.transformMatrix, + VALID_GRIP_WITH_POINTER_OFFSET, FLOAT_EPSILON, + "Target ray matrix is not offset properly."); + + assert_equals(input_pose.targetRay.origin.x, 4.0); + assert_equals(input_pose.targetRay.origin.y, 3.0); + assert_equals(input_pose.targetRay.origin.z, 3.0); + assert_equals(input_pose.targetRay.origin.w, 1.0); + + assert_equals(input_pose.targetRay.direction.x, 0.0); + assert_equals(input_pose.targetRay.direction.y, 0.0); + assert_equals(input_pose.targetRay.direction.z, -1.0); + assert_equals(input_pose.targetRay.direction.w, 0.0); + }, "Target ray computed properly with a pointer offset"); + + resolve(); + } + + // Can only request input poses in an xr frame. + session.requestAnimationFrame(CheckTargetRayNoOffset); + }); + }); + +xr_session_promise_test( + testFunction, fakeDeviceInitParams, requestSessionOptions, testName); + +</script>
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index 8680612c..58287cc 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -704,7 +704,6 @@ "platform/modules/cache_storage/cache_storage.mojom", "platform/modules/credentialmanager/credential_manager.mojom", "platform/modules/fetch/fetch_api_request.mojom", - "platform/modules/fetch/fetch_api_response.mojom", "platform/modules/geolocation/geolocation_service.mojom", "platform/modules/hyphenation/hyphenation.mojom", "platform/modules/insecure_input/insecure_input_service.mojom",
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 312a34a..f121b4d 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -22,6 +22,7 @@ "dom_storage/storage_area.mojom", "dom_storage/storage_partition_service.mojom", "feature_policy/feature_policy.mojom", + "fetch/fetch_api_response.mojom", "file/file_utilities.mojom", "frame/find_in_page.mojom", "leak_detector/leak_detector.mojom",
diff --git a/third_party/blink/public/mojom/fetch/OWNERS b/third_party/blink/public/mojom/fetch/OWNERS new file mode 100644 index 0000000..2eaf30a --- /dev/null +++ b/third_party/blink/public/mojom/fetch/OWNERS
@@ -0,0 +1,7 @@ +file://third_party/blink/renderer/core/fetch/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS + +# TEAM: blink-network-dev@chromium.org +# COMPONENT: Blink>Network>FetchAPI
diff --git a/third_party/blink/public/mojom/fetch/README.md b/third_party/blink/public/mojom/fetch/README.md new file mode 100644 index 0000000..1dfa89b --- /dev/null +++ b/third_party/blink/public/mojom/fetch/README.md
@@ -0,0 +1,2 @@ +Public mojom files that are referenced both from browser-side and renderer-side +for [Fetch API](https://fetch.spec.whatwg.org/#fetch-api).
diff --git a/third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom b/third_party/blink/public/mojom/fetch/fetch_api_response.mojom similarity index 100% rename from third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom rename to third_party/blink/public/mojom/fetch/fetch_api_response.mojom
diff --git a/third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom b/third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom index 0cfadd65..67c1693 100644 --- a/third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom +++ b/third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom
@@ -4,8 +4,8 @@ module blink.mojom; +import "third_party/blink/public/mojom/fetch/fetch_api_response.mojom"; import "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom"; -import "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom"; import "mojo/public/mojom/base/string16.mojom"; // This enum is used in histograms, so do not change the ordering and always
diff --git a/third_party/blink/public/web/web_settings.h b/third_party/blink/public/web/web_settings.h index 5c7b6cb..4f82311 100644 --- a/third_party/blink/public/web/web_settings.h +++ b/third_party/blink/public/web/web_settings.h
@@ -171,8 +171,6 @@ virtual void SetEnableScrollAnimator(bool) = 0; virtual void SetEnableTouchAdjustment(bool) = 0; virtual void SetSmoothScrollForFindEnabled(bool) = 0; - virtual bool MultiTargetTapNotificationEnabled() = 0; - virtual void SetMultiTargetTapNotificationEnabled(bool) = 0; virtual void SetWebGL1Enabled(bool) = 0; virtual void SetWebGL2Enabled(bool) = 0; virtual void SetFantasyFontFamily(const WebString&,
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index fcba338..2517f97 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h
@@ -80,7 +80,6 @@ using WebWidget::BeginFrame; using WebWidget::UpdateAllLifecyclePhases; using WebWidget::PaintContent; - using WebWidget::PaintContentIgnoringCompositing; using WebWidget::LayoutAndPaintAsync; using WebWidget::CompositeAndReadbackAsync; using WebWidget::ThemeChanged; @@ -191,11 +190,6 @@ WebRemoteFrame* from, WebLocalFrame* to) {} - // Animate a scale into the specified rect where multiple targets were - // found from previous tap gesture. - // Returns false if it doesn't do any zooming. - virtual bool ZoomToMultipleTargetsRect(const WebRect&) = 0; - // Zoom ---------------------------------------------------------------- // Returns the current zoom level. 0 is "original size", and each increment @@ -358,12 +352,6 @@ // Hides any popup (suggestions, selects...) that might be showing. virtual void HidePopups() = 0; - // Generate a synthetic touch event applying the result of a tap - // disambiguation popup. - virtual void ResolveTapDisambiguation(base::TimeTicks timestamp, - WebPoint tap_viewport_offset, - bool is_long_press) = 0; - // Visited link state -------------------------------------------------- // Tells all WebView instances to update the visited link state for the
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc b/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc index 250fff3..45e8cc1 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc
@@ -122,7 +122,9 @@ } void V8AbstractEventListener::SetListenerObject( - v8::Local<v8::Object> listener) { + ScriptState* script_state, + v8::Local<v8::Object> listener, + const V8PrivateProperty::Symbol& property) { DCHECK(listener_.IsEmpty()); // Balanced in WrapperCleared xor ClearListenerObject. if (worker_or_worklet_global_scope_) { @@ -131,6 +133,7 @@ keep_alive_ = this; } listener_.Set(GetIsolate(), listener, this, &WrapperCleared); + Attach(script_state, listener, property, this); } void V8AbstractEventListener::InvokeEventHandler(
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h b/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h index ee7f642..1bc7551 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h
@@ -118,7 +118,9 @@ return GetExistingListenerObject(); } - void SetListenerObject(v8::Local<v8::Object>); + void SetListenerObject(ScriptState*, + v8::Local<v8::Object>, + const V8PrivateProperty::Symbol&); void InvokeEventHandler(ScriptState*, Event*, v8::Local<v8::Value>);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_error_handler.h b/third_party/blink/renderer/bindings/core/v8/v8_error_handler.h index 39b09623..a5a00fa 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_error_handler.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_error_handler.h
@@ -43,10 +43,11 @@ public: static V8ErrorHandler* Create(v8::Local<v8::Object> listener, bool is_inline, - ScriptState* script_state) { + ScriptState* script_state, + const V8PrivateProperty::Symbol& property) { V8ErrorHandler* event_listener = new V8ErrorHandler(is_inline, script_state); - event_listener->SetListenerObject(listener); + event_listener->SetListenerObject(script_state, listener, property); return event_listener; } static void StoreExceptionOnErrorEventWrapper(
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_event_listener.h b/third_party/blink/renderer/bindings/core/v8/v8_event_listener.h index 0bf5edf..79975681 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_event_listener.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_event_listener.h
@@ -46,10 +46,11 @@ public: static V8EventListener* Create(v8::Local<v8::Object> listener, bool is_attribute, - ScriptState* script_state) { + ScriptState* script_state, + const V8PrivateProperty::Symbol& property) { V8EventListener* event_listener = new V8EventListener(is_attribute, script_state); - event_listener->SetListenerObject(listener); + event_listener->SetListenerObject(script_state, listener, property); return event_listener; }
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_event_listener_helper.cc b/third_party/blink/renderer/bindings/core/v8/v8_event_listener_helper.cc index 06f8c13..5866a90 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_event_listener_helper.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_event_listener_helper.cc
@@ -54,11 +54,7 @@ if (listener || lookup == kListenerFindOnly) return listener; - listener = listener_factory(); - if (listener) { - listener->Attach(script_state, object, listener_property, listener); - } - return listener; + return listener_factory(); } } // namespace @@ -83,12 +79,12 @@ return GetEventListenerInternal<V8EventListener>( script_state, object, listener_property, lookup, - [object, is_attribute, script_state]() { + [object, is_attribute, script_state, listener_property]() { return script_state->World().IsWorkerWorld() ? V8WorkerOrWorkletEventListener::Create( - object, is_attribute, script_state) - : V8EventListener::Create(object, is_attribute, - script_state); + object, is_attribute, script_state, listener_property) + : V8EventListener::Create(object, is_attribute, script_state, + listener_property); }); } @@ -105,9 +101,10 @@ return GetEventListenerInternal<V8ErrorHandler>( script_state, object, listener_property, kListenerFindOrCreate, - [object, script_state]() { + [object, script_state, listener_property]() { const bool is_attribute = true; - return V8ErrorHandler::Create(object, is_attribute, script_state); + return V8ErrorHandler::Create(object, is_attribute, script_state, + listener_property); }); }
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc b/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc index 0313cfc..037eb873 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc
@@ -203,7 +203,9 @@ wrapped_function->SetName(V8String(GetIsolate(), function_name_)); - SetListenerObject(wrapped_function); + SetListenerObject( + script_state, wrapped_function, + V8PrivateProperty::GetV8EventListenerListener(GetIsolate())); } void V8LazyEventListener::FireErrorEvent(v8::Local<v8::Context> v8_context,
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.h b/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.h index fa8e2b9..ee89e9e0 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.h
@@ -41,12 +41,14 @@ class V8WorkerOrWorkletEventListener final : public V8EventListener { public: - static V8WorkerOrWorkletEventListener* Create(v8::Local<v8::Object> listener, - bool is_inline, - ScriptState* script_state) { + static V8WorkerOrWorkletEventListener* Create( + v8::Local<v8::Object> listener, + bool is_inline, + ScriptState* script_state, + const V8PrivateProperty::Symbol& property) { V8WorkerOrWorkletEventListener* event_listener = new V8WorkerOrWorkletEventListener(is_inline, script_state); - event_listener->SetListenerObject(listener); + event_listener->SetListenerObject(script_state, listener, property); return event_listener; }
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.cc b/third_party/blink/renderer/core/css/css_style_sheet.cc index 7af9a18..d4dbe6ad 100644 --- a/third_party/blink/renderer/core/css/css_style_sheet.cc +++ b/third_party/blink/renderer/core/css/css_style_sheet.cc
@@ -214,14 +214,6 @@ ownerNode()->GetTreeScope()); if (StyleResolver* resolver = owner->GetStyleEngine().Resolver()) resolver->InvalidateMatchedPropertiesCache(); - } else if (!constructed_tree_scopes_.IsEmpty()) { - for (auto tree_scope : constructed_tree_scopes_) { - tree_scope->GetDocument().GetStyleEngine().SetNeedsActiveStyleUpdate( - *tree_scope); - if (StyleResolver* resolver = - tree_scope->GetDocument().GetStyleEngine().Resolver()) - resolver->InvalidateMatchedPropertiesCache(); - } } } @@ -576,7 +568,6 @@ visitor->Trace(contents_); visitor->Trace(owner_node_); visitor->Trace(owner_rule_); - visitor->Trace(constructed_tree_scopes_); visitor->Trace(media_cssom_wrapper_); visitor->Trace(child_rule_cssom_wrappers_); visitor->Trace(rule_list_cssom_wrapper_);
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.h b/third_party/blink/renderer/core/css/css_style_sheet.h index 2a3fd74..2ee79dd 100644 --- a/third_party/blink/renderer/core/css/css_style_sheet.h +++ b/third_party/blink/renderer/core/css/css_style_sheet.h
@@ -127,14 +127,6 @@ void SetAllowRuleAccessFromOrigin( scoped_refptr<const SecurityOrigin> allowed_origin); - void AddedConstructedToTreeScope(TreeScope* tree_scope) { - constructed_tree_scopes_.insert(tree_scope); - } - - void RemovedConstructedFromTreeScope(TreeScope* tree_scope) { - constructed_tree_scopes_.erase(tree_scope); - } - class RuleMutationScope { STACK_ALLOCATED(); @@ -230,7 +222,6 @@ Member<Node> owner_node_; Member<CSSRule> owner_rule_; - HeapHashSet<Member<TreeScope>> constructed_tree_scopes_; TextPosition start_position_; Member<MediaList> media_cssom_wrapper_;
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc index b9d0df5..8dafb53 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -90,11 +90,20 @@ } bool ShouldForceLegacyLayout(const ComputedStyle& style, + const ComputedStyle& layout_parent_style, const Element& element) { // Form controls are not supported yet. if (element.ShouldForceLegacyLayout()) return true; + // When the actual parent (to inherit style from) doesn't have a layout box + // (display:contents), it may not have been switched over to forcing legacy + // layout, even if it's inside a subtree that should use legacy. Check with + // the layout parent as well, so that we don't risk switching back to LayoutNG + // when we shouldn't. + if (layout_parent_style.ForceLegacyLayout()) + return true; + // TODO(layout-dev): Once LayoutNG handles inline content editable, we // should get rid of following code fragment. const Document& document = element.GetDocument(); @@ -711,7 +720,8 @@ } if (RuntimeEnabledFeatures::LayoutNGEnabled() && !style.ForceLegacyLayout() && - element && ShouldForceLegacyLayout(style, *element)) { + element && + ShouldForceLegacyLayout(style, layout_parent_style, *element)) { style.SetForceLegacyLayout(true); }
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index e5dae0b0..924e9820 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3043,15 +3043,12 @@ DCHECK(!ImportLoader()); if (frame_) { + // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps + // If |document| has an active parser whose script nesting level is greater + // than 0, then return |document|. if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) { - if (parser->IsParsing()) { - // FIXME: HTML5 doesn't tell us to check this, it might not be correct. - if (parser->IsExecutingScript()) - return; - - if (!parser->WasCreatedByScript() && parser->HasInsertionPoint()) - return; - } + if (parser->IsParsing() && parser->IsExecutingScript()) + return; } if (frame_->Loader().HasProvisionalNavigation()) {
diff --git a/third_party/blink/renderer/core/dom/dom_implementation.cc b/third_party/blink/renderer/core/dom/dom_implementation.cc index a2fbf847..c360933 100644 --- a/third_party/blink/renderer/core/dom/dom_implementation.cc +++ b/third_party/blink/renderer/core/dom/dom_implementation.cc
@@ -262,8 +262,10 @@ init, plugin_data->PluginBackgroundColorForMimeType(type)); } // multipart/x-mixed-replace is only supported for images. - if (Image::SupportsType(type) || type == "multipart/x-mixed-replace") + if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(type) || + type == "multipart/x-mixed-replace") { return ImageDocument::Create(init); + } // Check to see if the type can be played by our media player, if so create a // MediaDocument
diff --git a/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc b/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc index 0c31deb..17fe93c 100644 --- a/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc
@@ -37,12 +37,13 @@ GetDocument().body()->setContentEditable("false", ASSERT_NO_EXCEPTION); GetDocument().setDesignMode("on"); GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); - Selection().SetSelectionAndEndTyping( + Selection().SetSelection( SelectionInDOMTree::Builder() .SetBaseAndExtent( Position(GetDocument().documentElement(), 1), Position(GetDocument().getElementById("va")->firstChild(), 2)) - .Build()); + .Build(), + SetSelectionOptions()); FormatBlockCommand* command = FormatBlockCommand::Create(GetDocument(), HTMLNames::footerTag); @@ -63,10 +64,11 @@ GetDocument().setDesignMode("on"); UpdateAllLifecyclePhases(); - Selection().SetSelectionAndEndTyping( + Selection().SetSelection( SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().QuerySelector("li"), 0)) - .Build()); + .Build(), + SetSelectionOptions()); IndentOutdentCommand* command = IndentOutdentCommand::Create( GetDocument(), IndentOutdentCommand::kIndent); @@ -87,10 +89,11 @@ "</div>"); Element* button = GetDocument().QuerySelector("button"); Element* object = GetDocument().QuerySelector("object"); - Selection().SetSelectionAndEndTyping(SelectionInDOMTree::Builder() - .Collapse(Position(button, 0)) - .Extend(Position(object, 0)) - .Build()); + Selection().SetSelection(SelectionInDOMTree::Builder() + .Collapse(Position(button, 0)) + .Extend(Position(object, 0)) + .Build(), + SetSelectionOptions()); IndentOutdentCommand* command = IndentOutdentCommand::Create( GetDocument(), IndentOutdentCommand::kIndent); @@ -113,8 +116,10 @@ TEST_F(ApplyBlockElementCommandTest, InsertPlaceHolderAtDisconnectedPosition) { GetDocument().setDesignMode("on"); InsertStyleElement(".input:nth-of-type(2n+1) { visibility:collapse; }"); - Selection().SetSelectionAndEndTyping(SetSelectionTextToBody( - "^<input><input class=\"input\" style=\"position:absolute\">|")); + Selection().SetSelection( + SetSelectionTextToBody( + "^<input><input class=\"input\" style=\"position:absolute\">|"), + SetSelectionOptions()); FormatBlockCommand* command = FormatBlockCommand::Create(GetDocument(), HTMLNames::preTag); // Crash happens here.
diff --git a/third_party/blink/renderer/core/editing/commands/apply_style_command_test.cc b/third_party/blink/renderer/core/editing/commands/apply_style_command_test.cc index 93e43d8..edbe6e4 100644 --- a/third_party/blink/renderer/core/editing/commands/apply_style_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/apply_style_command_test.cc
@@ -35,10 +35,11 @@ Element* li = GetDocument().QuerySelector("li"); LocalFrame* frame = GetDocument().GetFrame(); - frame->Selection().SetSelectionAndEndTyping( + frame->Selection().SetSelection( SelectionInDOMTree::Builder() .Collapse(Position(li, PositionAnchorType::kBeforeAnchor)) - .Build()); + .Build(), + SetSelectionOptions()); MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode); @@ -82,8 +83,10 @@ // This is a regression test for https://crbug.com/726992 TEST_F(ApplyStyleCommandTest, FontSizeDeltaWithSpanElement) { - Selection().SetSelectionAndEndTyping(SetSelectionTextToBody( - "<div contenteditable>^<div></div>a<span></span>|</div>")); + Selection().SetSelection( + SetSelectionTextToBody( + "<div contenteditable>^<div></div>a<span></span>|</div>"), + SetSelectionOptions()); MutableCSSPropertyValueSet* style = MutableCSSPropertyValueSet::Create(kHTMLQuirksMode);
diff --git a/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc b/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc index 77cb714a..92d26c6 100644 --- a/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc
@@ -37,11 +37,12 @@ Element* br = GetDocument().QuerySelector("br"); LocalFrame* frame = GetDocument().GetFrame(); - frame->Selection().SetSelectionAndEndTyping( + frame->Selection().SetSelection( SelectionInDOMTree::Builder() .Collapse(Position(br, PositionAnchorType::kBeforeAnchor)) .Extend(Position(table, PositionAnchorType::kAfterAnchor)) - .Build()); + .Build(), + SetSelectionOptions()); DeleteSelectionCommand* command = DeleteSelectionCommand::Create(GetDocument(), @@ -63,8 +64,9 @@ TEST_F(DeleteSelectionCommandTest, ForwardDeleteWithFirstLetter) { InsertStyleElement("p::first-letter {font-size:200%;}"); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<p contenteditable>a^b|c</p>")); + Selection().SetSelection( + SetSelectionTextToBody("<p contenteditable>a^b|c</p>"), + SetSelectionOptions()); DeleteSelectionCommand& command = *DeleteSelectionCommand::Create( GetDocument(), DeleteSelectionOptions::Builder()
diff --git a/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command_test.cc b/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command_test.cc index 890caeb..b36ae21 100644 --- a/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command_test.cc
@@ -17,11 +17,11 @@ SetBodyContent("<div id=sample contenteditable><a>a</a>b😺</div>"); Element* const sample = GetDocument().getElementById("sample"); const String new_text(Vector<UChar>{0xD83D, 0xDE38}); // U+1F638 - Selection().SetSelectionAndEndTyping( - SelectionInDOMTree::Builder() - .Collapse(Position(sample->lastChild(), 1)) - .Extend(Position(sample->lastChild(), 3)) - .Build()); + Selection().SetSelection(SelectionInDOMTree::Builder() + .Collapse(Position(sample->lastChild(), 1)) + .Extend(Position(sample->lastChild(), 3)) + .Build(), + SetSelectionOptions()); CompositeEditCommand* const command = InsertIncrementalTextCommand::Create(GetDocument(), new_text); command->Apply(); @@ -35,11 +35,11 @@ SetBodyContent("<div id=sample contenteditable><a>a</a>b😺</div>"); Element* const sample = GetDocument().getElementById("sample"); const String new_text(Vector<UChar>{0xD83D, 0xDE3A}); // U+1F63A - Selection().SetSelectionAndEndTyping( - SelectionInDOMTree::Builder() - .Collapse(Position(sample->lastChild(), 1)) - .Extend(Position(sample->lastChild(), 3)) - .Build()); + Selection().SetSelection(SelectionInDOMTree::Builder() + .Collapse(Position(sample->lastChild(), 1)) + .Extend(Position(sample->lastChild(), 3)) + .Build(), + SetSelectionOptions()); CompositeEditCommand* const command = InsertIncrementalTextCommand::Create(GetDocument(), new_text); command->Apply(); @@ -55,11 +55,11 @@ "<div id=sample contenteditable><a>a</a>b😺😺</div>"); Element* const sample = GetDocument().getElementById("sample"); const String new_text(Vector<UChar>{0xD83D, 0xDE38}); // U+1F638 - Selection().SetSelectionAndEndTyping( - SelectionInDOMTree::Builder() - .Collapse(Position(sample->lastChild(), 1)) - .Extend(Position(sample->lastChild(), 5)) - .Build()); + Selection().SetSelection(SelectionInDOMTree::Builder() + .Collapse(Position(sample->lastChild(), 1)) + .Extend(Position(sample->lastChild(), 5)) + .Build(), + SetSelectionOptions()); CompositeEditCommand* const command = InsertIncrementalTextCommand::Create(GetDocument(), new_text); command->Apply();
diff --git a/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc b/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc index 66f7fb6..e7a61e4 100644 --- a/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc
@@ -36,11 +36,12 @@ GetDocument().body()->InsertBefore(empty_text, GetDocument().body()->firstChild()); UpdateAllLifecyclePhases(); - GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( + GetDocument().GetFrame()->Selection().SetSelection( SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body(), 0)) .Extend(Position(GetDocument().body(), 2)) - .Build()); + .Build(), + SetSelectionOptions()); InsertListCommand* command = InsertListCommand::Create(GetDocument(), InsertListCommand::kOrderedList); @@ -53,10 +54,11 @@ // Refer https://crbug.com/794356 TEST_F(InsertListCommandTest, UnlistifyParagraphCrashOnVisuallyEmptyParagraph) { GetDocument().setDesignMode("on"); - Selection().SetSelectionAndEndTyping( + Selection().SetSelection( SetSelectionTextToBody("^<dl>" "<textarea style='float:left;'></textarea>" - "</dl>|")); + "</dl>|"), + SetSelectionOptions()); InsertListCommand* command = InsertListCommand::Create( GetDocument(), InsertListCommand::kUnorderedList); // Crash happens here. @@ -75,9 +77,9 @@ "* { -webkit-appearance:checkbox; }" "br { visibility:hidden; }" "colgroup { -webkit-column-count:2; }"); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("^<table><col></table>" - "<button></button>|")); + Selection().SetSelection(SetSelectionTextToBody("^<table><col></table>" + "<button></button>|"), + SetSelectionOptions()); InsertListCommand* command = InsertListCommand::Create( GetDocument(), InsertListCommand::kUnorderedList); @@ -97,8 +99,8 @@ TEST_F(InsertListCommandTest, InsertListOnEmptyHiddenElements) { GetDocument().setDesignMode("on"); InsertStyleElement("br { visibility:hidden; }"); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("^<button></button>|")); + Selection().SetSelection(SetSelectionTextToBody("^<button></button>|"), + SetSelectionOptions()); InsertListCommand* command = InsertListCommand::Create( GetDocument(), InsertListCommand::kUnorderedList); @@ -118,7 +120,8 @@ "ul { visibility:collapse; }" "dl { visibility:visible; }"); - Selection().SetSelectionAndEndTyping(SetSelectionTextToBody("^<dl>a</dl>|")); + Selection().SetSelection(SetSelectionTextToBody("^<dl>a</dl>|"), + SetSelectionOptions()); InsertListCommand* command = InsertListCommand::Create(GetDocument(), InsertListCommand::kOrderedList);
diff --git a/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command_test.cc b/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command_test.cc index fab7d12..14e4e6f 100644 --- a/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command_test.cc
@@ -17,10 +17,12 @@ // http://crbug.com/777378 TEST_F(InsertParagraphSeparatorCommandTest, CrashWithAppearanceStyleOnEmptyColgroup) { - Selection().SetSelectionAndEndTyping(SetSelectionTextToBody( - "<table contenteditable>" - " <colgroup style='-webkit-appearance:radio;'><!--|--></colgroup>" - "</table>")); + Selection().SetSelection( + SetSelectionTextToBody( + "<table contenteditable>" + " <colgroup style='-webkit-appearance:radio;'><!--|--></colgroup>" + "</table>"), + SetSelectionOptions()); InsertParagraphSeparatorCommand* command = InsertParagraphSeparatorCommand::Create(GetDocument()); @@ -37,12 +39,13 @@ // http://crbug.com/777378 TEST_F(InsertParagraphSeparatorCommandTest, CrashWithAppearanceStyleOnEmptyColumn) { - Selection().SetSelectionAndEndTyping( + Selection().SetSelection( SetSelectionTextToBody("<table contenteditable>" " <colgroup style='-webkit-appearance:radio;'>" " <col><!--|--></col>" " </colgroup>" - "</table>")); + "</table>"), + SetSelectionOptions()); InsertParagraphSeparatorCommand* command = InsertParagraphSeparatorCommand::Create(GetDocument());
diff --git a/third_party/blink/renderer/core/editing/commands/insert_text_command_test.cc b/third_party/blink/renderer/core/editing/commands/insert_text_command_test.cc index 0b712ab..abfe0844 100644 --- a/third_party/blink/renderer/core/editing/commands/insert_text_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/insert_text_command_test.cc
@@ -17,8 +17,9 @@ TEST_F(InsertTextCommandTest, WithTypingStyle) { SetBodyContent("<div contenteditable=true><option id=sample></option></div>"); Element* const sample = GetDocument().getElementById("sample"); - Selection().SetSelectionAndEndTyping( - SelectionInDOMTree::Builder().Collapse(Position(sample, 0)).Build()); + Selection().SetSelection( + SelectionInDOMTree::Builder().Collapse(Position(sample, 0)).Build(), + SetSelectionOptions()); // Register typing style to make |InsertTextCommand| to attempt to apply // style to inserted text. GetDocument().execCommand("fontSizeDelta", false, "+3", ASSERT_NO_EXCEPTION); @@ -35,8 +36,9 @@ // http://crbug.com/741826 TEST_F(InsertTextCommandTest, InsertChar) { - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<p contenteditable><span>\ta|c</span></p>")); + Selection().SetSelection( + SetSelectionTextToBody("<p contenteditable><span>\ta|c</span></p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "B", ASSERT_NO_EXCEPTION); EXPECT_EQ("<p contenteditable><span>\taB|c</span></p>", GetSelectionTextFromBody()) @@ -45,8 +47,10 @@ // http://crbug.com/741826 TEST_F(InsertTextCommandTest, InsertCharToWhiteSpacePre) { - Selection().SetSelectionAndEndTyping(SetSelectionTextToBody( - "<p contenteditable><span style='white-space:pre'>\ta|c</span></p>")); + Selection().SetSelection( + SetSelectionTextToBody( + "<p contenteditable><span style='white-space:pre'>\ta|c</span></p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "B", ASSERT_NO_EXCEPTION); EXPECT_EQ( "<p contenteditable>" @@ -60,8 +64,9 @@ // http://crbug.com/741826 TEST_F(InsertTextCommandTest, InsertSpace) { - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<p contenteditable><span>\ta|c</span></p>")); + Selection().SetSelection( + SetSelectionTextToBody("<p contenteditable><span>\ta|c</span></p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, " ", ASSERT_NO_EXCEPTION); EXPECT_EQ("<p contenteditable><span>\ta\xC2\xA0 |c</span></p>", GetSelectionTextFromBody()) @@ -70,8 +75,10 @@ // http://crbug.com/741826 TEST_F(InsertTextCommandTest, InsertSpaceToWhiteSpacePre) { - Selection().SetSelectionAndEndTyping(SetSelectionTextToBody( - "<p contenteditable><span style='white-space:pre'>\ta|c</span></p>")); + Selection().SetSelection( + SetSelectionTextToBody( + "<p contenteditable><span style='white-space:pre'>\ta|c</span></p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, " ", ASSERT_NO_EXCEPTION); EXPECT_EQ( "<p contenteditable>" @@ -84,8 +91,9 @@ // http://crbug.com/741826 TEST_F(InsertTextCommandTest, InsertTab) { - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<p contenteditable><span>\ta|c</span></p>")); + Selection().SetSelection( + SetSelectionTextToBody("<p contenteditable><span>\ta|c</span></p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "\t", ASSERT_NO_EXCEPTION); EXPECT_EQ( "<p contenteditable>" @@ -96,8 +104,10 @@ // http://crbug.com/741826 TEST_F(InsertTextCommandTest, InsertTabToWhiteSpacePre) { - Selection().SetSelectionAndEndTyping(SetSelectionTextToBody( - "<p contenteditable><span style='white-space:pre'>\ta|c</span></p>")); + Selection().SetSelection( + SetSelectionTextToBody( + "<p contenteditable><span style='white-space:pre'>\ta|c</span></p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "\t", ASSERT_NO_EXCEPTION); EXPECT_EQ( "<p contenteditable><span style=\"white-space:pre\">\ta\t|c</span></p>", @@ -106,40 +116,45 @@ // http://crbug.com/752860 TEST_F(InsertTextCommandTest, WhitespaceFixupBeforeParagraph) { - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable>qux ^bar|<p>baz</p>")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>qux ^bar|<p>baz</p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "", ASSERT_NO_EXCEPTION); // The space after "qux" should have been converted to a no-break space // (U+00A0) to prevent it from being collapsed. EXPECT_EQ("<div contenteditable>qux\xC2\xA0|<p>baz</p></div>", GetSelectionTextFromBody()); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable>qux^ bar|<p>baz</p>")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>qux^ bar|<p>baz</p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, " ", ASSERT_NO_EXCEPTION); // The newly-inserted space should have been converted to a no-break space // (U+00A0) to prevent it from being collapsed. EXPECT_EQ("<div contenteditable>qux\xC2\xA0|<p>baz</p></div>", GetSelectionTextFromBody()); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable>qux^bar| <p>baz</p>")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>qux^bar| <p>baz</p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "", ASSERT_NO_EXCEPTION); // The space after "bar" was already being collapsed before the edit. It // should not have been converted to a no-break space. EXPECT_EQ("<div contenteditable>qux|<p>baz</p></div>", GetSelectionTextFromBody()); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable>qux^bar |<p>baz</p>")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>qux^bar |<p>baz</p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, " ", ASSERT_NO_EXCEPTION); // The newly-inserted space should have been converted to a no-break space // (U+00A0) to prevent it from being collapsed. EXPECT_EQ("<div contenteditable>qux\xC2\xA0|<p>baz</p></div>", GetSelectionTextFromBody()); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable>qux\t^bar|<p>baz</p>")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>qux\t^bar|<p>baz</p>"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "", ASSERT_NO_EXCEPTION); // The tab should have been converted to a no-break space (U+00A0) to prevent // it from being collapsed. @@ -148,40 +163,45 @@ } TEST_F(InsertTextCommandTest, WhitespaceFixupAfterParagraph) { - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable><p>baz</p>^bar| qux")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable><p>baz</p>^bar| qux"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "", ASSERT_NO_EXCEPTION); // The space before "qux" should have been converted to a no-break space // (U+00A0) to prevent it from being collapsed. EXPECT_EQ("<div contenteditable><p>baz</p>|\xC2\xA0qux</div>", GetSelectionTextFromBody()); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable><p>baz</p>^bar |qux")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable><p>baz</p>^bar |qux"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, " ", ASSERT_NO_EXCEPTION); // The newly-inserted space should have been converted to a no-break space // (U+00A0) to prevent it from being collapsed. EXPECT_EQ("<div contenteditable><p>baz</p>\xC2\xA0|qux</div>", GetSelectionTextFromBody()); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable><p>baz</p> ^bar|qux")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable><p>baz</p> ^bar|qux"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "", ASSERT_NO_EXCEPTION); // The space before "bar" was already being collapsed before the edit. It // should not have been converted to a no-break space. EXPECT_EQ("<div contenteditable><p>baz</p>|qux</div>", GetSelectionTextFromBody()); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable><p>baz</p>^ bar|qux")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable><p>baz</p>^ bar|qux"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, " ", ASSERT_NO_EXCEPTION); // The newly-inserted space should have been converted to a no-break space // (U+00A0) to prevent it from being collapsed. EXPECT_EQ("<div contenteditable><p>baz</p>\xC2\xA0|qux</div>", GetSelectionTextFromBody()); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable><p>baz</p>^bar|\tqux")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable><p>baz</p>^bar|\tqux"), + SetSelectionOptions()); GetDocument().execCommand("insertText", false, "", ASSERT_NO_EXCEPTION); // The tab should have been converted to a no-break space (U+00A0) to prevent // it from being collapsed. @@ -195,14 +215,15 @@ InsertStyleElement( "ruby {display: inline-block; height: 100%}" "navi {float: left}"); - Selection().SetSelectionAndEndTyping( + Selection().SetSelection( SetSelectionTextToBody("<div contenteditable>" " <ruby><strike>" " <navi></navi>" " <rtc>^믃7躙ᕐ</rtc>" " </strike></ruby>" " <hr>|" - "</div>")); + "</div>"), + SetSelectionOptions()); // Shouldn't crash inside GetDocument().execCommand("insertText", false, "x", ASSERT_NO_EXCEPTION); // This is only for recording the current behavior, which can be changed. @@ -225,10 +246,11 @@ body->parentNode()->appendChild(style); GetDocument().setDesignMode("on"); - Selection().SetSelectionAndEndTyping(SelectionInDOMTree::Builder() - .Collapse(Position(head, 0)) - .Extend(Position(body, 0)) - .Build()); + Selection().SetSelection(SelectionInDOMTree::Builder() + .Collapse(Position(head, 0)) + .Extend(Position(body, 0)) + .Build(), + SetSelectionOptions()); // Shouldn't crash inside GetDocument().execCommand("insertText", false, "\t", ASSERT_NO_EXCEPTION); @@ -266,11 +288,12 @@ nested_anchor->AppendChild(iElement); Node* const iElement_text_node = iElement->firstChild(); - Selection().SetSelectionAndEndTyping( + Selection().SetSelection( SelectionInDOMTree::Builder() .SetBaseAndExtent(Position(iElement_text_node, 0), Position(iElement_text_node, 4)) - .Build()); + .Build(), + SetSelectionOptions()); // Crash happens here with when '\n' is inserted. GetDocument().execCommand("inserttext", false, "a\n", ASSERT_NO_EXCEPTION); EXPECT_EQ(
diff --git a/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc b/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc index 73bb44c..b74e7f1 100644 --- a/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc
@@ -33,10 +33,11 @@ SetBodyContent("foo"); LocalFrame* frame = GetDocument().GetFrame(); - frame->Selection().SetSelectionAndEndTyping( + frame->Selection().SetSelection( SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body(), 0)) - .Build()); + .Build(), + SetSelectionOptions()); DocumentFragment* fragment = GetDocument().createDocumentFragment(); fragment->AppendChild(GetDocument().CreateRawElement(HTMLNames::spanTag)); @@ -64,10 +65,11 @@ Element* b_element = GetDocument().QuerySelector("b"); LocalFrame* frame = GetDocument().GetFrame(); - frame->Selection().SetSelectionAndEndTyping( + frame->Selection().SetSelection( SelectionInDOMTree::Builder() .Collapse(Position(b_element->firstChild(), 1)) - .Build()); + .Build(), + SetSelectionOptions()); DocumentFragment* fragment = GetDocument().createDocumentFragment(); fragment->ParseHTML("<span><div>bar</div></span>", b_element); @@ -85,10 +87,11 @@ TEST_F(ReplaceSelectionCommandTest, styleTagsInPastedHeadIncludedInContent) { GetDocument().setDesignMode("on"); UpdateAllLifecyclePhases(); - GetDummyPageHolder().GetFrame().Selection().SetSelectionAndEndTyping( + GetDummyPageHolder().GetFrame().Selection().SetSelection( SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body(), 0)) - .Build()); + .Build(), + SetSelectionOptions()); DocumentFragment* fragment = GetDocument().createDocumentFragment(); fragment->ParseHTML( @@ -137,11 +140,12 @@ Element* span = GetDocument().QuerySelector("span"); // Select "bar". - GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( + GetDocument().GetFrame()->Selection().SetSelection( SelectionInDOMTree::Builder() .Collapse(Position(span->firstChild(), 4)) .Extend(Position(span->firstChild(), 7)) - .Build()); + .Build(), + SetSelectionOptions()); DocumentFragment* fragment = GetDocument().createDocumentFragment(); fragment->ParseHTML("baz", span); @@ -160,8 +164,8 @@ // This is a regression test for https://crbug.com/781282 TEST_F(ReplaceSelectionCommandTest, TrailingNonVisibleTextCrash) { GetDocument().setDesignMode("on"); - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div>^foo|</div>")); + Selection().SetSelection(SetSelectionTextToBody("<div>^foo|</div>"), + SetSelectionOptions()); DocumentFragment* fragment = GetDocument().createDocumentFragment(); fragment->ParseHTML("<div>bar</div> ", GetDocument().QuerySelector("div"));
diff --git a/third_party/blink/renderer/core/editing/commands/typing_command_test.cc b/third_party/blink/renderer/core/editing/commands/typing_command_test.cc index a684a21..a020f98 100644 --- a/third_party/blink/renderer/core/editing/commands/typing_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/typing_command_test.cc
@@ -45,10 +45,11 @@ div->AppendChild(tr); LocalFrame* frame = GetDocument().GetFrame(); - frame->Selection().SetSelectionAndEndTyping(SelectionInDOMTree::Builder() - .Collapse(Position(form, 0)) - .Extend(Position(header, 0)) - .Build()); + frame->Selection().SetSelection(SelectionInDOMTree::Builder() + .Collapse(Position(form, 0)) + .Extend(Position(header, 0)) + .Build(), + SetSelectionOptions()); // Inserting line break should not crash or hit assertion. TypingCommand::InsertLineBreak(GetDocument()); @@ -57,8 +58,9 @@ // http://crbug.com/767599 TEST_F(TypingCommandTest, DontCrashWhenReplaceSelectionCommandLeavesBadSelection) { - Selection().SetSelectionAndEndTyping( - SetSelectionTextToBody("<div contenteditable>^<h1>H1</h1>ello|</div>")); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>^<h1>H1</h1>ello|</div>"), + SetSelectionOptions()); // This call shouldn't crash. TypingCommand::InsertText( @@ -71,13 +73,15 @@ // crbug.com/794397 TEST_F(TypingCommandTest, ForwardDeleteInvalidatesSelection) { GetDocument().setDesignMode("on"); - Selection().SetSelectionAndEndTyping(SetSelectionTextToBody( - "<blockquote>^" - "<q>" - "<table contenteditable=\"false\"><colgroup width=\"-1\">\n</table>|" - "</q>" - "</blockquote>" - "<q>\n<svg></svg></q>")); + Selection().SetSelection( + SetSelectionTextToBody( + "<blockquote>^" + "<q>" + "<table contenteditable=\"false\"><colgroup width=\"-1\">\n</table>|" + "</q>" + "</blockquote>" + "<q>\n<svg></svg></q>"), + SetSelectionOptions()); EditingState editing_state; TypingCommand::ForwardDeleteKeyPressed(GetDocument(), &editing_state);
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc index 5b780a4a..650ea7a 100644 --- a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc +++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
@@ -271,6 +271,7 @@ void DocumentMarkerController::AddMarkerToNode(const Node& node, DocumentMarker* new_marker) { + DCHECK_GE(ToText(node).length(), new_marker->EndOffset()); possibly_existing_marker_types_ = possibly_existing_marker_types_.Add( DocumentMarker::MarkerTypes(new_marker->GetType())); SetContext(document_);
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index c9bd8d9..4f5d20f 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -3433,13 +3433,6 @@ scale = web_view_impl->PageScaleFactor(); } -void SimulateMultiTargetZoom(WebViewImpl* web_view_impl, - const WebRect& rect, - float& scale) { - if (web_view_impl->ZoomToMultipleTargetsRect(rect)) - SimulatePageScale(web_view_impl, scale); -} - void SimulateDoubleTap(WebViewImpl* web_view_impl, WebPoint& point, float& scale) { @@ -4001,46 +3994,6 @@ EXPECT_EQ(rect_right_bottom, block_bound); } -TEST_F(WebFrameTest, DivMultipleTargetZoomMultipleDivsTest) { - RegisterMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html"); - - const float kDeviceScaleFactor = 2.0f; - int viewport_width = 640 / kDeviceScaleFactor; - int viewport_height = 1280 / kDeviceScaleFactor; - float double_tap_zoom_already_legible_ratio = 1.2f; - FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad( - base_url_ + "get_multiple_divs_for_auto_zoom_test.html"); - web_view_helper.Resize(WebSize(viewport_width, viewport_height)); - web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.5f, 4); - web_view_helper.GetWebView()->SetDeviceScaleFactor(kDeviceScaleFactor); - web_view_helper.GetWebView()->SetPageScaleFactor(0.5f); - web_view_helper.GetWebView()->SetMaximumLegibleScale(1.f); - web_view_helper.GetWebView()->UpdateAllLifecyclePhases(); - - web_view_helper.GetWebView()->EnableFakePageScaleAnimationForTesting(true); - - WebRect viewport_rect(0, 0, viewport_width, viewport_height); - WebRect top_div(200, 100, 200, 150); - WebRect bottom_div(200, 300, 200, 150); - float scale; - SetScaleAndScrollAndLayout( - web_view_helper.GetWebView(), WebPoint(0, 0), - (web_view_helper.GetWebView()->MinimumPageScaleFactor()) * - (1 + double_tap_zoom_already_legible_ratio) / 2); - - SimulateMultiTargetZoom(web_view_helper.GetWebView(), top_div, scale); - EXPECT_FLOAT_EQ(1, scale); - SimulateMultiTargetZoom(web_view_helper.GetWebView(), bottom_div, scale); - EXPECT_FLOAT_EQ(1, scale); - SimulateMultiTargetZoom(web_view_helper.GetWebView(), viewport_rect, scale); - EXPECT_FLOAT_EQ(1, scale); - web_view_helper.GetWebView()->SetPageScaleFactor( - web_view_helper.GetWebView()->MinimumPageScaleFactor()); - SimulateMultiTargetZoom(web_view_helper.GetWebView(), top_div, scale); - EXPECT_FLOAT_EQ(1, scale); -} - TEST_F(WebFrameTest, DontZoomInOnFocusedInTouchAction) { RegisterMockedHttpURLLoad("textbox_in_touch_action.html"); @@ -6530,317 +6483,6 @@ #endif #endif -class DisambiguationPopupTestWebViewClient - : public FrameTestHelpers::TestWebViewClient { - public: - DisambiguationPopupTestWebViewClient() = default; - ~DisambiguationPopupTestWebViewClient() override = default; - - // FrameTestHelpers::TestWebViewClient: - bool DidTapMultipleTargets(const WebSize&, - const WebRect&, - const WebVector<WebRect>& target_rects) override { - EXPECT_GE(target_rects.size(), 2u); - triggered_ = true; - return true; - } - - bool Triggered() const { return triggered_; } - void ResetTriggered() { triggered_ = false; } - bool triggered_; -}; - -static WebCoalescedInputEvent FatTap(int x, int y, int diameter) { - WebGestureEvent event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers, - WebInputEvent::GetStaticTimeStampForTests(), - kWebGestureDeviceTouchscreen); - event.SetPositionInWidget(WebFloatPoint(x, y)); - event.data.tap.width = diameter; - event.data.tap.height = diameter; - return WebCoalescedInputEvent(event); -} - -TEST_F(WebFrameTest, DisambiguationPopup) { - const std::string html_file = "disambiguation_popup.html"; - RegisterMockedHttpURLLoad(html_file); - - DisambiguationPopupTestWebViewClient client; - const int kTapDiameter = 100; - - // Make sure we initialize to minimum scale, even if the window size - // only becomes available after the load begins. - FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, &client); - web_view_helper.Resize(WebSize(1000, 1000)); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent(FatTap(0, 0, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(200, 115, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - - for (int i = 0; i <= 46; i++) { - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(120, 230 + i * 5, kTapDiameter)); - - int j = i % 10; - if (j >= 7 && j <= 9) - EXPECT_TRUE(client.Triggered()); - else - EXPECT_FALSE(client.Triggered()); - } - - for (int i = 0; i <= 46; i++) { - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(10 + i * 5, 590, kTapDiameter)); - - int j = i % 10; - if (j >= 7 && j <= 9) - EXPECT_TRUE(client.Triggered()); - else - EXPECT_FALSE(client.Triggered()); - } - - // The same taps shouldn't trigger didTapMultipleTargets() after disabling the - // notification for multi-target-tap. - web_view_helper.GetWebView() - ->GetSettings() - ->SetMultiTargetTapNotificationEnabled(false); - - for (int i = 0; i <= 46; i++) { - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(10 + i * 5, 590, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - } -} - -TEST_F(WebFrameTest, DisambiguationPopupNoContainer) { - RegisterMockedHttpURLLoad("disambiguation_popup_no_container.html"); - - DisambiguationPopupTestWebViewClient client; - const int kTapDiameter = 100; - - // Make sure we initialize to minimum scale, even if the window size - // only becomes available after the load begins. - FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad( - base_url_ + "disambiguation_popup_no_container.html", nullptr, &client); - web_view_helper.Resize(WebSize(1000, 1000)); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent(FatTap(50, 50, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); -} - -TEST_F(WebFrameTest, DisambiguationPopupMobileSite) { - const std::string html_file = "disambiguation_popup_mobile_site.html"; - RegisterMockedHttpURLLoad(html_file); - - DisambiguationPopupTestWebViewClient client; - const int kTapDiameter = 100; - - // Make sure we initialize to minimum scale, even if the window size - // only becomes available after the load begins. - FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, &client, - nullptr, ConfigureAndroid); - web_view_helper.Resize(WebSize(1000, 1000)); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent(FatTap(0, 0, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(200, 115, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - - for (int i = 0; i <= 46; i++) { - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(120, 230 + i * 5, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - } - - for (int i = 0; i <= 46; i++) { - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(10 + i * 5, 590, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - } -} - -TEST_F(WebFrameTest, DisambiguationPopupViewportSite) { - const std::string html_file = "disambiguation_popup_viewport_site.html"; - RegisterMockedHttpURLLoad(html_file); - - DisambiguationPopupTestWebViewClient client; - const int kTapDiameter = 100; - - // Make sure we initialize to minimum scale, even if the window size - // only becomes available after the load begins. - FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, &client, - nullptr, ConfigureAndroid); - web_view_helper.Resize(WebSize(1000, 1000)); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent(FatTap(0, 0, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(200, 115, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - - for (int i = 0; i <= 46; i++) { - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(120, 230 + i * 5, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - } - - for (int i = 0; i <= 46; i++) { - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(10 + i * 5, 590, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - } -} - -TEST_F(WebFrameTest, DisambiguationPopupVisualViewport) { - const std::string html_file = "disambiguation_popup_200_by_800.html"; - RegisterMockedHttpURLLoad(html_file); - - DisambiguationPopupTestWebViewClient client; - const int kTapDiameter = 100; - - FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, &client, - nullptr, ConfigureAndroid); - - WebViewImpl* web_view_impl = web_view_helper.GetWebView(); - ASSERT_TRUE(web_view_impl); - LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame(); - ASSERT_TRUE(frame); - - web_view_helper.Resize(WebSize(100, 200)); - - // Scroll main frame to the bottom of the document - web_view_impl->MainFrameImpl()->SetScrollOffset(WebSize(0, 400)); - EXPECT_EQ(ScrollOffset(0, 400), - frame->View()->LayoutViewport()->GetScrollOffset()); - - web_view_impl->SetPageScaleFactor(2.0); - - // Scroll visual viewport to the top of the main frame. - VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport(); - visual_viewport.SetLocation(FloatPoint(0, 0)); - EXPECT_EQ(ScrollOffset(0, 0), visual_viewport.GetScrollOffset()); - - // Tap at the top: there is nothing there. - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent(FatTap(10, 60, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - - // Scroll visual viewport to the bottom of the main frame. - visual_viewport.SetLocation(FloatPoint(0, 200)); - EXPECT_EQ(ScrollOffset(0, 200), visual_viewport.GetScrollOffset()); - - // Now the tap with the same coordinates should hit two elements. - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent(FatTap(10, 60, kTapDiameter)); - EXPECT_TRUE(client.Triggered()); - - // The same tap shouldn't trigger didTapMultipleTargets() after disabling the - // notification for multi-target-tap. - web_view_helper.GetWebView() - ->GetSettings() - ->SetMultiTargetTapNotificationEnabled(false); - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent(FatTap(10, 60, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); -} - -TEST_F(WebFrameTest, DisambiguationPopupBlacklist) { - const unsigned kViewportWidth = 500; - const unsigned kViewportHeight = 1000; - const unsigned kDivHeight = 100; - const std::string html_file = "disambiguation_popup_blacklist.html"; - RegisterMockedHttpURLLoad(html_file); - - DisambiguationPopupTestWebViewClient client; - const int kTapDiameter = 100; - - // Make sure we initialize to minimum scale, even if the window size - // only becomes available after the load begins. - FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, &client); - web_view_helper.Resize(WebSize(kViewportWidth, kViewportHeight)); - - // Click somewhere where the popup shouldn't appear. - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(kViewportWidth / 2, 0, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); - - // Click directly in between two container divs with click handlers, with - // children that don't handle clicks. - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(kViewportWidth / 2, kDivHeight, kTapDiameter)); - EXPECT_TRUE(client.Triggered()); - - // The third div container should be blacklisted if you click on the link it - // contains. - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(kViewportWidth / 2, kDivHeight * 3.25, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); -} - -TEST_F(WebFrameTest, DisambiguationPopupPageScale) { - RegisterMockedHttpURLLoad("disambiguation_popup_page_scale.html"); - - DisambiguationPopupTestWebViewClient client; - const int kTapDiameter = 50; - - // Make sure we initialize to minimum scale, even if the window size - // only becomes available after the load begins. - FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad( - base_url_ + "disambiguation_popup_page_scale.html", nullptr, &client); - web_view_helper.Resize(WebSize(1000, 1000)); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent(FatTap(80, 80, kTapDiameter)); - EXPECT_TRUE(client.Triggered()); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(230, 190, kTapDiameter)); - EXPECT_TRUE(client.Triggered()); - - web_view_helper.GetWebView()->SetPageScaleFactor(3.0f); - web_view_helper.GetWebView()->UpdateAllLifecyclePhases(); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(240, 240, kTapDiameter)); - EXPECT_TRUE(client.Triggered()); - - client.ResetTriggered(); - web_view_helper.GetWebView()->HandleInputEvent( - FatTap(690, 570, kTapDiameter)); - EXPECT_FALSE(client.Triggered()); -} - class TestSubstituteDataWebFrameClient : public FrameTestHelpers::TestWebFrameClient { public:
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.cc b/third_party/blink/renderer/core/exported/web_settings_impl.cc index 4760b2c..3bfe2a81 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.cc +++ b/third_party/blink/renderer/core/exported/web_settings_impl.cc
@@ -593,14 +593,6 @@ settings_->SetTouchAdjustmentEnabled(enabled); } -bool WebSettingsImpl::MultiTargetTapNotificationEnabled() { - return settings_->GetMultiTargetTapNotificationEnabled(); -} - -void WebSettingsImpl::SetMultiTargetTapNotificationEnabled(bool enabled) { - settings_->SetMultiTargetTapNotificationEnabled(enabled); -} - bool WebSettingsImpl::ViewportEnabled() const { return settings_->GetViewportEnabled(); } @@ -758,4 +750,11 @@ settings_->SetLazyFrameLoadingDistanceThresholdPx4G(distance_px); } +STATIC_ASSERT_ENUM(WebSettings::kImageAnimationPolicyAllowed, + kImageAnimationPolicyAllowed); +STATIC_ASSERT_ENUM(WebSettings::kImageAnimationPolicyAnimateOnce, + kImageAnimationPolicyAnimateOnce); +STATIC_ASSERT_ENUM(WebSettings::kImageAnimationPolicyNoAnimation, + kImageAnimationPolicyNoAnimation); + } // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.h b/third_party/blink/renderer/core/exported/web_settings_impl.h index 8dc554aa..e2f24b1 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.h +++ b/third_party/blink/renderer/core/exported/web_settings_impl.h
@@ -85,8 +85,6 @@ void SetEditingBehavior(EditingBehavior) override; void SetEnableScrollAnimator(bool) override; void SetEnableTouchAdjustment(bool) override; - bool MultiTargetTapNotificationEnabled() override; - void SetMultiTargetTapNotificationEnabled(bool) override; void SetWebGL1Enabled(bool) override; void SetWebGL2Enabled(bool) override; void SetFantasyFontFamily(const WebString&,
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 291d4b7a..851fc88 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -136,7 +136,6 @@ #include "third_party/blink/renderer/core/page/page_popup_client.h" #include "third_party/blink/renderer/core/page/pointer_lock_controller.h" #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h" -#include "third_party/blink/renderer/core/page/touch_disambiguation.h" #include "third_party/blink/renderer/core/page/validation_message_client_impl.h" #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h" #include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h" @@ -186,7 +185,6 @@ static const double doubleTapZoomAnimationDurationInSeconds = 0.25; static const float doubleTapZoomAlreadyLegibleRatio = 1.2f; -static const double multipleTargetsZoomAnimationDurationInSeconds = 0.25; static const double findInPageAnimationDurationInSeconds = 0; // Constants for viewport anchoring on resize. @@ -609,54 +607,6 @@ switch (event.GetType()) { case WebInputEvent::kGestureTap: { - // Don't trigger a disambiguation popup on sites designed for mobile - // devices. Instead, assume that the page has been designed with big - // enough buttons and links. Don't trigger a disambiguation popup when - // screencasting, since it's implemented outside of compositor pipeline - // and is not being screencasted itself. This leads to bad user - // experience. - WebDevToolsAgentImpl* dev_tools = MainFrameDevToolsAgentImpl(); - VisualViewport& visual_viewport = GetPage()->GetVisualViewport(); - bool screencast_enabled = dev_tools && dev_tools->ScreencastEnabled(); - if (event.data.tap.width > 0 && - !visual_viewport.ShouldDisableDesktopWorkarounds() && - !screencast_enabled) { - IntRect bounding_box(visual_viewport.ViewportToRootFrame( - IntRect(event.PositionInWidget().x - event.data.tap.width / 2, - event.PositionInWidget().y - event.data.tap.height / 2, - event.data.tap.width, event.data.tap.height))); - - // TODO(bokan): We shouldn't pass details of the VisualViewport offset - // to render_view_impl. crbug.com/459591 - WebSize visual_viewport_offset = - FlooredIntSize(visual_viewport.GetScrollOffset()); - - if (web_settings_->MultiTargetTapNotificationEnabled()) { - Vector<IntRect> good_targets; - HeapVector<Member<Node>> highlight_nodes; - FindGoodTouchTargets(bounding_box, MainFrameImpl()->GetFrame(), - good_targets, highlight_nodes); - // FIXME: replace touch adjustment code when numberOfGoodTargets == 1? - // Single candidate case is currently handled by: - // https://bugs.webkit.org/show_bug.cgi?id=85101 - if (good_targets.size() >= 2 && client_ && - client_->DidTapMultipleTargets(visual_viewport_offset, - bounding_box, good_targets)) { - // Stash the position of the node that would've been used absent - // disambiguation, for UMA purposes. - last_tap_disambiguation_best_candidate_position_ = - RoundedIntPoint(targeted_event.GetHitTestLocation().Point()) - - RoundedIntSize(targeted_event.GetHitTestResult().LocalPoint()); - - EnableTapHighlights(highlight_nodes); - GetPage()->GetLinkHighlights().StartHighlightAnimationIfNeeded(); - event_result = WebInputEventResult::kHandledSystem; - event_cancelled = true; - break; - } - } - } - { ContextMenuAllowedScope scope; event_result = @@ -729,58 +679,6 @@ return event_result; } -namespace { -// This enum is used to back a histogram, and should therefore be treated as -// append-only. -enum TapDisambiguationResult { - kUmaTapDisambiguationOther = 0, - kUmaTapDisambiguationBackButton = 1, - kUmaTapDisambiguationTappedOutside = 2, - kUmaTapDisambiguationTappedInsideDeprecated = 3, - kUmaTapDisambiguationTappedInsideSameNode = 4, - kUmaTapDisambiguationTappedInsideDifferentNode = 5, - kUmaTapDisambiguationCount = 6, -}; - -void RecordTapDisambiguation(TapDisambiguationResult result) { - UMA_HISTOGRAM_ENUMERATION("Touchscreen.TapDisambiguation", result, - kUmaTapDisambiguationCount); -} - -} // namespace - -void WebViewImpl::ResolveTapDisambiguation(base::TimeTicks timestamp, - WebPoint tap_viewport_offset, - bool is_long_press) { - WebGestureEvent event(is_long_press ? WebInputEvent::kGestureLongPress - : WebInputEvent::kGestureTap, - WebInputEvent::kNoModifiers, timestamp, - blink::kWebGestureDeviceTouchscreen); - - event.SetPositionInWidget(FloatPoint(tap_viewport_offset)); - - { - // Compute UMA stat about whether the node selected by disambiguation UI was - // different from the one preferred by the regular hit-testing + adjustment - // logic. - WebGestureEvent scaled_event = - TransformWebGestureEvent(MainFrameImpl()->GetFrameView(), event); - GestureEventWithHitTestResults targeted_event = - page_->DeprecatedLocalMainFrame()->GetEventHandler().TargetGestureEvent( - scaled_event); - WebPoint node_position = - RoundedIntPoint(targeted_event.GetHitTestLocation().Point()) - - RoundedIntSize(targeted_event.GetHitTestResult().LocalPoint()); - TapDisambiguationResult result = - (node_position == last_tap_disambiguation_best_candidate_position_) - ? kUmaTapDisambiguationTappedInsideSameNode - : kUmaTapDisambiguationTappedInsideDifferentNode; - RecordTapDisambiguation(result); - } - - HandleGestureEvent(event); -} - bool WebViewImpl::StartPageScaleAnimation(const IntPoint& target_position, bool use_anchor, float new_scale, @@ -1320,26 +1218,6 @@ findInPageAnimationDurationInSeconds); } -bool WebViewImpl::ZoomToMultipleTargetsRect(const WebRect& rect_in_root_frame) { - // TODO(lukasza): https://crbug.com/734209: Add OOPIF support. - if (!MainFrameImpl()) - return false; - - float scale; - WebPoint scroll; - - ComputeScaleAndScrollForBlockRect( - WebPoint(rect_in_root_frame.x, rect_in_root_frame.y), rect_in_root_frame, - nonUserInitiatedPointPadding, MinimumPageScaleFactor(), scale, scroll); - - if (scale <= PageScaleFactor()) - return false; - - StartPageScaleAnimation(scroll, false, scale, - multipleTargetsZoomAnimationDurationInSeconds); - return true; -} - #if !defined(OS_MACOSX) // Mac has no way to open a context menu based on a keyboard event. WebInputEventResult WebViewImpl::SendContextMenuEvent() {
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 9055bbe7..126e40dc 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -187,7 +187,6 @@ double maximum_zoom_level) override; float TextZoomFactor() override; float SetTextZoomFactor(float) override; - bool ZoomToMultipleTargetsRect(const WebRect&) override; float PageScaleFactor() const override; void SetDefaultPageScaleLimits(float min_scale, float max_scale) override; void SetInitialPageScaleOverride(float) override; @@ -368,10 +367,6 @@ void EnableTapHighlights(HeapVector<Member<Node>>&); void AnimateDoubleTapZoom(const IntPoint&); - void ResolveTapDisambiguation(base::TimeTicks timestamp, - WebPoint tap_viewport_offset, - bool is_long_press) override; - void EnableFakePageScaleAnimationForTesting(bool); bool FakeDoubleTapAnimationPendingForTesting() const { return double_tap_zoom_pending_; @@ -650,8 +645,6 @@ std::unique_ptr<FullscreenController> fullscreen_controller_; - WebPoint last_tap_disambiguation_best_candidate_position_; - SkColor base_background_color_; bool base_background_color_override_enabled_; SkColor base_background_color_override_;
diff --git a/third_party/blink/renderer/core/fetch/fetch_response_data.h b/third_party/blink/renderer/core/fetch/fetch_response_data.h index 5810fcd..b32bb79 100644 --- a/third_party/blink/renderer/core/fetch/fetch_response_data.h +++ b/third_party/blink/renderer/core/fetch/fetch_response_data.h
@@ -10,8 +10,8 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "services/network/public/mojom/fetch_api.mojom-blink.h" +#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h" #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-blink.h" -#include "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h" #include "third_party/blink/public/platform/web_cors.h" #include "third_party/blink/renderer/core/core_export.h"
diff --git a/third_party/blink/renderer/core/fetch/response.h b/third_party/blink/renderer/core/fetch/response.h index 33463f8..10caa9a 100644 --- a/third_party/blink/renderer/core/fetch/response.h +++ b/third_party/blink/renderer/core/fetch/response.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_RESPONSE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_RESPONSE_H_ -#include "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom-blink.h" +#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/dictionary.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/core/core_export.h"
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index 47270324..87a0e73 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -542,7 +542,7 @@ bool HTMLPlugInElement::IsImageType() const { if (GetDocument().GetFrame()) return GetObjectContentType() == ObjectContentType::kImage; - return Image::SupportsType(service_type_); + return MIMETypeRegistry::IsSupportedImageResourceMIMEType(service_type_); } LayoutEmbeddedObject* HTMLPlugInElement::GetLayoutEmbeddedObject() const {
diff --git a/third_party/blink/renderer/core/page/BUILD.gn b/third_party/blink/renderer/core/page/BUILD.gn index ec5831d..612cc87 100644 --- a/third_party/blink/renderer/core/page/BUILD.gn +++ b/third_party/blink/renderer/core/page/BUILD.gn
@@ -89,8 +89,6 @@ "spatial_navigation.h", "touch_adjustment.cc", "touch_adjustment.h", - "touch_disambiguation.cc", - "touch_disambiguation.h", "validation_message_client.h", "validation_message_client_impl.cc", "validation_message_client_impl.h",
diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc index 7fec9ff..380a77d 100644 --- a/third_party/blink/renderer/core/page/drag_controller.cc +++ b/third_party/blink/renderer/core/page/drag_controller.cc
@@ -474,29 +474,28 @@ Range*& range, const LayoutPoint& point) { frame->Selection().SetSelectionAndEndTyping(drag_caret); - if (frame->Selection() - .ComputeVisibleSelectionInDOMTreeDeprecated() - .IsNone()) { - // TODO(editing-dev): The use of - // updateStyleAndLayoutIgnorePendingStylesheets - // needs to be audited. See http://crbug.com/590369 for more details. - // |LocalFrame::positinForPoint()| requires clean layout. - frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); + // TODO(editing-dev): The use of + // UpdateStyleAndLayoutIgnorePendingStylesheets + // needs to be audited. See http://crbug.com/590369 for more details. + frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); + if (frame->Selection().ComputeVisibleSelectionInDOMTree().IsNone()) { const PositionWithAffinity& position = frame->PositionForPoint(point); if (!position.IsConnected()) return false; frame->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder().Collapse(position).Build()); + // TODO(editing-dev): The use of + // UpdateStyleAndLayoutIgnorePendingStylesheets + // needs to be audited. See http://crbug.com/590369 for more details. + frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); const VisibleSelection& drag_caret = - frame->Selection().ComputeVisibleSelectionInDOMTreeDeprecated(); + frame->Selection().ComputeVisibleSelectionInDOMTree(); range = CreateRange(drag_caret.ToNormalizedEphemeralRange()); } - return !frame->Selection() - .ComputeVisibleSelectionInDOMTreeDeprecated() - .IsNone() && + return !frame->Selection().ComputeVisibleSelectionInDOMTree().IsNone() && frame->Selection() - .ComputeVisibleSelectionInDOMTreeDeprecated() + .ComputeVisibleSelectionInDOMTree() .IsContentEditable(); }
diff --git a/third_party/blink/renderer/core/page/touch_disambiguation.cc b/third_party/blink/renderer/core/page/touch_disambiguation.cc deleted file mode 100644 index f6678b7..0000000 --- a/third_party/blink/renderer/core/page/touch_disambiguation.cc +++ /dev/null
@@ -1,162 +0,0 @@ -/* - * Copyright (C) 2012 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER OR 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. - */ - -#include "third_party/blink/renderer/core/page/touch_disambiguation.h" - -#include <algorithm> -#include <cmath> -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/element.h" -#include "third_party/blink/renderer/core/dom/node_traversal.h" -#include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/core/frame/local_frame_view.h" -#include "third_party/blink/renderer/core/html/html_html_element.h" -#include "third_party/blink/renderer/core/input/event_handler.h" -#include "third_party/blink/renderer/core/layout/hit_test_result.h" -#include "third_party/blink/renderer/core/layout/layout_block.h" - -namespace blink { - -static IntRect BoundingBoxForEventNodes(Node* event_node) { - if (!event_node->GetDocument().View()) - return IntRect(); - - IntRect result; - Node* node = event_node; - while (node) { - // Skip the whole sub-tree if the node doesn't propagate events. - if (node != event_node && node->WillRespondToMouseClickEvents()) { - node = NodeTraversal::NextSkippingChildren(*node, event_node); - continue; - } - result.Unite(node->PixelSnappedBoundingBox()); - node = NodeTraversal::Next(*node, event_node); - } - return event_node->GetDocument().View()->ConvertToRootFrame(result); -} - -static float ScoreTouchTarget(const IntRect& touch_rect, IntRect bounding_box) { - if (bounding_box.IsEmpty()) - return 0; - - float touch_radius = - ceil(std::max(touch_rect.Width(), touch_rect.Height()) * 0.5f); - float score = 1; - - IntSize distance = bounding_box.DifferenceToPoint(touch_rect.Center()); - score *= std::max(1 - (abs(distance.Width()) / touch_radius), 0.f); - score *= std::max(1 - (abs(distance.Height()) / touch_radius), 0.f); - - return score; -} - -struct TouchTargetData { - IntRect window_bounding_box; - float score; -}; - -void FindGoodTouchTargets(const IntRect& touch_box_in_root_frame, - LocalFrame* main_frame, - Vector<IntRect>& good_targets, - HeapVector<Member<Node>>& highlight_nodes) { - good_targets.clear(); - LayoutPoint hit_point(main_frame->View()->ConvertFromRootFrame( - touch_box_in_root_frame.Location())); - HitTestLocation location( - LayoutRect(hit_point, LayoutSize(touch_box_in_root_frame.Size()))); - HitTestResult result = main_frame->GetEventHandler().HitTestResultAtLocation( - location, HitTestRequest::kReadOnly | HitTestRequest::kActive | - HitTestRequest::kListBased); - const HeapListHashSet<Member<Node>>& hit_results = - result.ListBasedTestResult(); - - // Blacklist nodes that are container of disambiguated nodes. - // It is not uncommon to have a clickable <div> that contains other clickable - // objects. This heuristic avoids excessive disambiguation in that case. - HeapHashSet<Member<Node>> black_list; - for (const auto& hit_result : hit_results) { - // Ignore any Nodes that can't be clicked on. - LayoutObject* layout_object = hit_result.Get()->GetLayoutObject(); - if (!layout_object || !hit_result.Get()->WillRespondToMouseClickEvents()) - continue; - - // Blacklist all of the Node's containers. - for (LayoutBlock* container = layout_object->ContainingBlock(); container; - container = container->ContainingBlock()) { - Node* container_node = container->GetNode(); - if (!container_node) - continue; - if (!black_list.insert(container_node).is_new_entry) - break; - } - } - - HeapHashMap<Member<Node>, TouchTargetData> touch_targets; - float best_score = 0; - for (const auto& hit_result : hit_results) { - if (!hit_result) - continue; - for (Node& node : NodeTraversal::InclusiveAncestorsOf(*hit_result)) { - if (black_list.Contains(&node)) - continue; - if (node.IsDocumentNode() || IsHTMLHtmlElement(node) || - IsHTMLBodyElement(node)) - break; - if (node.WillRespondToMouseClickEvents()) { - TouchTargetData& target_data = - touch_targets.insert(&node, TouchTargetData()).stored_value->value; - target_data.window_bounding_box = BoundingBoxForEventNodes(&node); - target_data.score = ScoreTouchTarget(touch_box_in_root_frame, - target_data.window_bounding_box); - best_score = std::max(best_score, target_data.score); - break; - } - } - } - - // The scoring function uses the overlap area with the fat point as the score. - // We ignore the candidates that have less than this (empirically tuned) - // fraction of overlap than the best candidate to avoid excessive popups. - // - // If this value were 1, then the disambiguation feature would only be seen - // when two nodes have precisely the same overlap with the touch radius. If - // it were 0, then any miniscule overlap with the edge of another node would - // trigger it. - const float kRelativeAmbiguityThreshold = 0.75f; - - for (const auto& touch_target : touch_targets) { - if (touch_target.value.score < best_score * kRelativeAmbiguityThreshold) - continue; - good_targets.push_back(touch_target.value.window_bounding_box); - highlight_nodes.push_back(touch_target.key); - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/page/touch_disambiguation.h b/third_party/blink/renderer/core/page/touch_disambiguation.h deleted file mode 100644 index 2fe45a0..0000000 --- a/third_party/blink/renderer/core/page/touch_disambiguation.h +++ /dev/null
@@ -1,52 +0,0 @@ -/* - * Copyright (C) 2012 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER OR 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. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_TOUCH_DISAMBIGUATION_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_TOUCH_DISAMBIGUATION_H_ - -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" - -namespace blink { - -class LocalFrame; -class IntRect; -class Node; - -CORE_EXPORT void FindGoodTouchTargets( - const IntRect& touch_box, - LocalFrame* main_frame, - Vector<IntRect>& good_targets, - HeapVector<Member<Node>>& highlight_nodes); - -} // namespace blink - -#endif
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc index 88bb5c8..3282070f 100644 --- a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc +++ b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -46,7 +46,6 @@ #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/input/event_handler.h" #include "third_party/blink/renderer/core/page/page.h" -#include "third_party/blink/renderer/core/page/touch_disambiguation.h" #include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/geometry/int_rect.h" @@ -228,34 +227,6 @@ EXPECT_TRUE(highlight_layer->GetLinkHighlights().at(0)); } -TEST_P(LinkHighlightImplTest, multipleHighlights) { - WebViewImpl* web_view_impl = web_view_helper_.GetWebView(); - - int page_width = 640; - int page_height = 480; - web_view_impl->Resize(WebSize(page_width, page_height)); - web_view_impl->UpdateAllLifecyclePhases(); - - WebGestureEvent touch_event; - touch_event.SetPositionInWidget(WebFloatPoint(50, 310)); - touch_event.data.tap.width = 30; - touch_event.data.tap.height = 30; - - Vector<IntRect> good_targets; - HeapVector<Member<Node>> highlight_nodes; - IntRect bounding_box( - touch_event.PositionInWidget().x - touch_event.data.tap.width / 2, - touch_event.PositionInWidget().y - touch_event.data.tap.height / 2, - touch_event.data.tap.width, touch_event.data.tap.height); - FindGoodTouchTargets(bounding_box, web_view_impl->MainFrameImpl()->GetFrame(), - good_targets, highlight_nodes); - - web_view_impl->EnableTapHighlights(highlight_nodes); - const auto& highlights = - web_view_impl->GetPage()->GetLinkHighlights().link_highlights_; - EXPECT_EQ(2U, highlights.size()); -} - TEST_P(LinkHighlightImplTest, HighlightLayerEffectNode) { // This is testing the blink->cc layer integration. if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
diff --git a/third_party/blink/renderer/core/testing/data/disambiguation_popup.html b/third_party/blink/renderer/core/testing/data/disambiguation_popup.html deleted file mode 100644 index b1af285c..0000000 --- a/third_party/blink/renderer/core/testing/data/disambiguation_popup.html +++ /dev/null
@@ -1,30 +0,0 @@ -<html> -<head> -<title>Disambiguation Popup Test</title> -<style type="text/css"> -.horizontal-link { - display:block; - width:200px; - height:30px; - margin:20px; - background-color:#ccccff; -} -.vertical-link { - display:inline-block; - width:30px; - height:200px; - margin:10px; - background-color:#ccccff; -} -</style> -</head> -<body style="margin:0px;"> -<a href="#" class="horizontal-link" style="margin:100px">Link</a> -<a href="#" class="horizontal-link">Link 1</a> -<a href="#" class="horizontal-link">Link 2</a> -<a href="#" class="horizontal-link">Link 3</a> -<a href="#" class="horizontal-link">Link 4</a> -<a href="#" class="horizontal-link">Link 5</a> -<a href="#" class="vertical-link">Link 1</a><a href="#" class="vertical-link">Link 2</a><a href="#" class="vertical-link">Link 3</a><a href="#" class="vertical-link">Link 4</a><a href="#" class="vertical-link">Link 5</a> -</body> -</html>
diff --git a/third_party/blink/renderer/core/testing/data/disambiguation_popup_200_by_800.html b/third_party/blink/renderer/core/testing/data/disambiguation_popup_200_by_800.html deleted file mode 100644 index ab0f4e33..0000000 --- a/third_party/blink/renderer/core/testing/data/disambiguation_popup_200_by_800.html +++ /dev/null
@@ -1,37 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta name="viewport" content="width=200"> - - <style type="text/css"> - body { - margin: 0px; - } - .upper { - background-color: #ffbbaa; - width: 200px; - height: 400px; - } - .lower { - background-color: #ffddaa; - width: 200px; - height: 400px; - } - .horizontal-link { - display:block; - width:200px; - height:30px; - margin-top:2px; - background-color:#ccccff; - } - </style> - </head> - <body> - <div class="upper"></div> - <div class="lower"> - <div style="height:200px"></div> - <a href="#" class="horizontal-link">Link 1</a> - <a href="#" class="horizontal-link">Link 2</a> - </div> - </body> -</html>
diff --git a/third_party/blink/renderer/core/testing/data/disambiguation_popup_blacklist.html b/third_party/blink/renderer/core/testing/data/disambiguation_popup_blacklist.html deleted file mode 100644 index 8c19676b..0000000 --- a/third_party/blink/renderer/core/testing/data/disambiguation_popup_blacklist.html +++ /dev/null
@@ -1,36 +0,0 @@ -<html> - <head> - <style> - div { - height: 100px; - margin: 0px; - text-align: center; - width: 100%; - } - div.tightlyPacked { - background-color: pink; - border: 1px solid black; - } - div.bugContainer { - background-color: cyan; - } - </style> - </head> - <body> - <div class="tightlyPacked" onclick="window.location='#first';"> - <div>Leaf node #1</div> - </div> - <div class="tightlyPacked" onclick="window.location='#second';"> - <div>Leaf node #2</div> - </div> - <div></div> - <div class="bugContainer" onclick="window.location='#third';"> - <p class="title"> - <a class="title" href="#fourth">Random link</a> - </p> - <p> - Breaking node - </p> - </div> - </body> -</html>
diff --git a/third_party/blink/renderer/core/testing/data/disambiguation_popup_mobile_site.html b/third_party/blink/renderer/core/testing/data/disambiguation_popup_mobile_site.html deleted file mode 100644 index 3d468f2..0000000 --- a/third_party/blink/renderer/core/testing/data/disambiguation_popup_mobile_site.html +++ /dev/null
@@ -1,31 +0,0 @@ -<html> -<head> -<title>Disambiguation Popup Test</title> -<style type="text/css"> -.horizontal-link { - display:block; - width:200px; - height:30px; - margin:20px; - background-color:#ccccff; -} -.vertical-link { - display:inline-block; - width:30px; - height:200px; - margin:10px; - background-color:#ccccff; -} -</style> -<meta name="viewport" content="width=device-width"> -</head> -<body style="margin:0px;"> -<a href="#" class="horizontal-link" style="margin:100px">Link</a> -<a href="#" class="horizontal-link">Link 1</a> -<a href="#" class="horizontal-link">Link 2</a> -<a href="#" class="horizontal-link">Link 3</a> -<a href="#" class="horizontal-link">Link 4</a> -<a href="#" class="horizontal-link">Link 5</a> -<a href="#" class="vertical-link">Link 1</a><a href="#" class="vertical-link">Link 2</a><a href="#" class="vertical-link">Link 3</a><a href="#" class="vertical-link">Link 4</a><a href="#" class="vertical-link">Link 5</a> -</body> -</html>
diff --git a/third_party/blink/renderer/core/testing/data/disambiguation_popup_no_container.html b/third_party/blink/renderer/core/testing/data/disambiguation_popup_no_container.html deleted file mode 100644 index 7d2af3e..0000000 --- a/third_party/blink/renderer/core/testing/data/disambiguation_popup_no_container.html +++ /dev/null
@@ -1,25 +0,0 @@ -<html> -<head> -<title>Disambiguation Popup Test</title> -<style type="text/css"> -.outer-div { - display:block; - width:200px; - height:200px; - margin:0px; - padding:50px; - background-color:#ffcccc; -} -.inner-link { - display:block; - width:200px; - height:200px; - margin:0px; - background-color:#ccffcc; -} -</style> -</head> -<body style="margin:0px;"> -<div class="outer-div" onclick=";"><a href="#" class="inner-link"></a></a> -</body> -</html>
diff --git a/third_party/blink/renderer/core/testing/data/disambiguation_popup_page_scale.html b/third_party/blink/renderer/core/testing/data/disambiguation_popup_page_scale.html deleted file mode 100644 index 0b8b7f5..0000000 --- a/third_party/blink/renderer/core/testing/data/disambiguation_popup_page_scale.html +++ /dev/null
@@ -1,20 +0,0 @@ -<html> -<head> -<title>Disambiguation Popup Test</title> -<style type="text/css"> -.link { - display:block; - position:absolute; - width:200px; - height:30px; - background-color:#ccccff; -} -</style> -</head> -<body> -<a href="#" class="link" style="left:50px;top:50px;">Link 1</a> -<a href="#" class="link" style="left:50px;top:80px;">Link 2</a> -<a href="#" class="link" style="left:200px;top:150px;">Link 3</a> -<a href="#" class="link" style="left:200px;top:200px;">Link 4</a> -</body> -</html>
diff --git a/third_party/blink/renderer/core/testing/data/disambiguation_popup_viewport_site.html b/third_party/blink/renderer/core/testing/data/disambiguation_popup_viewport_site.html deleted file mode 100644 index 9042185..0000000 --- a/third_party/blink/renderer/core/testing/data/disambiguation_popup_viewport_site.html +++ /dev/null
@@ -1,38 +0,0 @@ -<html> -<head> -<title>Disambiguation Popup Test</title> -<style type="text/css"> -@viewport { - width: auto; - height: auto; - min-zoom: auto; - max-zoom: auto; - zoom: auto; - user-zoom: zoom; -} -.horizontal-link { - display:block; - width:200px; - height:30px; - margin:20px; - background-color:#ccccff; -} -.vertical-link { - display:inline-block; - width:30px; - height:200px; - margin:10px; - background-color:#ccccff; -} -</style> -</head> -<body style="margin:0px;"> -<a href="#" class="horizontal-link" style="margin:100px">Link</a> -<a href="#" class="horizontal-link">Link 1</a> -<a href="#" class="horizontal-link">Link 2</a> -<a href="#" class="horizontal-link">Link 3</a> -<a href="#" class="horizontal-link">Link 4</a> -<a href="#" class="horizontal-link">Link 5</a> -<a href="#" class="vertical-link">Link 1</a><a href="#" class="vertical-link">Link 2</a><a href="#" class="vertical-link">Link 3</a><a href="#" class="vertical-link">Link 4</a><a href="#" class="vertical-link">Link 5</a> -</body> -</html>
diff --git a/third_party/blink/renderer/devtools/BUILD.gn b/third_party/blink/renderer/devtools/BUILD.gn index 5d9d54e..219ea5f 100644 --- a/third_party/blink/renderer/devtools/BUILD.gn +++ b/third_party/blink/renderer/devtools/BUILD.gn
@@ -87,8 +87,6 @@ "front_end/bindings_test_runner/module.json", "front_end/bindings_test_runner/PersistenceTestRunner.js", "front_end/bindings_test_runner/OverridesTestRunner.js", - "front_end/browser_components/ImagePreview.js", - "front_end/browser_components/imagePreview.css", "front_end/browser_console/BrowserConsole.js", "front_end/browser_console/module.json", "front_end/browser_debugger/DOMBreakpointsSidebarPane.js", @@ -99,9 +97,7 @@ "front_end/browser_debugger/eventListenerBreakpoints.css", "front_end/browser_debugger/module.json", "front_end/browser_debugger/xhrBreakpointsSidebarPane.css", - "front_end/browser_sdk/HAREntry.js", "front_end/browser_sdk/LogManager.js", - "front_end/browser_sdk/NetworkLog.js", "front_end/browser_sdk/module.json", "front_end/changes/ChangesHighlighter.js", "front_end/changes/changesView.css", @@ -164,6 +160,8 @@ "front_end/common/UIString.js", "front_end/common/Worker.js", "front_end/components/DockController.js", + "front_end/components/ImagePreview.js", + "front_end/components/imagePreview.css", "front_end/components/JSPresentationUtils.js", "front_end/components/Linkifier.js", "front_end/components/TargetDetachedDialog.js", @@ -590,10 +588,12 @@ "front_end/sdk/DOMModel.js", "front_end/sdk/EmulationModel.js", "front_end/sdk/FilmStripModel.js", + "front_end/sdk/HARLog.js", "front_end/sdk/HeapProfilerModel.js", "front_end/sdk/LayerTreeBase.js", "front_end/sdk/LogModel.js", "front_end/sdk/module.json", + "front_end/sdk/NetworkLog.js", "front_end/sdk/NetworkManager.js", "front_end/sdk/NetworkRequest.js", "front_end/sdk/OverlayModel.js",
diff --git a/third_party/blink/renderer/devtools/front_end/browser_components/module.json b/third_party/blink/renderer/devtools/front_end/browser_components/module.json deleted file mode 100644 index bf178cb..0000000 --- a/third_party/blink/renderer/devtools/front_end/browser_components/module.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "dependencies": [ - "browser_sdk", - "components" - ], - "scripts": [ - "ImagePreview.js" - ], - "resources": [ - "imagePreview.css" - ] -}
diff --git a/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js b/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js index aee39714..a98df12 100644 --- a/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js +++ b/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js
@@ -15,7 +15,7 @@ */ appendApplicableItems(event, contextMenu, object) { const consoleMessage = /** @type {!SDK.ConsoleMessage} */ (object); - const request = BrowserSDK.NetworkLog.requestForConsoleMessage(consoleMessage); + const request = SDK.NetworkLog.requestForConsoleMessage(consoleMessage); if (request && SDK.NetworkManager.canReplayRequest(request)) { contextMenu.debugSection().appendItem( Common.UIString('Replay XHR'), SDK.NetworkManager.replayRequest.bind(null, request)); @@ -30,7 +30,7 @@ */ render(object, options) { const consoleMessage = /** @type {!SDK.ConsoleMessage} */ (object); - const request = BrowserSDK.NetworkLog.requestForConsoleMessage(consoleMessage); + const request = SDK.NetworkLog.requestForConsoleMessage(consoleMessage); let messageElement = null; if (request) { messageElement = createElement('span');
diff --git a/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js b/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js index 0681aa9..8fa6c8b 100644 --- a/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js +++ b/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js
@@ -41,7 +41,7 @@ data.entry.timestamp, undefined, undefined, data.entry.workerId); if (data.entry.networkRequestId) - BrowserSDK.networkLog.associateConsoleMessageWithRequest(consoleMessage, data.entry.networkRequestId); + SDK.networkLog.associateConsoleMessageWithRequest(consoleMessage, data.entry.networkRequestId); SDK.consoleModel.addMessage(consoleMessage); } };
diff --git a/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json b/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json index 445eb49f..1c276e0 100644 --- a/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json +++ b/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json
@@ -22,9 +22,7 @@ } ], "scripts": [ - "LogManager.js", - "NetworkLog.js", - "HAREntry.js" + "LogManager.js" ], "dependencies": [ "sdk"
diff --git a/third_party/blink/renderer/devtools/front_end/browser_components/ImagePreview.js b/third_party/blink/renderer/devtools/front_end/components/ImagePreview.js similarity index 96% rename from third_party/blink/renderer/devtools/front_end/browser_components/ImagePreview.js rename to third_party/blink/renderer/devtools/front_end/components/ImagePreview.js index 4abc3c3..f278a498 100644 --- a/third_party/blink/renderer/devtools/front_end/browser_components/ImagePreview.js +++ b/third_party/blink/renderer/devtools/front_end/components/ImagePreview.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -BrowserComponents.ImagePreview = class { +Components.ImagePreview = class { /** * @param {!SDK.Target} target * @param {string} originalImageURL @@ -41,7 +41,7 @@ function buildContent() { const container = createElement('table'); - UI.appendStyle(container, 'browser_components/imagePreview.css'); + UI.appendStyle(container, 'components/imagePreview.css'); container.className = 'image-preview-container'; const naturalWidth = precomputedFeatures ? precomputedFeatures.naturalWidth : imageElement.naturalWidth; const naturalHeight = precomputedFeatures ? precomputedFeatures.naturalHeight : imageElement.naturalHeight;
diff --git a/third_party/blink/renderer/devtools/front_end/browser_components/imagePreview.css b/third_party/blink/renderer/devtools/front_end/components/imagePreview.css similarity index 100% rename from third_party/blink/renderer/devtools/front_end/browser_components/imagePreview.css rename to third_party/blink/renderer/devtools/front_end/components/imagePreview.css
diff --git a/third_party/blink/renderer/devtools/front_end/components/module.json b/third_party/blink/renderer/devtools/front_end/components/module.json index 8986fdfe..b7b5ca92 100644 --- a/third_party/blink/renderer/devtools/front_end/components/module.json +++ b/third_party/blink/renderer/devtools/front_end/components/module.json
@@ -7,11 +7,13 @@ "scripts": [ "JSPresentationUtils.js", "DockController.js", + "ImagePreview.js", "Linkifier.js", "Reload.js", "TargetDetachedDialog.js" ], "resources": [ + "imagePreview.css", "jsUtils.css" ] }
diff --git a/third_party/blink/renderer/devtools/front_end/devtools_app.json b/third_party/blink/renderer/devtools/front_end/devtools_app.json index e444158..02e578e 100644 --- a/third_party/blink/renderer/devtools/front_end/devtools_app.json +++ b/third_party/blink/renderer/devtools/front_end/devtools_app.json
@@ -3,7 +3,6 @@ { "name": "emulation", "type": "autostart" }, { "name": "inspector_main", "type": "autostart" }, { "name": "mobile_throttling", "type": "autostart" }, - { "name": "browser_components", "type": "autostart" }, { "name": "accessibility", "type": "remote" }, { "name": "animation" },
diff --git a/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js b/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js index 8979f943..7ae9081 100644 --- a/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js +++ b/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js
@@ -483,7 +483,7 @@ const node = this.selectedDOMNode(); if (!node) return false; - const preview = await BrowserComponents.ImagePreview.build( + const preview = await Components.ImagePreview.build( node.domModel().target(), link[Elements.ElementsTreeElement.HrefSymbol], true); if (preview) popover.contentElement.appendChild(preview);
diff --git a/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js index e5c1c4f8..8cc0dcd2 100644 --- a/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js +++ b/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
@@ -529,7 +529,7 @@ const listItem = link.enclosingNodeOrSelfWithNodeName('li'); const node = /** @type {!Elements.ElementsTreeElement} */ (listItem.treeElement).node(); const precomputedFeatures = await this._loadDimensionsForNode(node); - const preview = await BrowserComponents.ImagePreview.build( + const preview = await Components.ImagePreview.build( node.domModel().target(), link[Elements.ElementsTreeElement.HrefSymbol], true, precomputedFeatures); if (preview) popover.contentElement.appendChild(preview);
diff --git a/third_party/blink/renderer/devtools/front_end/elements/module.json b/third_party/blink/renderer/devtools/front_end/elements/module.json index b655b00..6cffd5f 100644 --- a/third_party/blink/renderer/devtools/front_end/elements/module.json +++ b/third_party/blink/renderer/devtools/front_end/elements/module.json
@@ -289,7 +289,7 @@ } ], "dependencies": [ - "browser_components", + "components", "extensions", "inline_editor", "color_picker",
diff --git a/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js b/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js index cb93140..d06a9dc 100644 --- a/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js +++ b/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js
@@ -378,7 +378,7 @@ return this._status.OK(); } - const request = BrowserSDK.networkLog.requestForURL(message.url); + const request = SDK.networkLog.requestForURL(message.url); if (request) { Common.Revealer.reveal(request); return this._status.OK(); @@ -434,8 +434,8 @@ } async _onGetHAR() { - const requests = BrowserSDK.networkLog.requests(); - const harLog = await BrowserSDK.HARLog.build(requests); + const requests = SDK.networkLog.requests(); + const harLog = await SDK.HARLog.build(requests); for (let i = 0; i < harLog.entries.length; ++i) harLog.entries[i]._requestId = this._requestId(requests[i]); return harLog; @@ -640,7 +640,7 @@ async _notifyRequestFinished(event) { const request = /** @type {!SDK.NetworkRequest} */ (event.data); - const entry = await BrowserSDK.HAREntry.build(request); + const entry = await SDK.HARLog.Entry.build(request); this._postNotification(Extensions.extensionAPI.Events.NetworkRequestFinished, this._requestId(request), entry); }
diff --git a/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js b/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js index 260f476..ce1e59a 100644 --- a/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js +++ b/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js
@@ -15,7 +15,7 @@ log.entries.sort((a, b) => a.startedDateTime - b.startedDateTime); - /** @type {!Map<string, !BrowserSDK.PageLoad>} */ + /** @type {!Map<string, !SDK.NetworkLog.PageLoad>} */ const pageLoads = new Map(); /** @type {!Array<!SDK.NetworkRequest>} */ const requests = []; @@ -39,10 +39,10 @@ /** * @param {!HARImporter.HARPage} page * @param {!SDK.NetworkRequest} mainRequest - * @return {!BrowserSDK.PageLoad} + * @return {!SDK.NetworkLog.PageLoad} */ static _buildPageLoad(page, mainRequest) { - const pageLoad = new BrowserSDK.PageLoad(mainRequest); + const pageLoad = new SDK.NetworkLog.PageLoad(mainRequest); pageLoad.startTime = page.startedDateTime; pageLoad.contentLoadTime = page.pageTimings.onContentLoad * 1000; pageLoad.loadTime = page.pageTimings.onLoad * 1000; @@ -52,7 +52,7 @@ /** * @param {!SDK.NetworkRequest} request * @param {!HARImporter.HAREntry} entry - * @param {?BrowserSDK.PageLoad} pageLoad + * @param {?SDK.NetworkLog.PageLoad} pageLoad */ static _fillRequestFromHAREntry(request, entry, pageLoad) { // Request data.
diff --git a/third_party/blink/renderer/devtools/front_end/network/HARWriter.js b/third_party/blink/renderer/devtools/front_end/network/HARWriter.js index 52aa0b0..b7f20e8 100644 --- a/third_party/blink/renderer/devtools/front_end/network/HARWriter.js +++ b/third_party/blink/renderer/devtools/front_end/network/HARWriter.js
@@ -54,7 +54,7 @@ progress.setTitle(Common.UIString('Collecting content\u2026')); progress.setTotalWork(requests.length); - const harLog = await BrowserSDK.HARLog.build(requests); + const harLog = await SDK.HARLog.build(requests); const promises = []; for (let i = 0; i < requests.length; i++) { const promise = requests[i].contentData();
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js b/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js index cbc6fb4..5f3e5040 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js
@@ -546,7 +546,7 @@ showingInitiatorChainChanged() { const showInitiatorChain = this.showingInitiatorChain(); - const initiatorGraph = BrowserSDK.networkLog.initiatorGraphForRequest(this._request); + const initiatorGraph = SDK.networkLog.initiatorGraphForRequest(this._request); for (const request of initiatorGraph.initiators) { if (request === this._request) continue; @@ -636,7 +636,7 @@ * @return {boolean} */ isNavigationRequest() { - const pageLoad = BrowserSDK.PageLoad.forRequest(this._request); + const pageLoad = SDK.NetworkLog.PageLoad.forRequest(this._request); return pageLoad ? pageLoad.mainRequest === this._request : false; } @@ -882,7 +882,7 @@ _renderInitiatorCell(cell) { this._initiatorCell = cell; const request = this._request; - const initiator = BrowserSDK.networkLog.initiatorInfoForRequest(request); + const initiator = SDK.networkLog.initiatorInfoForRequest(request); const timing = request.timing; if (timing && timing.pushStart)
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js index 19bc05754..308d7fd 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
@@ -146,9 +146,9 @@ .addChangeListener(this._invalidateAllItems.bind(this, false), this); SDK.targetManager.observeModels(SDK.NetworkManager, this); - BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.RequestAdded, this._onRequestUpdated, this); - BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.RequestUpdated, this._onRequestUpdated, this); - BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.Reset, this._reset, this); + SDK.networkLog.addEventListener(SDK.NetworkLog.Events.RequestAdded, this._onRequestUpdated, this); + SDK.networkLog.addEventListener(SDK.NetworkLog.Events.RequestUpdated, this._onRequestUpdated, this); + SDK.networkLog.addEventListener(SDK.NetworkLog.Events.Reset, this._reset, this); this._updateGroupByFrame(); Common.moduleSetting('network.group-by-frame').addChangeListener(() => this._updateGroupByFrame()); @@ -466,7 +466,7 @@ this._harLoadFailed(e); return; } - BrowserSDK.networkLog.importRequests(HARImporter.Importer.requestsFromHARLog(harRoot.log)); + SDK.networkLog.importRequests(HARImporter.Importer.requestsFromHARLog(harRoot.log)); } /** @@ -691,7 +691,7 @@ let maxTime = -1; let nodeCount = 0; - for (const request of BrowserSDK.networkLog.requests()) { + for (const request of SDK.networkLog.requests()) { const node = request[Network.NetworkLogView._networkNodeSymbol]; if (!node) continue; @@ -797,7 +797,7 @@ * @param {boolean=} deferUpdate */ _invalidateAllItems(deferUpdate) { - this._staleRequests = new Set(BrowserSDK.networkLog.requests()); + this._staleRequests = new Set(SDK.networkLog.requests()); if (deferUpdate) this.scheduleRefresh(); else @@ -1228,12 +1228,12 @@ } _harRequests() { - const httpRequests = BrowserSDK.networkLog.requests().filter(Network.NetworkLogView.HTTPRequestsFilter); + const httpRequests = SDK.networkLog.requests().filter(Network.NetworkLogView.HTTPRequestsFilter); return httpRequests.filter(Network.NetworkLogView.FinishedRequestsFilter); } async _copyAll() { - const harArchive = {log: await BrowserSDK.HARLog.build(this._harRequests())}; + const harArchive = {log: await SDK.HARLog.build(this._harRequests())}; InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2)); } @@ -1250,7 +1250,7 @@ * @param {string} platform */ async _copyAllCurlCommand(platform) { - const requests = BrowserSDK.networkLog.requests(); + const requests = SDK.networkLog.requests(); const commands = await Promise.all(requests.map(request => this._generateCurlCommand(request, platform))); if (platform === 'win') InspectorFrontendHost.copyText(commands.join(' &\r\n')); @@ -1268,7 +1268,7 @@ } async _copyAllFetchCall() { - const requests = BrowserSDK.networkLog.requests(); + const requests = SDK.networkLog.requests(); const commands = await Promise.all(requests.map(request => this._generateFetchCall(request))); InspectorFrontendHost.copyText(commands.join(' ;\n')); } @@ -1282,7 +1282,7 @@ } async _copyAllPowerShellCommand() { - const requests = BrowserSDK.networkLog.requests(); + const requests = SDK.networkLog.requests(); const commands = await Promise.all(requests.map(request => this._generatePowerShellCommand(request))); InspectorFrontendHost.copyText(commands.join(';\r\n')); }
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js b/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js index 1d2fc78d..06013d2 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js
@@ -137,9 +137,9 @@ SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.WillReloadPage, this._willReloadPage, this); SDK.targetManager.addModelListener(SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this._load, this); this._networkLogView.addEventListener(Network.NetworkLogView.Events.RequestSelected, this._onRequestSelected, this); - BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.RequestAdded, this._onUpdateRequest, this); - BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.RequestUpdated, this._onUpdateRequest, this); - BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.Reset, this._onNetworkLogReset, this); + SDK.networkLog.addEventListener(SDK.NetworkLog.Events.RequestAdded, this._onUpdateRequest, this); + SDK.networkLog.addEventListener(SDK.NetworkLog.Events.RequestUpdated, this._onUpdateRequest, this); + SDK.networkLog.addEventListener(SDK.NetworkLog.Events.Reset, this._onNetworkLogReset, this); } /** @@ -191,7 +191,7 @@ } this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._toggleRecordAction)); const clearButton = new UI.ToolbarButton(Common.UIString('Clear'), 'largeicon-clear'); - clearButton.addEventListener(UI.ToolbarButton.Events.Click, () => BrowserSDK.networkLog.reset(), this); + clearButton.addEventListener(UI.ToolbarButton.Events.Click, () => SDK.networkLog.reset(), this); this._panelToolbar.appendToolbarItem(clearButton); this._panelToolbar.appendSeparator(); const recordFilmStripButton = new UI.ToolbarSettingToggle( @@ -255,7 +255,7 @@ _toggleRecording() { if (!this._preserveLogSetting.get() && !this._toggleRecordAction.toggled()) - BrowserSDK.networkLog.reset(); + SDK.networkLog.reset(); this._toggleRecord(!this._toggleRecordAction.toggled()); } @@ -269,7 +269,7 @@ this._filmStripRecorder.stopRecording(this._filmStripAvailable.bind(this)); // TODO(einbinder) This should be moved to a setting/action that NetworkLog owns but NetworkPanel controls, but // always be present in the command menu. - BrowserSDK.networkLog.setIsRecording(toggled); + SDK.networkLog.setIsRecording(toggled); } /**
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js b/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js index 8320051..57afb465 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js
@@ -24,8 +24,7 @@ */ async performSearch(searchConfig, progress, searchResultCallback, searchFinishedCallback) { const promises = []; - const requests = - BrowserSDK.networkLog.requests().filter(request => searchConfig.filePathMatchesFileQuery(request.url())); + const requests = SDK.networkLog.requests().filter(request => searchConfig.filePathMatchesFileQuery(request.url())); progress.setTotalWork(requests.length); for (const request of requests) { const promise = this._searchRequest(searchConfig, request, progress);
diff --git a/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js b/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js index 869853f..95f78d8 100644 --- a/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js +++ b/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js
@@ -54,7 +54,7 @@ }; NetworkTestRunner.networkRequests = function() { - return Array.from(BrowserSDK.networkLog.requests()); + return Array.from(SDK.networkLog.requests()); }; NetworkTestRunner.dumpNetworkRequests = function() { @@ -71,7 +71,7 @@ }; NetworkTestRunner.dumpNetworkRequestsWithSignedExchangeInfo = function() { - for (const request of BrowserSDK.networkLog.requests()) { + for (const request of SDK.networkLog.requests()) { TestRunner.addResult(`* ${request.url()}`); TestRunner.addResult(` failed: ${!!request.failed}`); TestRunner.addResult(` statusCode: ${request.statusCode}`);
diff --git a/third_party/blink/renderer/devtools/front_end/browser_sdk/HAREntry.js b/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js similarity index 90% rename from third_party/blink/renderer/devtools/front_end/browser_sdk/HAREntry.js rename to third_party/blink/renderer/devtools/front_end/sdk/HARLog.js index cf90721..9ad29cb1d 100644 --- a/third_party/blink/renderer/devtools/front_end/browser_sdk/HAREntry.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js
@@ -36,7 +36,87 @@ /** * @unrestricted */ -BrowserSDK.HAREntry = class { +SDK.HARLog = class { + /** + * @param {!SDK.NetworkRequest} request + * @param {number} monotonicTime + * @return {!Date} + */ + static pseudoWallTime(request, monotonicTime) { + return new Date(request.pseudoWallTime(monotonicTime) * 1000); + } + + /** + * @param {!Array.<!SDK.NetworkRequest>} requests + * @return {!Promise<!Object>} + */ + static async build(requests) { + const log = new SDK.HARLog(); + const entryPromises = []; + for (const request of requests) + entryPromises.push(SDK.HARLog.Entry.build(request)); + const entries = await Promise.all(entryPromises); + return {version: '1.2', creator: log._creator(), pages: log._buildPages(requests), entries: entries}; + } + + _creator() { + const webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent); + + return {name: 'WebInspector', version: webKitVersion ? webKitVersion[1] : 'n/a'}; + } + + /** + * @param {!Array.<!SDK.NetworkRequest>} requests + * @return {!Array.<!Object>} + */ + _buildPages(requests) { + const seenIdentifiers = {}; + const pages = []; + for (let i = 0; i < requests.length; ++i) { + const request = requests[i]; + const page = SDK.NetworkLog.PageLoad.forRequest(request); + if (!page || seenIdentifiers[page.id]) + continue; + seenIdentifiers[page.id] = true; + pages.push(this._convertPage(page, request)); + } + return pages; + } + + /** + * @param {!SDK.NetworkLog.PageLoad} page + * @param {!SDK.NetworkRequest} request + * @return {!Object} + */ + _convertPage(page, request) { + return { + startedDateTime: SDK.HARLog.pseudoWallTime(request, page.startTime).toJSON(), + id: 'page_' + page.id, + title: page.url, // We don't have actual page title here. URL is probably better than nothing. + pageTimings: { + onContentLoad: this._pageEventTime(page, page.contentLoadTime), + onLoad: this._pageEventTime(page, page.loadTime) + } + }; + } + + /** + * @param {!SDK.NetworkLog.PageLoad} page + * @param {number} time + * @return {number} + */ + _pageEventTime(page, time) { + const startTime = page.startTime; + if (time === -1 || startTime === -1) + return -1; + return SDK.HARLog.Entry._toMilliseconds(time - startTime); + } +}; + +/** + * @unrestricted + */ +SDK.HARLog.Entry = class { /** * @param {!SDK.NetworkRequest} request */ @@ -57,7 +137,7 @@ * @return {!Promise<!Object>} */ static async build(request) { - const harEntry = new BrowserSDK.HAREntry(request); + const harEntry = new SDK.HARLog.Entry(request); let ipAddress = harEntry._request.remoteAddress(); const portPositionInString = ipAddress.lastIndexOf(':'); if (portPositionInString !== -1) @@ -70,7 +150,7 @@ time += Math.max(t, 0); const entry = { - startedDateTime: BrowserSDK.HARLog.pseudoWallTime(harEntry._request, harEntry._request.issueTime()).toJSON(), + startedDateTime: SDK.HARLog.pseudoWallTime(harEntry._request, harEntry._request.issueTime()).toJSON(), time: time, request: await harEntry._buildRequest(), response: harEntry._buildResponse(), @@ -86,7 +166,7 @@ if (harEntry._request.connectionId !== '0') entry.connection = harEntry._request.connectionId; - const page = BrowserSDK.PageLoad.forRequest(harEntry._request); + const page = SDK.NetworkLog.PageLoad.forRequest(harEntry._request); if (page) entry.pageref = 'page_' + page.id; return entry; @@ -150,7 +230,7 @@ } /** - * @return {!BrowserSDK.HAREntry.Timing} + * @return {!SDK.HARLog.Entry.Timing} */ _buildTimings() { // Order of events: request_start = 0, [proxy], [dns], [connect [ssl]], [send], duration @@ -162,7 +242,7 @@ const queuedTime = (issueTime < startTime) ? startTime - issueTime : -1; result.blocked = queuedTime; - result._blocked_queueing = BrowserSDK.HAREntry._toMilliseconds(queuedTime); + result._blocked_queueing = SDK.HARLog.Entry._toMilliseconds(queuedTime); let highestTime = 0; if (timing) { @@ -207,11 +287,11 @@ const requestTime = timing ? timing.requestTime : startTime; const waitStart = highestTime; - const waitEnd = BrowserSDK.HAREntry._toMilliseconds(this._request.responseReceivedTime - requestTime); + const waitEnd = SDK.HARLog.Entry._toMilliseconds(this._request.responseReceivedTime - requestTime); result.wait = waitEnd - waitStart; const receiveStart = waitEnd; - const receiveEnd = BrowserSDK.HAREntry._toMilliseconds(this._request.endTime - issueTime); + const receiveEnd = SDK.HARLog.Entry._toMilliseconds(this._request.endTime - issueTime); result.receive = Math.max(receiveEnd - receiveStart, 0); return result; @@ -273,7 +353,7 @@ value: cookie.value(), path: cookie.path(), domain: cookie.domain(), - expires: cookie.expiresDate(BrowserSDK.HARLog.pseudoWallTime(this._request, this._request.startTime)), + expires: cookie.expiresDate(SDK.HARLog.pseudoWallTime(this._request, this._request.startTime)), httpOnly: cookie.httpOnly(), secure: cookie.secure() }; @@ -323,85 +403,4 @@ _blocked_queueing: number, _blocked_proxy: (number|undefined) }} */ -BrowserSDK.HAREntry.Timing; - - -/** - * @unrestricted - */ -BrowserSDK.HARLog = class { - /** - * @param {!SDK.NetworkRequest} request - * @param {number} monotonicTime - * @return {!Date} - */ - static pseudoWallTime(request, monotonicTime) { - return new Date(request.pseudoWallTime(monotonicTime) * 1000); - } - - /** - * @param {!Array.<!SDK.NetworkRequest>} requests - * @return {!Promise<!Object>} - */ - static async build(requests) { - const log = new BrowserSDK.HARLog(); - const entryPromises = []; - for (const request of requests) - entryPromises.push(BrowserSDK.HAREntry.build(request)); - const entries = await Promise.all(entryPromises); - return {version: '1.2', creator: log._creator(), pages: log._buildPages(requests), entries: entries}; - } - - _creator() { - const webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent); - - return {name: 'WebInspector', version: webKitVersion ? webKitVersion[1] : 'n/a'}; - } - - /** - * @param {!Array.<!SDK.NetworkRequest>} requests - * @return {!Array.<!Object>} - */ - _buildPages(requests) { - const seenIdentifiers = {}; - const pages = []; - for (let i = 0; i < requests.length; ++i) { - const request = requests[i]; - const page = BrowserSDK.PageLoad.forRequest(request); - if (!page || seenIdentifiers[page.id]) - continue; - seenIdentifiers[page.id] = true; - pages.push(this._convertPage(page, request)); - } - return pages; - } - - /** - * @param {!BrowserSDK.PageLoad} page - * @param {!SDK.NetworkRequest} request - * @return {!Object} - */ - _convertPage(page, request) { - return { - startedDateTime: BrowserSDK.HARLog.pseudoWallTime(request, page.startTime).toJSON(), - id: 'page_' + page.id, - title: page.url, // We don't have actual page title here. URL is probably better than nothing. - pageTimings: { - onContentLoad: this._pageEventTime(page, page.contentLoadTime), - onLoad: this._pageEventTime(page, page.loadTime) - } - }; - } - - /** - * @param {!BrowserSDK.PageLoad} page - * @param {number} time - * @return {number} - */ - _pageEventTime(page, time) { - const startTime = page.startTime; - if (time === -1 || startTime === -1) - return -1; - return BrowserSDK.HAREntry._toMilliseconds(time - startTime); - } -}; +SDK.HARLog.Entry.Timing; \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/browser_sdk/NetworkLog.js b/third_party/blink/renderer/devtools/front_end/sdk/NetworkLog.js similarity index 82% rename from third_party/blink/renderer/devtools/front_end/browser_sdk/NetworkLog.js rename to third_party/blink/renderer/devtools/front_end/sdk/NetworkLog.js index 78447fdd..bcb9bf82 100644 --- a/third_party/blink/renderer/devtools/front_end/browser_sdk/NetworkLog.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/NetworkLog.js
@@ -31,14 +31,14 @@ /** * @implements {SDK.SDKModelObserver<!SDK.NetworkManager>} */ -BrowserSDK.NetworkLog = class extends Common.Object { +SDK.NetworkLog = class extends Common.Object { constructor() { super(); /** @type {!Array<!SDK.NetworkRequest>} */ this._requests = []; /** @type {!Set<!SDK.NetworkRequest>} */ this._requestsSet = new Set(); - /** @type {!Map<!SDK.NetworkManager, !BrowserSDK.PageLoad>} */ + /** @type {!Map<!SDK.NetworkManager, !SDK.NetworkLog.PageLoad>} */ this._pageLoadForManager = new Map(); this._isRecording = true; SDK.targetManager.observeModels(SDK.NetworkManager, this); @@ -72,7 +72,7 @@ SDK.ResourceTreeModel.Events.DOMContentLoaded, this._onDOMContentLoaded.bind(this, resourceTreeModel))); } - networkManager[BrowserSDK.NetworkLog._events] = eventListeners; + networkManager[SDK.NetworkLog._events] = eventListeners; } /** @@ -87,7 +87,7 @@ * @param {!SDK.NetworkManager} networkManager */ _removeNetworkManagerListeners(networkManager) { - Common.EventTarget.removeEventListeners(networkManager[BrowserSDK.NetworkLog._events]); + Common.EventTarget.removeEventListeners(networkManager[SDK.NetworkLog._events]); } /** @@ -152,9 +152,9 @@ * @param {!SDK.NetworkRequest} request */ _initializeInitiatorSymbolIfNeeded(request) { - if (!request[BrowserSDK.NetworkLog._initiatorDataSymbol]) { - /** @type {!{info: ?BrowserSDK.NetworkLog._InitiatorInfo, chain: !Set<!SDK.NetworkRequest>, request: (?SDK.NetworkRequest|undefined)}} */ - request[BrowserSDK.NetworkLog._initiatorDataSymbol] = { + if (!request[SDK.NetworkLog._initiatorDataSymbol]) { + /** @type {!{info: ?SDK.NetworkLog._InitiatorInfo, chain: !Set<!SDK.NetworkRequest>, request: (?SDK.NetworkRequest|undefined)}} */ + request[SDK.NetworkLog._initiatorDataSymbol] = { info: null, chain: null, request: undefined, @@ -164,12 +164,12 @@ /** * @param {!SDK.NetworkRequest} request - * @return {!BrowserSDK.NetworkLog._InitiatorInfo} + * @return {!SDK.NetworkLog._InitiatorInfo} */ initiatorInfoForRequest(request) { this._initializeInitiatorSymbolIfNeeded(request); - if (request[BrowserSDK.NetworkLog._initiatorDataSymbol].info) - return request[BrowserSDK.NetworkLog._initiatorDataSymbol].info; + if (request[SDK.NetworkLog._initiatorDataSymbol].info) + return request[SDK.NetworkLog._initiatorDataSymbol].info; let type = SDK.NetworkRequest.InitiatorType.Other; let url = ''; @@ -215,7 +215,7 @@ } } - request[BrowserSDK.NetworkLog._initiatorDataSymbol].info = { + request[SDK.NetworkLog._initiatorDataSymbol].info = { type: type, url: url, lineNumber: lineNumber, @@ -223,12 +223,12 @@ scriptId: scriptId, stack: initiatorStack }; - return request[BrowserSDK.NetworkLog._initiatorDataSymbol].info; + return request[SDK.NetworkLog._initiatorDataSymbol].info; } /** * @param {!SDK.NetworkRequest} request - * @return {!BrowserSDK.NetworkLog.InitiatorGraph} + * @return {!SDK.NetworkLog.InitiatorGraph} */ initiatorGraphForRequest(request) { /** @type {!Set<!SDK.NetworkRequest>} */ @@ -249,7 +249,7 @@ _initiatorChain(request) { this._initializeInitiatorSymbolIfNeeded(request); let initiatorChainCache = - /** @type {?Set<!SDK.NetworkRequest>} */ (request[BrowserSDK.NetworkLog._initiatorDataSymbol].chain); + /** @type {?Set<!SDK.NetworkRequest>} */ (request[SDK.NetworkLog._initiatorDataSymbol].chain); if (initiatorChainCache) return initiatorChainCache; @@ -257,8 +257,8 @@ let checkRequest = request; do { - if (checkRequest[BrowserSDK.NetworkLog._initiatorDataSymbol].chain) { - initiatorChainCache.addAll(checkRequest[BrowserSDK.NetworkLog._initiatorDataSymbol].chain); + if (checkRequest[SDK.NetworkLog._initiatorDataSymbol].chain) { + initiatorChainCache.addAll(checkRequest[SDK.NetworkLog._initiatorDataSymbol].chain); break; } if (initiatorChainCache.has(checkRequest)) @@ -266,7 +266,7 @@ initiatorChainCache.add(checkRequest); checkRequest = this._initiatorRequest(checkRequest); } while (checkRequest); - request[BrowserSDK.NetworkLog._initiatorDataSymbol].chain = initiatorChainCache; + request[SDK.NetworkLog._initiatorDataSymbol].chain = initiatorChainCache; return initiatorChainCache; } @@ -276,13 +276,13 @@ */ _initiatorRequest(request) { this._initializeInitiatorSymbolIfNeeded(request); - if (request[BrowserSDK.NetworkLog._initiatorDataSymbol].request !== undefined) - return request[BrowserSDK.NetworkLog._initiatorDataSymbol].request; + if (request[SDK.NetworkLog._initiatorDataSymbol].request !== undefined) + return request[SDK.NetworkLog._initiatorDataSymbol].request; const url = this.initiatorInfoForRequest(request).url; const networkManager = SDK.NetworkManager.forRequest(request); - request[BrowserSDK.NetworkLog._initiatorDataSymbol].request = + request[SDK.NetworkLog._initiatorDataSymbol].request = networkManager ? this._requestByManagerAndURL(networkManager, url) : null; - return request[BrowserSDK.NetworkLog._initiatorDataSymbol].request; + return request[SDK.NetworkLog._initiatorDataSymbol].request; } _willReloadPage() { @@ -303,7 +303,7 @@ const oldRequestsSet = this._requestsSet; this._requests = []; this._requestsSet = new Set(); - this.dispatchEventToListeners(BrowserSDK.NetworkLog.Events.Reset); + this.dispatchEventToListeners(SDK.NetworkLog.Events.Reset); // Preserve requests from the new session. let currentPageLoad = null; @@ -312,7 +312,7 @@ if (request.loaderId !== mainFrame.loaderId) continue; if (!currentPageLoad) { - currentPageLoad = new BrowserSDK.PageLoad(request); + currentPageLoad = new SDK.NetworkLog.PageLoad(request); let redirectSource = request.redirectSource(); while (redirectSource) { requestsToAdd.push(redirectSource); @@ -327,14 +327,14 @@ this._requests.push(request); this._requestsSet.add(request); currentPageLoad.bindRequest(request); - this.dispatchEventToListeners(BrowserSDK.NetworkLog.Events.RequestAdded, request); + this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestAdded, request); } if (Common.moduleSetting('network_log.preserve-log').get()) { for (const request of oldRequestsSet) { this._requests.push(request); this._requestsSet.add(request); - this.dispatchEventToListeners(BrowserSDK.NetworkLog.Events.RequestAdded, request); + this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestAdded, request); } } @@ -352,7 +352,7 @@ for (const request of requests) { this._requests.push(request); this._requestsSet.add(request); - this.dispatchEventToListeners(BrowserSDK.NetworkLog.Events.RequestAdded, request); + this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestAdded, request); } } @@ -367,7 +367,7 @@ const pageLoad = manager ? this._pageLoadForManager.get(manager) : null; if (pageLoad) pageLoad.bindRequest(request); - this.dispatchEventToListeners(BrowserSDK.NetworkLog.Events.RequestAdded, request); + this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestAdded, request); } /** @@ -377,7 +377,7 @@ const request = /** @type {!SDK.NetworkRequest} */ (event.data); if (!this._requestsSet.has(request)) return; - this.dispatchEventToListeners(BrowserSDK.NetworkLog.Events.RequestUpdated, request); + this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestUpdated, request); } /** @@ -385,7 +385,7 @@ */ _onRequestRedirect(event) { const request = /** @type {!SDK.NetworkRequest} */ (event.data); - delete request[BrowserSDK.NetworkLog._initiatorDataSymbol]; + delete request[SDK.NetworkLog._initiatorDataSymbol]; } /** @@ -418,7 +418,7 @@ this._pageLoadForManager.delete(manager); } - this.dispatchEventToListeners(BrowserSDK.NetworkLog.Events.Reset); + this.dispatchEventToListeners(SDK.NetworkLog.Events.Reset); } /** @@ -447,7 +447,7 @@ const request = this.requestByManagerAndId(networkManager, requestId); if (!request) return; - consoleMessage[BrowserSDK.NetworkLog._requestSymbol] = request; + consoleMessage[SDK.NetworkLog._requestSymbol] = request; const initiator = request.initiator(); if (initiator) { consoleMessage.stackTrace = initiator.stack || undefined; @@ -463,16 +463,16 @@ * @return {?SDK.NetworkRequest} */ static requestForConsoleMessage(consoleMessage) { - return consoleMessage[BrowserSDK.NetworkLog._requestSymbol] || null; + return consoleMessage[SDK.NetworkLog._requestSymbol] || null; } }; -BrowserSDK.PageLoad = class { +SDK.NetworkLog.PageLoad = class { /** * @param {!SDK.NetworkRequest} mainRequest */ constructor(mainRequest) { - this.id = ++BrowserSDK.PageLoad._lastIdentifier; + this.id = ++SDK.NetworkLog.PageLoad._lastIdentifier; this.url = mainRequest.url(); this.startTime = mainRequest.startTime; /** @type {number} */ @@ -491,53 +491,53 @@ if (!this.mainRequest.finished) await this.mainRequest.once(SDK.NetworkRequest.Events.FinishedLoading); const saveDataHeader = this.mainRequest.requestHeaderValue('Save-Data'); - if (!BrowserSDK.PageLoad._dataSaverMessageWasShown && saveDataHeader && saveDataHeader === 'on') { + if (!SDK.NetworkLog.PageLoad._dataSaverMessageWasShown && saveDataHeader && saveDataHeader === 'on') { const message = Common.UIString( 'Consider disabling %s while debugging. For more info see: %s', Common.UIString('Chrome Data Saver'), 'https://support.google.com/chrome/?p=datasaver'); manager.dispatchEventToListeners( SDK.NetworkManager.Events.MessageGenerated, {message: message, requestId: this.mainRequest.requestId(), warning: true}); - BrowserSDK.PageLoad._dataSaverMessageWasShown = true; + SDK.NetworkLog.PageLoad._dataSaverMessageWasShown = true; } } /** * @param {!SDK.NetworkRequest} request - * @return {?BrowserSDK.PageLoad} + * @return {?SDK.NetworkLog.PageLoad} */ static forRequest(request) { - return request[BrowserSDK.PageLoad._pageLoadForRequestSymbol] || null; + return request[SDK.NetworkLog.PageLoad._pageLoadForRequestSymbol] || null; } /** * @param {!SDK.NetworkRequest} request */ bindRequest(request) { - request[BrowserSDK.PageLoad._pageLoadForRequestSymbol] = this; + request[SDK.NetworkLog.PageLoad._pageLoadForRequestSymbol] = this; } }; -BrowserSDK.PageLoad._lastIdentifier = 0; -BrowserSDK.PageLoad._pageLoadForRequestSymbol = Symbol('PageLoadForRequest'); -BrowserSDK.NetworkLog._requestSymbol = Symbol('_request'); +SDK.NetworkLog.PageLoad._lastIdentifier = 0; +SDK.NetworkLog.PageLoad._pageLoadForRequestSymbol = Symbol('PageLoadForRequest'); +SDK.NetworkLog._requestSymbol = Symbol('_request'); -BrowserSDK.PageLoad._dataSaverMessageWasShown = false; +SDK.NetworkLog.PageLoad._dataSaverMessageWasShown = false; /** @typedef {!{initiators: !Set<!SDK.NetworkRequest>, initiated: !Set<!SDK.NetworkRequest>}} */ -BrowserSDK.NetworkLog.InitiatorGraph; +SDK.NetworkLog.InitiatorGraph; -BrowserSDK.NetworkLog.Events = { +SDK.NetworkLog.Events = { Reset: Symbol('Reset'), RequestAdded: Symbol('RequestAdded'), RequestUpdated: Symbol('RequestUpdated') }; /** @typedef {!{type: !SDK.NetworkRequest.InitiatorType, url: string, lineNumber: number, columnNumber: number, scriptId: ?string, stack: ?Protocol.Runtime.StackTrace}} */ -BrowserSDK.NetworkLog._InitiatorInfo; +SDK.NetworkLog._InitiatorInfo; -BrowserSDK.NetworkLog._initiatorDataSymbol = Symbol('InitiatorData'); -BrowserSDK.NetworkLog._events = Symbol('BrowserSDK.NetworkLog.events'); +SDK.NetworkLog._initiatorDataSymbol = Symbol('InitiatorData'); +SDK.NetworkLog._events = Symbol('SDK.NetworkLog.events'); -/** @type {!BrowserSDK.NetworkLog} */ -BrowserSDK.networkLog = new BrowserSDK.NetworkLog(); +/** @type {!SDK.NetworkLog} */ +SDK.networkLog = new SDK.NetworkLog();
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/module.json b/third_party/blink/renderer/devtools/front_end/sdk/module.json index 7edcfedf..89048fb 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/module.json +++ b/third_party/blink/renderer/devtools/front_end/sdk/module.json
@@ -284,6 +284,7 @@ "DOMModel.js", "DebuggerModel.js", "EmulationModel.js", + "HARLog.js", "LayerTreeBase.js", "LogModel.js", "ServiceWorkerManager.js", @@ -301,6 +302,7 @@ "SourceMap.js", "SourceMapManager.js", "NetworkManager.js", + "NetworkLog.js", "NetworkRequest.js", "PaintProfiler.js", "HeapProfilerModel.js",
diff --git a/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js b/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js index 23ed009..4b9571a 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js +++ b/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
@@ -81,9 +81,10 @@ if (UI.viewManager.hasViewsForLocation('run-view-sidebar')) { const navigatorSplitWidget = new UI.SplitWidget(false, true, 'sourcePanelNavigatorSidebarSplitViewState'); navigatorSplitWidget.setMainWidget(tabbedPane); - navigatorSplitWidget.setSidebarWidget( - UI.viewManager.createTabbedLocation(this._revealNavigatorSidebar.bind(this), 'run-view-sidebar') - .tabbedPane()); + const runViewTabbedPane = + UI.viewManager.createTabbedLocation(this._revealNavigatorSidebar.bind(this), 'run-view-sidebar').tabbedPane(); + navigatorSplitWidget.setSidebarWidget(runViewTabbedPane); + navigatorSplitWidget.installResizer(runViewTabbedPane.headerElement()); this.editorView.setSidebarWidget(navigatorSplitWidget); } else { this.editorView.setSidebarWidget(tabbedPane);
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js index 628d070..59f25d6 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js +++ b/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
@@ -785,7 +785,7 @@ let previewElement = null; const url = TimelineModel.TimelineData.forEvent(event).url; if (url) - previewElement = await BrowserComponents.ImagePreview.build(target, url, false); + previewElement = await Components.ImagePreview.build(target, url, false); else if (TimelineModel.TimelineData.forEvent(event).picture) previewElement = await Timeline.TimelineUIUtils.buildPicturePreviewContent(event, target); event[Timeline.TimelineUIUtils._previewElementSymbol] = previewElement; @@ -1256,7 +1256,7 @@ } if (!request.previewElement && request.url && target) - request.previewElement = await BrowserComponents.ImagePreview.build(target, request.url, false); + request.previewElement = await Components.ImagePreview.build(target, request.url, false); if (request.previewElement) contentHelper.appendElementRow(Common.UIString('Preview'), request.previewElement); return contentHelper.fragment; @@ -1496,7 +1496,7 @@ if (!imageURL) return null; const container = createElement('div'); - UI.appendStyle(container, 'browser_components/imagePreview.css'); + UI.appendStyle(container, 'components/imagePreview.css'); container.classList.add('image-preview-container', 'vbox', 'link'); const img = container.createChild('img'); img.src = imageURL;
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/module.json b/third_party/blink/renderer/devtools/front_end/timeline/module.json index 75f4094..f175531 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline/module.json +++ b/third_party/blink/renderer/devtools/front_end/timeline/module.json
@@ -218,7 +218,7 @@ } ], "dependencies": [ - "browser_components", + "components", "layer_viewer", "timeline_model", "perf_ui",
diff --git a/third_party/blink/renderer/devtools/front_end/worker_app.json b/third_party/blink/renderer/devtools/front_end/worker_app.json index deadd1f..bb5c7d43 100644 --- a/third_party/blink/renderer/devtools/front_end/worker_app.json +++ b/third_party/blink/renderer/devtools/front_end/worker_app.json
@@ -2,7 +2,6 @@ "modules" : [ { "name": "mobile_throttling", "type": "autostart" }, { "name": "worker_main", "type": "autostart" }, - { "name": "browser_components", "type": "autostart" }, { "name": "browser_console" }, { "name": "browser_debugger" },
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index b4ad9a0..1c29d0cd 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -437,6 +437,7 @@ "xr/xr_input_source_event.idl", "xr/xr_layer.idl", "xr/xr_presentation_context.idl", + "xr/xr_ray.idl", "xr/xr_session.idl", "xr/xr_session_event.idl", "xr/xr_stage_bounds.idl",
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc index 0fef66c..4554fcbbd 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
@@ -42,7 +42,8 @@ GLint layer, GLenum access, GLenum format) { - SynthesizeGLError(GL_INVALID_OPERATION, "bindImageTexture", "UNIMPLEMENTED"); + ContextGL()->BindImageTexture(unit, ObjectOrZero(texture), level, layered, + layer, access, format); } void WebGL2ComputeRenderingContextBase::memoryBarrier(GLbitfield barriers) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 496ef66..2c7b940 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -3768,6 +3768,27 @@ base_type = GL_INT; length = 1; break; + case GL_IMAGE_2D: + case GL_IMAGE_3D: + case GL_IMAGE_CUBE: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D: + case GL_INT_IMAGE_3D: + case GL_INT_IMAGE_CUBE: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: { + if (context_type_ != Platform::kWebGL2ComputeContextType) { + SynthesizeGLError(GL_INVALID_VALUE, "getUniform", + "unhandled type"); + return ScriptValue::CreateNull(script_state); + } + base_type = GL_INT; + length = 1; + break; + } default: // Can't handle this type SynthesizeGLError(GL_INVALID_VALUE, "getUniform",
diff --git a/third_party/blink/renderer/modules/xr/BUILD.gn b/third_party/blink/renderer/modules/xr/BUILD.gn index 689c7af..c9d3f2f 100644 --- a/third_party/blink/renderer/modules/xr/BUILD.gn +++ b/third_party/blink/renderer/modules/xr/BUILD.gn
@@ -36,6 +36,8 @@ "xr_layer.h", "xr_presentation_context.cc", "xr_presentation_context.h", + "xr_ray.cc", + "xr_ray.h", "xr_session.cc", "xr_session.h", "xr_session_event.cc",
diff --git a/third_party/blink/renderer/modules/xr/xr_input_pose.cc b/third_party/blink/renderer/modules/xr/xr_input_pose.cc index c40afa39..8057426 100644 --- a/third_party/blink/renderer/modules/xr/xr_input_pose.cc +++ b/third_party/blink/renderer/modules/xr/xr_input_pose.cc
@@ -11,18 +11,12 @@ XRInputPose::XRInputPose(std::unique_ptr<TransformationMatrix> pointer_matrix, std::unique_ptr<TransformationMatrix> grip_matrix, bool emulated_position) - : pointer_matrix_(std::move(pointer_matrix)), + : target_ray_(new XRRay(std::move(pointer_matrix))), grip_matrix_(std::move(grip_matrix)), emulated_position_(emulated_position) {} XRInputPose::~XRInputPose() {} -DOMFloat32Array* XRInputPose::pointerMatrix() const { - if (!pointer_matrix_) - return nullptr; - return transformationMatrixToFloat32Array(*pointer_matrix_); -} - DOMFloat32Array* XRInputPose::gripMatrix() const { if (!grip_matrix_) return nullptr; @@ -30,6 +24,7 @@ } void XRInputPose::Trace(blink::Visitor* visitor) { + visitor->Trace(target_ray_); ScriptWrappable::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/xr/xr_input_pose.h b/third_party/blink/renderer/modules/xr/xr_input_pose.h index a377f642..7d5448d 100644 --- a/third_party/blink/renderer/modules/xr/xr_input_pose.h +++ b/third_party/blink/renderer/modules/xr/xr_input_pose.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_POSE_H_ #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" +#include "third_party/blink/renderer/modules/xr/xr_ray.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" @@ -17,19 +18,19 @@ DEFINE_WRAPPERTYPEINFO(); public: - XRInputPose(std::unique_ptr<TransformationMatrix> pointer_matrix, + XRInputPose(std::unique_ptr<TransformationMatrix> target_ray_matrix, std::unique_ptr<TransformationMatrix> grip_matrix, bool emulated_position = false); ~XRInputPose() override; - DOMFloat32Array* pointerMatrix() const; + XRRay* targetRay() const { return target_ray_; } DOMFloat32Array* gripMatrix() const; bool emulatedPosition() const { return emulated_position_; } void Trace(blink::Visitor*) override; private: - const std::unique_ptr<TransformationMatrix> pointer_matrix_; + const Member<XRRay> target_ray_; const std::unique_ptr<TransformationMatrix> grip_matrix_; const bool emulated_position_; };
diff --git a/third_party/blink/renderer/modules/xr/xr_input_pose.idl b/third_party/blink/renderer/modules/xr/xr_input_pose.idl index 6113cc72..377ee58a 100644 --- a/third_party/blink/renderer/modules/xr/xr_input_pose.idl +++ b/third_party/blink/renderer/modules/xr/xr_input_pose.idl
@@ -6,7 +6,7 @@ SecureContext, OriginTrialEnabled=WebXR ] interface XRInputPose { - readonly attribute Float32Array pointerMatrix; + readonly attribute XRRay targetRay; readonly attribute Float32Array? gripMatrix; readonly attribute boolean emulatedPosition; }; \ No newline at end of file
diff --git a/third_party/blink/renderer/modules/xr/xr_ray.cc b/third_party/blink/renderer/modules/xr/xr_ray.cc new file mode 100644 index 0000000..22ae3d4 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_ray.cc
@@ -0,0 +1,39 @@ +// Copyright 2018 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 "third_party/blink/renderer/modules/xr/xr_ray.h" + +#include "third_party/blink/renderer/modules/xr/xr_utils.h" +#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" + +namespace blink { +XRRay::XRRay(std::unique_ptr<TransformationMatrix> transform_matrix) + : transform_matrix_(std::move(transform_matrix)) { + FloatPoint3D origin = transform_matrix_->MapPoint(FloatPoint3D(0, 0, 0)); + FloatPoint3D dir = transform_matrix_->MapPoint(FloatPoint3D(0, 0, -1)); + dir.Move(-origin.X(), -origin.Y(), -origin.Z()); + dir.Normalize(); + + origin_ = DOMPointReadOnly::Create(origin.X(), origin.Y(), origin.Z(), 1.0); + direction_ = DOMPointReadOnly::Create(dir.X(), dir.Y(), dir.Z(), 0.0); +} + +XRRay::~XRRay() {} + +DOMFloat32Array* XRRay::transformMatrix() const { + if (!transform_matrix_) + return nullptr; + // TODO(https://crbug.com/845296): rename + // transformationMatrixToFloat32Array() to + // TransformationMatrixToDOMFloat32Array(). + return transformationMatrixToFloat32Array(*transform_matrix_); +} + +void XRRay::Trace(blink::Visitor* visitor) { + visitor->Trace(origin_); + visitor->Trace(direction_); + ScriptWrappable::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_ray.h b/third_party/blink/renderer/modules/xr/xr_ray.h new file mode 100644 index 0000000..e157b24 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_ray.h
@@ -0,0 +1,37 @@ +// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_RAY_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_RAY_H_ + +#include "third_party/blink/renderer/core/geometry/dom_point_read_only.h" +#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" +#include "third_party/blink/renderer/platform/heap/handle.h" + +namespace blink { + +class TransformationMatrix; + +class XRRay final : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + explicit XRRay(std::unique_ptr<TransformationMatrix>); + ~XRRay() override; + + DOMPointReadOnly* origin() const { return origin_; } + DOMPointReadOnly* direction() const { return direction_; } + DOMFloat32Array* transformMatrix() const; + + void Trace(blink::Visitor*) override; + + private: + Member<DOMPointReadOnly> origin_; + Member<DOMPointReadOnly> direction_; + const std::unique_ptr<TransformationMatrix> transform_matrix_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_RAY_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_ray.idl b/third_party/blink/renderer/modules/xr/xr_ray.idl new file mode 100644 index 0000000..b9ca32e3 --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_ray.idl
@@ -0,0 +1,10 @@ +// Copyright 2018 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. + +// https://immersive-web.github.io/webxr/#xrray-interface +[SecureContext, OriginTrialEnabled=WebXR] interface XRRay { + readonly attribute DOMPointReadOnly origin; + readonly attribute DOMPointReadOnly direction; + readonly attribute Float32Array transformMatrix; +}; \ No newline at end of file
diff --git a/third_party/blink/renderer/platform/graphics/DEPS b/third_party/blink/renderer/platform/graphics/DEPS index af03830e..137bba4 100644 --- a/third_party/blink/renderer/platform/graphics/DEPS +++ b/third_party/blink/renderer/platform/graphics/DEPS
@@ -38,7 +38,6 @@ "+third_party/blink/renderer/platform/json", "+third_party/blink/renderer/platform/length.h", "+third_party/blink/renderer/platform/mojo/mojo_helper.h", - "+third_party/blink/renderer/platform/network/mime/mime_type_registry.h", "+third_party/blink/renderer/platform/platform_export.h", "+third_party/blink/renderer/platform/runtime_enabled_features.h", "+third_party/blink/renderer/platform/scheduler", @@ -52,7 +51,6 @@ "+third_party/blink/renderer/platform/weborigin/kurl.h", "+third_party/blink/renderer/platform/web_task_runner.h", "+third_party/blink/renderer/platform/wtf", - "+third_party/blink/public/web/web_settings.h", "+ui/gfx/geometry", ]
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image.cc b/third_party/blink/renderer/platform/graphics/bitmap_image.cc index 8bf47e9..93c8d90 100644 --- a/third_party/blink/renderer/platform/graphics/bitmap_image.cc +++ b/third_party/blink/renderer/platform/graphics/bitmap_image.cc
@@ -32,7 +32,6 @@ #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_macros.h" -#include "third_party/blink/public/web/web_settings.h" #include "third_party/blink/renderer/platform/geometry/float_rect.h" #include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h" #include "third_party/blink/renderer/platform/graphics/deferred_image_decoder.h" @@ -414,11 +413,4 @@ ResetAnimation(); } -STATIC_ASSERT_ENUM(WebSettings::kImageAnimationPolicyAllowed, - kImageAnimationPolicyAllowed); -STATIC_ASSERT_ENUM(WebSettings::kImageAnimationPolicyAnimateOnce, - kImageAnimationPolicyAnimateOnce); -STATIC_ASSERT_ENUM(WebSettings::kImageAnimationPolicyNoAnimation, - kImageAnimationPolicyNoAnimation); - } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/image.cc b/third_party/blink/renderer/platform/graphics/image.cc index 883b046..28935ae 100644 --- a/third_party/blink/renderer/platform/graphics/image.cc +++ b/third_party/blink/renderer/platform/graphics/image.cc
@@ -46,7 +46,6 @@ #include "third_party/blink/renderer/platform/instrumentation/platform_instrumentation.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/length.h" -#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h" #include "third_party/blink/renderer/platform/shared_buffer.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -95,10 +94,6 @@ return image; } -bool Image::SupportsType(const String& type) { - return MIMETypeRegistry::IsSupportedImageResourceMIMEType(type); -} - Image::SizeAvailability Image::SetData(scoped_refptr<SharedBuffer> data, bool all_data_received) { encoded_image_data_ = std::move(data);
diff --git a/third_party/blink/renderer/platform/graphics/image.h b/third_party/blink/renderer/platform/graphics/image.h index 7524079..c7e847c 100644 --- a/third_party/blink/renderer/platform/graphics/image.h +++ b/third_party/blink/renderer/platform/graphics/image.h
@@ -75,7 +75,6 @@ static cc::ImageDecodeCache& SharedCCDecodeCache(); static scoped_refptr<Image> LoadPlatformResource(const char* name); - static bool SupportsType(const String&); virtual bool IsSVGImage() const { return false; } virtual bool IsBitmapImage() const { return false; }
diff --git a/third_party/blink/renderer/platform/graphics/image_data_buffer.cc b/third_party/blink/renderer/platform/graphics/image_data_buffer.cc index c3d7df4..252baeb 100644 --- a/third_party/blink/renderer/platform/graphics/image_data_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/image_data_buffer.cc
@@ -37,7 +37,6 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" #include "third_party/blink/renderer/platform/image-encoders/image_encoder.h" -#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/text/base64.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -154,7 +153,6 @@ String ImageDataBuffer::ToDataURL(const String& mime_type, const double& quality) const { DCHECK(is_valid_); - DCHECK(MIMETypeRegistry::IsSupportedImageMIMETypeForEncoding(mime_type)); // toDataURL always encodes in sRGB and does not include the color space // information.
diff --git a/third_party/blink/renderer/platform/heap/heap_page.cc b/third_party/blink/renderer/platform/heap/heap_page.cc index 07ae942..67b2e27 100644 --- a/third_party/blink/renderer/platform/heap/heap_page.cc +++ b/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -1496,6 +1496,7 @@ void NormalPage::MakeConsistentForMutator() { object_start_bit_map()->Clear(); + size_t marked_object_size = 0; Address start_of_gap = Payload(); NormalPageArena* normal_arena = ArenaForNormalPage(); for (Address header_address = Payload(); header_address < PayloadEnd();) { @@ -1519,6 +1520,7 @@ normal_arena->AddToFreeList(start_of_gap, header_address - start_of_gap); if (header->IsMarked()) { header->Unmark(); + marked_object_size += size; } object_start_bit_map()->SetBit(header_address); header_address += size; @@ -1528,6 +1530,11 @@ if (start_of_gap != PayloadEnd()) normal_arena->AddToFreeList(start_of_gap, PayloadEnd() - start_of_gap); + if (marked_object_size) { + ArenaForNormalPage()->GetThreadState()->Heap().IncreaseMarkedObjectSize( + marked_object_size); + } + VerifyObjectStartBitmapIsConsistentWithPayload(); } @@ -1709,8 +1716,10 @@ void LargeObjectPage::MakeConsistentForMutator() { HeapObjectHeader* header = ObjectHeader(); - if (header->IsMarked()) + if (header->IsMarked()) { header->Unmark(); + Arena()->GetThreadState()->Heap().IncreaseMarkedObjectSize(size()); + } } #if defined(ADDRESS_SANITIZER)
diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc index a1e440f..fd4e72b 100644 --- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
@@ -643,7 +643,7 @@ IntSize UvSize() const { return uv_size_; } private: - JSAMPARRAY AllocateSampleArray() { + NO_SANITIZE_CFI_ICALL JSAMPARRAY AllocateSampleArray() { // Some output color spaces don't need the sample array: don't allocate in that // case. #if defined(TURBO_JPEG_RGB_SWIZZLE)
diff --git a/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc b/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc index dbc2740fa..1b67826 100644 --- a/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc +++ b/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h" +#include <initializer_list> + #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h" @@ -20,10 +22,10 @@ namespace { -template <size_t N> -void Append(StringBuilder& builder, const StringView (&views)[N]) { - for (size_t i = 0; i < N; ++i) - builder.Append(views[i]); +void Append(StringBuilder& builder, std::initializer_list<StringView> views) { + for (const StringView& view : views) { + builder.Append(view); + } } bool IsPreflightError(network::mojom::CORSError error_code) {
diff --git a/third_party/blink/renderer/platform/wtf/compiler.h b/third_party/blink/renderer/platform/wtf/compiler.h index 51595af..5225a70 100644 --- a/third_party/blink/renderer/platform/wtf/compiler.h +++ b/third_party/blink/renderer/platform/wtf/compiler.h
@@ -57,8 +57,10 @@ #if defined(__clang__) #define NO_SANITIZE_UNRELATED_CAST \ __attribute__((no_sanitize("cfi-unrelated-cast", "vptr"))) +#define NO_SANITIZE_CFI_ICALL __attribute__((no_sanitize("cfi-icall"))) #else #define NO_SANITIZE_UNRELATED_CAST +#define NO_SANITIZE_CFI_ICALL #endif #endif /* WTF_Compiler_h */
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 5828c9a..d8f8aa3 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-9-1-115 -Revision: b532d7ce708cb5ca9bf88abaa2eb213ddcf9babb +Version: VER-2-9-1-143 +Revision: 578bcf103a12fb742cdb314565819011d1ac12a7 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/third_party/freetype/include/freetype-custom-config/ftconfig.h b/third_party/freetype/include/freetype-custom-config/ftconfig.h index 3b6bbaf..80751c2 100644 --- a/third_party/freetype/include/freetype-custom-config/ftconfig.h +++ b/third_party/freetype/include/freetype-custom-config/ftconfig.h
@@ -482,7 +482,7 @@ #ifdef FT2_BUILD_LIBRARY -#if defined( _WIN32 ) && ( defined( _DLL ) || defined( DLL_EXPORT ) ) +#if defined( _WIN32 ) && defined( DLL_EXPORT ) #define FT_EXPORT( x ) __declspec( dllexport ) x #elif defined( __GNUC__ ) && __GNUC__ >= 4 #define FT_EXPORT( x ) __attribute__(( visibility( "default" ) )) x @@ -494,7 +494,7 @@ #else -#if defined( FT2_DLLIMPORT ) +#if defined( _WIN32 ) && defined( DLL_IMPORT ) #define FT_EXPORT( x ) __declspec( dllimport ) x #elif defined( __cplusplus ) #define FT_EXPORT( x ) extern "C" x
diff --git a/third_party/libjingle_xmpp/task_runner/task.h b/third_party/libjingle_xmpp/task_runner/task.h index 27c44f5..4111470c 100644 --- a/third_party/libjingle_xmpp/task_runner/task.h +++ b/third_party/libjingle_xmpp/task_runner/task.h
@@ -16,7 +16,7 @@ #include <string> #include "third_party/libjingle_xmpp/task_runner/taskparent.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" ///////////////////////////////////////////////////////////////////// //
diff --git a/third_party/libjingle_xmpp/task_runner/taskrunner.h b/third_party/libjingle_xmpp/task_runner/taskrunner.h index fbdc1e94..0c54899 100644 --- a/third_party/libjingle_xmpp/task_runner/taskrunner.h +++ b/third_party/libjingle_xmpp/task_runner/taskrunner.h
@@ -17,7 +17,7 @@ #include "third_party/libjingle_xmpp/task_runner/taskparent.h" #include "third_party/webrtc/rtc_base/checks.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace rtc { class Task;
diff --git a/third_party/libjingle_xmpp/xmpp/asyncsocket.h b/third_party/libjingle_xmpp/xmpp/asyncsocket.h index eb19c617..6be51d7 100644 --- a/third_party/libjingle_xmpp/xmpp/asyncsocket.h +++ b/third_party/libjingle_xmpp/xmpp/asyncsocket.h
@@ -13,7 +13,7 @@ #include <string> -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace rtc { class SocketAddress;
diff --git a/third_party/libjingle_xmpp/xmpp/jingleinfotask.h b/third_party/libjingle_xmpp/xmpp/jingleinfotask.h index 12dd922..b1637f84 100644 --- a/third_party/libjingle_xmpp/xmpp/jingleinfotask.h +++ b/third_party/libjingle_xmpp/xmpp/jingleinfotask.h
@@ -15,8 +15,8 @@ #include "third_party/libjingle_xmpp/xmpp/xmppengine.h" #include "third_party/libjingle_xmpp/xmpp/xmpptask.h" -#include "third_party/webrtc/rtc_base/sigslot.h" #include "third_party/webrtc/p2p/client/httpportallocator.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace buzz {
diff --git a/third_party/libjingle_xmpp/xmpp/prexmppauth.h b/third_party/libjingle_xmpp/xmpp/prexmppauth.h index 27667cd..60de88c 100644 --- a/third_party/libjingle_xmpp/xmpp/prexmppauth.h +++ b/third_party/libjingle_xmpp/xmpp/prexmppauth.h
@@ -12,7 +12,7 @@ #define WEBRTC_LIBJINGLE_XMPP_PREXMPPAUTH_H_ #include "third_party/libjingle_xmpp/xmpp/saslhandler.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace rtc { class SocketAddress;
diff --git a/third_party/libjingle_xmpp/xmpp/xmppclient.cc b/third_party/libjingle_xmpp/xmpp/xmppclient.cc index 8c68577..918a4dc27 100644 --- a/third_party/libjingle_xmpp/xmpp/xmppclient.cc +++ b/third_party/libjingle_xmpp/xmpp/xmppclient.cc
@@ -14,8 +14,8 @@ #include "third_party/libjingle_xmpp/xmpp/plainsaslhandler.h" #include "third_party/libjingle_xmpp/xmpp/prexmppauth.h" #include "third_party/libjingle_xmpp/xmpp/saslplainmechanism.h" -#include "third_party/webrtc/rtc_base/sigslot.h" #include "third_party/webrtc/rtc_base/stringutils.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" #include "third_party/webrtc_overrides/rtc_base/logging.h" #include "xmpptask.h"
diff --git a/third_party/libjingle_xmpp/xmpp/xmppclient.h b/third_party/libjingle_xmpp/xmpp/xmppclient.h index 6ea7a60f..ae606ce2 100644 --- a/third_party/libjingle_xmpp/xmpp/xmppclient.h +++ b/third_party/libjingle_xmpp/xmpp/xmppclient.h
@@ -19,7 +19,7 @@ #include "third_party/libjingle_xmpp/xmpp/xmppclientsettings.h" #include "third_party/libjingle_xmpp/xmpp/xmppengine.h" #include "third_party/libjingle_xmpp/xmpp/xmpptask.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace buzz {
diff --git a/third_party/libjingle_xmpp/xmpp/xmpptask.h b/third_party/libjingle_xmpp/xmpp/xmpptask.h index 5ad07005..7537880 100644 --- a/third_party/libjingle_xmpp/xmpp/xmpptask.h +++ b/third_party/libjingle_xmpp/xmpp/xmpptask.h
@@ -19,7 +19,7 @@ #include "third_party/libjingle_xmpp/task_runner/taskparent.h" #include "third_party/libjingle_xmpp/xmpp/xmppengine.h" #include "third_party/webrtc/rtc_base/constructormagic.h" -#include "third_party/webrtc/rtc_base/sigslot.h" +#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" namespace buzz {
diff --git a/tools/cygprofile/phased_orderfile.py b/tools/cygprofile/phased_orderfile.py index ac0d27fb..58b5706 100755 --- a/tools/cygprofile/phased_orderfile.py +++ b/tools/cygprofile/phased_orderfile.py
@@ -46,12 +46,6 @@ It maintains common data such as symbol table information to make analysis more convenient. """ - # These figures are taken from running memory and speedometer telemetry - # benchmarks, and are still subject to change as of 2018-01-24. - STARTUP_STABILITY_THRESHOLD = 1.5 - COMMON_STABILITY_THRESHOLD = 1.75 - INTERACTION_STABILITY_THRESHOLD = 2.5 - # The process name of the browser as used in the profile dumps. BROWSER = 'browser' @@ -70,99 +64,6 @@ self._annotated_offsets = None self._process_list = None - def IsStableProfile(self): - """Verify that the profiling has been stable. - - See ComputeStability for details. - - Returns: - True if the profile was stable as described above. - """ - (startup_stability, common_stability, - interaction_stability) = [s[0] for s in self.ComputeStability()] - - stable = True - if startup_stability > self.STARTUP_STABILITY_THRESHOLD: - logging.error('Startup unstable: %.3f', startup_stability) - stable = False - if common_stability > self.COMMON_STABILITY_THRESHOLD: - logging.error('Common unstable: %.3f', common_stability) - stable = False - if interaction_stability > self.INTERACTION_STABILITY_THRESHOLD: - logging.error('Interaction unstable: %.3f', interaction_stability) - stable = False - - return stable - - def ComputeStability(self): - """Compute heuristic phase stability metrics. - - This computes the ratio in size of symbols between the union and - intersection of all orderfile phases. Intuitively if this ratio is not too - large it means that the profiling phases are stable with respect to the code - they cover. - - Returns: - ((float, int), (float, int), (float, int)) A heuristic stability metric - for startup, common and interaction orderfile phases, - respectively. Each metric is a pair of the ratio of symbol sizes as - described above, and the size of the intersection. - """ - (startup_intersection, startup_union, - common_intersection, common_union, - interaction_intersection, interaction_union, - _, _) = self.GetCombinedOffsets() - startup_intersection_size = self._processor.OffsetsPrimarySize( - startup_intersection) - common_intersection_size = self._processor.OffsetsPrimarySize( - common_intersection) - interaction_intersection_size = self._processor.OffsetsPrimarySize( - interaction_intersection) - startup_stability = self._SafeDiv( - self._processor.OffsetsPrimarySize(startup_union), - startup_intersection_size) - common_stability = self._SafeDiv( - self._processor.OffsetsPrimarySize(common_union), - common_intersection_size) - interaction_stability = self._SafeDiv( - self._processor.OffsetsPrimarySize(interaction_union), - interaction_intersection_size) - return ((startup_stability, startup_intersection_size), - (common_stability, common_intersection_size), - (interaction_stability, interaction_intersection_size)) - - def GetCombinedOffsets(self): - """Get offsets for the union and intersection of orderfile phases. - - Returns: - ([int] * 8) For each of startup, common, interaction and all, respectively - the intersection and union offsets, in that order. - """ - phase_offsets = self._GetOrderfilePhaseOffsets() - assert phase_offsets - if len(phase_offsets) == 1: - logging.error('Only one run set, the combined offset files will all be ' - 'identical') - - startup_union = set(phase_offsets[0].startup) - startup_intersection = set(phase_offsets[0].startup) - common_union = set(phase_offsets[0].common) - common_intersection = set(phase_offsets[0].common) - interaction_union = set(phase_offsets[0].interaction) - interaction_intersection = set(phase_offsets[0].interaction) - for offsets in phase_offsets[1:]: - startup_union |= set(offsets.startup) - startup_intersection &= set(offsets.startup) - common_union |= set(offsets.common) - common_intersection &= set(offsets.common) - interaction_union |= set(offsets.interaction) - interaction_intersection &= set(offsets.interaction) - return (startup_intersection, startup_union, - common_intersection, common_union, - interaction_intersection, interaction_union, - (startup_union & common_union & interaction_union), - (startup_union | common_union | interaction_union)) - def GetOffsetsForMemoryFootprint(self): """Get offsets organized to minimize the memory footprint. @@ -367,12 +268,6 @@ return self._phase_offsets - @classmethod - def _SafeDiv(cls, a, b): - if not b: - return None - return float(a) / b - def _CreateArgumentParser(): parser = argparse.ArgumentParser(
diff --git a/tools/cygprofile/phased_orderfile_unittest.py b/tools/cygprofile/phased_orderfile_unittest.py index 6941f7f..47b908b9 100755 --- a/tools/cygprofile/phased_orderfile_unittest.py +++ b/tools/cygprofile/phased_orderfile_unittest.py
@@ -59,32 +59,6 @@ def setUp(self): self._file_counter = 0 - def testProfileStability(self): - symbols = [SimpleTestSymbol(str(i), i, 10) - for i in xrange(20)] - phaser = phased_orderfile.PhasedAnalyzer( - None, TestSymbolOffsetProcessor(symbols)) - opo = lambda s, c, i: phased_orderfile.OrderfilePhaseOffsets( - startup=s, common=c, interaction=i) - phaser._phase_offsets = [opo(range(5), range(6, 10), range(11,15)), - opo(range(4), range(6, 10), range(18, 20))] - self.assertEquals((1.25, 1, None), - tuple(s[0] for s in phaser.ComputeStability())) - - def testIsStable(self): - symbols = [SimpleTestSymbol(str(i), i, 10) - for i in xrange(20)] - phaser = phased_orderfile.PhasedAnalyzer( - None, TestSymbolOffsetProcessor(symbols)) - opo = lambda s, c, i: phased_orderfile.OrderfilePhaseOffsets( - startup=s, common=c, interaction=i) - phaser._phase_offsets = [opo(range(5), range(6, 10), range(11,15)), - opo(range(4), range(6, 10), range(18, 20))] - phaser.STARTUP_STABILITY_THRESHOLD = 1.1 - self.assertFalse(phaser.IsStableProfile()) - phaser.STARTUP_STABILITY_THRESHOLD = 1.5 - self.assertTrue(phaser.IsStableProfile()) - def testGetOrderfilePhaseOffsets(self): mgr = TestProfileManager({ ProfileFile(0, 0): [12, 21, -1, 33],
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 93b9768..fc486ae 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -33529,6 +33529,18 @@ </summary> </histogram> +<histogram name="GraphicsPipeline.ReceivedBeginFrame" units="microseconds"> + <owner>yiyix@chromium.org</owner> + <owner>chrome-gpu-metrics@google.com</owner> + <summary> + The amount of time it takes for the BeginFrame to travel to the Client from + the DisplayCompositor. + + Note that this metrics is only recorded on clients on which a + high-resolution clock is available + </summary> +</histogram> + <histogram name="Hardware.Display.Count.OnChange"> <owner>erikchen@chromium.org</owner> <summary> @@ -104476,6 +104488,9 @@ </histogram> <histogram name="Touchscreen.TapDisambiguation" enum="TapDisambiguation"> + <obsolete> + Deprecated as of 7/2018. + </obsolete> <owner>aelias@chromium.org</owner> <summary> How the user interacted with the tap disambiguation feature on Android. @@ -119091,6 +119106,12 @@ <affected-histogram name="GPU.BlacklistFeatureTestResultsWindows2"/> </histogram_suffixes> +<histogram_suffixes name="GraphicsPipeline" separator="." ordering="prefix"> + <suffix name="Browser" label="for browser process."/> + <suffix name="Renderer" label="for renderer process."/> + <affected-histogram name="GraphicsPipeline.ReceivedBeginFrame"/> +</histogram_suffixes> + <histogram_suffixes name="GWSChromeJointExperiment" separator="_"> <suffix name="Experiment1" label="Only page loads that are a result of a navigation from a web
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index f7b742e..ae3dcdd 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -1689,4 +1689,11 @@ return attributes; } +void AXPlatformNodeAuraLinux::AddAttributeToList( + const char* name, + const char* value, + PlatformAttributeList* attributes) { + NOTREACHED(); +} + } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h index e34398c..0c6f9b50 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.h +++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -90,6 +90,11 @@ void Init(AXPlatformNodeDelegate* delegate) override; int GetIndexInParent() override; + protected: + void AddAttributeToList(const char* name, + const char* value, + PlatformAttributeList* attributes) override; + private: enum AtkInterfaces { ATK_ACTION_INTERFACE,
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc index 895b32b0..e28a4c3 100644 --- a/ui/accessibility/platform/ax_platform_node_base.cc +++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -4,7 +4,12 @@ #include "ui/accessibility/platform/ax_platform_node_base.h" +#include <string> +#include <utility> +#include <vector> + #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_node_data.h" @@ -572,4 +577,334 @@ return value; } +void AXPlatformNodeBase::ComputeAttributes(PlatformAttributeList* attributes) { + // Expose some HTML and ARIA attributes in the IAccessible2 attributes string + // "display", "tag", and "xml-roles" have somewhat unusual names for + // historical reasons. Aside from that virtually every ARIA attribute + // is exposed in a really straightforward way, i.e. "aria-foo" is exposed + // as "foo". + AddAttributeToList(ax::mojom::StringAttribute::kDisplay, "display", + attributes); + AddAttributeToList(ax::mojom::StringAttribute::kHtmlTag, "tag", attributes); + AddAttributeToList(ax::mojom::StringAttribute::kRole, "xml-roles", + attributes); + AddAttributeToList(ax::mojom::StringAttribute::kPlaceholder, "placeholder", + attributes); + + AddAttributeToList(ax::mojom::StringAttribute::kAutoComplete, "autocomplete", + attributes); + if (!HasStringAttribute(ax::mojom::StringAttribute::kAutoComplete) && + IsFocusedInputWithSuggestions()) { + AddAttributeToList("autocomplete", "list", attributes); + } + + AddAttributeToList(ax::mojom::StringAttribute::kRoleDescription, + "roledescription", attributes); + AddAttributeToList(ax::mojom::StringAttribute::kKeyShortcuts, "keyshortcuts", + attributes); + + AddAttributeToList(ax::mojom::IntAttribute::kHierarchicalLevel, "level", + attributes); + AddAttributeToList(ax::mojom::IntAttribute::kSetSize, "setsize", attributes); + AddAttributeToList(ax::mojom::IntAttribute::kPosInSet, "posinset", + attributes); + + if (HasIntAttribute(ax::mojom::IntAttribute::kCheckedState)) + AddAttributeToList("checkable", "true", attributes); + + // Expose live region attributes. + AddAttributeToList(ax::mojom::StringAttribute::kLiveStatus, "live", + attributes); + AddAttributeToList(ax::mojom::StringAttribute::kLiveRelevant, "relevant", + attributes); + AddAttributeToList(ax::mojom::BoolAttribute::kLiveAtomic, "atomic", + attributes); + // Busy is usually associated with live regions but can occur anywhere: + AddAttributeToList(ax::mojom::BoolAttribute::kBusy, "busy", attributes); + + // Expose container live region attributes. + AddAttributeToList(ax::mojom::StringAttribute::kContainerLiveStatus, + "container-live", attributes); + AddAttributeToList(ax::mojom::StringAttribute::kContainerLiveRelevant, + "container-relevant", attributes); + AddAttributeToList(ax::mojom::BoolAttribute::kContainerLiveAtomic, + "container-atomic", attributes); + AddAttributeToList(ax::mojom::BoolAttribute::kContainerLiveBusy, + "container-busy", attributes); + + // Expose the non-standard explicit-name IA2 attribute. + int name_from; + if (GetIntAttribute(ax::mojom::IntAttribute::kNameFrom, &name_from) && + name_from != static_cast<int32_t>(ax::mojom::NameFrom::kContents)) { + AddAttributeToList("explicit-name", "true", attributes); + } + + // Expose the aria-haspopup attribute. + int32_t has_popup; + if (GetIntAttribute(ax::mojom::IntAttribute::kHasPopup, &has_popup)) { + switch (static_cast<ax::mojom::HasPopup>(has_popup)) { + case ax::mojom::HasPopup::kFalse: + break; + case ax::mojom::HasPopup::kTrue: + AddAttributeToList("haspopup", "true", attributes); + break; + case ax::mojom::HasPopup::kMenu: + AddAttributeToList("haspopup", "menu", attributes); + break; + case ax::mojom::HasPopup::kListbox: + AddAttributeToList("haspopup", "listbox", attributes); + break; + case ax::mojom::HasPopup::kTree: + AddAttributeToList("haspopup", "tree", attributes); + break; + case ax::mojom::HasPopup::kGrid: + AddAttributeToList("haspopup", "grid", attributes); + break; + break; + case ax::mojom::HasPopup::kDialog: + AddAttributeToList("haspopup", "dialog", attributes); + break; + } + } else if (IsFocusedInputWithSuggestions()) { + // Note: suggestions are special-cased here because there is no way + // for the browser to know when a suggestion popup is available. + AddAttributeToList("haspopup", "menu", attributes); + } + + // Expose the aria-current attribute. + int32_t aria_current_state; + if (GetIntAttribute(ax::mojom::IntAttribute::kAriaCurrentState, + &aria_current_state)) { + switch (static_cast<ax::mojom::AriaCurrentState>(aria_current_state)) { + case ax::mojom::AriaCurrentState::kNone: + break; + case ax::mojom::AriaCurrentState::kFalse: + AddAttributeToList("current", "false", attributes); + break; + case ax::mojom::AriaCurrentState::kTrue: + AddAttributeToList("current", "true", attributes); + break; + case ax::mojom::AriaCurrentState::kPage: + AddAttributeToList("current", "page", attributes); + break; + case ax::mojom::AriaCurrentState::kStep: + AddAttributeToList("current", "step", attributes); + break; + case ax::mojom::AriaCurrentState::kLocation: + AddAttributeToList("current", "location", attributes); + break; + case ax::mojom::AriaCurrentState::kUnclippedLocation: + AddAttributeToList("current", "unclippedLocation", attributes); + break; + case ax::mojom::AriaCurrentState::kDate: + AddAttributeToList("current", "date", attributes); + break; + case ax::mojom::AriaCurrentState::kTime: + AddAttributeToList("current", "time", attributes); + break; + } + } + + // Expose table cell index. + if (IsCellOrTableHeaderRole(GetData().role)) { + AXPlatformNodeBase* table = GetTable(); + if (table) { + int32_t index = table->delegate_->CellIdToIndex(GetData().id); + if (index >= 0) { + std::string str_index(base::IntToString(index)); + AddAttributeToList("table-cell-index", str_index, attributes); + } + } + } + if (GetData().role == ax::mojom::Role::kLayoutTable) + AddAttributeToList("layout-guess", "true", attributes); + + // Expose aria-colcount and aria-rowcount in a table, grid or treegrid. + if (IsTableLikeRole(GetData().role)) { + AddAttributeToList(ax::mojom::IntAttribute::kAriaColumnCount, "colcount", + attributes); + AddAttributeToList(ax::mojom::IntAttribute::kAriaRowCount, "rowcount", + attributes); + } + + // Expose aria-colindex and aria-rowindex in a cell or row. + if (IsCellOrTableHeaderRole(GetData().role) || + GetData().role == ax::mojom::Role::kRow) { + if (GetData().role != ax::mojom::Role::kRow) + AddAttributeToList(ax::mojom::IntAttribute::kAriaCellColumnIndex, + "colindex", attributes); + AddAttributeToList(ax::mojom::IntAttribute::kAriaCellRowIndex, "rowindex", + attributes); + + // Experimental: expose aria-rowtext / aria-coltext. Not standardized + // yet, but obscure enough that it's safe to expose. + // http://crbug.com/791634 + for (size_t i = 0; i < GetData().html_attributes.size(); ++i) { + const std::string& attr = GetData().html_attributes[i].first; + const std::string& value = GetData().html_attributes[i].second; + if (attr == "aria-coltext") { + AddAttributeToList("coltext", value, attributes); + } + if (attr == "aria-rowtext") { + AddAttributeToList("rowtext", value, attributes); + } + } + } + + // Expose row or column header sort direction. + int32_t sort_direction; + if ((GetData().role == ax::mojom::Role::kColumnHeader || + GetData().role == ax::mojom::Role::kRowHeader) && + GetIntAttribute(ax::mojom::IntAttribute::kSortDirection, + &sort_direction)) { + switch (static_cast<ax::mojom::SortDirection>(sort_direction)) { + case ax::mojom::SortDirection::kNone: + break; + case ax::mojom::SortDirection::kUnsorted: + AddAttributeToList("sort", "none", attributes); + break; + case ax::mojom::SortDirection::kAscending: + AddAttributeToList("sort", "ascending", attributes); + break; + case ax::mojom::SortDirection::kDescending: + AddAttributeToList("sort", "descending", attributes); + break; + case ax::mojom::SortDirection::kOther: + AddAttributeToList("sort", "other", attributes); + break; + } + } + + if (IsCellOrTableHeaderRole(GetData().role)) { + // Expose colspan attribute. + std::string colspan; + if (GetData().GetHtmlAttribute("aria-colspan", &colspan)) { + AddAttributeToList("colspan", colspan, attributes); + } + // Expose rowspan attribute. + std::string rowspan; + if (GetData().GetHtmlAttribute("aria-rowspan", &rowspan)) { + AddAttributeToList("rowspan", rowspan, attributes); + } + } + + // Expose slider value. + if (IsRangeValueSupported()) { + std::string value = base::UTF16ToUTF8(GetRangeValueText()); + if (!value.empty()) + AddAttributeToList("valuetext", value, attributes); + } + + // Expose dropeffect attribute. + std::string drop_effect; + if (GetData().GetHtmlAttribute("aria-dropeffect", &drop_effect)) { + AddAttributeToList("dropeffect", drop_effect, attributes); + } + + // Expose grabbed attribute. + std::string grabbed; + if (GetData().GetHtmlAttribute("aria-grabbed", &grabbed)) { + AddAttributeToList("grabbed", grabbed, attributes); + } + + // Expose class attribute. + std::string class_attr; + if (GetData().GetHtmlAttribute("class", &class_attr) || + GetData().GetStringAttribute(ax::mojom::StringAttribute::kClassName, + &class_attr)) { + AddAttributeToList("class", class_attr, attributes); + } + + // Expose datetime attribute. + std::string datetime; + if (GetData().role == ax::mojom::Role::kTime && + GetData().GetHtmlAttribute("datetime", &datetime)) { + AddAttributeToList("datetime", datetime, attributes); + } + + // Expose id attribute. + std::string id; + if (GetData().GetHtmlAttribute("id", &id)) { + AddAttributeToList("id", id, attributes); + } + + // Expose src attribute. + std::string src; + if (GetData().role == ax::mojom::Role::kImage && + GetData().GetHtmlAttribute("src", &src)) { + AddAttributeToList("src", src, attributes); + } + + // Text fields need to report the attribute "text-model:a1" to instruct + // screen readers to use IAccessible2 APIs to handle text editing in this + // object (as opposed to treating it like a native Windows text box). + // The text-model:a1 attribute is documented here: + // http://www.linuxfoundation.org/collaborate/workgroups/accessibility/ia2/ia2_implementation_guide + if (IsPlainTextField() || IsRichTextField()) + AddAttributeToList("text-model", "a1", attributes); + + // Expose input-text type attribute. + std::string type; + std::string html_tag = + GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag); + if (IsPlainTextField() && base::LowerCaseEqualsASCII(html_tag, "input") && + GetData().GetHtmlAttribute("type", &type)) { + AddAttributeToList("text-input-type", type, attributes); + } +} + +void AXPlatformNodeBase::AddAttributeToList( + const ax::mojom::StringAttribute attribute, + const char* name, + PlatformAttributeList* attributes) { + DCHECK(attributes); + std::string value; + if (GetStringAttribute(attribute, &value)) { + AddAttributeToList(name, value, attributes); + } +} + +void AXPlatformNodeBase::AddAttributeToList( + const ax::mojom::BoolAttribute attribute, + const char* name, + PlatformAttributeList* attributes) { + DCHECK(attributes); + bool value; + if (GetBoolAttribute(attribute, &value)) { + AddAttributeToList(name, value ? "true" : "false", attributes); + } +} + +void AXPlatformNodeBase::AddAttributeToList( + const ax::mojom::IntAttribute attribute, + const char* name, + PlatformAttributeList* attributes) { + DCHECK(attributes); + int value; + if (GetIntAttribute(attribute, &value)) { + std::string str_value = base::IntToString(value); + AddAttributeToList(name, str_value, attributes); + } +} + +void AXPlatformNodeBase::AddAttributeToList(const char* name, + const std::string& value, + PlatformAttributeList* attributes) { + AddAttributeToList(name, value.c_str(), attributes); +} + +// static +void AXPlatformNodeBase::SanitizeStringAttribute(const std::string& input, + std::string* output) { + DCHECK(output); + // According to the IA2 spec and AT-SPI2, these characters need to be escaped + // with a backslash: backslash, colon, comma, equals and semicolon. Note + // that backslash must be replaced first. + base::ReplaceChars(input, "\\", "\\\\", output); + base::ReplaceChars(*output, ":", "\\:", output); + base::ReplaceChars(*output, ",", "\\,", output); + base::ReplaceChars(*output, "=", "\\=", output); + base::ReplaceChars(*output, ";", "\\;", output); +} + } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h index efb4040..c6030d6 100644 --- a/ui/accessibility/platform/ax_platform_node_base.h +++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -5,6 +5,8 @@ #ifndef UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_BASE_H_ #define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_BASE_H_ +#include <string> + #include "base/macros.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/platform/ax_platform_node.h" @@ -191,6 +193,46 @@ // Sets the text selection in this object if possible. bool SetTextSelection(int start_offset, int end_offset); + // Compute the attributes exposed via platform accessibility objects and put + // them into an attribute list, |attributes|. Currently only used by + // IAccessible2 on Windows, but will soon be shared with other ports. + using PlatformAttributeList = std::vector<base::string16>; + void ComputeAttributes(PlatformAttributeList* attributes); + + // If the string attribute |attribute| is present, add its value as an + // IAccessible2 attribute with the name |name|. + void AddAttributeToList(const ax::mojom::StringAttribute attribute, + const char* name, + PlatformAttributeList* attributes); + + // If the bool attribute |attribute| is present, add its value as an + // IAccessible2 attribute with the name |name|. + void AddAttributeToList(const ax::mojom::BoolAttribute attribute, + const char* name, + PlatformAttributeList* attributes); + + // If the int attribute |attribute| is present, add its value as an + // IAccessible2 attribute with the name |name|. + void AddAttributeToList(const ax::mojom::IntAttribute attribute, + const char* name, + PlatformAttributeList* attributes); + + // A helper to add the given string value to |attributes|. + virtual void AddAttributeToList(const char* name, + const std::string& value, + PlatformAttributeList* attributes); + + // A pure virtual method that subclasses use to actually add the attribute to + // |attributes|. + virtual void AddAttributeToList(const char* name, + const char* value, + PlatformAttributeList* attributes) = 0; + + // Escapes characters in string attributes as required by the IA2 Spec + // and AT-SPI2. It's okay for input to be the same as output. + static void SanitizeStringAttribute(const std::string& input, + std::string* output); + private: DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeBase); };
diff --git a/ui/accessibility/platform/ax_platform_node_mac.h b/ui/accessibility/platform/ax_platform_node_mac.h index 18002fe..f3512b1 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.h +++ b/ui/accessibility/platform/ax_platform_node_mac.h
@@ -29,6 +29,11 @@ void Destroy() override; int GetIndexInParent() override; + protected: + void AddAttributeToList(const char* name, + const char* value, + PlatformAttributeList* attributes) override; + private: ~AXPlatformNodeMac() override;
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index cbc4ea6..5e28513 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -1006,4 +1006,10 @@ } } +void AXPlatformNodeMac::AddAttributeToList(const char* name, + const char* value, + PlatformAttributeList* attributes) { + NOTREACHED(); +} + } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 6879281..092f0e8 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -182,6 +182,15 @@ } // namespace +void AXPlatformNodeWin::AddAttributeToList(const char* name, + const char* value, + PlatformAttributeList* attributes) { + std::string str_value = value; + SanitizeStringAttribute(str_value, &str_value); + attributes->push_back(base::UTF8ToUTF16(name) + L":" + + base::UTF8ToUTF16(str_value)); +} + // There is no easy way to decouple |kScreenReader| and |kHTML| accessibility // modes when Windows screen readers are used. For example, certain roles use // the HTML tag name. Input fields require their type attribute to be exposed. @@ -278,54 +287,6 @@ } // Static -void AXPlatformNodeWin::SanitizeStringAttributeForIA2( - const base::string16& input, - base::string16* output) { - DCHECK(output); - // According to the IA2 Spec, these characters need to be escaped with a - // backslash: backslash, colon, comma, equals and semicolon. - // Note that backslash must be replaced first. - base::ReplaceChars(input, L"\\", L"\\\\", output); - base::ReplaceChars(*output, L":", L"\\:", output); - base::ReplaceChars(*output, L",", L"\\,", output); - base::ReplaceChars(*output, L"=", L"\\=", output); - base::ReplaceChars(*output, L";", L"\\;", output); -} - -void AXPlatformNodeWin::StringAttributeToIA2( - std::vector<base::string16>& attributes, - ax::mojom::StringAttribute attribute, - const char* ia2_attr) { - base::string16 value; - if (GetString16Attribute(attribute, &value)) { - SanitizeStringAttributeForIA2(value, &value); - attributes.push_back(base::ASCIIToUTF16(ia2_attr) + L":" + value); - } -} - -void AXPlatformNodeWin::BoolAttributeToIA2( - std::vector<base::string16>& attributes, - ax::mojom::BoolAttribute attribute, - const char* ia2_attr) { - bool value; - if (GetBoolAttribute(attribute, &value)) { - attributes.push_back((base::ASCIIToUTF16(ia2_attr) + L":") + - (value ? L"true" : L"false")); - } -} - -void AXPlatformNodeWin::IntAttributeToIA2( - std::vector<base::string16>& attributes, - ax::mojom::IntAttribute attribute, - const char* ia2_attr) { - int value; - if (GetIntAttribute(attribute, &value)) { - attributes.push_back(base::ASCIIToUTF16(ia2_attr) + L":" + - base::IntToString16(value)); - } -} - -// Static void AXPlatformNodeWin::SanitizeStringAttributeForUIAAriaProperty( const base::string16& input, base::string16* output) { @@ -4279,289 +4240,9 @@ } std::vector<base::string16> AXPlatformNodeWin::ComputeIA2Attributes() { - std::vector<base::string16> result; - // Expose some HTLM and ARIA attributes in the IAccessible2 attributes string. - // "display", "tag", and "xml-roles" have somewhat unusual names for - // historical reasons. Aside from that virtually every ARIA attribute - // is exposed in a really straightforward way, i.e. "aria-foo" is exposed - // as "foo". - StringAttributeToIA2(result, ax::mojom::StringAttribute::kDisplay, "display"); - StringAttributeToIA2(result, ax::mojom::StringAttribute::kHtmlTag, "tag"); - StringAttributeToIA2(result, ax::mojom::StringAttribute::kRole, "xml-roles"); - StringAttributeToIA2(result, ax::mojom::StringAttribute::kPlaceholder, - "placeholder"); - - StringAttributeToIA2(result, ax::mojom::StringAttribute::kAutoComplete, - "autocomplete"); - if (!HasStringAttribute(ax::mojom::StringAttribute::kAutoComplete) && - IsFocusedInputWithSuggestions()) { - result.push_back(L"autocomplete:list"); - } - - StringAttributeToIA2(result, ax::mojom::StringAttribute::kRoleDescription, - "roledescription"); - StringAttributeToIA2(result, ax::mojom::StringAttribute::kKeyShortcuts, - "keyshortcuts"); - - IntAttributeToIA2(result, ax::mojom::IntAttribute::kHierarchicalLevel, - "level"); - IntAttributeToIA2(result, ax::mojom::IntAttribute::kSetSize, "setsize"); - IntAttributeToIA2(result, ax::mojom::IntAttribute::kPosInSet, "posinset"); - - if (HasIntAttribute(ax::mojom::IntAttribute::kCheckedState)) - result.emplace_back(L"checkable:true"); - - // Expose live region attributes. - StringAttributeToIA2(result, ax::mojom::StringAttribute::kLiveStatus, "live"); - StringAttributeToIA2(result, ax::mojom::StringAttribute::kLiveRelevant, - "relevant"); - BoolAttributeToIA2(result, ax::mojom::BoolAttribute::kLiveAtomic, "atomic"); - // Busy is usually associated with live regions but can occur anywhere: - BoolAttributeToIA2(result, ax::mojom::BoolAttribute::kBusy, "busy"); - - // Expose container live region attributes. - StringAttributeToIA2(result, ax::mojom::StringAttribute::kContainerLiveStatus, - "container-live"); - StringAttributeToIA2(result, - ax::mojom::StringAttribute::kContainerLiveRelevant, - "container-relevant"); - BoolAttributeToIA2(result, ax::mojom::BoolAttribute::kContainerLiveAtomic, - "container-atomic"); - BoolAttributeToIA2(result, ax::mojom::BoolAttribute::kContainerLiveBusy, - "container-busy"); - - // Expose the non-standard explicit-name IA2 attribute. - int name_from; - if (GetIntAttribute(ax::mojom::IntAttribute::kNameFrom, &name_from) && - name_from != static_cast<int32_t>(ax::mojom::NameFrom::kContents)) { - result.push_back(L"explicit-name:true"); - } - - // Expose the aria-haspopup attribute. - int32_t has_popup; - if (GetIntAttribute(ax::mojom::IntAttribute::kHasPopup, &has_popup)) { - switch (static_cast<ax::mojom::HasPopup>(has_popup)) { - case ax::mojom::HasPopup::kFalse: - break; - case ax::mojom::HasPopup::kTrue: - result.push_back(L"haspopup:true"); - break; - case ax::mojom::HasPopup::kMenu: - result.push_back(L"haspopup:menu"); - break; - case ax::mojom::HasPopup::kListbox: - result.push_back(L"haspopup:listbox"); - break; - case ax::mojom::HasPopup::kTree: - result.push_back(L"haspopup:tree"); - break; - case ax::mojom::HasPopup::kGrid: - result.push_back(L"haspopup:grid"); - break; - case ax::mojom::HasPopup::kDialog: - result.push_back(L"haspopup:dialog"); - break; - } - } else if (IsFocusedInputWithSuggestions()) { - // Note: suggestions are special-cased here because there is no way - // for the browser to know when a suggestion popup is available. - result.push_back(L"haspopup:menu"); - } - - // Expose the aria-current attribute. - int32_t aria_current_state; - if (GetIntAttribute(ax::mojom::IntAttribute::kAriaCurrentState, - &aria_current_state)) { - switch (static_cast<ax::mojom::AriaCurrentState>(aria_current_state)) { - case ax::mojom::AriaCurrentState::kNone: - break; - case ax::mojom::AriaCurrentState::kFalse: - result.push_back(L"current:false"); - break; - case ax::mojom::AriaCurrentState::kTrue: - result.push_back(L"current:true"); - break; - case ax::mojom::AriaCurrentState::kPage: - result.push_back(L"current:page"); - break; - case ax::mojom::AriaCurrentState::kStep: - result.push_back(L"current:step"); - break; - case ax::mojom::AriaCurrentState::kLocation: - result.push_back(L"current:location"); - break; - case ax::mojom::AriaCurrentState::kUnclippedLocation: - result.push_back(L"current:unclippedLocation"); - break; - case ax::mojom::AriaCurrentState::kDate: - result.push_back(L"current:date"); - break; - case ax::mojom::AriaCurrentState::kTime: - result.push_back(L"current:time"); - break; - } - } - - // Expose table cell index. - if (IsCellOrTableHeaderRole(GetData().role)) { - AXPlatformNodeBase* table = GetTable(); - if (table) { - int32_t index = table->delegate_->CellIdToIndex(GetData().id); - if (index >= 0) { - result.push_back(base::string16(L"table-cell-index:") + - base::IntToString16(index)); - } - } - } - if (GetData().role == ax::mojom::Role::kLayoutTable) - result.push_back(base::string16(L"layout-guess:true")); - - // Expose aria-colcount and aria-rowcount in a table, grid or treegrid. - if (IsTableLikeRole(GetData().role)) { - IntAttributeToIA2(result, ax::mojom::IntAttribute::kAriaColumnCount, - "colcount"); - IntAttributeToIA2(result, ax::mojom::IntAttribute::kAriaRowCount, - "rowcount"); - } - - // Expose aria-colindex and aria-rowindex in a cell or row. - if (IsCellOrTableHeaderRole(GetData().role) || - GetData().role == ax::mojom::Role::kRow) { - if (GetData().role != ax::mojom::Role::kRow) - IntAttributeToIA2(result, ax::mojom::IntAttribute::kAriaCellColumnIndex, - "colindex"); - IntAttributeToIA2(result, ax::mojom::IntAttribute::kAriaCellRowIndex, - "rowindex"); - - // Experimental: expose aria-rowtext / aria-coltext. Not standardized - // yet, but obscure enough that it's safe to expose. - // http://crbug.com/791634 - for (size_t i = 0; i < GetData().html_attributes.size(); ++i) { - const std::string& attr = GetData().html_attributes[i].first; - const std::string& value = GetData().html_attributes[i].second; - if (attr == "aria-coltext") { - result.push_back(base::string16(L"coltext:") + - base::UTF8ToUTF16(value)); - } - if (attr == "aria-rowtext") { - result.push_back(base::string16(L"rowtext:") + - base::UTF8ToUTF16(value)); - } - } - } - - // Expose row or column header sort direction. - int32_t sort_direction; - if ((MSAARole() == ROLE_SYSTEM_COLUMNHEADER || - MSAARole() == ROLE_SYSTEM_ROWHEADER) && - GetIntAttribute(ax::mojom::IntAttribute::kSortDirection, - &sort_direction)) { - switch (static_cast<ax::mojom::SortDirection>(sort_direction)) { - case ax::mojom::SortDirection::kNone: - break; - case ax::mojom::SortDirection::kUnsorted: - result.push_back(L"sort:none"); - break; - case ax::mojom::SortDirection::kAscending: - result.push_back(L"sort:ascending"); - break; - case ax::mojom::SortDirection::kDescending: - result.push_back(L"sort:descending"); - break; - case ax::mojom::SortDirection::kOther: - result.push_back(L"sort:other"); - break; - } - } - - if (IsCellOrTableHeaderRole(GetData().role)) { - // Expose colspan attribute. - base::string16 colspan; - if (GetData().GetHtmlAttribute("aria-colspan", &colspan)) { - SanitizeStringAttributeForIA2(colspan, &colspan); - result.push_back(L"colspan:" + colspan); - } - // Expose rowspan attribute. - base::string16 rowspan; - if (GetData().GetHtmlAttribute("aria-rowspan", &rowspan)) { - SanitizeStringAttributeForIA2(rowspan, &rowspan); - result.push_back(L"rowspan:" + rowspan); - } - } - - // Expose slider value. - if (IsRangeValueSupported()) { - base::string16 value = GetRangeValueText(); - SanitizeStringAttributeForIA2(value, &value); - if (!value.empty()) - result.push_back(L"valuetext:" + value); - } - - // Expose dropeffect attribute. - base::string16 drop_effect; - if (GetData().GetHtmlAttribute("aria-dropeffect", &drop_effect)) { - SanitizeStringAttributeForIA2(drop_effect, &drop_effect); - result.push_back(L"dropeffect:" + drop_effect); - } - - // Expose grabbed attribute. - base::string16 grabbed; - if (GetData().GetHtmlAttribute("aria-grabbed", &grabbed)) { - SanitizeStringAttributeForIA2(grabbed, &grabbed); - result.push_back(L"grabbed:" + grabbed); - } - - // Expose class attribute. - base::string16 class_attr; - if (GetData().GetHtmlAttribute("class", &class_attr) || - GetData().GetString16Attribute(ax::mojom::StringAttribute::kClassName, - &class_attr)) { - SanitizeStringAttributeForIA2(class_attr, &class_attr); - result.push_back(L"class:" + class_attr); - } - - // Expose datetime attribute. - base::string16 datetime; - if (GetData().role == ax::mojom::Role::kTime && - GetData().GetHtmlAttribute("datetime", &datetime)) { - SanitizeStringAttributeForIA2(datetime, &datetime); - result.push_back(L"datetime:" + datetime); - } - - // Expose id attribute. - base::string16 id; - if (GetData().GetHtmlAttribute("id", &id)) { - SanitizeStringAttributeForIA2(id, &id); - result.push_back(L"id:" + id); - } - - // Expose src attribute. - base::string16 src; - if (GetData().role == ax::mojom::Role::kImage && - GetData().GetHtmlAttribute("src", &src)) { - SanitizeStringAttributeForIA2(src, &src); - result.push_back(L"src:" + src); - } - - // Text fields need to report the attribute "text-model:a1" to instruct - // screen readers to use IAccessible2 APIs to handle text editing in this - // object (as opposed to treating it like a native Windows text box). - // The text-model:a1 attribute is documented here: - // http://www.linuxfoundation.org/collaborate/workgroups/accessibility/ia2/ia2_implementation_guide - if (IsPlainTextField() || IsRichTextField()) - result.push_back(L"text-model:a1;"); - - // Expose input-text type attribute. - base::string16 type; - base::string16 html_tag = - GetString16Attribute(ax::mojom::StringAttribute::kHtmlTag); - if (IsPlainTextField() && html_tag == L"input" && - GetData().GetHtmlAttribute("type", &type)) { - SanitizeStringAttributeForIA2(type, &type); - result.push_back(L"text-input-type:" + type); - } - - return result; + std::vector<base::string16> attribute_list; + ComputeAttributes(&attribute_list); + return attribute_list; } base::string16 AXPlatformNodeWin::UIAAriaRole() {
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h index 33356be..e2161634 100644 --- a/ui/accessibility/platform/ax_platform_node_win.h +++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -925,6 +925,11 @@ // Convert from a IA2TextBoundaryType to a TextBoundaryType. TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type); + // A helper to add the given string value to |attributes|. + void AddAttributeToList(const char* name, + const char* value, + PlatformAttributeList* attributes) override; + private: int MSAAEvent(ax::mojom::Event event); bool IsWebAreaForPresentationalIframe(); @@ -934,32 +939,9 @@ HRESULT GetStringAttributeAsBstr(ax::mojom::StringAttribute attribute, BSTR* value_bstr) const; - // Escapes characters in string attributes as required by the IA2 Spec. - // It's okay for input to be the same as output. - static void SanitizeStringAttributeForIA2(const base::string16& input, - base::string16* output); - // Sets the selection given a start and end offset in IA2 Hypertext. void SetIA2HypertextSelection(LONG start_offset, LONG end_offset); - // If the string attribute |attribute| is present, add its value as an - // IAccessible2 attribute with the name |ia2_attr|. - void StringAttributeToIA2(std::vector<base::string16>& attributes, - ax::mojom::StringAttribute attribute, - const char* ia2_attr); - - // If the bool attribute |attribute| is present, add its value as an - // IAccessible2 attribute with the name |ia2_attr|. - void BoolAttributeToIA2(std::vector<base::string16>& attributes, - ax::mojom::BoolAttribute attribute, - const char* ia2_attr); - - // If the int attribute |attribute| is present, add its value as an - // IAccessible2 attribute with the name |ia2_attr|. - void IntAttributeToIA2(std::vector<base::string16>& attributes, - ax::mojom::IntAttribute attribute, - const char* ia2_attr); - // Escapes characters in string attributes as required by the UIA Aria // Property Spec. It's okay for input to be the same as output. static void SanitizeStringAttributeForUIAAriaProperty(
diff --git a/ui/base/ui_base_switches_util.h b/ui/base/ui_base_switches_util.h index 827ff0a1..89bdd97a 100644 --- a/ui/base/ui_base_switches_util.h +++ b/ui/base/ui_base_switches_util.h
@@ -9,7 +9,6 @@ namespace switches { -UI_BASE_EXPORT bool IsLinkDisambiguationPopupEnabled(); UI_BASE_EXPORT bool IsTouchDragDropEnabled(); // Returns whether the touchable app context menu switch has been set. Prefer
diff --git a/ui/file_manager/file_manager/common/js/mock_entry.js b/ui/file_manager/file_manager/common/js/mock_entry.js index 115c399f..1991c8e 100644 --- a/ui/file_manager/file_manager/common/js/mock_entry.js +++ b/ui/file_manager/file_manager/common/js/mock_entry.js
@@ -91,20 +91,33 @@ return children; }; +/** @interface */ +function MockEntryInterface() {} + +/** + * Clones the entry with the new fullpath. + * + * @param {string} fullpath New fullpath. + * @param {FileSystem=} opt_filesystem New file system + * @return {Entry} Cloned entry. + */ +MockEntryInterface.prototype.clone = function(fullpath, opt_filesystem) {}; + /** * Base class of mock entries. * * @param {FileSystem} filesystem File system where the entry is localed. * @param {string} fullPath Full path of the entry. - * @param {!Metadata} metadata Metadata. + * @param {Metadata=} opt_metadata Metadata. * @constructor * @extends {Entry} + * @implements {MockEntryInterface} */ -function MockEntry(filesystem, fullPath, metadata) { +function MockEntry(filesystem, fullPath, opt_metadata) { filesystem.entries[fullPath] = this; this.filesystem = filesystem; this.fullPath = fullPath; - this.metadata = metadata; + this.metadata = opt_metadata || /** @type {!Metadata} */ ({}); this.removed_ = false; } @@ -221,13 +234,7 @@ throw new Error('expected removed for file ' + this.name); }; -/** - * Clones the entry with the new fullpath. - * - * @param {string} fullpath New fullpath. - * @param {FileSystem=} opt_filesystem New file system - * @return {Entry} Cloned entry. - */ +/** @override */ MockEntry.prototype.clone = function(fullpath, opt_filesystem) { throw new Error('Not implemented.'); }; @@ -237,14 +244,19 @@ * * @param {FileSystem} filesystem File system where the entry is localed. * @param {string} fullPath Full path for the entry. - * @param {!Metadata} metadata Metadata. + * @param {Metadata=} opt_metadata Metadata. * @param {Blob=} opt_content Optional content. - * @extends {MockEntry} + * @extends {FileEntry} + * @implements {MockEntryInterface} * @constructor */ -function MockFileEntry(filesystem, fullPath, metadata, opt_content) { - MockEntry.call(this, filesystem, fullPath, metadata); +function MockFileEntry(filesystem, fullPath, opt_metadata, opt_content) { + filesystem.entries[fullPath] = this; + this.filesystem = filesystem; + this.fullPath = fullPath; + this.metadata = opt_metadata || /** @type {!Metadata} */ ({}); this.content = opt_content || new Blob([]); + this.removed_ = false; this.isFile = true; this.isDirectory = false; } @@ -257,15 +269,13 @@ * Returns a File that this represents. * * @param {function(!File)} onSuccess Function to take the file. - * @param {function(!Error)} onError + * @param {function(!FileError)=} onError */ MockFileEntry.prototype.file = function(onSuccess, onError) { onSuccess(new File([this.content], this.toURL())); }; -/** - * @override - */ +/** @override */ MockFileEntry.prototype.clone = function(path, opt_filesystem) { return new MockFileEntry( opt_filesystem || this.filesystem, path, this.metadata, this.content); @@ -293,9 +303,7 @@ __proto__: MockEntry.prototype }; -/** - * @override - */ +/** @override */ MockDirectoryEntry.prototype.clone = function(path, opt_filesystem) { return new MockDirectoryEntry(opt_filesystem || this.filesystem, path); };
diff --git a/ui/file_manager/file_manager/foreground/css/file_types.css b/ui/file_manager/file_manager/foreground/css/file_types.css index cdbc193e..ba1bb90 100644 --- a/ui/file_manager/file_manager/foreground/css/file_types.css +++ b/ui/file_manager/file_manager/foreground/css/file_types.css
@@ -44,8 +44,8 @@ .team-drive-root[file-type-icon='folder'] { background-image: -webkit-image-set( - url(../images/filetype/filetype_team_drive.png) 1x, - url(../images/filetype/2x/filetype_team_drive.png) 2x); + url(../images/volumes/hard_drive.png) 1x, + url(../images/volumes/2x/hard_drive.png) 2x); } tree .tree-item[selected] > .tree-row > [file-type-icon='folder'] { @@ -271,8 +271,7 @@ url(../images/volumes/2x/service_drive_active.png) 2x); } -[volume-type-icon='team_drives_grand_root'], -[volume-type-icon='team_drive'] { +[volume-type-icon='team_drives_grand_root'] { background-image: -webkit-image-set( url(../images/volumes/team_drive.png) 1x, url(../images/volumes/2x/team_drive.png) 2x); @@ -284,10 +283,16 @@ url(../images/volumes/2x/team_drive_active.png) 2x); } +[volume-type-icon='team_drive'] { + background-image: -webkit-image-set( + url(../images/volumes/hard_drive.png) 1x, + url(../images/volumes/2x/hard_drive.png) 2x); +} + .tree-row[selected] [volume-type-icon='team_drive'] { background-image: -webkit-image-set( - url(../images/volumes/team_drive_active.png) 1x, - url(../images/volumes/2x/team_drive_active.png) 2x); + url(../images/volumes/hard_drive_active.png) 1x, + url(../images/volumes/2x/hard_drive_active.png) 2x); } [volume-type-icon='drive_offline'] {
diff --git a/ui/file_manager/gallery/js/image_editor/BUILD.gn b/ui/file_manager/gallery/js/image_editor/BUILD.gn index 84f58f7c1..47962a3 100644 --- a/ui/file_manager/gallery/js/image_editor/BUILD.gn +++ b/ui/file_manager/gallery/js/image_editor/BUILD.gn
@@ -22,6 +22,7 @@ ":image_transform", ":image_util", ":image_view", + ":image_view_unittest", ":test_util", ":viewport", ] @@ -180,6 +181,14 @@ ] } +js_library("image_view_unittest") { + deps = [ + ":image_view", + "../../../file_manager/common/js:mock_entry", + "//ui/webui/resources/js:webui_resource_test", + ] +} + js_library("test_util") { }
diff --git a/ui/file_manager/gallery/js/image_editor/image_view_unittest.js b/ui/file_manager/gallery/js/image_editor/image_view_unittest.js index 70afa9c..a2f889e 100644 --- a/ui/file_manager/gallery/js/image_editor/image_view_unittest.js +++ b/ui/file_manager/gallery/js/image_editor/image_view_unittest.js
@@ -2,53 +2,77 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/** + * Helper to construct testing GalleryItem objects. + * + * @param {!FileEntry} entry + * @param {EntryLocation} locationInfo + * @param {Object} metadataItem + * @param {ThumbnailMetadataItem=} opt_thumbnailMetadataItem + * @param {boolean=} opt_original Whether the entry is original or edited. + * @constructor + * @extends GalleryItem + */ +function MockGalleryItem( + entry, locationInfo, metadataItem, opt_thumbnailMetadataItem, + opt_original) { + let entryLocation = locationInfo || /** @type {!EntryLocation} */ ({}); + GalleryItem.call( + this, entry, entryLocation, /** @type {MetadataItem} */ (metadataItem), + opt_thumbnailMetadataItem || null, opt_original || false); +} + +MockGalleryItem.prototype = { + __proto__: GalleryItem.prototype +}; + function testImageView() { var mockFileSystem = new MockFileSystem('volumeId'); - var mockEntry = new MockEntry(mockFileSystem, '/test.jpg'); + var mockEntry = new MockFileEntry(mockFileSystem, '/test.jpg'); // Item has full size cache. - var itemWithFullCache = new GalleryItem(mockEntry, null, {}, null, false); - itemWithFullCache.contentImage = document.createElement('canvas'); + var itemWithFullCache = new MockGalleryItem(mockEntry, null, {}); + itemWithFullCache.contentImage = + assertInstanceof(document.createElement('canvas'), HTMLCanvasElement); assertEquals( ImageView.LoadTarget.CACHED_MAIN_IMAGE, ImageView.getLoadTarget(itemWithFullCache, new ImageView.Effect.None())); // Item with content thumbnail. - var itemWithContentThumbnail = new GalleryItem( - mockEntry, null, {thumbnail: {url: 'url'}}, null, false); + var itemWithContentThumbnail = + new MockGalleryItem(mockEntry, null, {thumbnail: {url: 'url'}}); assertEquals( ImageView.LoadTarget.THUMBNAIL, ImageView.getLoadTarget( itemWithContentThumbnail, new ImageView.Effect.None())); // Item with external thumbnail. - var itemWithExternalThumbnail = new GalleryItem( - mockEntry, null, {external: {thumbnailUrl: 'url'}}, null, false); + var itemWithExternalThumbnail = + new MockGalleryItem(mockEntry, null, {external: {thumbnailUrl: 'url'}}); assertEquals( ImageView.LoadTarget.THUMBNAIL, ImageView.getLoadTarget( itemWithExternalThumbnail, new ImageView.Effect.None())); - // Item with external thumbnail but present localy. - var itemWithExternalThumbnailPresent = new GalleryItem( - mockEntry, null, {external: {thumbnailUrl: 'url', present: true}}, null, - false); + // Item with external thumbnail but present locally. + var itemWithExternalThumbnailPresent = new MockGalleryItem( + mockEntry, null, {external: {thumbnailUrl: 'url', present: true}}); assertEquals( ImageView.LoadTarget.MAIN_IMAGE, ImageView.getLoadTarget( itemWithExternalThumbnailPresent, new ImageView.Effect.None())); // Item with external thumbnail shown by slide effect. - var itemWithExternalThumbnailSlide = new GalleryItem( - mockEntry, null, {external: {thumbnailUrl: 'url'}}, null, false); + var itemWithExternalThumbnailSlide = + new MockGalleryItem(mockEntry, null, {external: {thumbnailUrl: 'url'}}); assertEquals( ImageView.LoadTarget.THUMBNAIL, ImageView.getLoadTarget( itemWithExternalThumbnailSlide, new ImageView.Effect.Slide(1))); // Item with external thumbnail shown by zoom to screen effect. - var itemWithExternalThumbnailZoomToScreen = new GalleryItem( - mockEntry, null, {external: {thumbnailUrl: 'url'}}, null, false); + var itemWithExternalThumbnailZoomToScreen = + new MockGalleryItem(mockEntry, null, {external: {thumbnailUrl: 'url'}}); assertEquals( ImageView.LoadTarget.THUMBNAIL, ImageView.getLoadTarget( @@ -56,17 +80,16 @@ new ImageView.Effect.ZoomToScreen(new ImageRect(0, 0, 100, 100)))); // Item with external thumbnail shown by zoom effect. - var itemWithExternalThumbnailZoom = new GalleryItem( - mockEntry, null, {external: {thumbnailUrl: 'url'}}, null, false); + var itemWithExternalThumbnailZoom = + new MockGalleryItem(mockEntry, null, {external: {thumbnailUrl: 'url'}}); assertEquals( ImageView.LoadTarget.MAIN_IMAGE, ImageView.getLoadTarget( itemWithExternalThumbnailZoom, - new ImageView.Effect.Zoom(0, 0, null))); + new ImageView.Effect.Zoom(0, 0, new ImageRect(0, 0, 1, 1)))); // Item without cache/thumbnail. - var itemWithoutCacheOrThumbnail = new GalleryItem( - mockEntry, null, {}, null, false); + var itemWithoutCacheOrThumbnail = new MockGalleryItem(mockEntry, null, {}); assertEquals( ImageView.LoadTarget.MAIN_IMAGE, ImageView.getLoadTarget( @@ -74,27 +97,31 @@ } function testLoadVideo(callback) { - var container = document.createElement('div'); + var container = assertInstanceof(document.createElement('div'), HTMLElement); // We re-use the image-container for video, it starts with this class. container.classList.add('image-container'); var viewport = new Viewport(window); - // Mock volume manager. - var volumeManager = { - getVolumeInfo: function(entry) { - return {volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS}; - } - }; + /** + * Mock volume manager. + * @constructor + * @extends MetadataProvider + */ + function MockDownloadVolumeManager() { + this.__proto__.getVolumeInfo = + function(entry) { + return {volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS}; + }; + } - var metadataModel = new MetadataModel(volumeManager); + var metadataModel = new MetadataModel(new MockDownloadVolumeManager()); var imageView = new ImageView(container, viewport, metadataModel); var downloads = new MockFileSystem('file:///downloads'); var getGalleryItem = function(path) { - return new GalleryItem( - new MockEntry(downloads, path), {isReadOnly: false}, {size: 100}, {}, - true /* original */); + return new MockGalleryItem( + new MockFileEntry(downloads, path), null, {size: 100}); }; var item = getGalleryItem('/test.webm'); var effect = new ImageView.Effect.None();
diff --git a/ui/file_manager/gallery/manifest.json b/ui/file_manager/gallery/manifest.json index 1781b33b1..c59f6c7 100644 --- a/ui/file_manager/gallery/manifest.json +++ b/ui/file_manager/gallery/manifest.json
@@ -53,7 +53,22 @@ "nrw", "orf", "raf", - "rw2" + "rw2", + // Video. + "3gp", + "avi", + "m4v", + "mkv", + "mov", + "mp4", + "mpeg", + "mpeg4", + "mpg", + "mpg4", + "ogm", + "ogv", + "ogx", + "webm" ] } },
diff --git a/ui/file_manager/integration_tests/audio_player_test_manifest.json b/ui/file_manager/integration_tests/audio_player_test_manifest.json index 7fae908..72989dc 100644 --- a/ui/file_manager/integration_tests/audio_player_test_manifest.json +++ b/ui/file_manager/integration_tests/audio_player_test_manifest.json
@@ -1,9 +1,10 @@ { // chrome-extension:/ddabbgbggambiildohfagdkliahiecfl/ "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqyMPfoy88DMSxVONd2NEK9u7OQfKjWQujB541dn+NNSFUEqSF6lYehgX77x7eGEs1DCHhZynX71o5JYLe2oeWt/HBDR/tWpdwwh80owIQDwaKJrfRtisyVL++dMmf0pNjFv1F5tFXObO84F22oZyBA89Z0S0jNlHjyVzm7U4BwbDHhHBoGXGJxf5AXL5quLdwlVe69d6ZjiSkYvaAAGwwYDWuqG8VFaZuz4Onh/bSYocBtd6rpeRwS7tAkTugCU0Mnivaj/x9WYajomcg+/QSQhwjbH+9+8zqsmpnKIeCY/qxadI9CYMMyg3Kbo53THQKRe6/DaXazgthMqAL9TGAwIDAQAB", - "name": "chrome os audio player browser tests", + "name": "Audio Player test extension", "version": "0.1", "manifest_version": 2, + "description": "Audio Player test extension", "web_accessible_resources": ["*"], "background": { "scripts": [
diff --git a/ui/file_manager/integration_tests/file_manager/providers.js b/ui/file_manager/integration_tests/file_manager/providers.js index 39b6e3e..e9462558 100644 --- a/ui/file_manager/integration_tests/file_manager/providers.js +++ b/ui/file_manager/integration_tests/file_manager/providers.js
@@ -6,6 +6,25 @@ (function() { +/** + * Returns provider name of the given testing provider manifest viz., the + * the value of the name field in the |manifest| file. + * @param {string} manifest Testing provider manifest file name. + * @return {string} Testing provider name. + */ +function getProviderNameForTest(manifest) { + if (manifest === 'manifest.json') + return 'Files Testing Provider test extension'; + if (manifest === 'manifest_multiple_mounts.json') + return 'Files Testing Provider multiple mounts test extension'; + if (manifest === 'manifest_source_device.json') + return 'Files Testing Provider device test extension'; + if (manifest === 'manifest_source_file.json') + return 'Files Testing Provider file test extension'; + + throw new Error('unknown mainfest: '.concat(manifest)); +} + var appId; /** @@ -101,6 +120,8 @@ * extension. */ function requestMountInternal(multipleMounts, manifest) { + const providerName = getProviderNameForTest(manifest); + StepsRunner.runGroups([ getSetupSteps(manifest), getClickMenuSteps(), @@ -114,7 +135,7 @@ .then(this.next); }, function(result) { - chrome.test.assertEq('Testing Provider', result.text); + chrome.test.assertEq(providerName, result.text); remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, @@ -140,7 +161,7 @@ }, function(result) { if (multipleMounts) - chrome.test.assertEq('Testing Provider', result.text); + chrome.test.assertEq(providerName, result.text); checkIfNoErrorsOccured(this.next); } ]
diff --git a/ui/file_manager/integration_tests/file_manager_test_manifest.json b/ui/file_manager/integration_tests/file_manager_test_manifest.json index eef0baf8..5ec7057f 100644 --- a/ui/file_manager/integration_tests/file_manager_test_manifest.json +++ b/ui/file_manager/integration_tests/file_manager_test_manifest.json
@@ -1,10 +1,11 @@ { // chrome-extension://oobinhbdbiehknkpbpejbbpdbkdjmoco/ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBjsTE4ocXJWzgcCDCUcsPASoRCGaTHrHn6b4zDTCayTuJtyGKzw4xZPMiG4dbEbmSAwEU7UCoyJAM1XfLS7UQ/Zz7ft8wpZkSS8/PJW+E4Qu++tMS0csj2Wdrrd2c5yyWxlJ+H9o2ivwtwuxs7pd+LXt+gsBA0epnT04T9EvOTQIDAQAB", - "name": "chrome file manager browser tests", + "name": "Files test extension", "version": "0.1", "incognito": "split", // Run a separate instance for the incognito mode. "manifest_version": 2, + "description": "Files test extension", "background": { "scripts": [ // List test_util.js and background.js first because the testcase
diff --git a/ui/file_manager/integration_tests/gallery_test_manifest.json b/ui/file_manager/integration_tests/gallery_test_manifest.json index aacc606..51bdb70 100644 --- a/ui/file_manager/integration_tests/gallery_test_manifest.json +++ b/ui/file_manager/integration_tests/gallery_test_manifest.json
@@ -1,9 +1,10 @@ { // chrome-extension://ejhcmmdhhpdhhgmifplfmjobgegbibkn/ "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2fEDh/TfZD2T2rabtuF922S/6n6Yby1EbjYFEaMExJrir3KJOxOMbUMF+6xChlweGnHBy7CQPtzMfYfjmftHpN7SDWVRRjcAb8vu8pyEcaEkdFQPkij5k8L9v6d7uoygbEsak/IOTYNWTZDrqPc47ypuEM4AG7/bf8NNVDq7EYlj1Lq4AfboEujMb7iif5VNRSfCTUcfddbLxk/J6QyomYlSpssKBCw1LRDnM+aRMFt70ElTozf3Oho7/22P7BXEYPr6YHdZotzb2HyBZ6pV6W9LAhuhsbmNByj0s9C+UmiqeyLoL0ALlqTydW7zDSYGHDRRDZLVMIgrb9D1ZQcUnwIDAQAB", - "name": "chrome gallery browser tests", + "name": "Gallery test extension", "version": "0.1", "manifest_version": 2, + "description": "Gallery test extension", "web_accessible_resources": ["*"], "background": { "scripts": [
diff --git a/ui/file_manager/integration_tests/testing_provider/background.js b/ui/file_manager/integration_tests/testing_provider/background.js index f3377f4e..840aa0e 100644 --- a/ui/file_manager/integration_tests/testing_provider/background.js +++ b/ui/file_manager/integration_tests/testing_provider/background.js
@@ -54,7 +54,7 @@ // If the manifest for device or file source is used, then mount a fake file // system on install. -if (chrome.runtime.getManifest().name === "Testing Provider Device" || - chrome.runtime.getManifest().name === "Testing Provider File") { +if (chrome.runtime.getManifest().description === "Testing Provider device" || + chrome.runtime.getManifest().description === "Testing Provider file") { chrome.runtime.onInstalled.addListener(mountFileSystem); }
diff --git a/ui/file_manager/integration_tests/testing_provider/manifest.json b/ui/file_manager/integration_tests/testing_provider/manifest.json index cc60746..502879eb 100644 --- a/ui/file_manager/integration_tests/testing_provider/manifest.json +++ b/ui/file_manager/integration_tests/testing_provider/manifest.json
@@ -1,7 +1,7 @@ { // chrome-extension://pkplfbidichfdicaijlchgnapepdginl "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDfX9dHNh948bt00YhZBm3P6E5QLaOt+v8kXVtibQfiPtOD2FTScB/f0wX/EQWVO7BkaSOsRkTPcPIgocyMPYr2FLgqGLFlYT9nQpKJZUFNF5oJ5rG6Nv7ppf4zEB3j6da1IBRTz2yOZ+6O1TMZxol/V62/QcqrJeggsHTEPGLdr9Ua4b1Ka0xKJnJngZljsbw93FI1o+P9dAh5BS6wTPiZI/vmJVjvMTkSTnaZ3n9Go2t7A0XLcSxLcVyuLAd2mAvSN0mIviOukdM66wr7llif71nKuUt+4qvlr/r9HfwzN6pA4jkwhtS1UD+3CmB+wsHwsnohNcuu4FIQ6rgq/7QIDAQAB", - "name": "Testing Provider", + "name": "Files Testing Provider test extension", "version": "0.1", "manifest_version": 2, "description": "Testing Provider",
diff --git a/ui/file_manager/integration_tests/testing_provider/manifest_multiple_mounts.json b/ui/file_manager/integration_tests/testing_provider/manifest_multiple_mounts.json index 20e980a..729ea70 100644 --- a/ui/file_manager/integration_tests/testing_provider/manifest_multiple_mounts.json +++ b/ui/file_manager/integration_tests/testing_provider/manifest_multiple_mounts.json
@@ -1,10 +1,10 @@ { // chrome-extension://pkplfbidichfdicaijlchgnapepdginl "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDfX9dHNh948bt00YhZBm3P6E5QLaOt+v8kXVtibQfiPtOD2FTScB/f0wX/EQWVO7BkaSOsRkTPcPIgocyMPYr2FLgqGLFlYT9nQpKJZUFNF5oJ5rG6Nv7ppf4zEB3j6da1IBRTz2yOZ+6O1TMZxol/V62/QcqrJeggsHTEPGLdr9Ua4b1Ka0xKJnJngZljsbw93FI1o+P9dAh5BS6wTPiZI/vmJVjvMTkSTnaZ3n9Go2t7A0XLcSxLcVyuLAd2mAvSN0mIviOukdM66wr7llif71nKuUt+4qvlr/r9HfwzN6pA4jkwhtS1UD+3CmB+wsHwsnohNcuu4FIQ6rgq/7QIDAQAB", - "name": "Testing Provider", + "name": "Files Testing Provider multiple mounts test extension", "version": "0.1", "manifest_version": 2, - "description": "Testing Provider", + "description": "Testing Provider multiple mounts", "permissions": [ "fileSystemProvider" ],
diff --git a/ui/file_manager/integration_tests/testing_provider/manifest_source_device.json b/ui/file_manager/integration_tests/testing_provider/manifest_source_device.json index 2f92087..e8acb27 100644 --- a/ui/file_manager/integration_tests/testing_provider/manifest_source_device.json +++ b/ui/file_manager/integration_tests/testing_provider/manifest_source_device.json
@@ -1,10 +1,10 @@ { // chrome-extension://pkplfbidichfdicaijlchgnapepdginl "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDfX9dHNh948bt00YhZBm3P6E5QLaOt+v8kXVtibQfiPtOD2FTScB/f0wX/EQWVO7BkaSOsRkTPcPIgocyMPYr2FLgqGLFlYT9nQpKJZUFNF5oJ5rG6Nv7ppf4zEB3j6da1IBRTz2yOZ+6O1TMZxol/V62/QcqrJeggsHTEPGLdr9Ua4b1Ka0xKJnJngZljsbw93FI1o+P9dAh5BS6wTPiZI/vmJVjvMTkSTnaZ3n9Go2t7A0XLcSxLcVyuLAd2mAvSN0mIviOukdM66wr7llif71nKuUt+4qvlr/r9HfwzN6pA4jkwhtS1UD+3CmB+wsHwsnohNcuu4FIQ6rgq/7QIDAQAB", - "name": "Testing Provider Device", + "name": "Files Testing Provider device test extension", "version": "0.1", "manifest_version": 2, - "description": "Testing Provider", + "description": "Testing Provider device", "permissions": [ "fileSystemProvider" ],
diff --git a/ui/file_manager/integration_tests/testing_provider/manifest_source_file.json b/ui/file_manager/integration_tests/testing_provider/manifest_source_file.json index 17b71a18..021c49f 100644 --- a/ui/file_manager/integration_tests/testing_provider/manifest_source_file.json +++ b/ui/file_manager/integration_tests/testing_provider/manifest_source_file.json
@@ -1,10 +1,10 @@ { // chrome-extension://pkplfbidichfdicaijlchgnapepdginl "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDfX9dHNh948bt00YhZBm3P6E5QLaOt+v8kXVtibQfiPtOD2FTScB/f0wX/EQWVO7BkaSOsRkTPcPIgocyMPYr2FLgqGLFlYT9nQpKJZUFNF5oJ5rG6Nv7ppf4zEB3j6da1IBRTz2yOZ+6O1TMZxol/V62/QcqrJeggsHTEPGLdr9Ua4b1Ka0xKJnJngZljsbw93FI1o+P9dAh5BS6wTPiZI/vmJVjvMTkSTnaZ3n9Go2t7A0XLcSxLcVyuLAd2mAvSN0mIviOukdM66wr7llif71nKuUt+4qvlr/r9HfwzN6pA4jkwhtS1UD+3CmB+wsHwsnohNcuu4FIQ6rgq/7QIDAQAB", - "name": "Testing Provider File", + "name": "Files Testing Provider file test extension", "version": "0.1", "manifest_version": 2, - "description": "Testing Provider", + "description": "Testing Provider file", "permissions": [ "fileSystemProvider" ],
diff --git a/ui/file_manager/integration_tests/video_player_test_manifest.json b/ui/file_manager/integration_tests/video_player_test_manifest.json index cd2623ce..3dbcc7c7 100644 --- a/ui/file_manager/integration_tests/video_player_test_manifest.json +++ b/ui/file_manager/integration_tests/video_player_test_manifest.json
@@ -1,9 +1,10 @@ { // chrome-extension://ljoplibgfehghmibaoaepfagnmbbfiga "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvT+IcKSOCmrC9IOpAGaNaUX2pbJSJchiYUuE9YilghsxGTWA8nC34k5/+BycWnBOEUow2pQmTRHuxt9E/CBzH15ah7NmikclL6UsoRgDb0Sj3zmhVNLXWX2jbFnECjTBPPbASj8Xnf20n6HNX3Yp9nnAJKzk5d/xzSgFz8uL9defwlZQB7t0E28+3DD9IoOWkEJWz6FRzhiY07TC2n6tjo0CPS150x1jEHyZF2oVLn8Cus28hBkoZ70GPWB6BQCxzGLcYWUJ6EKgE4iO9tcSDC2MMvA++n18JMb1APtxH3MIqQyGE/2cydjxEhhNLiD5Mp4tYHKObGWFefKQ0WlmEwIDAQAB", - "name": "chrome os video player browser tests", + "name": "Video Player test extension", "version": "0.1", "manifest_version": 2, + "description": "Video Player test extension", "web_accessible_resources": ["*"], "background": { "scripts": [
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index ac31e4d..71ec283 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -120,6 +120,8 @@ "views/desktop_popup_alignment_delegate.h", "views/message_popup_collection.cc", "views/message_popup_collection.h", + "views/message_popup_view.cc", + "views/message_popup_view.h", "views/message_view.cc", "views/message_view.h", "views/message_view_factory.cc", @@ -144,8 +146,6 @@ "views/proportional_image_view.h", "views/slide_out_controller.cc", "views/slide_out_controller.h", - "views/toast_contents_view.cc", - "views/toast_contents_view.h", ] if (!is_chromeos) { sources += [
diff --git a/ui/message_center/message_center.h b/ui/message_center/message_center.h index 6546d7d..99e2b64 100644 --- a/ui/message_center/message_center.h +++ b/ui/message_center/message_center.h
@@ -211,7 +211,7 @@ friend class MessageCenterImplTestWithoutChangeQueue; friend class UiControllerTest; friend class TrayViewControllerTest; - friend class test::MessagePopupCollectionTest; + friend class MessagePopupCollectionTest; virtual void DisableTimersForTest() = 0; MessageCenter();
diff --git a/ui/message_center/views/desktop_popup_alignment_delegate.cc b/ui/message_center/views/desktop_popup_alignment_delegate.cc index e0d93645..49d3fa87 100644 --- a/ui/message_center/views/desktop_popup_alignment_delegate.cc +++ b/ui/message_center/views/desktop_popup_alignment_delegate.cc
@@ -56,10 +56,10 @@ return (alignment_ & POPUP_ALIGNMENT_LEFT) != 0; } -void DesktopPopupAlignmentDelegate::RecomputeAlignment( +bool DesktopPopupAlignmentDelegate::RecomputeAlignment( const display::Display& display) { if (work_area_ == display.work_area()) - return; + return false; work_area_ = display.work_area(); @@ -79,6 +79,8 @@ work_area_.y() == display.bounds().y()) ? POPUP_ALIGNMENT_LEFT : POPUP_ALIGNMENT_RIGHT; + + return true; } void DesktopPopupAlignmentDelegate::ConfigureWidgetInitParamsForContainer( @@ -101,8 +103,8 @@ display::Display primary_display = screen_->GetPrimaryDisplay(); if (primary_display.id() != primary_display_id_) { primary_display_id_ = primary_display.id(); - RecomputeAlignment(primary_display); - DoUpdateIfPossible(); + if (RecomputeAlignment(primary_display)) + ResetBounds(); } }
diff --git a/ui/message_center/views/desktop_popup_alignment_delegate.h b/ui/message_center/views/desktop_popup_alignment_delegate.h index 93fb52c..6342116b 100644 --- a/ui/message_center/views/desktop_popup_alignment_delegate.h +++ b/ui/message_center/views/desktop_popup_alignment_delegate.h
@@ -37,7 +37,7 @@ gfx::Rect GetWorkArea() const override; bool IsTopDown() const override; bool IsFromLeft() const override; - void RecomputeAlignment(const display::Display& display) override; + bool RecomputeAlignment(const display::Display& display) override; void ConfigureWidgetInitParamsForContainer( views::Widget* widget, views::Widget::InitParams* init_params) override;
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc index 82127545..bd67745f 100644 --- a/ui/message_center/views/message_popup_collection.cc +++ b/ui/message_center/views/message_popup_collection.cc
@@ -4,446 +4,555 @@ #include "ui/message_center/views/message_popup_collection.h" -#include <set> - -#include "base/bind.h" -#include "base/feature_list.h" -#include "base/i18n/rtl.h" -#include "base/logging.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "build/build_config.h" -#include "ui/accessibility/ax_enums.mojom.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/animation/slide_animation.h" +#include "ui/gfx/animation/linear_animation.h" +#include "ui/gfx/animation/tween.h" #include "ui/message_center/message_center.h" -#include "ui/message_center/notification_list.h" -#include "ui/message_center/public/cpp/features.h" #include "ui/message_center/public/cpp/message_center_constants.h" -#include "ui/message_center/public/cpp/notification.h" -#include "ui/message_center/views/message_view.h" -#include "ui/message_center/views/message_view_context_menu_controller.h" -#include "ui/message_center/views/message_view_factory.h" +#include "ui/message_center/views/message_popup_view.h" #include "ui/message_center/views/popup_alignment_delegate.h" -#include "ui/message_center/views/toast_contents_view.h" -#include "ui/views/background.h" -#include "ui/views/layout/fill_layout.h" -#include "ui/views/view.h" -#include "ui/views/views_delegate.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" namespace message_center { + namespace { -// The margin between messages (and between the anchor unless -// first_item_has_no_margin was specified). -const int kToastMarginY = kMarginBetweenPopups; +// Animation duration for FADE_IN and FADE_OUT. +constexpr base::TimeDelta kFadeInFadeOutDuration = + base::TimeDelta::FromMilliseconds(200); -} // namespace. +// Animation duration for MOVE_DOWN. +constexpr base::TimeDelta kMoveDownDuration = + base::TimeDelta::FromMilliseconds(120); + +} // namespace MessagePopupCollection::MessagePopupCollection( - MessageCenter* message_center, PopupAlignmentDelegate* alignment_delegate) - : message_center_(message_center), + : animation_(std::make_unique<gfx::LinearAnimation>(this)), alignment_delegate_(alignment_delegate) { - DCHECK(message_center_); - message_center_->AddObserver(this); + MessageCenter::Get()->AddObserver(this); alignment_delegate_->set_collection(this); -#if !defined(OS_CHROMEOS) - if (!base::FeatureList::IsEnabled(message_center::kNewStyleNotifications)) - context_menu_controller_.reset(new MessageViewContextMenuController()); -#endif } MessagePopupCollection::~MessagePopupCollection() { - weak_factory_.InvalidateWeakPtrs(); - - message_center_->RemoveObserver(this); - - CloseAllWidgets(); + for (const auto& item : popup_items_) + item.popup->Close(); + MessageCenter::Get()->RemoveObserver(this); } -void MessagePopupCollection::OnViewPreferredSizeChanged( - views::View* observed_view) { - OnNotificationUpdated( - static_cast<MessageView*>(observed_view)->notification_id()); -} +void MessagePopupCollection::Update() { + if (is_updating_) + return; + base::AutoReset<bool> reset(&is_updating_, true); -void MessagePopupCollection::OnViewIsDeleting(views::View* observed_view) { - observed_views_.Remove(observed_view); + if (animation_->is_animating()) { + UpdateByAnimation(); + return; + } + + if (state_ != State::IDLE) + TransitionFromAnimation(); + + if (state_ == State::IDLE) + TransitionToAnimation(); + + UpdatePopupTimers(); + + if (state_ != State::IDLE) { + // If not in IDLE state, start animation. + animation_->SetDuration(state_ == State::MOVE_DOWN + ? kMoveDownDuration + : kFadeInFadeOutDuration); + animation_->Start(); + UpdateByAnimation(); + } + + DCHECK(state_ == State::IDLE || animation_->is_animating()); } void MessagePopupCollection::MarkAllPopupsShown() { - std::set<std::string> closed_ids = CloseAllWidgets(); - for (std::set<std::string>::iterator iter = closed_ids.begin(); - iter != closed_ids.end(); iter++) { - message_center_->MarkSinglePopupAsShown(*iter, false); - } -} - -void MessagePopupCollection::PausePopupTimers() { - DCHECK(timer_pause_counter_ >= 0); - if (timer_pause_counter_ <= 0) { - message_center_->PausePopupTimers(); - timer_pause_counter_ = 1; - } else { - timer_pause_counter_++; - } -} - -void MessagePopupCollection::RestartPopupTimers() { - DCHECK(timer_pause_counter_ >= 1); - if (timer_pause_counter_ <= 1) { - message_center_->RestartPopupTimers(); - timer_pause_counter_ = 0; - } else { - timer_pause_counter_--; - } -} - -void MessagePopupCollection::UpdateWidgets() { - if (message_center_->IsMessageCenterVisible()) { - DCHECK_EQ(0u, message_center_->GetPopupNotifications().size()); + if (is_updating_) return; - } + base::AutoReset<bool> reset(&is_updating_, true); - NotificationList::PopupNotifications popups = - message_center_->GetPopupNotifications(); - if (popups.empty()) { - CloseAllWidgets(); + for (const auto& item : popup_items_) { + item.popup->Close(); + MessageCenter::Get()->MarkSinglePopupAsShown(item.id, false); + } + popup_items_.clear(); + + ResetHotMode(); + state_ = State::IDLE; + animation_->End(); +} + +void MessagePopupCollection::ResetBounds() { + if (is_updating_) return; - } + { + base::AutoReset<bool> reset(&is_updating_, true); - bool top_down = alignment_delegate_->IsTopDown(); - int base = GetBaseline(); -#if defined(OS_CHROMEOS) - bool is_primary_display = - alignment_delegate_->IsPrimaryDisplayForNotification(); -#endif + ResetHotMode(); + state_ = State::IDLE; + animation_->End(); - // Check if the popups contain a new notification. - bool has_new_toasts = false; - for (auto* popup : popups) { - if (!FindToast(popup->id())) { - has_new_toasts = true; - break; + CalculateBounds(); + + // Remove popups that are no longer in work area. + ClosePopupsOutsideWorkArea(); + + // Reset bounds and opacity of popups. + for (auto& item : popup_items_) { + item.popup->SetPopupBounds(item.bounds); + item.popup->SetOpacity(1.0); } } - // If a new notification is found, collapse all existing notifications - // beforehand. - if (has_new_toasts) { - for (Toasts::const_iterator iter = toasts_.begin(); - iter != toasts_.end();) { - // SetExpanded() may fire PreferredSizeChanged(), which may end up - // removing the toast in OnNotificationUpdated(). So we have to increment - // the iterator in a way that is safe even if the current iterator is - // invalidated during the loop. - MessageView* view = (*iter++)->message_view(); - if (view->IsMouseHovered() || view->IsManuallyExpandedOrCollapsed()) - continue; - view->SetExpanded(false); - } - } - - // Iterate in the reverse order to keep the oldest toasts on screen. Newer - // items may be ignored if there are no room to place them. - for (NotificationList::PopupNotifications::const_reverse_iterator iter = - popups.rbegin(); iter != popups.rend(); ++iter) { - const Notification& notification = *(*iter); - if (FindToast(notification.id())) - continue; - -#if defined(OS_CHROMEOS) - // Disables popup of custom notification on non-primary displays, since - // currently custom notification supports only on one display at the same - // time. - // TODO(yoshiki): Support custom popup notification on multiple display - // (crbug.com/715370). - if (!is_primary_display && notification.type() == NOTIFICATION_TYPE_CUSTOM) - continue; -#endif - - // Create top-level notification. - MessageView* view = MessageViewFactory::Create(notification, true); - observed_views_.Add(view); - if (!view->IsManuallyExpandedOrCollapsed()) - view->SetExpanded(view->IsAutoExpandingAllowed()); - -#if !defined(OS_CHROMEOS) - view->set_context_menu_controller(context_menu_controller_.get()); -#endif - - int view_height = ToastContentsView::GetToastSizeForView(view).height(); - int height_available = - top_down ? alignment_delegate_->GetWorkArea().bottom() - base - : base - alignment_delegate_->GetWorkArea().y(); - - if (height_available - view_height - kToastMarginY < 0) { - delete view; - break; - } - - ToastContentsView* toast = new ToastContentsView( - notification.id(), alignment_delegate_, weak_factory_.GetWeakPtr()); - - const RichNotificationData& optional_fields = - notification.rich_notification_data(); - bool a11y_feedback_for_updates = - optional_fields.should_make_spoken_feedback_for_popup_updates; - - // There will be no contents already since this is a new ToastContentsView. - toast->SetContents(view, a11y_feedback_for_updates); - toasts_.push_back(toast); - - gfx::Size preferred_size = toast->GetPreferredSize(); - gfx::Point origin( - alignment_delegate_->GetToastOriginX(gfx::Rect(preferred_size)), base); - // The toast slides in from the edge of the screen horizontally. - if (alignment_delegate_->IsFromLeft()) - origin.set_x(origin.x() - preferred_size.width()); - else - origin.set_x(origin.x() + preferred_size.width()); - if (top_down) - origin.set_y(origin.y() + view_height); - - toast->RevealWithAnimation(origin); - - // Shift the base line to be a few pixels above the last added toast or (few - // pixels below last added toast if top-aligned). - if (top_down) - base += view_height + kToastMarginY; - else - base -= view_height + kToastMarginY; - - if (views::ViewsDelegate::GetInstance() && a11y_feedback_for_updates) { - views::ViewsDelegate::GetInstance()->NotifyAccessibilityEvent( - toast, ax::mojom::Event::kAlert); - } - - message_center_->DisplayedNotification(notification.id(), - DISPLAY_SOURCE_POPUP); - } + // Restart animation for FADE_OUT. + Update(); } -void MessagePopupCollection::OnMouseEntered(ToastContentsView* toast_entered) { - // Sometimes we can get two MouseEntered/MouseExited in a row when animating - // toasts. So we need to keep track of which one is the currently active one. - latest_toast_entered_ = toast_entered; - - PausePopupTimers(); -} - -void MessagePopupCollection::OnMouseExited(ToastContentsView* toast_exited) { - // If we're exiting a toast after entering a different toast, then ignore - // this mouse event. - if (toast_exited != latest_toast_entered_) - return; - latest_toast_entered_ = NULL; - - RestartPopupTimers(); -} - -std::set<std::string> MessagePopupCollection::CloseAllWidgets() { - std::set<std::string> closed_toast_ids; - - while (!toasts_.empty()) { - ToastContentsView* toast = toasts_.front(); - toasts_.pop_front(); - closed_toast_ids.insert(toast->id()); - - OnMouseExited(toast); - - // CloseWithAnimation will cause the toast to forget about |this| so it is - // required when we forget a toast. - toast->CloseWithAnimation(); - } - - return closed_toast_ids; -} - -void MessagePopupCollection::ForgetToast(ToastContentsView* toast) { - toasts_.remove(toast); - OnMouseExited(toast); -} - -void MessagePopupCollection::RemoveToast(ToastContentsView* toast, - bool mark_as_shown) { - ForgetToast(toast); - - toast->CloseWithAnimation(); - - if (mark_as_shown) - message_center_->MarkSinglePopupAsShown(toast->id(), false); -} - -void MessagePopupCollection::RepositionWidgets() { - bool top_down = alignment_delegate_->IsTopDown(); - // We don't want to position relative to last toast - we want re-position. - int base = alignment_delegate_->GetBaseline(); - - for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end();) { - Toasts::const_iterator curr = iter++; - gfx::Rect bounds((*curr)->bounds()); - bounds.set_x(alignment_delegate_->GetToastOriginX(bounds)); - bounds.set_y(top_down ? base : base - bounds.height()); - - // The notification may scrolls the boundary of the screen due to image - // load and such notifications should disappear. Do not call - // CloseWithAnimation, we don't want to show the closing animation, and we - // don't want to mark such notifications as shown. See crbug.com/233424 - if ((top_down - ? alignment_delegate_->GetWorkArea().bottom() - bounds.bottom() - : bounds.y() - alignment_delegate_->GetWorkArea().y()) >= 0) - (*curr)->SetBoundsWithAnimation(bounds); - else - RemoveToast(*curr, /*mark_as_shown=*/false); - - // Shift the base line to be a few pixels above the last added toast or (few - // pixels below last added toast if top-aligned). - if (top_down) - base += bounds.height() + kToastMarginY; - else - base -= bounds.height() + kToastMarginY; - } -} - -int MessagePopupCollection::GetBaseline() const { - if (toasts_.empty()) - return alignment_delegate_->GetBaseline(); - - if (alignment_delegate_->IsTopDown()) - return toasts_.back()->bounds().bottom() + kToastMarginY; - - return toasts_.back()->origin().y() - kToastMarginY; -} - -int MessagePopupCollection::GetBaselineForToast( - ToastContentsView* toast) const { - if (alignment_delegate_->IsTopDown()) - return toast->bounds().y(); - else - return toast->bounds().bottom(); +void MessagePopupCollection::NotifyPopupResized() { + resize_requested_ = true; + Update(); } void MessagePopupCollection::OnNotificationAdded( const std::string& notification_id) { - DoUpdate(); + Update(); } void MessagePopupCollection::OnNotificationRemoved( const std::string& notification_id, bool by_user) { - // Find a toast. - Toasts::const_iterator iter = toasts_.begin(); - for (; iter != toasts_.end(); ++iter) { - if ((*iter)->id() == notification_id) - break; - } - if (iter == toasts_.end()) - return; - - RemoveToast(*iter, /*mark_as_shown=*/true); - - DoUpdate(); + Update(); } void MessagePopupCollection::OnNotificationUpdated( const std::string& notification_id) { - // Find a toast. - Toasts::const_iterator toast_iter = toasts_.begin(); - for (; toast_iter != toasts_.end(); ++toast_iter) { - if ((*toast_iter)->id() == notification_id) + // Find Notification object with |notification_id|. + const auto& notifications = MessageCenter::Get()->GetPopupNotifications(); + auto it = notifications.begin(); + while (it != notifications.end()) { + if ((*it)->id() == notification_id) break; + ++it; } - if (toast_iter == toasts_.end()) + + if (it == notifications.end()) { + // If not found, probably |notification_id| is removed from popups by + // timeout. + Update(); return; - - NotificationList::PopupNotifications notifications = - message_center_->GetPopupNotifications(); - bool updated = false; - - for (NotificationList::PopupNotifications::iterator iter = - notifications.begin(); iter != notifications.end(); ++iter) { - Notification* notification = *iter; - DCHECK(notification); - ToastContentsView* toast_contents_view = *toast_iter; - DCHECK(toast_contents_view); - - if (notification->id() != notification_id) - continue; - - const RichNotificationData& optional_fields = - notification->rich_notification_data(); - bool a11y_feedback_for_updates = - optional_fields.should_make_spoken_feedback_for_popup_updates; - - toast_contents_view->UpdateContents(*notification, - a11y_feedback_for_updates); - - updated = true; } - // OnNotificationUpdated() can be called when a notification is excluded from - // the popup notification list but still remains in the full notification - // list. In that case the widget for the notification has to be closed here. - if (!updated) - RemoveToast(*toast_iter, /*mark_as_shown=*/true); - - DoUpdate(); -} - -ToastContentsView* MessagePopupCollection::FindToast( - const std::string& notification_id) const { - for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end(); - ++iter) { - if ((*iter)->id() == notification_id) - return *iter; - } - return NULL; -} - -// This is the main sequencer of tasks. It does a step, then waits for -// all started transitions to play out before doing the next step. -// First, remove all expired toasts. -// Then, reposition widgets. -// Then, see if there is vacant space for new toasts. -void MessagePopupCollection::DoUpdate() { - RepositionWidgets(); - - // Reposition could create extra space which allows additional widgets. - UpdateWidgets(); -} - -void MessagePopupCollection::OnDisplayMetricsChanged( - const display::Display& display) { - alignment_delegate_->RecomputeAlignment(display); -} - -views::Widget* MessagePopupCollection::GetWidgetForTest(const std::string& id) - const { - for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end(); - ++iter) { - if ((*iter)->id() == id) - return (*iter)->GetWidget(); - } - return NULL; -} - -gfx::Rect MessagePopupCollection::GetToastRectAt(size_t index) const { - size_t i = 0; - for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end(); - ++iter) { - if (i++ == index) { - views::Widget* widget = (*iter)->GetWidget(); - if (widget) - return widget->GetWindowBoundsInScreen(); + // Update contents of the notification. + for (auto& item : popup_items_) { + if (item.id == notification_id) { + item.popup->UpdateContents(**it); break; } } - return gfx::Rect(); + + Update(); +} + +void MessagePopupCollection::AnimationEnded(const gfx::Animation* animation) { + Update(); +} + +void MessagePopupCollection::AnimationProgressed( + const gfx::Animation* animation) { + Update(); +} + +void MessagePopupCollection::AnimationCanceled( + const gfx::Animation* animation) { + Update(); +} + +MessagePopupView* MessagePopupCollection::CreatePopup( + const Notification& notification) { + return new MessagePopupView(notification, alignment_delegate_, this); +} + +void MessagePopupCollection::RestartPopupTimers() { + MessageCenter::Get()->RestartPopupTimers(); +} + +void MessagePopupCollection::PausePopupTimers() { + MessageCenter::Get()->PausePopupTimers(); +} + +bool MessagePopupCollection::IsPrimaryDisplayForNotification() const { + return alignment_delegate_->IsPrimaryDisplayForNotification(); +} + +void MessagePopupCollection::TransitionFromAnimation() { + DCHECK_NE(state_, State::IDLE); + DCHECK(!animation_->is_animating()); + + // The animation of type |state_| is now finished. + UpdateByAnimation(); + + // If FADE_OUT animation is finished, remove the animated popup. + if (state_ == State::FADE_OUT) + CloseAnimatingPopups(); + + if (state_ == State::FADE_IN || state_ == State::MOVE_DOWN || + (state_ == State::FADE_OUT && popup_items_.empty())) { + // If the animation is finished, transition to IDLE. + state_ = State::IDLE; + } else if (state_ == State::FADE_OUT && !popup_items_.empty()) { + // If FADE_OUT animation is finished and we still have remaining popups, + // we have to MOVE_DOWN them. + state_ = State::MOVE_DOWN; + + // If we're going to add a new popup after this MOVE_DOWN, do the collapse + // animation at the same time. Otherwise it will take another MOVE_DOWN. + if (HasAddedPopup()) + CollapseAllPopups(); + + MoveDownPopups(); + } +} + +void MessagePopupCollection::TransitionToAnimation() { + DCHECK_EQ(state_, State::IDLE); + DCHECK(!animation_->is_animating()); + + if (HasRemovedPopup()) { + MarkRemovedPopup(); + + // Start hot mode to allow a user to continually close many notifications. + StartHotMode(); + + if (CloseTransparentPopups()) { + // If the popup is already transparent, skip FADE_OUT. + state_ = State::MOVE_DOWN; + MoveDownPopups(); + } else { + state_ = State::FADE_OUT; + } + return; + } + + if (HasAddedPopup()) { + if (CollapseAllPopups()) { + // If we had existing popups that weren't collapsed, first show collapsing + // animation. + state_ = State::MOVE_DOWN; + MoveDownPopups(); + return; + } else if (AddPopup()) { + // If a popup is actually added, show FADE_IN animation. + state_ = State::FADE_IN; + return; + } + } + + if (resize_requested_) { + // Resize is requested e.g. a user manually expanded notification. + resize_requested_ = false; + state_ = State::MOVE_DOWN; + MoveDownPopups(); + ClosePopupsOutsideWorkArea(); + return; + } + + if (!IsAnyPopupHovered() && is_hot_) { + // Reset hot mode and animate to the normal positions. + state_ = State::MOVE_DOWN; + ResetHotMode(); + MoveDownPopups(); + } +} + +void MessagePopupCollection::UpdatePopupTimers() { + if (state_ == State::IDLE) { + if (IsAnyPopupHovered() || IsAnyPopupActive()) { + // If any popup is hovered or activated, pause popup timer. + PausePopupTimers(); + } else { + // If in IDLE state, restart popup timer. + RestartPopupTimers(); + } + } else { + // If not in IDLE state, pause popup timer. + PausePopupTimers(); + } +} + +void MessagePopupCollection::CalculateBounds() { + int base = alignment_delegate_->GetBaseline(); + for (size_t i = 0; i < popup_items_.size(); ++i) { + gfx::Size preferred_size( + kNotificationWidth, + popup_items_[i].popup->GetHeightForWidth(kNotificationWidth)); + + // Align the top of i-th popup to |hot_top_|. + if (is_hot_ && hot_index_ == i) { + base = hot_top_; + if (!alignment_delegate_->IsTopDown()) + base += preferred_size.height(); + } + + int origin_x = + alignment_delegate_->GetToastOriginX(gfx::Rect(preferred_size)); + + int origin_y = base; + if (!alignment_delegate_->IsTopDown()) + origin_y -= preferred_size.height(); + + popup_items_[i].start_bounds = popup_items_[i].bounds; + popup_items_[i].bounds = + gfx::Rect(gfx::Point(origin_x, origin_y), preferred_size); + + const int delta = preferred_size.height() + kMarginBetweenPopups; + if (alignment_delegate_->IsTopDown()) + base += delta; + else + base -= delta; + } +} + +void MessagePopupCollection::UpdateByAnimation() { + DCHECK_NE(state_, State::IDLE); + + for (auto& item : popup_items_) { + if (!item.is_animating) + continue; + + double value = gfx::Tween::CalculateValue( + state_ == State::FADE_OUT ? gfx::Tween::EASE_IN : gfx::Tween::EASE_OUT, + animation_->GetCurrentValue()); + + if (state_ == State::FADE_IN) + item.popup->SetOpacity(gfx::Tween::FloatValueBetween(value, 0.0f, 1.0f)); + else if (state_ == State::FADE_OUT) + item.popup->SetOpacity(gfx::Tween::FloatValueBetween(value, 1.0f, 0.0f)); + + if (state_ == State::FADE_IN || state_ == State::MOVE_DOWN) { + item.popup->SetPopupBounds( + gfx::Tween::RectValueBetween(value, item.start_bounds, item.bounds)); + } + } +} + +bool MessagePopupCollection::AddPopup() { + std::set<std::string> existing_ids; + for (const auto& item : popup_items_) + existing_ids.insert(item.id); + + auto notifications = MessageCenter::Get()->GetPopupNotifications(); + Notification* new_notification = nullptr; + // Reverse iterating because notifications are in reverse chronological order. + for (auto it = notifications.rbegin(); it != notifications.rend(); ++it) { + // Disables popup of custom notification on non-primary displays, since + // currently custom notification supports only on one display at the same + // time. + // TODO(yoshiki): Support custom popup notification on multiple display + // (https://crbug.com/715370). + if (!IsPrimaryDisplayForNotification() && + (*it)->type() == NOTIFICATION_TYPE_CUSTOM) { + continue; + } + + if (!existing_ids.count((*it)->id())) { + new_notification = *it; + break; + } + } + + if (!new_notification) + return false; + + // Reset animation flag of existing popups. + for (auto& item : popup_items_) + item.is_animating = false; + + { + PopupItem item; + item.id = new_notification->id(); + item.is_animating = true; + item.popup = CreatePopup(*new_notification); + + if (IsNextEdgeOutsideWorkArea(item)) { + item.popup->Close(); + return false; + } + + item.popup->Show(); + popup_items_.push_back(item); + } + + MessageCenter::Get()->DisplayedNotification(new_notification->id(), + DISPLAY_SOURCE_POPUP); + + CalculateBounds(); + + auto& item = popup_items_.back(); + item.start_bounds = item.bounds; + item.start_bounds += gfx::Vector2d( + (alignment_delegate_->IsFromLeft() ? -1 : 1) * item.bounds.width(), 0); + return true; +} + +void MessagePopupCollection::MarkRemovedPopup() { + std::set<std::string> existing_ids; + for (Notification* notification : + MessageCenter::Get()->GetPopupNotifications()) { + existing_ids.insert(notification->id()); + } + + for (auto& item : popup_items_) + item.is_animating = !existing_ids.count(item.id); +} + +void MessagePopupCollection::MoveDownPopups() { + CalculateBounds(); + for (auto& item : popup_items_) + item.is_animating = true; +} + +int MessagePopupCollection::GetNextEdge(const PopupItem& item) const { + const int delta = + item.popup->GetHeightForWidth(kNotificationWidth) + kMarginBetweenPopups; + + int base = 0; + if (popup_items_.empty()) { + base = alignment_delegate_->GetBaseline(); + } else { + base = alignment_delegate_->IsTopDown() + ? popup_items_.back().bounds.bottom() + : popup_items_.back().bounds.y(); + } + + return alignment_delegate_->IsTopDown() ? base + delta : base - delta; +} + +bool MessagePopupCollection::IsNextEdgeOutsideWorkArea( + const PopupItem& item) const { + const int next_edge = GetNextEdge(item); + const gfx::Rect work_area = alignment_delegate_->GetWorkArea(); + return alignment_delegate_->IsTopDown() ? next_edge > work_area.bottom() + : next_edge < work_area.y(); +} + +void MessagePopupCollection::StartHotMode() { + for (size_t i = 0; i < popup_items_.size(); ++i) { + if (popup_items_[i].is_animating && popup_items_[i].popup->is_hovered()) { + is_hot_ = true; + hot_index_ = i; + hot_top_ = popup_items_[i].bounds.y(); + break; + } + } +} + +void MessagePopupCollection::ResetHotMode() { + is_hot_ = false; + hot_index_ = 0; + hot_top_ = 0; +} + +void MessagePopupCollection::CloseAnimatingPopups() { + for (auto& item : popup_items_) { + if (!item.is_animating) + continue; + item.popup->Close(); + item.popup = nullptr; + } + RemoveClosedPopupItems(); +} + +bool MessagePopupCollection::CloseTransparentPopups() { + bool removed = false; + for (auto& item : popup_items_) { + if (item.popup->GetOpacity() > 0.0) + continue; + item.popup->Close(); + item.popup = nullptr; + removed = true; + } + RemoveClosedPopupItems(); + return removed; +} + +void MessagePopupCollection::ClosePopupsOutsideWorkArea() { + const gfx::Rect work_area = alignment_delegate_->GetWorkArea(); + for (auto& item : popup_items_) { + if (work_area.Contains(item.bounds)) + continue; + item.popup->Close(); + item.popup = nullptr; + } + RemoveClosedPopupItems(); +} + +void MessagePopupCollection::RemoveClosedPopupItems() { + popup_items_.erase( + std::remove_if(popup_items_.begin(), popup_items_.end(), + [](const auto& item) { return !item.popup; }), + popup_items_.end()); +} + +bool MessagePopupCollection::CollapseAllPopups() { + bool changed = false; + for (auto& item : popup_items_) { + int old_height = item.popup->GetHeightForWidth(kNotificationWidth); + + item.popup->AutoCollapse(); + + int new_height = item.popup->GetHeightForWidth(kNotificationWidth); + if (old_height != new_height) + changed = true; + } + + resize_requested_ = false; + return changed; +} + +bool MessagePopupCollection::HasAddedPopup() const { + std::set<std::string> existing_ids; + for (const auto& item : popup_items_) + existing_ids.insert(item.id); + + for (Notification* notification : + MessageCenter::Get()->GetPopupNotifications()) { + if (!existing_ids.count(notification->id())) + return true; + } + return false; +} + +bool MessagePopupCollection::HasRemovedPopup() const { + std::set<std::string> existing_ids; + for (Notification* notification : + MessageCenter::Get()->GetPopupNotifications()) { + existing_ids.insert(notification->id()); + } + + for (const auto& item : popup_items_) { + if (!existing_ids.count(item.id)) + return true; + } + return false; +} + +bool MessagePopupCollection::IsAnyPopupHovered() const { + for (const auto& item : popup_items_) { + if (item.popup->is_hovered()) + return true; + } + return false; +} + +bool MessagePopupCollection::IsAnyPopupActive() const { + for (const auto& item : popup_items_) { + if (item.popup->is_active()) + return true; + } + return false; } } // namespace message_center
diff --git a/ui/message_center/views/message_popup_collection.h b/ui/message_center/views/message_popup_collection.h index e018e3d..4d6faa82 100644 --- a/ui/message_center/views/message_popup_collection.h +++ b/ui/message_center/views/message_popup_collection.h
@@ -5,142 +5,206 @@ #ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_ #define UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_ -#include <stddef.h> - -#include <list> -#include <map> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/scoped_observer.h" -#include "base/timer/timer.h" +#include "ui/gfx/animation/animation_delegate.h" #include "ui/gfx/geometry/rect.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/message_center_observer.h" -#include "ui/message_center/views/toast_contents_view.h" -#include "ui/views/view_observer.h" -#include "ui/views/widget/widget_observer.h" -namespace display { -class Display; -} - -namespace views { -class Widget; -} +namespace gfx { +class LinearAnimation; +} // namespace gfx namespace message_center { -namespace test { -class MessagePopupCollectionTest; -} -class MessageCenter; -class MessageViewContextMenuController; +class MessagePopupView; +class Notification; class PopupAlignmentDelegate; -// Container for popup toasts. Because each toast is a frameless window rather -// than a view in a bubble, now the container just manages all of those toasts. -// This is similar to chrome/browser/notifications/balloon_collection, but the -// contents of each toast are for the message center and layout strategy would -// be slightly different. +// Container of notification popups usually shown at the right bottom of the +// screen. Manages animation state and updates these popup widgets. class MESSAGE_CENTER_EXPORT MessagePopupCollection : public MessageCenterObserver, - public views::ViewObserver { + public gfx::AnimationDelegate { public: - MessagePopupCollection(MessageCenter* message_center, - PopupAlignmentDelegate* alignment_delegate); + explicit MessagePopupCollection(PopupAlignmentDelegate* alignment_delegate); ~MessagePopupCollection() override; - // Overridden from views::ViewObserver: - void OnViewPreferredSizeChanged(views::View* observed_view) override; - void OnViewIsDeleting(views::View* observed_view) override; + // Update popups based on current |state_|. + void Update(); + // Close all popups. Called from UiController when Notification Center is + // opened. void MarkAllPopupsShown(); - // Inclement the timer counter, and pause the popup timer if necessary. - void PausePopupTimers(); - // Declement the timer counter, and restart the popup timer if necessary. - void RestartPopupTimers(); + // Reset all popup positions. Called from PopupAlignmentDelegate when + // alignment and work area might be changed. + void ResetBounds(); - // Since these events are really coming from individual toast widgets, - // it helps to be able to keep track of the sender. - void OnMouseEntered(ToastContentsView* toast_entered); - void OnMouseExited(ToastContentsView* toast_exited); + // Notify the popup size is changed. Called from MessagePopupView. + void NotifyPopupResized(); - // Runs the next step in update/animate sequence. - void DoUpdate(); - - // Removes the toast from our internal list of toasts; this is called when the - // toast is irrevocably closed (such as within RemoveToast). - void ForgetToast(ToastContentsView* toast); - - // Called when the display bounds has been changed. Used in Windows only. - void OnDisplayMetricsChanged(const display::Display& display); - - private: - friend class test::MessagePopupCollectionTest; - typedef std::list<ToastContentsView*> Toasts; - - // Iterates toasts and starts closing them. - std::set<std::string> CloseAllWidgets(); - - // Called by ToastContentsView when its window is closed. - void RemoveToast(ToastContentsView* toast, bool mark_as_shown); - - // Creates new widgets for new toast notifications, and updates |toasts_| and - // |widgets_| correctly. - void UpdateWidgets(); - - // Repositions all of the widgets based on the current work area. - void RepositionWidgets(); - - // The baseline is an (imaginary) line that would touch the bottom of the - // next created notification if bottom-aligned or its top if top-aligned. - int GetBaseline() const; - - // Returns the top of the toast when IsTopDown() is true, otherwise returns - // the bottom of the toast. - int GetBaselineForToast(ToastContentsView* toast) const; - - // Overridden from MessageCenterObserver: + // MessageCenterObserver: void OnNotificationAdded(const std::string& notification_id) override; void OnNotificationRemoved(const std::string& notification_id, bool by_user) override; void OnNotificationUpdated(const std::string& notification_id) override; - ToastContentsView* FindToast(const std::string& notification_id) const; + // AnimationDelegate: + void AnimationEnded(const gfx::Animation* animation) override; + void AnimationProgressed(const gfx::Animation* animation) override; + void AnimationCanceled(const gfx::Animation* animation) override; - // While the toasts are animated, avoid updating the collection, to reduce - // user confusion. Instead, update the collection when all animations are - // done. This method is run when defer counter is zero, may initiate next - // update/animation step. - void OnDeferTimerExpired(); + protected: + // TODO(tetsui): Merge PopupAlignmentDelegate into MessagePopupCollection and + // make subclasses e.g. DesktopMessagePopupCollection and + // AshMessagePopupCollection. - // "ForTest" methods. - views::Widget* GetWidgetForTest(const std::string& id) const; - gfx::Rect GetToastRectAt(size_t index) const; + // virtual for testing. + virtual MessagePopupView* CreatePopup(const Notification& notification); + virtual void RestartPopupTimers(); + virtual void PausePopupTimers(); + virtual bool IsPrimaryDisplayForNotification() const; - MessageCenter* message_center_; - Toasts toasts_; + gfx::LinearAnimation* animation() { return animation_.get(); } - PopupAlignmentDelegate* alignment_delegate_; + private: + // MessagePopupCollection always runs single animation at one time. + // State is an enum of which animation is running right now. + // If |state_| is IDLE, animation_->is_animating() is always false and vice + // versa. + enum class State { + // No animation is running. + IDLE, - // This is only used to compare with incoming events, do not assume that - // the toast will be valid if this pointer is non-NULL. - ToastContentsView* latest_toast_entered_ = nullptr; + // Fading in an added notification. + FADE_IN, - // This is the number of pause request for timer. If it's more than zero, the - // timer is paused. If zero, the timer is not paused. - int timer_pause_counter_ = 0; + // Fading out a removed notification. After the animation, if there are + // still remaining notifications, it will transition to MOVE_DOWN. + FADE_OUT, - std::unique_ptr<MessageViewContextMenuController> context_menu_controller_; + // Moving down notifications. Notification collapsing and resizing are also + // done in MOVE_DOWN. + MOVE_DOWN + }; - ScopedObserver<views::View, views::ViewObserver> observed_views_{this}; + // Stores animation related state of a popup. + struct PopupItem { + // Notification ID. + std::string id; - // Gives out weak pointers to toast contents views which have an unrelated - // lifetime. Must remain the last member variable. - base::WeakPtrFactory<MessagePopupCollection> weak_factory_{this}; + // The bounds that the popup starts animating from. + // If |is_animating| is false, it is ignored. Also the value is only used + // when the animation type is FADE_IN or MOVE_DOWN. + gfx::Rect start_bounds; + + // The final bounds of the popup. + gfx::Rect bounds; + + // If the popup is animating. + bool is_animating = false; + + // Unowned. + MessagePopupView* popup = nullptr; + }; + + // Transition from animation state (FADE_IN, FADE_OUT, and MOVE_DOWN) to + // IDLE state or next animation state (MOVE_DOWN). + void TransitionFromAnimation(); + + // Transition from IDLE state to animation state (FADE_IN, FADE_OUT or + // MOVE_DOWN). + void TransitionToAnimation(); + + // Pause or restart popup timers depending on |state_|. + void UpdatePopupTimers(); + + // Calculate |bounds| of all popups and moves old |bounds| to |start_bounds|. + void CalculateBounds(); + + // Update bounds and opacity of popups during animation. + void UpdateByAnimation(); + + // Add a new popup to |popup_items_| for FADE_IN animation. + // Return true if a popup is actually added. It may still return false when + // HasAddedPopup() return true by the lack of work area to show popup. + bool AddPopup(); + + // Mark |is_animating| flag of removed popup to true for FADE_OUT animation. + void MarkRemovedPopup(); + + // Mark |is_animating| flag of all popups for MOVE_DOWN animation. + void MoveDownPopups(); + + // Get the y-axis edge of the new popup. In usual bottom-to-top layout, it + // means the topmost y-axis when |item| is added. + int GetNextEdge(const PopupItem& item) const; + + // Returns true if the edge is outside work area. + bool IsNextEdgeOutsideWorkArea(const PopupItem& item) const; + + // Implements hot mode. The purpose of hot mode is to allow a user to + // continually close many notifications by mouse without moving it. Similar + // functionality is also implemented in browser tab strips. + void StartHotMode(); + void ResetHotMode(); + + void CloseAnimatingPopups(); + bool CloseTransparentPopups(); + void ClosePopupsOutsideWorkArea(); + void RemoveClosedPopupItems(); + + // Collapse all existing popups. Return true if size of any popup is actually + // changed. + bool CollapseAllPopups(); + + // Return true if there is a new popup to add. + bool HasAddedPopup() const; + // Return true is there is a old popup to remove. + bool HasRemovedPopup() const; + + // Return true if any popup is hovered by mouse. + bool IsAnyPopupHovered() const; + // Return true if any popup is activated. + bool IsAnyPopupActive() const; + + // Animation state. See the comment of State. + State state_ = State::IDLE; + + // Covers all animation performed by MessagePopupCollection. When the + // animation is running, it is always one of FADE_IN (sliding in and opacity + // change), FADE_OUT (opacity change), and MOVE_DOWN (sliding down). + // MessagePopupCollection does not use implicit animation. The position and + // opacity changes are explicitly set from UpdateByAnimation(). + const std::unique_ptr<gfx::LinearAnimation> animation_; + + // Notification popups. The first element is the oldest one. + std::vector<PopupItem> popup_items_; + + // Unowned. + PopupAlignmentDelegate* const alignment_delegate_; + + // True during Update() to avoid reentrancy. For example, popup size change + // might be notified during Update() because Update() changes popup sizes, but + // popup might change the size by itself e.g. expanding notification by mouse. + bool is_updating_ = false; + + // If true, popup sizes are resized on the next time Update() is called with + // IDLE state. + bool resize_requested_ = false; + + // Hot mode related variables. See StartHotMode() and ResetHotMode(). + + // True if the close button of the popup at |hot_index_| is hot. + bool is_hot_ = false; + + // An index in |popup_items_|. Only valid if |is_hot_| is true. + size_t hot_index_ = 0; + + // Fixed Y coordinate of the popup at |hot_index_|. While |is_hot_| is true, + // CalculateBounds() always lays out popups in a way the top of the popup at + // |hot_index_| is aligned to |hot_top_|. Only valid if |is_hot_| is true. + int hot_top_ = 0; DISALLOW_COPY_AND_ASSIGN(MessagePopupCollection); };
diff --git a/ui/message_center/views/message_popup_collection_unittest.cc b/ui/message_center/views/message_popup_collection_unittest.cc index feeaa1e8..ac05bfd 100644 --- a/ui/message_center/views/message_popup_collection_unittest.cc +++ b/ui/message_center/views/message_popup_collection_unittest.cc
@@ -4,49 +4,25 @@ #include "ui/message_center/views/message_popup_collection.h" -#include <stddef.h> - -#include <algorithm> -#include <list> -#include <memory> -#include <numeric> -#include <utility> - -#include "base/optional.h" -#include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" #include "ui/display/display.h" -#include "ui/events/event.h" -#include "ui/events/event_constants.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/image/image_unittest_util.h" -#include "ui/message_center/fake_message_center.h" +#include "ui/events/base_event_utils.h" +#include "ui/gfx/animation/linear_animation.h" +#include "ui/message_center/message_center.h" #include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/views/desktop_popup_alignment_delegate.h" -#include "ui/message_center/views/toast_contents_view.h" +#include "ui/message_center/views/message_popup_view.h" #include "ui/views/test/views_test_base.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" + +using message_center::MessageCenter; +using message_center::Notification; namespace message_center { namespace { -std::unique_ptr<Notification> CreateTestNotification(std::string id, - std::string text) { - return std::make_unique<Notification>( - NOTIFICATION_TYPE_BASE_FORMAT, id, base::UTF8ToUTF16("test title"), - base::ASCIIToUTF16(text), gfx::Image(), - base::string16() /* display_source */, GURL(), - NotifierId(NotifierId::APPLICATION, id), RichNotificationData(), - new NotificationDelegate()); -} +class MockMessagePopupView; // Provides an aura window context for widget creation. class TestPopupAlignmentDelegate : public DesktopPopupAlignmentDelegate { @@ -68,288 +44,671 @@ DISALLOW_COPY_AND_ASSIGN(TestPopupAlignmentDelegate); }; +class MockMessagePopupCollection : public MessagePopupCollection { + public: + explicit MockMessagePopupCollection( + PopupAlignmentDelegate* alignment_delegate) + : MessagePopupCollection(alignment_delegate), + alignment_delegate_(alignment_delegate) {} + + ~MockMessagePopupCollection() override = default; + + void SetAnimationValue(double current) { + animation()->SetCurrentValue(current); + if (current == 1.0) + animation()->End(); + else + AnimationProgressed(animation()); + } + + void RemovePopup(MockMessagePopupView* popup) { + popups_.erase(std::remove(popups_.begin(), popups_.end(), popup), + popups_.end()); + } + + bool IsAnimating() { return animation()->is_animating(); } + + void set_is_primary_display(bool is_primary_display) { + is_primary_display_ = is_primary_display; + } + + void set_new_popup_height(int new_popup_height) { + new_popup_height_ = new_popup_height; + } + + std::vector<MockMessagePopupView*>& popups() { return popups_; } + + bool popup_timer_started() const { return popup_timer_started_; } + + protected: + MessagePopupView* CreatePopup(const Notification& notification) override; + + void RestartPopupTimers() override { + MessagePopupCollection::RestartPopupTimers(); + popup_timer_started_ = true; + } + + void PausePopupTimers() override { + MessagePopupCollection::PausePopupTimers(); + popup_timer_started_ = false; + } + + bool IsPrimaryDisplayForNotification() const override { + return is_primary_display_; + } + + private: + PopupAlignmentDelegate* alignment_delegate_; + std::vector<MockMessagePopupView*> popups_; + + bool popup_timer_started_ = false; + bool is_primary_display_ = true; + int new_popup_height_ = 84; + + DISALLOW_COPY_AND_ASSIGN(MockMessagePopupCollection); +}; + +class MockMessagePopupView : public MessagePopupView { + public: + MockMessagePopupView(const std::string& id, + int init_height, + PopupAlignmentDelegate* alignment_delegate, + MockMessagePopupCollection* popup_collection) + : MessagePopupView(alignment_delegate, popup_collection), + popup_collection_(popup_collection), + id_(id) { + auto* view = new views::View; + view->SetPreferredSize(gfx::Size(kNotificationWidth, init_height)); + AddChildView(view); + } + + ~MockMessagePopupView() override = default; + + void Close() override { + popup_collection_->RemovePopup(this); + MessagePopupView::Close(); + } + + void UpdateContents(const Notification& notification) override { + updated_ = true; + } + + void AutoCollapse() override { + if (expandable_) + child_at(0)->SetPreferredSize(gfx::Size(kNotificationWidth, 42)); + } + + void SetPreferredHeight(int height) { + child_at(0)->SetPreferredSize(gfx::Size(kNotificationWidth, height)); + } + + void SetHovered(bool is_hovered) { + if (is_hovered) { + ui::MouseEvent enter_event(ui::ET_MOUSE_ENTERED, gfx::Point(), + gfx::Point(), ui::EventTimeForNow(), 0, 0); + OnMouseEntered(enter_event); + } else { + ui::MouseEvent exit_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), 0, 0); + OnMouseExited(exit_event); + } + } + + void Activate() { + set_can_activate(true); + GetWidget()->Activate(); + } + + const std::string& id() const { return id_; } + bool updated() const { return updated_; } + + void set_expandable(bool expandable) { expandable_ = expandable; } + + private: + MockMessagePopupCollection* const popup_collection_; + + std::string id_; + bool updated_ = false; + bool expandable_ = false; +}; + +MessagePopupView* MockMessagePopupCollection::CreatePopup( + const Notification& notification) { + auto* popup = new MockMessagePopupView(notification.id(), new_popup_height_, + alignment_delegate_, this); + popups_.push_back(popup); + return popup; +} + } // namespace -namespace test { - class MessagePopupCollectionTest : public views::ViewsTestBase, - public views::WidgetObserver { + public MessageCenterObserver { public: + MessagePopupCollectionTest() = default; + ~MessagePopupCollectionTest() override = default; + + // views::ViewTestBase: void SetUp() override { views::ViewsTestBase::SetUp(); MessageCenter::Initialize(); MessageCenter::Get()->DisableTimersForTest(); - alignment_delegate_.reset(new TestPopupAlignmentDelegate(GetContext())); - collection_.reset(new MessagePopupCollection(MessageCenter::Get(), - alignment_delegate_.get())); - // This size fits test machines resolution and also can keep a few toasts + MessageCenter::Get()->AddObserver(this); + + alignment_delegate_ = + std::make_unique<TestPopupAlignmentDelegate>(GetContext()); + popup_collection_ = + std::make_unique<MockMessagePopupCollection>(alignment_delegate_.get()); + + // This size fits test machines resolution and also can keep a few popups // w/o ill effects of hitting the screen overflow. This allows us to assume // and verify normal layout of the toast stack. SetDisplayInfo(gfx::Rect(0, 0, 1920, 1070), // taskbar at the bottom. gfx::Rect(0, 0, 1920, 1080)); - id_ = 0; } void TearDown() override { - collection_.reset(); + MessageCenter::Get()->RemoveAllNotifications( + false /* by_user */, MessageCenter::RemoveType::ALL); + AnimateUntilIdle(); + popup_collection_.reset(); + + MessageCenter::Get()->RemoveObserver(this); MessageCenter::Shutdown(); views::ViewsTestBase::TearDown(); } + // MessageCenterObserver: + void OnNotificationDisplayed(const std::string& notification_id, + const DisplaySource source) override { + last_displayed_id_ = notification_id; + } + protected: - MessagePopupCollection* collection() { return collection_.get(); } - - size_t GetToastCounts() { - return collection_->toasts_.size(); + std::unique_ptr<Notification> CreateNotification(const std::string& id) { + return std::make_unique<Notification>( + NOTIFICATION_TYPE_BASE_FORMAT, id, base::UTF8ToUTF16("test title"), + base::UTF8ToUTF16("test message"), gfx::Image(), + base::string16() /* display_source */, GURL(), NotifierId(), + RichNotificationData(), new NotificationDelegate()); } - bool MouseInCollection() { - return collection_->latest_toast_entered_ != NULL; + std::string AddNotification() { + std::string id = base::IntToString(id_++); + MessageCenter::Get()->AddNotification(CreateNotification(id)); + return id; } - bool IsToastShown(const std::string& id) { - views::Widget* widget = collection_->GetWidgetForTest(id); - return widget && widget->IsVisible(); + void Update() { popup_collection_->Update(); } + + void SetAnimationValue(double current) { + popup_collection_->SetAnimationValue(current); } - views::Widget* GetWidget(const std::string& id) { - return collection_->GetWidgetForTest(id); + bool IsAnimating() const { return popup_collection_->IsAnimating(); } + + void AnimateUntilIdle() { + while (popup_collection_->IsAnimating()) + popup_collection_->SetAnimationValue(1.0); } + void AnimateToMiddle() { popup_collection_->SetAnimationValue(0.5); } + + void AnimateToEnd() { popup_collection_->SetAnimationValue(1.0); } + + MockMessagePopupView* GetPopup(const std::string& id) { + for (auto* popup : popup_collection_->popups()) { + if (popup->id() == id) + return popup; + } + return nullptr; + } + + MockMessagePopupView* GetPopupAt(size_t index) { + return popup_collection_->popups()[index]; + } + + size_t GetPopupCounts() const { return popup_collection_->popups().size(); } + void SetDisplayInfo(const gfx::Rect& work_area, const gfx::Rect& display_bounds) { display::Display dummy_display; dummy_display.set_bounds(display_bounds); dummy_display.set_work_area(work_area); + work_area_ = work_area; alignment_delegate_->RecomputeAlignment(dummy_display); } - gfx::Rect GetWorkArea() { - return alignment_delegate_->work_area_; + bool IsPopupTimerStarted() const { + return popup_collection_->popup_timer_started(); } - ToastContentsView* GetToast(const std::string& id) { - for (MessagePopupCollection::Toasts::iterator iter = - collection_->toasts_.begin(); - iter != collection_->toasts_.end(); ++iter) { - if ((*iter)->id() == id) - return *iter; - } - return NULL; + MockMessagePopupCollection* popup_collection() const { + return popup_collection_.get(); } + const gfx::Rect& work_area() const { return work_area_; } - std::string AddNotification() { - std::string id = base::IntToString(id_++); - std::unique_ptr<Notification> notification = std::make_unique<Notification>( - NOTIFICATION_TYPE_BASE_FORMAT, id, base::UTF8ToUTF16("test title"), - base::UTF8ToUTF16("test message"), gfx::Image(), - base::string16() /* display_source */, GURL(), NotifierId(), - RichNotificationData(), new NotificationDelegate()); - MessageCenter::Get()->AddNotification(std::move(notification)); - return id; - } - - std::string AddImageNotification() { - std::string id = base::IntToString(id_++); - std::unique_ptr<Notification> notification = std::make_unique<Notification>( - NOTIFICATION_TYPE_IMAGE, id, base::UTF8ToUTF16("test title"), - base::UTF8ToUTF16("test message"), gfx::Image(), - base::string16() /* display_source */, GURL(), NotifierId(), - RichNotificationData(), new NotificationDelegate()); - notification->set_image(gfx::test::CreateImage(100, 100)); - MessageCenter::Get()->AddNotification(std::move(notification)); - return id; - } - - void CloseAllToasts() { - // Assumes there is at least one toast to close. - EXPECT_TRUE(GetToastCounts() > 0); - - auto toasts = collection_->toasts_; - for (ToastContentsView* toast : toasts) { - toast->GetWidget()->CloseNow(); - } - } - - gfx::Rect GetToastRectAt(size_t index) { - return collection_->GetToastRectAt(index); - } - - void RemoveToastAndWaitForClose(const std::string& id) { - GetWidget(id)->AddObserver(this); - MessageCenter::Get()->RemoveNotification(id, true /* by_user */); - widget_close_run_loop_.Run(); - } - - // views::WidgetObserver - void OnWidgetDestroyed(views::Widget* widget) override { - widget_close_run_loop_.Quit(); - } - - // Checks: - // 1) sizes of toast and corresponding widget are equal; - // 2) widgets do not owerlap; - // 3) after animation is done, aligment is propper; - class CheckedAnimationDelegate : public gfx::AnimationDelegate { - public: - explicit CheckedAnimationDelegate(MessagePopupCollectionTest* test); - ~CheckedAnimationDelegate() override; - - // returns first encountered error - const base::Optional<std::string>& error_msg() const { return error_msg_; } - - // gfx::AnimationDelegate overrides - void AnimationEnded(const gfx::Animation* animation) override; - void AnimationProgressed(const gfx::Animation* animation) override; - void AnimationCanceled(const gfx::Animation* animation) override; - - private: - // we attach ourselves to the last toast, because we accept - // invalidation of invariants during intermidiate - // notification updates. - ToastContentsView& animation_delegate() { return *toasts_->back(); } - const ToastContentsView& animation_delegate() const { - return *toasts_->back(); - } - - void CheckWidgetLEView(const std::string& calling_func); - void CheckToastsAreAligned(const std::string& calling_func); - void CheckToastsDontOverlap(const std::string& calling_func); - - static int ComputeYDistance(const ToastContentsView& top, - const ToastContentsView& bottom); - - MessagePopupCollection::Toasts* toasts_; - - // first encountered error - base::Optional<std::string> error_msg_; - - DISALLOW_COPY_AND_ASSIGN(CheckedAnimationDelegate); - }; - - static std::string YPositionsToString( - const MessagePopupCollection::Toasts& toasts); + const std::string& last_displayed_id() const { return last_displayed_id_; } private: - base::RunLoop widget_close_run_loop_; - std::unique_ptr<MessagePopupCollection> collection_; + int id_ = 0; + + std::unique_ptr<MockMessagePopupCollection> popup_collection_; std::unique_ptr<DesktopPopupAlignmentDelegate> alignment_delegate_; - int id_; + + gfx::Rect work_area_; + std::string last_displayed_id_; + + DISALLOW_COPY_AND_ASSIGN(MessagePopupCollectionTest); }; -MessagePopupCollectionTest::CheckedAnimationDelegate::CheckedAnimationDelegate( - MessagePopupCollectionTest* test) - : toasts_(&test->collection_->toasts_) { - DCHECK(!toasts_->empty()); - animation_delegate().bounds_animation_->set_delegate(this); +TEST_F(MessagePopupCollectionTest, Nothing) { + EXPECT_FALSE(IsAnimating()); + Update(); + // If no popups are available, nothing changes. + EXPECT_FALSE(IsAnimating()); } -MessagePopupCollectionTest::CheckedAnimationDelegate:: - ~CheckedAnimationDelegate() { - animation_delegate().bounds_animation_->set_delegate(&animation_delegate()); +TEST_F(MessagePopupCollectionTest, FadeInFadeOutNotification) { + // Add a notification. + std::string id = AddNotification(); + EXPECT_TRUE(IsAnimating()); + EXPECT_EQ(1u, GetPopupCounts()); + + // The popup will fade in from right. + const int before_x = GetPopup(id)->GetBoundsInScreen().x(); + EXPECT_EQ(0.0f, GetPopup(id)->GetOpacity()); + + AnimateToMiddle(); + EXPECT_GT(before_x, GetPopup(id)->GetBoundsInScreen().x()); + EXPECT_LT(0.0f, GetPopup(id)->GetOpacity()); + + AnimateToEnd(); + EXPECT_EQ(1.0f, GetPopup(id)->GetOpacity()); + EXPECT_FALSE(IsAnimating()); + EXPECT_TRUE(work_area().Contains(GetPopup(id)->GetBoundsInScreen())); + EXPECT_EQ(id, last_displayed_id()); + + // The popup will fade out because of timeout. + MessageCenter::Get()->MarkSinglePopupAsShown(id, false); + EXPECT_TRUE(IsAnimating()); + + AnimateToMiddle(); + EXPECT_GT(1.0f, GetPopup(id)->GetOpacity()); + + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + EXPECT_FALSE(GetPopup(id)); } -void MessagePopupCollectionTest::CheckedAnimationDelegate::AnimationEnded( - const gfx::Animation* animation) { - animation_delegate().AnimationEnded(animation); - CheckWidgetLEView("AnimationEnded"); - CheckToastsAreAligned("AnimationEnded"); -} +TEST_F(MessagePopupCollectionTest, FadeInMultipleNotifications) { + std::vector<std::string> ids; + for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i) + ids.push_back(AddNotification()); -void MessagePopupCollectionTest::CheckedAnimationDelegate::AnimationProgressed( - const gfx::Animation* animation) { - animation_delegate().AnimationProgressed(animation); - CheckWidgetLEView("AnimationProgressed"); - CheckToastsDontOverlap("AnimationProgressed"); -} - -void MessagePopupCollectionTest::CheckedAnimationDelegate::AnimationCanceled( - const gfx::Animation* animation) { - animation_delegate().AnimationCanceled(animation); - CheckWidgetLEView("AnimationCanceled"); - CheckToastsDontOverlap("AnimationCanceled"); -} - -void MessagePopupCollectionTest::CheckedAnimationDelegate::CheckWidgetLEView( - const std::string& calling_func) { - if (error_msg_) - return; - for (ToastContentsView* toast : *toasts_) { - auto* widget = toast->GetWidget(); - DCHECK(widget) << "no widget for: " << toast->id(); - if (toast->bounds().height() < widget->GetWindowBoundsInScreen().height()) { - error_msg_ = calling_func + " CheckWidgetSizeLEView: id: " + toast->id() + - "\ntoast size: " + toast->bounds().size().ToString() + - "\nwidget size: " + - widget->GetWindowBoundsInScreen().size().ToString(); - return; - } + for (size_t i = 0; i < ids.size(); ++i) { + EXPECT_EQ(ids[i], last_displayed_id()); + EXPECT_EQ(i + 1, GetPopupCounts()); + AnimateToMiddle(); + EXPECT_LT(0.0f, GetPopupAt(i)->GetOpacity()); + AnimateToEnd(); + EXPECT_EQ(1.0f, GetPopupAt(i)->GetOpacity()); + EXPECT_TRUE(work_area().Contains(GetPopupAt(i)->GetBoundsInScreen())); } -}; + EXPECT_FALSE(IsAnimating()); -void MessagePopupCollectionTest::CheckedAnimationDelegate:: - CheckToastsAreAligned(const std::string& calling_func) { - if (error_msg_) - return; - auto poorly_aligned = std::adjacent_find( - toasts_->begin(), toasts_->end(), - [](ToastContentsView* top, ToastContentsView* bottom) { - return ComputeYDistance(*top, *bottom) != kMarginBetweenPopups; - }); - if (poorly_aligned != toasts_->end()) - error_msg_ = calling_func + " CheckToastsAreAligned: distance between: " + - (*poorly_aligned)->id() + ' ' + - (*std::next(poorly_aligned))->id() + ": " + - std::to_string(ComputeYDistance(**poorly_aligned, - **std::next(poorly_aligned))) + - " expected: " + std::to_string(kMarginBetweenPopups) + - "\nLayout:\n" + YPositionsToString(*toasts_); + EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); + + for (size_t i = 0; i < ids.size(); ++i) + EXPECT_EQ(ids[i], GetPopupAt(i)->id()); + + for (size_t i = 0; i < ids.size() - 1; ++i) { + EXPECT_GT(GetPopupAt(i)->GetBoundsInScreen().x(), + GetPopupAt(i + 1)->GetBoundsInScreen().bottom()); + } } -void MessagePopupCollectionTest::CheckedAnimationDelegate:: - CheckToastsDontOverlap(const std::string& calling_func) { - if (error_msg_) - return; - auto poorly_aligned = std::adjacent_find( - toasts_->begin(), toasts_->end(), - [](ToastContentsView* top, ToastContentsView* bottom) { - return ComputeYDistance(*top, *bottom) < 0; - }); - if (poorly_aligned != toasts_->end()) - error_msg_ = calling_func + " CheckToastsDontOverlap: distance between: " + - (*poorly_aligned)->id() + ' ' + - (*std::next(poorly_aligned))->id() + ": " + - std::to_string(ComputeYDistance(**poorly_aligned, - **std::next(poorly_aligned))) + - "\nLayout:\n" + YPositionsToString(*toasts_); +TEST_F(MessagePopupCollectionTest, UpdateContents) { + std::string id = AddNotification(); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + EXPECT_EQ(1u, GetPopupCounts()); + EXPECT_FALSE(GetPopup(id)->updated()); + + auto updated_notification = CreateNotification(id); + updated_notification->set_message(base::ASCIIToUTF16("updated")); + MessageCenter::Get()->UpdateNotification(id, std::move(updated_notification)); + EXPECT_EQ(1u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id)->updated()); } -// static -std::string MessagePopupCollectionTest::YPositionsToString( - const MessagePopupCollection::Toasts& toasts) { - return std::accumulate(toasts.begin(), toasts.end(), std::string(), - [](std::string res, const ToastContentsView* toast) { - const auto& bounds = - toast->GetWidget()->GetWindowBoundsInScreen(); - res += toast->id(); - res += ' '; - res += std::to_string(bounds.y()); - res += ", "; - res += std::to_string(bounds.y() + bounds.height()); - res += '\n'; - return res; - }); +TEST_F(MessagePopupCollectionTest, MarkAllPopupsShown) { + for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i) + AddNotification(); + AnimateUntilIdle(); + + EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); + + popup_collection()->MarkAllPopupsShown(); + + EXPECT_EQ(0u, GetPopupCounts()); + EXPECT_EQ(0u, MessageCenter::Get()->GetPopupNotifications().size()); } -// static -int MessagePopupCollectionTest::CheckedAnimationDelegate::ComputeYDistance( - const ToastContentsView& top, - const ToastContentsView& bottom) { - const auto* top_widget = top.GetWidget(); - const auto* bottom_widget = bottom.GetWidget(); - const auto& top_bounds = top_widget->GetWindowBoundsInScreen(); - const auto& bottom_bounds = bottom_widget->GetWindowBoundsInScreen(); - return bottom_bounds.y() - (top_bounds.y() + top_bounds.height()); +TEST_F(MessagePopupCollectionTest, ShowCustomOnPrimaryDisplay) { + // TODO(yoshiki): Support custom popup notification on multiple display + // (crbug.com/715370). + popup_collection()->set_is_primary_display(true); + auto custom = CreateNotification("id"); + custom->set_type(NOTIFICATION_TYPE_CUSTOM); + MessageCenter::Get()->AddNotification(std::move(custom)); + EXPECT_TRUE(IsAnimating()); + EXPECT_EQ(1u, GetPopupCounts()); +} + +TEST_F(MessagePopupCollectionTest, NotShowCustomOnSubDisplay) { + // Disables popup of custom notification on non-primary displays, since + // currently custom notification supports only on one display at the same + // time. + // TODO(yoshiki): Support custom popup notification on multiple display + // (crbug.com/715370). + + popup_collection()->set_is_primary_display(false); + auto custom = CreateNotification("id"); + custom->set_type(NOTIFICATION_TYPE_CUSTOM); + MessageCenter::Get()->AddNotification(std::move(custom)); + EXPECT_FALSE(IsAnimating()); + EXPECT_EQ(0u, GetPopupCounts()); +} + +TEST_F(MessagePopupCollectionTest, NotificationsMoveDown) { + std::vector<std::string> ids; + for (size_t i = 0; i < kMaxVisiblePopupNotifications + 1; ++i) + ids.push_back(AddNotification()); + + AnimateUntilIdle(); + + EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); + EXPECT_FALSE(IsAnimating()); + + gfx::Rect dismissed = GetPopup(ids.front())->GetBoundsInScreen(); + + MessageCenter::Get()->MarkSinglePopupAsShown(ids.front(), false); + EXPECT_TRUE(IsAnimating()); + + AnimateToMiddle(); + EXPECT_GT(1.0f, GetPopup(ids[0])->GetOpacity()); + EXPECT_EQ(ids[0], GetPopup(ids[0])->id()); + + AnimateToEnd(); + EXPECT_EQ(ids[1], GetPopup(ids[1])->id()); + EXPECT_TRUE(IsAnimating()); + + gfx::Rect before = GetPopup(ids[1])->GetBoundsInScreen(); + + AnimateToMiddle(); + gfx::Rect moving = GetPopup(ids[1])->GetBoundsInScreen(); + EXPECT_GT(moving.bottom(), before.bottom()); + EXPECT_GT(dismissed.bottom(), moving.bottom()); + + AnimateToEnd(); + gfx::Rect after = GetPopup(ids[1])->GetBoundsInScreen(); + EXPECT_EQ(dismissed, after); + EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); + EXPECT_TRUE(IsAnimating()); + + EXPECT_EQ(0.f, GetPopup(ids.back())->GetOpacity()); + + AnimateToMiddle(); + EXPECT_LT(0.0f, GetPopup(ids.back())->GetOpacity()); + + AnimateToEnd(); + EXPECT_EQ(1.0f, GetPopup(ids.back())->GetOpacity()); + EXPECT_FALSE(IsAnimating()); +} + +TEST_F(MessagePopupCollectionTest, PopupResized) { + std::vector<std::string> ids; + for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i) + ids.push_back(AddNotification()); + AnimateUntilIdle(); + + std::vector<gfx::Rect> previous_bounds; + for (const auto& id : ids) + previous_bounds.push_back(GetPopup(id)->GetBoundsInScreen()); + + const int changed_height = 256; + GetPopup(ids[1])->SetPreferredHeight(changed_height); + + EXPECT_TRUE(IsAnimating()); + + AnimateToMiddle(); + EXPECT_EQ(previous_bounds[0], GetPopup(ids[0])->GetBoundsInScreen()); + EXPECT_EQ(previous_bounds[1].bottom(), + GetPopup(ids[1])->GetBoundsInScreen().bottom()); + EXPECT_GT(previous_bounds[1].y(), GetPopup(ids[1])->GetBoundsInScreen().y()); + EXPECT_GT(previous_bounds[2].bottom(), + GetPopup(ids[2])->GetBoundsInScreen().bottom()); + EXPECT_GT(previous_bounds[2].y(), GetPopup(ids[2])->GetBoundsInScreen().y()); + + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + EXPECT_EQ(previous_bounds[0], GetPopup(ids[0])->GetBoundsInScreen()); + EXPECT_EQ(changed_height, GetPopup(ids[1])->GetBoundsInScreen().height()); +} + +TEST_F(MessagePopupCollectionTest, ExpandLatest) { + std::string id = AddNotification(); + AnimateToEnd(); + GetPopup(id)->set_expandable(true); + const int top_y = GetPopup(id)->GetBoundsInScreen().y(); + + AddNotification(); + EXPECT_TRUE(IsAnimating()); + EXPECT_EQ(1u, GetPopupCounts()); + AnimateToMiddle(); + EXPECT_LT(top_y, GetPopup(id)->GetBoundsInScreen().y()); + AnimateToEnd(); + EXPECT_LT(top_y, GetPopup(id)->GetBoundsInScreen().y()); + + EXPECT_TRUE(IsAnimating()); + EXPECT_EQ(2u, GetPopupCounts()); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); +} + +TEST_F(MessagePopupCollectionTest, ExpandLatestWithMoveDown) { + std::vector<std::string> ids; + for (size_t i = 0; i < kMaxVisiblePopupNotifications + 1; ++i) + ids.push_back(AddNotification()); + + AnimateUntilIdle(); + EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); + + GetPopup(ids[1])->set_expandable(true); + + const int top_y = GetPopup(ids[1])->GetBoundsInScreen().y(); + + MessageCenter::Get()->MarkSinglePopupAsShown(ids.front(), false); + AnimateToEnd(); + EXPECT_TRUE(IsAnimating()); + EXPECT_EQ(kMaxVisiblePopupNotifications - 1, GetPopupCounts()); + + AnimateToMiddle(); + EXPECT_LT(top_y, GetPopup(ids[2])->GetBoundsInScreen().y()); + AnimateToEnd(); + EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts()); + EXPECT_TRUE(IsAnimating()); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); +} + +TEST_F(MessagePopupCollectionTest, HoverClose) { + std::string id0 = AddNotification(); + AnimateToEnd(); + popup_collection()->set_new_popup_height(256); + std::string id1 = AddNotification(); + AnimateToEnd(); + popup_collection()->set_new_popup_height(84); + std::string id2 = AddNotification(); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + + EXPECT_TRUE(IsPopupTimerStarted()); + GetPopup(id0)->SetHovered(true); + EXPECT_FALSE(IsPopupTimerStarted()); + + const int first_popup_top = GetPopup(id0)->GetBoundsInScreen().y(); + + MessageCenter::Get()->RemoveNotification(id0, true); + EXPECT_TRUE(IsAnimating()); + AnimateToEnd(); + EXPECT_TRUE(IsAnimating()); + AnimateToMiddle(); + GetPopup(id1)->SetHovered(true); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + EXPECT_EQ(first_popup_top, GetPopup(id1)->GetBoundsInScreen().y()); + + EXPECT_FALSE(IsPopupTimerStarted()); + GetPopup(id1)->SetHovered(false); + EXPECT_TRUE(IsAnimating()); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + EXPECT_TRUE(IsPopupTimerStarted()); + EXPECT_GT(first_popup_top, GetPopup(id1)->GetBoundsInScreen().y()); +} + +TEST_F(MessagePopupCollectionTest, ActivatedClose) { + std::string id0 = AddNotification(); + AnimateToEnd(); + popup_collection()->set_new_popup_height(256); + std::string id1 = AddNotification(); + AnimateToEnd(); + popup_collection()->set_new_popup_height(84); + std::string id2 = AddNotification(); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + + EXPECT_TRUE(IsPopupTimerStarted()); + GetPopup(id0)->Activate(); + EXPECT_FALSE(IsPopupTimerStarted()); + + const int first_popup_top = GetPopup(id0)->GetBoundsInScreen().y(); + + MessageCenter::Get()->RemoveNotification(id0, true); + AnimateToEnd(); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + EXPECT_GT(first_popup_top, GetPopup(id1)->GetBoundsInScreen().y()); + EXPECT_TRUE(IsPopupTimerStarted()); +} + +TEST_F(MessagePopupCollectionTest, SlideOutClose) { + std::vector<std::string> ids; + for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i) + ids.push_back(AddNotification()); + + AnimateUntilIdle(); + + GetPopup(ids[1])->SetOpacity(0); + MessageCenter::Get()->RemoveNotification(ids[1], true); + AnimateToEnd(); + + EXPECT_FALSE(IsAnimating()); + EXPECT_TRUE(IsPopupTimerStarted()); +} + +TEST_F(MessagePopupCollectionTest, TooTallNotification) { + SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom. + gfx::Rect(0, 0, 800, 480)); + + std::string id0 = AddNotification(); + std::string id1 = AddNotification(); + + AnimateUntilIdle(); + + EXPECT_EQ(2u, GetPopupCounts()); + + popup_collection()->set_new_popup_height(400); + std::string id2 = AddNotification(); + + EXPECT_FALSE(IsAnimating()); + EXPECT_EQ(2u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id0)); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_FALSE(GetPopup(id2)); + + MessageCenter::Get()->MarkSinglePopupAsShown(id0, false); + AnimateUntilIdle(); + EXPECT_EQ(1u, GetPopupCounts()); + EXPECT_FALSE(GetPopup(id2)); + + MessageCenter::Get()->MarkSinglePopupAsShown(id1, false); + AnimateUntilIdle(); + EXPECT_EQ(1u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id2)); +} + +TEST_F(MessagePopupCollectionTest, DisplaySizeChanged) { + std::string id0 = AddNotification(); + AnimateToEnd(); + std::string id1 = AddNotification(); + AnimateToEnd(); + popup_collection()->set_new_popup_height(400); + std::string id2 = AddNotification(); + AnimateToEnd(); + EXPECT_FALSE(IsAnimating()); + + EXPECT_TRUE(GetPopup(id0)); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_TRUE(GetPopup(id2)); + + SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom. + gfx::Rect(0, 0, 800, 480)); + popup_collection()->ResetBounds(); + + EXPECT_TRUE(GetPopup(id0)); + EXPECT_TRUE(work_area().Contains(GetPopup(id0)->GetBoundsInScreen())); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_TRUE(work_area().Contains(GetPopup(id1)->GetBoundsInScreen())); + EXPECT_FALSE(GetPopup(id2)); + + MessageCenter::Get()->MarkSinglePopupAsShown(id0, false); + MessageCenter::Get()->MarkSinglePopupAsShown(id1, false); + AnimateUntilIdle(); + EXPECT_EQ(1u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id2)); +} + +TEST_F(MessagePopupCollectionTest, PopupResizedAndOverflown) { + SetDisplayInfo(gfx::Rect(0, 0, 800, 470), // taskbar at the bottom. + gfx::Rect(0, 0, 800, 480)); + + std::string id0 = AddNotification(); + std::string id1 = AddNotification(); + std::string id2 = AddNotification(); + AnimateUntilIdle(); + + EXPECT_TRUE(GetPopup(id0)); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_TRUE(GetPopup(id2)); + + const int changed_height = 300; + GetPopup(id1)->SetPreferredHeight(changed_height); + + AnimateUntilIdle(); + + EXPECT_TRUE(GetPopup(id0)); + EXPECT_TRUE(work_area().Contains(GetPopup(id0)->GetBoundsInScreen())); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_TRUE(work_area().Contains(GetPopup(id1)->GetBoundsInScreen())); + EXPECT_FALSE(GetPopup(id2)); + + MessageCenter::Get()->MarkSinglePopupAsShown(id0, false); + AnimateUntilIdle(); + EXPECT_EQ(2u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id2)); } TEST_F(MessagePopupCollectionTest, DismissOnClick) { @@ -357,26 +716,26 @@ std::string id1 = AddNotification(); std::string id2 = AddNotification(); - views::Widget* widget1 = GetWidget(id1); - views::Widget* widget2 = GetWidget(id2); - EXPECT_EQ(2u, GetToastCounts()); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_TRUE(IsToastShown(id2)); + AnimateUntilIdle(); + + EXPECT_EQ(2u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_TRUE(GetPopup(id2)); MessageCenter::Get()->ClickOnNotification(id2); + AnimateUntilIdle(); - EXPECT_EQ(1u, GetToastCounts()); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_FALSE(IsToastShown(id2)); + EXPECT_EQ(1u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_FALSE(GetPopup(id2)); MessageCenter::Get()->ClickOnNotificationButton(id1, 0); - EXPECT_EQ(0u, GetToastCounts()); - EXPECT_FALSE(IsToastShown(id1)); - EXPECT_FALSE(IsToastShown(id2)); + AnimateUntilIdle(); - widget1->CloseNow(); - widget2->CloseNow(); + EXPECT_EQ(0u, GetPopupCounts()); + EXPECT_FALSE(GetPopup(id1)); + EXPECT_FALSE(GetPopup(id2)); } TEST_F(MessagePopupCollectionTest, NotDismissedOnClick) { @@ -385,40 +744,25 @@ std::string id1 = AddNotification(); std::string id2 = AddNotification(); - EXPECT_EQ(2u, GetToastCounts()); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_TRUE(IsToastShown(id2)); + AnimateUntilIdle(); + + EXPECT_EQ(2u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_TRUE(GetPopup(id2)); MessageCenter::Get()->ClickOnNotification(id2); - collection()->DoUpdate(); + AnimateUntilIdle(); - EXPECT_EQ(2u, GetToastCounts()); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_TRUE(IsToastShown(id2)); + EXPECT_EQ(2u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_TRUE(GetPopup(id2)); MessageCenter::Get()->ClickOnNotificationButton(id1, 0); - collection()->DoUpdate(); - EXPECT_EQ(2u, GetToastCounts()); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_TRUE(IsToastShown(id2)); + AnimateUntilIdle(); - GetWidget(id1)->CloseNow(); - GetWidget(id2)->CloseNow(); -} - -TEST_F(MessagePopupCollectionTest, ShutdownDuringShowing) { - std::string id1 = AddNotification(); - std::string id2 = AddNotification(); - EXPECT_EQ(2u, GetToastCounts()); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_TRUE(IsToastShown(id2)); - - // Finish without cleanup of notifications, which may cause use-after-free. - // See crbug.com/236448 - GetWidget(id1)->CloseNow(); - collection()->OnMouseExited(GetToast(id2)); - - GetWidget(id2)->CloseNow(); + EXPECT_EQ(2u, GetPopupCounts()); + EXPECT_TRUE(GetPopup(id1)); + EXPECT_TRUE(GetPopup(id2)); } TEST_F(MessagePopupCollectionTest, DefaultPositioning) { @@ -427,16 +771,16 @@ std::string id2 = AddNotification(); std::string id3 = AddNotification(); - gfx::Rect r0 = GetToastRectAt(0); - gfx::Rect r1 = GetToastRectAt(1); - gfx::Rect r2 = GetToastRectAt(2); - gfx::Rect r3 = GetToastRectAt(3); + AnimateUntilIdle(); + + gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); + gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); + gfx::Rect r2 = GetPopup(id2)->GetBoundsInScreen(); + + // The 4th toast is not shown yet. + EXPECT_FALSE(GetPopup(id3)); // 3 toasts are shown, equal size, vertical stack. - EXPECT_TRUE(IsToastShown(id0)); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_TRUE(IsToastShown(id2)); - EXPECT_EQ(r0.width(), r1.width()); EXPECT_EQ(r1.width(), r2.width()); @@ -448,14 +792,6 @@ EXPECT_EQ(r0.x(), r1.x()); EXPECT_EQ(r1.x(), r2.x()); - - // The 4th toast is not shown yet. - EXPECT_FALSE(IsToastShown(id3)); - EXPECT_EQ(0, r3.width()); - EXPECT_EQ(0, r3.height()); - - CloseAllToasts(); - EXPECT_EQ(0u, GetToastCounts()); } TEST_F(MessagePopupCollectionTest, DefaultPositioningWithRightTaskbar) { @@ -467,20 +803,16 @@ std::string id0 = AddNotification(); std::string id1 = AddNotification(); - gfx::Rect r0 = GetToastRectAt(0); - gfx::Rect r1 = GetToastRectAt(1); + AnimateUntilIdle(); + + gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); + gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); // 2 toasts are shown, equal size, vertical stack. - EXPECT_TRUE(IsToastShown(id0)); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_EQ(r0.width(), r1.width()); EXPECT_EQ(r0.height(), r1.height()); EXPECT_GT(r0.y(), r1.y()); EXPECT_EQ(r0.x(), r1.x()); - - CloseAllToasts(); - EXPECT_EQ(0u, GetToastCounts()); } TEST_F(MessagePopupCollectionTest, TopDownPositioningWithTopTaskbar) { @@ -490,20 +822,16 @@ std::string id0 = AddNotification(); std::string id1 = AddNotification(); - gfx::Rect r0 = GetToastRectAt(0); - gfx::Rect r1 = GetToastRectAt(1); + AnimateUntilIdle(); + + gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); + gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); // 2 toasts are shown, equal size, vertical stack. - EXPECT_TRUE(IsToastShown(id0)); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_EQ(r0.width(), r1.width()); EXPECT_EQ(r0.height(), r1.height()); EXPECT_LT(r0.y(), r1.y()); EXPECT_EQ(r0.x(), r1.x()); - - CloseAllToasts(); - EXPECT_EQ(0u, GetToastCounts()); } TEST_F(MessagePopupCollectionTest, TopDownPositioningWithLeftAndTopTaskbar) { @@ -516,20 +844,16 @@ std::string id0 = AddNotification(); std::string id1 = AddNotification(); - gfx::Rect r0 = GetToastRectAt(0); - gfx::Rect r1 = GetToastRectAt(1); + AnimateUntilIdle(); + + gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); + gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); // 2 toasts are shown, equal size, vertical stack. - EXPECT_TRUE(IsToastShown(id0)); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_EQ(r0.width(), r1.width()); EXPECT_EQ(r0.height(), r1.height()); EXPECT_LT(r0.y(), r1.y()); EXPECT_EQ(r0.x(), r1.x()); - - CloseAllToasts(); - EXPECT_EQ(0u, GetToastCounts()); } TEST_F(MessagePopupCollectionTest, TopDownPositioningWithBottomAndTopTaskbar) { @@ -542,20 +866,16 @@ std::string id0 = AddNotification(); std::string id1 = AddNotification(); - gfx::Rect r0 = GetToastRectAt(0); - gfx::Rect r1 = GetToastRectAt(1); + AnimateUntilIdle(); + + gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); + gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); // 2 toasts are shown, equal size, vertical stack. - EXPECT_TRUE(IsToastShown(id0)); - EXPECT_TRUE(IsToastShown(id1)); - EXPECT_EQ(r0.width(), r1.width()); EXPECT_EQ(r0.height(), r1.height()); EXPECT_LT(r0.y(), r1.y()); EXPECT_EQ(r0.x(), r1.x()); - - CloseAllToasts(); - EXPECT_EQ(0u, GetToastCounts()); } TEST_F(MessagePopupCollectionTest, LeftPositioningWithLeftTaskbar) { @@ -565,12 +885,10 @@ std::string id0 = AddNotification(); std::string id1 = AddNotification(); - gfx::Rect r0 = GetToastRectAt(0); - gfx::Rect r1 = GetToastRectAt(1); + AnimateUntilIdle(); - // 2 toasts are shown, equal size, vertical stack. - EXPECT_TRUE(IsToastShown(id0)); - EXPECT_TRUE(IsToastShown(id1)); + gfx::Rect r0 = GetPopup(id0)->GetBoundsInScreen(); + gfx::Rect r1 = GetPopup(id1)->GetBoundsInScreen(); EXPECT_EQ(r0.width(), r1.width()); EXPECT_EQ(r0.height(), r1.height()); @@ -578,199 +896,9 @@ EXPECT_EQ(r0.x(), r1.x()); // Ensure that toasts are on the left. - EXPECT_LT(r1.x(), GetWorkArea().CenterPoint().x()); - - CloseAllToasts(); - EXPECT_EQ(0u, GetToastCounts()); + EXPECT_LT(r1.x(), work_area().CenterPoint().x()); + EXPECT_TRUE(work_area().Contains(r0)); + EXPECT_TRUE(work_area().Contains(r1)); } -// Regression test for https://crbug.com/679397 -TEST_F(MessagePopupCollectionTest, MultipleNotificationHeight) { - std::string id0 = AddNotification(); - std::string id1 = AddImageNotification(); - EXPECT_EQ(2u, GetToastCounts()); - - gfx::Rect r0 = GetToast(id0)->bounds(); - - RemoveToastAndWaitForClose(id0); - EXPECT_EQ(1u, GetToastCounts()); - - gfx::Rect r1 = GetToast(id1)->bounds(); - - // The heights should be different as one is an image notification while - // another is a basic notification, but the bottom positions after the - // animation should be same even though the heights are different. - EXPECT_NE(r0.height(), r1.height()); - EXPECT_EQ(r0.bottom(), r1.bottom()); - - CloseAllToasts(); - EXPECT_EQ(0u, GetToastCounts()); -} - -TEST_F(MessagePopupCollectionTest, DetectMouseHover) { - std::string id0 = AddNotification(); - std::string id1 = AddNotification(); - - views::WidgetDelegateView* toast0 = GetToast(id0); - EXPECT_TRUE(toast0 != NULL); - views::WidgetDelegateView* toast1 = GetToast(id1); - EXPECT_TRUE(toast1 != NULL); - - ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - - // Test that mouse detection logic works in presence of out-of-order events. - toast0->OnMouseEntered(event); - EXPECT_TRUE(MouseInCollection()); - toast1->OnMouseEntered(event); - EXPECT_TRUE(MouseInCollection()); - toast0->OnMouseExited(event); - EXPECT_TRUE(MouseInCollection()); - toast1->OnMouseExited(event); - EXPECT_FALSE(MouseInCollection()); - - // Test that mouse detection logic works in presence of WindowClosing events. - toast0->OnMouseEntered(event); - EXPECT_TRUE(MouseInCollection()); - toast1->OnMouseEntered(event); - EXPECT_TRUE(MouseInCollection()); - toast0->GetWidget()->CloseNow(); - EXPECT_TRUE(MouseInCollection()); - toast1->GetWidget()->CloseNow(); - EXPECT_FALSE(MouseInCollection()); -} - -// TODO(dimich): Test repositioning - both normal one and when user is closing -// the toasts. -TEST_F(MessagePopupCollectionTest, DetectMouseHoverWithUserClose) { - std::string id0 = AddNotification(); - std::string id1 = AddNotification(); - - views::WidgetDelegateView* toast0 = GetToast(id0); - EXPECT_TRUE(toast0 != NULL); - views::WidgetDelegateView* toast1 = GetToast(id1); - ASSERT_TRUE(toast1 != NULL); - - ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - toast1->OnMouseEntered(event); - RemoveToastAndWaitForClose(id1); - - EXPECT_FALSE(MouseInCollection()); - std::string id2 = AddNotification(); - - views::WidgetDelegateView* toast2 = GetToast(id2); - EXPECT_TRUE(toast2 != NULL); - - CloseAllToasts(); -} - -TEST_F(MessagePopupCollectionTest, ManyPopupNotifications) { - // Add the max visible popup notifications +1, ensure the correct num visible. - size_t notifications_to_add = 3 + 1; - std::vector<std::string> ids(notifications_to_add); - for (size_t i = 0; i < notifications_to_add; ++i) { - ids[i] = AddNotification(); - } - - - for (size_t i = 0; i < notifications_to_add - 1; ++i) { - EXPECT_TRUE(IsToastShown(ids[i])) << "Should show the " << i << "th ID"; - } - EXPECT_FALSE(IsToastShown(ids[notifications_to_add - 1])); - - CloseAllToasts(); -} - -#if defined(OS_CHROMEOS) - -TEST_F(MessagePopupCollectionTest, CloseNonClosableNotifications) { - const char* kNotificationId = "NOTIFICATION1"; - - std::unique_ptr<Notification> notification(new Notification( - NOTIFICATION_TYPE_BASE_FORMAT, kNotificationId, - base::UTF8ToUTF16("test title"), base::UTF8ToUTF16("test message"), - gfx::Image(), base::string16() /* display_source */, GURL(), - NotifierId(NotifierId::APPLICATION, kNotificationId), - RichNotificationData(), new NotificationDelegate())); - notification->set_pinned(true); - - // Add a pinned notification. - MessageCenter::Get()->AddNotification(std::move(notification)); - - // Confirms that there is a toast. - EXPECT_EQ(1u, GetToastCounts()); - EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount()); - - // Close the toast. - views::WidgetDelegateView* toast1 = GetToast(kNotificationId); - ASSERT_TRUE(toast1 != NULL); - ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - toast1->OnMouseEntered(event); - static_cast<MessageCenterObserver*>(collection()) - ->OnNotificationRemoved(kNotificationId, true); - - // Confirms that there is no toast. - EXPECT_EQ(0u, GetToastCounts()); - // But the notification still exists. - EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount()); -} - -#endif // defined(OS_CHROMEOS) - -// When notifications were displayed on top, change of notification -// size didn't affect corresponding widget. -TEST_F(MessagePopupCollectionTest, ChangingNotificationSize) { - // Simulate a taskbar at the top. - SetDisplayInfo(gfx::Rect(0, 10, 600, 390), // Work-area. - gfx::Rect(0, 0, 600, 400)); // Display-bounds. - - struct TestCase { - std::string name; - std::string text; - }; - std::vector<TestCase> updates = { - {"shrinking", ""}, - {"enlarging", "abc\ndef\nghi\n"}, - {"restoring", "abc\n"}, - }; - - std::vector<std::string> notification_ids; - // adding notifications - { - // adding popup notifications - constexpr int max_visible_popup_notifications = 3; - notification_ids.reserve(max_visible_popup_notifications); - for (int i = 0; i < max_visible_popup_notifications; ++i) { - notification_ids.push_back(std::to_string(i)); - auto notification = - CreateTestNotification(notification_ids.back(), updates.back().text); - MessageCenter::Get()->AddNotification(std::move(notification)); - } - } - - - // Confirms that there are 2 toasts of 3 notifications. - EXPECT_EQ(3u, GetToastCounts()); - EXPECT_EQ(3u, MessageCenter::Get()->NotificationCount()); - - // updating notifications one by one - for (const std::string& id : notification_ids) { - for (const auto& update : updates) { - MessageCenter::Get()->UpdateNotification( - id, CreateTestNotification(id, update.text)); - - CheckedAnimationDelegate checked_animation(this); - - EXPECT_FALSE(checked_animation.error_msg()) - << "Animation error, test case: " << id << ' ' << update.name << ":\n" - << *checked_animation.error_msg(); - } - } - - CloseAllToasts(); -} - -} // namespace test } // namespace message_center
diff --git a/ui/message_center/views/message_popup_view.cc b/ui/message_center/views/message_popup_view.cc new file mode 100644 index 0000000..774e063 --- /dev/null +++ b/ui/message_center/views/message_popup_view.cc
@@ -0,0 +1,192 @@ +// Copyright 2018 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/message_popup_view.h" + +#include "base/feature_list.h" +#include "build/build_config.h" +#include "ui/accessibility/ax_enums.mojom.h" +#include "ui/accessibility/ax_node_data.h" +#include "ui/aura/window.h" +#include "ui/aura/window_targeter.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/message_center/public/cpp/features.h" +#include "ui/message_center/public/cpp/message_center_constants.h" +#include "ui/message_center/views/message_popup_collection.h" +#include "ui/message_center/views/message_view.h" +#include "ui/message_center/views/message_view_context_menu_controller.h" +#include "ui/message_center/views/message_view_factory.h" +#include "ui/message_center/views/popup_alignment_delegate.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/widget/widget.h" + +#if defined(OS_WIN) +#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" +#endif + +namespace message_center { + +MessagePopupView::MessagePopupView(const Notification& notification, + PopupAlignmentDelegate* alignment_delegate, + MessagePopupCollection* popup_collection) + : message_view_(MessageViewFactory::Create(notification, true)), + alignment_delegate_(alignment_delegate), + popup_collection_(popup_collection), + a11y_feedback_on_init_( + notification.rich_notification_data() + .should_make_spoken_feedback_for_popup_updates) { +#if !defined(OS_CHROMEOS) + if (!base::FeatureList::IsEnabled(message_center::kNewStyleNotifications)) { + context_menu_controller_ = + std::make_unique<MessageViewContextMenuController>(); + message_view_->set_context_menu_controller(context_menu_controller_.get()); + } +#endif + + SetLayoutManager(std::make_unique<views::FillLayout>()); + + if (!message_view_->IsManuallyExpandedOrCollapsed()) + message_view_->SetExpanded(message_view_->IsAutoExpandingAllowed()); + AddChildView(message_view_); + set_notify_enter_exit_on_child(true); +} + +MessagePopupView::MessagePopupView(PopupAlignmentDelegate* alignment_delegate, + MessagePopupCollection* popup_collection) + : message_view_(nullptr), + alignment_delegate_(alignment_delegate), + popup_collection_(popup_collection), + a11y_feedback_on_init_(false) { + SetLayoutManager(std::make_unique<views::FillLayout>()); +} + +MessagePopupView::~MessagePopupView() = default; + +void MessagePopupView::UpdateContents(const Notification& notification) { + message_view_->UpdateWithNotification(notification); + popup_collection_->NotifyPopupResized(); + if (notification.rich_notification_data() + .should_make_spoken_feedback_for_popup_updates) { + NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); + } +} + +float MessagePopupView::GetOpacity() const { + return GetWidget()->GetLayer()->opacity(); +} + +void MessagePopupView::SetPopupBounds(const gfx::Rect& bounds) { + GetWidget()->SetBounds(bounds); +} + +void MessagePopupView::SetOpacity(float opacity) { + GetWidget()->SetOpacity(opacity); +} + +void MessagePopupView::AutoCollapse() { + if (is_hovered_ || message_view_->IsManuallyExpandedOrCollapsed()) + return; + message_view_->SetExpanded(false); +} + +void MessagePopupView::Show() { + views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); + params.keep_on_top = true; +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + params.opacity = views::Widget::InitParams::OPAQUE_WINDOW; +#else + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; +#endif + params.delegate = this; + views::Widget* widget = new views::Widget(); + alignment_delegate_->ConfigureWidgetInitParamsForContainer(widget, ¶ms); + widget->set_focus_on_creation(false); + widget->AddObserver(this); + +#if defined(OS_WIN) + // We want to ensure that this toast always goes to the native desktop, + // not the Ash desktop (since there is already another toast contents view + // there. + if (!params.parent) + params.native_widget = new views::DesktopNativeWidgetAura(widget); +#endif + + widget->Init(params); + +#if defined(OS_CHROMEOS) + // On Chrome OS, this widget is shown in the shelf container. It means this + // widget would inherit the parent's window targeter (ShelfWindowTarget) by + // default. But it is not good for popup. So we override it with the normal + // WindowTargeter. + gfx::NativeWindow native_window = widget->GetNativeWindow(); + native_window->SetEventTargeter(std::make_unique<aura::WindowTargeter>()); +#endif + + widget->SetOpacity(0.0); + widget->ShowInactive(); + + if (a11y_feedback_on_init_) + NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); +} + +void MessagePopupView::Close() { + if (!GetWidget()) { + DeleteDelegate(); + return; + } + + if (!GetWidget()->IsClosed()) + GetWidget()->CloseNow(); +} + +void MessagePopupView::OnMouseEntered(const ui::MouseEvent& event) { + is_hovered_ = true; + popup_collection_->Update(); +} + +void MessagePopupView::OnMouseExited(const ui::MouseEvent& event) { + is_hovered_ = false; + popup_collection_->Update(); +} + +void MessagePopupView::ChildPreferredSizeChanged(views::View* child) { + popup_collection_->NotifyPopupResized(); +} + +void MessagePopupView::GetAccessibleNodeData(ui::AXNodeData* node_data) { + message_view_->GetAccessibleNodeData(node_data); + node_data->role = ax::mojom::Role::kAlertDialog; +} + +const char* MessagePopupView::GetClassName() const { + return "MessagePopupView"; +} + +void MessagePopupView::OnDisplayChanged() { + OnWorkAreaChanged(); +} + +void MessagePopupView::OnWorkAreaChanged() { + views::Widget* widget = GetWidget(); + if (!widget) + return; + + gfx::NativeView native_view = widget->GetNativeView(); + if (!native_view) + return; + + if (alignment_delegate_->RecomputeAlignment( + display::Screen::GetScreen()->GetDisplayNearestView(native_view))) { + popup_collection_->ResetBounds(); + } +} + +void MessagePopupView::OnWidgetActivationChanged(views::Widget* widget, + bool active) { + is_active_ = active; + popup_collection_->Update(); +} + +} // namespace message_center
diff --git a/ui/message_center/views/message_popup_view.h b/ui/message_center/views/message_popup_view.h new file mode 100644 index 0000000..0910f44 --- /dev/null +++ b/ui/message_center/views/message_popup_view.h
@@ -0,0 +1,92 @@ +// Copyright 2018 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_MESSAGE_POPUP_VIEW_H_ +#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_VIEW_H_ + +#include "ui/message_center/message_center_export.h" +#include "ui/views/widget/widget_delegate.h" +#include "ui/views/widget/widget_observer.h" + +namespace message_center { + +class MessagePopupCollection; +class MessageView; +class MessageViewContextMenuController; +class Notification; +class PopupAlignmentDelegate; + +// The widget delegate of a notification popup. The view is owned by the widget. +class MESSAGE_CENTER_EXPORT MessagePopupView : public views::WidgetDelegateView, + public views::WidgetObserver { + public: + MessagePopupView(const Notification& notification, + PopupAlignmentDelegate* alignment_delegate, + MessagePopupCollection* popup_collection); + ~MessagePopupView() override; + + // Update notification contents to |notification|. Virtual for unit testing. + virtual void UpdateContents(const Notification& notification); + + // Return opacity of the widget. + float GetOpacity() const; + + // Sets widget bounds. + void SetPopupBounds(const gfx::Rect& bounds); + + // Set widget opacity. + void SetOpacity(float opacity); + + // Collapses the notification unless the user is interacting with it. The + // request can be ignored. Virtual for unit testing. + virtual void AutoCollapse(); + + // Shows popup. After this call, MessagePopupView should be owned by the + // widget. + void Show(); + + // Closes popup. It should be callable even if Show() is not called, and + // in such case MessagePopupView should be deleted. Virtual for unit testing. + virtual void Close(); + + // views::WidgetDelegateView: + void OnMouseEntered(const ui::MouseEvent& event) override; + void OnMouseExited(const ui::MouseEvent& event) override; + void ChildPreferredSizeChanged(views::View* child) override; + void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + const char* GetClassName() const override; + void OnDisplayChanged() override; + void OnWorkAreaChanged() override; + + // views::WidgetObserver: + void OnWidgetActivationChanged(views::Widget* widget, bool active) override; + + bool is_hovered() const { return is_hovered_; } + bool is_active() const { return is_active_; } + + protected: + // For unit testing. + MessagePopupView(PopupAlignmentDelegate* alignment_delegate, + MessagePopupCollection* popup_collection); + + private: + // Owned by views hierarchy. + MessageView* message_view_; + + // Unowned. + PopupAlignmentDelegate* const alignment_delegate_; + MessagePopupCollection* const popup_collection_; + + std::unique_ptr<MessageViewContextMenuController> context_menu_controller_; + + const bool a11y_feedback_on_init_; + bool is_hovered_ = false; + bool is_active_ = false; + + DISALLOW_COPY_AND_ASSIGN(MessagePopupView); +}; + +} // namespace message_center + +#endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_VIEW_H_
diff --git a/ui/message_center/views/popup_alignment_delegate.cc b/ui/message_center/views/popup_alignment_delegate.cc index 219e721..aabdf7d6 100644 --- a/ui/message_center/views/popup_alignment_delegate.cc +++ b/ui/message_center/views/popup_alignment_delegate.cc
@@ -12,9 +12,9 @@ PopupAlignmentDelegate::~PopupAlignmentDelegate() {} -void PopupAlignmentDelegate::DoUpdateIfPossible() { +void PopupAlignmentDelegate::ResetBounds() { if (collection_) - collection_->DoUpdate(); + collection_->ResetBounds(); } } // namespace message_center
diff --git a/ui/message_center/views/popup_alignment_delegate.h b/ui/message_center/views/popup_alignment_delegate.h index 43e6a62..274fed2 100644 --- a/ui/message_center/views/popup_alignment_delegate.h +++ b/ui/message_center/views/popup_alignment_delegate.h
@@ -47,8 +47,9 @@ // Called when a new toast appears or toasts are rearranged in the |display|. // The subclass may override this method to check the current desktop status - // so that the toasts are arranged at the correct place. - virtual void RecomputeAlignment(const display::Display& display) = 0; + // so that the toasts are arranged at the correct place. Return true if + // alignment is actually changed. + virtual bool RecomputeAlignment(const display::Display& display) = 0; // Sets the parent container for popups. If it does not set a parent a // default parent will be used (e.g. the native desktop on Windows). @@ -63,7 +64,7 @@ protected: virtual ~PopupAlignmentDelegate(); - void DoUpdateIfPossible(); + void ResetBounds(); private: MessagePopupCollection* collection_;
diff --git a/ui/message_center/views/toast_contents_view.cc b/ui/message_center/views/toast_contents_view.cc deleted file mode 100644 index 23c84cf..0000000 --- a/ui/message_center/views/toast_contents_view.cc +++ /dev/null
@@ -1,363 +0,0 @@ -// Copyright (c) 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 "ui/message_center/views/toast_contents_view.h" - -#include <memory> - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/memory/weak_ptr.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "ui/accessibility/ax_enums.mojom.h" -#include "ui/accessibility/ax_node_data.h" -#include "ui/aura/window.h" -#include "ui/aura/window_targeter.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/message_center/public/cpp/message_center_constants.h" -#include "ui/message_center/public/cpp/notification.h" -#include "ui/message_center/views/message_popup_collection.h" -#include "ui/message_center/views/message_view.h" -#include "ui/message_center/views/popup_alignment_delegate.h" -#include "ui/views/background.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -#if defined(OS_WIN) -#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" -#endif - -using display::Screen; - -namespace message_center { -namespace { - -// The width of a toast before animated reveal and after closing. -const int kClosedToastWidth = 5; - -// FadeIn/Out look a bit better if they are slightly longer then default slide. -const int kFadeInOutDuration = 200; - -} // namespace. - -// static -const char ToastContentsView::kViewClassName[] = "ToastContentsView"; - -// static -gfx::Size ToastContentsView::GetToastSizeForView(const views::View* view) { - int width = kNotificationWidth + view->GetInsets().width(); - return gfx::Size(width, view->GetHeightForWidth(width)); -} - -ToastContentsView::ToastContentsView( - const std::string& notification_id, - PopupAlignmentDelegate* alignment_delegate, - base::WeakPtr<MessagePopupCollection> collection) - : collection_(collection), - id_(notification_id), - is_closing_(false), - closing_animation_(NULL) { - DCHECK(alignment_delegate); - set_notify_enter_exit_on_child(true); - // Sets the transparent background. Then, when the message view is slid out, - // the whole toast seems to slide although the actual bound of the widget - // remains. This is hacky but easier to keep the consistency. - SetBackground(views::CreateSolidBackground(SK_ColorTRANSPARENT)); - - fade_animation_.reset(new gfx::SlideAnimation(this)); - fade_animation_->SetSlideDuration(kFadeInOutDuration); - - CreateWidget(alignment_delegate); -} - -// This is destroyed when the toast window closes. -ToastContentsView::~ToastContentsView() { - if (collection_) - collection_->ForgetToast(this); -} - -void ToastContentsView::SetContents(MessageView* view, - bool a11y_feedback_for_updates) { - message_view_ = view; - RemoveAllChildViews(true); - AddChildView(view); - UpdatePreferredSize(); - if (a11y_feedback_for_updates) - NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); -} - -void ToastContentsView::UpdateContents(const Notification& notification, - bool a11y_feedback_for_updates) { - DCHECK_GT(child_count(), 0); - MessageView* message_view = static_cast<MessageView*>(child_at(0)); - message_view->UpdateWithNotification(notification); - UpdatePreferredSize(); - if (a11y_feedback_for_updates) - NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); -} - -void ToastContentsView::RevealWithAnimation(gfx::Point origin) { - // Place/move the toast widgets. Currently it stacks the widgets from the - // right-bottom of the work area. - // TODO(mukai): allow to specify the placement policy from outside of this - // class. The policy should be specified from preference on Windows, or - // the launcher alignment on ChromeOS. - origin_ = gfx::Point(origin.x() - preferred_size_.width(), - origin.y() - preferred_size_.height()); - - gfx::Rect stable_bounds(origin_, preferred_size_); - - SetBoundsInstantly(GetClosedToastBounds(stable_bounds)); - StartFadeIn(); - SetBoundsWithAnimation(stable_bounds); -} - -void ToastContentsView::CloseWithAnimation() { - if (is_closing_) - return; - is_closing_ = true; - StartFadeOut(); -} - -void ToastContentsView::SetBoundsInstantly(gfx::Rect new_bounds) { - DCHECK(new_bounds.size().width() <= preferred_size_.width() && - new_bounds.size().height() <= preferred_size_.height()) - << "we can not display widget bigger than notification"; - - if (!GetWidget()) - return; - - if (new_bounds == GetWidget()->GetWindowBoundsInScreen()) - return; - - origin_ = new_bounds.origin(); - GetWidget()->SetBounds(new_bounds); -} - -void ToastContentsView::SetBoundsWithAnimation(gfx::Rect new_bounds) { - DCHECK(new_bounds.size().width() <= preferred_size_.width() && - new_bounds.size().height() <= preferred_size_.height()) - << "we can not display widget bigger than notification"; - - if (!GetWidget()) - return; - - if (new_bounds == animated_bounds_end_) - return; - - origin_ = new_bounds.origin(); - // This picks up the current bounds, so if there was a previous animation - // half-done, the next one will pick up from the current location. - // This is the only place that should query current location of the Widget - // on screen, the rest should refer to the bounds_. - animated_bounds_start_ = GetWidget()->GetWindowBoundsInScreen(); - animated_bounds_end_ = new_bounds; - - if (bounds_animation_.get()) - bounds_animation_->Stop(); - - bounds_animation_.reset(new gfx::SlideAnimation(this)); - bounds_animation_->Show(); -} - -void ToastContentsView::StartFadeIn() { - fade_animation_->Stop(); - - GetWidget()->SetOpacity(0); - GetWidget()->ShowInactive(); - fade_animation_->Reset(0); - fade_animation_->Show(); -} - -void ToastContentsView::StartFadeOut() { - fade_animation_->Stop(); - - closing_animation_ = (is_closing_ ? fade_animation_.get() : nullptr); - if (GetWidget()->GetLayer()->opacity() > 0.0) { - fade_animation_->Reset(1); - fade_animation_->Hide(); - } else { - // If the layer is already transparent, do not trigger animation again. - // It happens when the toast is removed by touch gesture. - OnBoundsAnimationEndedOrCancelled(fade_animation_.get()); - } -} - -void ToastContentsView::OnBoundsAnimationEndedOrCancelled( - const gfx::Animation* animation) { - if (is_closing_ && closing_animation_ == animation && GetWidget()) { - views::Widget* widget = GetWidget(); - - // TODO(dewittj): This is a workaround to prevent a nasty bug where - // closing a transparent widget doesn't actually remove the window, - // causing entire areas of the screen to become unresponsive to clicks. - // See crbug.com/243469 - widget->Hide(); -#if defined(OS_WIN) - widget->SetOpacity(1.f); -#endif - - widget->Close(); - } -} - -// gfx::AnimationDelegate -void ToastContentsView::AnimationProgressed(const gfx::Animation* animation) { - if (animation == bounds_animation_.get()) { - gfx::Rect current(animation->CurrentValueBetween( - animated_bounds_start_, animated_bounds_end_)); - GetWidget()->SetBounds(current); - } else if (animation == fade_animation_.get()) { - GetWidget()->SetOpacity( - static_cast<float>(fade_animation_->GetCurrentValue())); - } -} - -void ToastContentsView::AnimationEnded(const gfx::Animation* animation) { - OnBoundsAnimationEndedOrCancelled(animation); -} - -void ToastContentsView::AnimationCanceled( - const gfx::Animation* animation) { - OnBoundsAnimationEndedOrCancelled(animation); -} - -// views::WidgetDelegate -void ToastContentsView::WindowClosing() { - if (!is_closing_ && collection_) - collection_->ForgetToast(this); -} - -void ToastContentsView::OnDisplayChanged() { - views::Widget* widget = GetWidget(); - if (!widget) - return; - - gfx::NativeView native_view = widget->GetNativeView(); - if (!native_view || !collection_.get()) - return; - - collection_->OnDisplayMetricsChanged( - Screen::GetScreen()->GetDisplayNearestView(native_view)); -} - -void ToastContentsView::OnWorkAreaChanged() { - views::Widget* widget = GetWidget(); - if (!widget) - return; - - gfx::NativeView native_view = widget->GetNativeView(); - if (!native_view || !collection_.get()) - return; - - collection_->OnDisplayMetricsChanged( - Screen::GetScreen()->GetDisplayNearestView(native_view)); -} - -void ToastContentsView::OnWidgetActivationChanged(views::Widget* widget, - bool active) { - if (active) - collection_->PausePopupTimers(); - else - collection_->RestartPopupTimers(); -} - -// views::View -void ToastContentsView::OnMouseEntered(const ui::MouseEvent& event) { - if (collection_) - collection_->OnMouseEntered(this); -} - -void ToastContentsView::OnMouseExited(const ui::MouseEvent& event) { - if (collection_) - collection_->OnMouseExited(this); -} - -void ToastContentsView::Layout() { - if (child_count() > 0) { - child_at(0)->SetBounds( - 0, 0, preferred_size_.width(), preferred_size_.height()); - } -} - -gfx::Size ToastContentsView::CalculatePreferredSize() const { - return child_count() ? GetToastSizeForView(child_at(0)) : gfx::Size(); -} - -void ToastContentsView::UpdatePreferredSize() { - DCHECK_GT(child_count(), 0); - gfx::Size new_size = GetToastSizeForView(child_at(0)); - if (preferred_size_ == new_size) - return; - // Growing notifications instantly can cause notification's to overlap - // And shrinking with animation, leaves area, where nothing is drawn - const bool change_instantly = preferred_size_.width() > new_size.width() || - preferred_size_.height() > new_size.height(); - preferred_size_ = new_size; - Layout(); - if (change_instantly) { - SetBoundsInstantly(bounds()); - return; - } - SetBoundsWithAnimation(bounds()); -} - -void ToastContentsView::GetAccessibleNodeData(ui::AXNodeData* node_data) { - if (child_count() > 0) - child_at(0)->GetAccessibleNodeData(node_data); - node_data->role = ax::mojom::Role::kAlertDialog; -} - -const char* ToastContentsView::GetClassName() const { - return kViewClassName; -} - -void ToastContentsView::CreateWidget( - PopupAlignmentDelegate* alignment_delegate) { - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); - params.keep_on_top = true; -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) - params.opacity = views::Widget::InitParams::OPAQUE_WINDOW; -#else - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; -#endif - params.delegate = this; - views::Widget* widget = new views::Widget(); - alignment_delegate->ConfigureWidgetInitParamsForContainer(widget, ¶ms); - widget->set_focus_on_creation(false); - widget->AddObserver(this); - -#if defined(OS_WIN) - // We want to ensure that this toast always goes to the native desktop, - // not the Ash desktop (since there is already another toast contents view - // there. - if (!params.parent) - params.native_widget = new views::DesktopNativeWidgetAura(widget); -#endif - - widget->Init(params); - -#if defined(OS_CHROMEOS) - // On Chrome OS, this widget is shown in the shelf container. It means this - // widget would inherit the parent's window targeter (ShelfWindowTarget) by - // default. But it is not good for popup. So we override it with the normal - // WindowTargeter. - gfx::NativeWindow native_window = widget->GetNativeWindow(); - native_window->SetEventTargeter(std::make_unique<aura::WindowTargeter>()); -#endif -} - -gfx::Rect ToastContentsView::GetClosedToastBounds(gfx::Rect bounds) { - return gfx::Rect(bounds.x() + bounds.width() - kClosedToastWidth, - bounds.y(), - kClosedToastWidth, - bounds.height()); -} - -} // namespace message_center
diff --git a/ui/message_center/views/toast_contents_view.h b/ui/message_center/views/toast_contents_view.h deleted file mode 100644 index 87c0aa9b..0000000 --- a/ui/message_center/views/toast_contents_view.h +++ /dev/null
@@ -1,154 +0,0 @@ -// Copyright (c) 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 UI_MESSAGE_CENTER_VIEWS_TOAST_CONTENTS_VIEW_H_ -#define UI_MESSAGE_CENTER_VIEWS_TOAST_CONTENTS_VIEW_H_ - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" -#include "ui/message_center/message_center_export.h" -#include "ui/views/widget/widget_delegate.h" -#include "ui/views/widget/widget_observer.h" - -namespace gfx { -class Animation; -class SlideAnimation; -} - -namespace views { -class View; -} - -namespace message_center { - -namespace test { -class MessagePopupCollectionTest; -} - -class MessagePopupCollection; -class MessageView; -class Notification; -class PopupAlignmentDelegate; - -// The widget host for a popup. Also implements MessageViewDelegate -// which delegates over to MessagePopupCollection, but takes care about -// checking the weakref since MessagePopupCollection may disappear before -// widget/views are closed/destructed. -class MESSAGE_CENTER_EXPORT ToastContentsView - : public views::WidgetDelegateView, - public views::WidgetObserver, - public gfx::AnimationDelegate { - public: - static const char kViewClassName[]; - - // Computes the size of a toast assuming it will host the given view. - static gfx::Size GetToastSizeForView(const views::View* view); - - ToastContentsView(const std::string& notification_id, - PopupAlignmentDelegate* alignment_delegate, - base::WeakPtr<MessagePopupCollection> collection); - ~ToastContentsView() override; - - // Sets the inner view of the toast. If it has contents already, - // |a11y_feedback_for_updates| causes the view to notify that the - // accessibility message should be read after this update. - void SetContents(MessageView* view, bool a11y_feedback_for_updates); - - void UpdateContents(const Notification& notification, - bool a11y_feedback_for_updates); - - // Shows the new toast for the first time, animated. - // |origin| is the right-bottom corner of the toast. - void RevealWithAnimation(gfx::Point origin); - - // Disconnectes the toast from the rest of the system immediately and start - // an animation. Once animation finishes, closes the widget. - void CloseWithAnimation(); - - void SetBoundsWithAnimation(gfx::Rect new_bounds); - - // Origin and bounds are not 'instant', but rather 'current stable values', - // there could be animation in progress that targets these values. - gfx::Point origin() { return origin_; } - gfx::Rect bounds() { return gfx::Rect(origin_, preferred_size_); } - - const std::string& id() const { return id_; } - - MessageView* message_view() { return message_view_; } - - // Overridden from views::View: - void OnMouseEntered(const ui::MouseEvent& event) override; - void OnMouseExited(const ui::MouseEvent& event) override; - void Layout() override; - gfx::Size CalculatePreferredSize() const override; - void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - const char* GetClassName() const override; - - private: - friend class test::MessagePopupCollectionTest; - - // Overridden from gfx::AnimationDelegate: - void AnimationProgressed(const gfx::Animation* animation) override; - void AnimationEnded(const gfx::Animation* animation) override; - void AnimationCanceled(const gfx::Animation* animation) override; - - // Overridden from views::WidgetDelegate: - void WindowClosing() override; - void OnDisplayChanged() override; - void OnWorkAreaChanged() override; - - // Overridden from views::WidgetObserver: - void OnWidgetActivationChanged(views::Widget* widget, bool active) override; - - // Recalculates preferred size from underlying view and notifies about it. - void UpdatePreferredSize(); - - // Initialization and update. - void CreateWidget(PopupAlignmentDelegate* alignment_delegate); - - // Immediately moves the toast without any sort of delay or animation. - void SetBoundsInstantly(gfx::Rect new_bounds); - - // Given the bounds of a toast on the screen, compute the bounds for that - // toast in 'closed' node_data. The 'closed' node_data is used as - // origin/destination in reveal/closing animations. - gfx::Rect GetClosedToastBounds(gfx::Rect bounds); - - void StartFadeIn(); - void StartFadeOut(); // Will call Widget::Close() when animation ends. - void OnBoundsAnimationEndedOrCancelled(const gfx::Animation* animation); - - base::WeakPtr<MessagePopupCollection> collection_; - - // Id if the corresponding Notification. - std::string id_; - - std::unique_ptr<gfx::SlideAnimation> bounds_animation_; - std::unique_ptr<gfx::SlideAnimation> fade_animation_; - - gfx::Rect animated_bounds_start_; - gfx::Rect animated_bounds_end_; - // Started closing animation, will close at the end. - bool is_closing_; - // Closing animation - when it ends, close the widget. Weak, only used - // for referential equality. - gfx::Animation* closing_animation_; - - gfx::Point origin_; - gfx::Size preferred_size_; - - // Weak reference to the MessageView. - MessageView* message_view_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(ToastContentsView); -}; - -} // namespace message_center - -#endif // UI_MESSAGE_CENTER_VIEWS_TOAST_CONTENTS_VIEW_H_