diff --git a/.gitignore b/.gitignore index f9e53d7..b3dbcaa 100644 --- a/.gitignore +++ b/.gitignore
@@ -54,6 +54,7 @@ Thumbs.db v8.log vs-chromium-project.txt +/.clangd-index/ # Settings directories for eclipse /.externalToolBuilders/ /.settings/
diff --git a/.gn b/.gn index b358758..635ee41 100644 --- a/.gn +++ b/.gn
@@ -440,7 +440,6 @@ "//third_party/isimpledom/*", "//third_party/javax_inject/*", "//third_party/jinja2/*", - "//third_party/jmake/*", "//third_party/jsoncpp/*", "//third_party/jsr-305/*", "//third_party/jstemplate/*",
diff --git a/.vpython b/.vpython index 712ddf1..0677a171 100644 --- a/.vpython +++ b/.vpython
@@ -232,7 +232,7 @@ wheel < name: "infra/python/wheels/pytest-py2_py3" - version: "version:3.5.0" + version: "version:3.6.2" > wheel < @@ -257,7 +257,7 @@ wheel < name: "infra/python/wheels/pluggy-py2_py3" - version: "version:0.6.0" + version: "version:0.7.1" > wheel < @@ -278,3 +278,13 @@ name: "infra/python/wheels/colorama-py2_py3" version: "version:0.4.1" > + +wheel: < + name: "infra/python/wheels/atomicwrites-py2_py3" + version: "version:1.3.0" +> + +wheel: < + name: "infra/python/wheels/pathlib2-py2_py3" + version: "version:2.3.3" +>
diff --git a/BUILD.gn b/BUILD.gn index 99b74571..b708c27a 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -724,6 +724,7 @@ (is_win && (use_drfuzz || use_libfuzzer)) || (use_libfuzzer && is_mac)) { deps += [ "//testing/libfuzzer/fuzzers", + "//third_party/grpc:fuzzers", "//third_party/icu/fuzzers", "//third_party/qcms:fuzzers", "//third_party/zlib/contrib/tests/fuzzers",
diff --git a/DEPS b/DEPS index 9aa2909c..4beb18da 100644 --- a/DEPS +++ b/DEPS
@@ -126,7 +126,7 @@ # 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': 'c74512c7ff9ed10113cfba8804d21b10427f820b', + 'skia_revision': 'bf0bcfecda685fc313ce136fec4379841684c8bc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -138,15 +138,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '3d544fffe7ff9284b21e3a15f638297c827bbc21', + 'angle_revision': 'ffd399789203e28ea9a30e7f31c002fb5d38aa7b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '8f79d388784c4870b87c3e87753d5e054af07011', + 'swiftshader_revision': 'e4ef5f77dab4f3ff5fbb9387bf83c216b92b4d55', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'e19ff219c47881212dff8be4a168dce2f60fdb13', + 'pdfium_revision': 'ce88174adfcfe75bf8760851943a612769f239c8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -189,7 +189,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'e8ab7db4d4da917c3abb111de4143e867bebfe21', + 'catapult_revision': 'f627a76e8dac96282b0a9f76eeda8c7db70cc030', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -237,7 +237,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '5994ae2a045015004cce24802dc47c33736486ea', + 'spv_tools_revision': '76730a46a1d81bdf46f25f33684e04b429ff1718', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -253,7 +253,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'f20f5b94939e90e33392dd5b1de01a6cc93eb510', + 'dawn_revision': '938811eef933dfacb16a464968f6dda038750705', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -334,7 +334,7 @@ 'packages': [ { 'package': 'chromium/chrome/test/data/autofill/captured_sites', - 'version': 'iTTirmwddgzWZrhbBLyYSUn-PFZNRIm5NjY9eYBgk0cC', + 'version': 'jYvTM_KjFi4v_BTqCfkAxM1XJ4PkMDSi31FgEDf0z9sC', } ], 'condition': 'checkout_chromium_autofill_test_dependencies', @@ -737,7 +737,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'ad6d56748d98a9c9d927564d330e92eb79bc15cf', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'efb8d2fcbd4f0e8d3f1249d5ef41e52eb5d445c4', 'condition': 'checkout_linux', }, @@ -762,7 +762,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '177cd13347a9137c42e882b9eac2eab404c587f8', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b53fdae2f2dded2d6c43e4e68a43a5a73217aabf', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1101,7 +1101,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '74142cf4ffe76f8ed19ce734efc3a8f0a1c4e384', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '8ecd6eea833595872a4a63cd34274fd2e5266f7b', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1316,7 +1316,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e1834d8c6d381affad98f96c06b3470bd5b9039b', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5d614691a03a3aa45e448bd2b2dc9d2ab3d15c29', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/aw_gl_functor.h b/android_webview/browser/aw_gl_functor.h index b54d5134..17d2294 100644 --- a/android_webview/browser/aw_gl_functor.h +++ b/android_webview/browser/aw_gl_functor.h
@@ -15,7 +15,7 @@ class AwGLFunctor { public: - AwGLFunctor(const JavaObjectWeakGlobalRef& java_ref); + explicit AwGLFunctor(const JavaObjectWeakGlobalRef& java_ref); ~AwGLFunctor(); void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
diff --git a/android_webview/docs/OWNERS b/android_webview/docs/OWNERS new file mode 100644 index 0000000..9e5c10f --- /dev/null +++ b/android_webview/docs/OWNERS
@@ -0,0 +1,5 @@ +# Feel free to send CLs to any Android WebView team member and ask for an OWNERS +# stamp, either from an android_webview/ top-level owner or someone listed in +# this file. + +ntfschr@chromium.org
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/DrawGLFunctor.java b/android_webview/glue/java/src/com/android/webview/chromium/DrawGLFunctor.java index 63bda3cd..5fbf7e57 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/DrawGLFunctor.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/DrawGLFunctor.java
@@ -14,7 +14,7 @@ /** * Simple Java abstraction and wrapper for the native DrawGLFunctor flow. - * An instance of this class can be constructed, bound to a single view context (i.e. AwContennts) + * An instance of this class can be constructed, bound to a single view context (i.e. AwContents) * and then drawn and detached from the view tree any number of times (using requestDrawGL and * detach respectively). */
diff --git a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/TelemetryActivity.java b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/TelemetryActivity.java index a29e525..7128202 100644 --- a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/TelemetryActivity.java +++ b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/TelemetryActivity.java
@@ -16,26 +16,44 @@ * This activity is designed for Telemetry testing of WebView. */ public class TelemetryActivity extends Activity { + static final String START_UP_TRACE_TAG_NAME = "WebViewStartUpTraceTag"; static final String DEFAULT_START_UP_TRACE_TAG = "WebViewStartupInterval"; + + static final String LOAD_URL_TRACE_TAG_NAME = "WebViewLoadUrlTraceTag"; static final String DEFAULT_LOAD_URL_TRACE_TAG = "WebViewBlankUrlLoadInterval"; + + static final String START_UP_AND_LOAD_URL_TRACE_TAG_NAME = "WebViewStartUpAndLoadUrlTraceTag"; static final String DEFAULT_START_UP_AND_LOAD_URL_TRACE_TAG = "WebViewStartupAndLoadBlankUrlInterval"; + static final String DUMMY_TRACE_TAG_NAME = "WebViewDummyTraceTag"; + static final String DEFAULT_DUMMY_TRACE_TAG = "WebViewDummyInterval"; + + private Intent mIntent; + + private String getTraceTag(String tagName, String tagDefault) { + String tag = mIntent.getStringExtra(tagName); + return tag == null ? tagDefault : tag; + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mIntent = getIntent(); + getWindow().setTitle( getResources().getString(R.string.title_activity_telemetry)); - Intent intent = getIntent(); - final String startUpTraceTag = intent.getStringExtra("WebViewStartUpTraceTag"); - final String loadUrlTraceTag = intent.getStringExtra("WebViewLoadUrlTraceTag"); - final String startUpAndLoadUrlTraceTag = - intent.getStringExtra("WebViewStartUpAndLoadUrlTraceTag"); + final String startUpTraceTag = + getTraceTag(START_UP_TRACE_TAG_NAME, DEFAULT_START_UP_TRACE_TAG); + final String loadUrlTraceTag = + getTraceTag(LOAD_URL_TRACE_TAG_NAME, DEFAULT_LOAD_URL_TRACE_TAG); + final String startUpAndLoadUrlTraceTag = getTraceTag( + START_UP_AND_LOAD_URL_TRACE_TAG_NAME, DEFAULT_START_UP_AND_LOAD_URL_TRACE_TAG); + final String dummyTraceTag = getTraceTag(DUMMY_TRACE_TAG_NAME, DEFAULT_DUMMY_TRACE_TAG); - Trace.beginSection(startUpTraceTag == null ? DEFAULT_START_UP_AND_LOAD_URL_TRACE_TAG - : startUpAndLoadUrlTraceTag); - Trace.beginSection(startUpTraceTag == null ? DEFAULT_START_UP_TRACE_TAG : startUpTraceTag); + Trace.beginSection(startUpAndLoadUrlTraceTag); + Trace.beginSection(startUpTraceTag); WebView webView = new WebView(this); setContentView(webView); Trace.endSection(); @@ -47,7 +65,7 @@ settings.setLoadWithOverviewMode(true); settings.setDomStorageEnabled(true); settings.setMediaPlaybackRequiresUserGesture(false); - String userAgentString = intent.getStringExtra("userAgent"); + String userAgentString = mIntent.getStringExtra("userAgent"); if (userAgentString != null) { settings.setUserAgentString(userAgentString); } @@ -62,12 +80,31 @@ @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); + // dummyTraceTag was ended by code in Android intended to end + // activityStart before onPageFinished was called, so the time + // reported as the activityStart will be longer than actual. + // The actual duration of activityStart will be from the + // beginning of the activityStart to the end of the dummyTraceTag + + // Ends loadUrlTraceTag Trace.endSection(); + + // Ends startUpAndLoadUrlTraceTag + Trace.endSection(); + + // Ends activityStart Trace.endSection(); } }); - Trace.beginSection(loadUrlTraceTag == null ? DEFAULT_LOAD_URL_TRACE_TAG : loadUrlTraceTag); + Trace.beginSection(loadUrlTraceTag); + webView.loadUrl("about:blank"); + + // TODO(aluo): Use async tracing to avoid having to do this + // dummyTraceTag is needed here to prevent code in Android intended to + // end activityStart from ending loadUrlTraceTag prematurely, + // see crbug/919221 + Trace.beginSection(dummyTraceTag); } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 1ae7c99..5b54f596 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -70,8 +70,10 @@ "wm/mru_window_tracker.h", "wm/overview/overview_controller.h", "wm/splitview/split_view_controller.h", + "wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h", "wm/tablet_mode/tablet_mode_controller.h", "wm/tablet_mode/tablet_mode_observer.h", + "wm/tablet_mode/tablet_mode_window_drag_controller.h", "wm/tablet_mode/tablet_mode_window_drag_delegate.h", "wm/window_finder.h", "wm/window_positioner.h", @@ -1148,14 +1150,11 @@ "wm/tablet_mode/tablet_mode_backdrop_delegate_impl.cc", "wm/tablet_mode/tablet_mode_backdrop_delegate_impl.h", "wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc", - "wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h", "wm/tablet_mode/tablet_mode_controller.cc", "wm/tablet_mode/tablet_mode_event_handler.cc", "wm/tablet_mode/tablet_mode_event_handler.h", "wm/tablet_mode/tablet_mode_window_drag_controller.cc", - "wm/tablet_mode/tablet_mode_window_drag_controller.h", "wm/tablet_mode/tablet_mode_window_drag_delegate.cc", - "wm/tablet_mode/tablet_mode_window_drag_delegate.h", "wm/tablet_mode/tablet_mode_window_drag_metrics.cc", "wm/tablet_mode/tablet_mode_window_drag_metrics.h", "wm/tablet_mode/tablet_mode_window_manager.cc",
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 7464c0db..d801aa7 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -68,6 +68,27 @@ Shell::Get()->assistant_controller()->ui_controller()->CloseUi(exit_point); } +// Minimize all windows that aren't the app list in reverse order to preserve +// the mru ordering. +// Returns false if no window is minimized. +bool MinimizeAllWindows() { + bool handled = false; + aura::Window* app_list_container = + Shell::Get()->GetPrimaryRootWindow()->GetChildById( + kShellWindowId_AppListTabletModeContainer); + aura::Window::Windows windows = + Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(); + std::reverse(windows.begin(), windows.end()); + for (auto* window : windows) { + if (!app_list_container->Contains(window) && + !wm::GetWindowState(window)->IsMinimized()) { + wm::GetWindowState(window)->Minimize(); + handled = true; + } + } + return handled; +} + } // namespace AppListControllerImpl::AppListControllerImpl() @@ -671,7 +692,9 @@ if (!assistant::util::IsEmbeddedUiEntryPoint(entry_point.value())) break; - if (!IsVisible()) { + if (IsTabletMode()) { + MinimizeAllWindows(); + } else if (!IsVisible()) { Show(GetDisplayIdToShowAppListOn(), app_list::kAssistantEntryPoint, base::TimeTicks()); } @@ -688,10 +711,16 @@ if (!IsShowingEmbeddedAssistantUI()) break; - if (exit_point == AssistantExitPoint::kBackInLauncher) + if (exit_point == AssistantExitPoint::kBackInLauncher) { presenter_.ShowEmbeddedAssistantUI(false); - else + } else if (!IsTabletMode()) { DismissAppList(); + } + if (IsTabletMode()) { + presenter_.GetView()->app_list_main_view()->ResetForShow(); + presenter_.GetView()->SetState( + app_list::AppListViewState::FULLSCREEN_ALL_APPS); + } break; } } @@ -725,23 +754,8 @@ } } - if (!handled) { - // Minimize all windows that aren't the app list in reverse order to - // preserve the mru ordering. - aura::Window* app_list_container = - Shell::Get()->GetPrimaryRootWindow()->GetChildById( - kShellWindowId_AppListTabletModeContainer); - aura::Window::Windows windows = - Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(); - std::reverse(windows.begin(), windows.end()); - for (auto* window : windows) { - if (!app_list_container->Contains(window) && - !wm::GetWindowState(window)->IsMinimized()) { - wm::GetWindowState(window)->Minimize(); - handled = true; - } - } - } + if (!handled) + handled = MinimizeAllWindows(); // Perform the "back" action for the app list. if (!handled) @@ -784,7 +798,13 @@ // Methods of |client_|: void AppListControllerImpl::StartAssistant() { - if (!IsTabletMode() && !app_list_features::IsEmbeddedAssistantUIEnabled()) + if (app_list_features::IsEmbeddedAssistantUIEnabled()) { + ash::Shell::Get()->assistant_controller()->ui_controller()->ShowUi( + ash::AssistantEntryPoint::kLauncherSearchBoxMic); + return; + } + + if (!IsTabletMode()) DismissAppList(); ash::Shell::Get()->assistant_controller()->ui_controller()->ShowUi( @@ -1005,6 +1025,9 @@ void AppListControllerImpl::NotifyHomeLauncherAnimationComplete( bool shown, int64_t display_id) { + CloseAssistantUi(shown ? AssistantExitPoint::kLauncherOpen + : AssistantExitPoint::kLauncherClose); + for (auto& observer : observers_) observer.OnHomeLauncherAnimationComplete(shown, display_id); }
diff --git a/ash/app_list/test/run_all_unittests.cc b/ash/app_list/test/run_all_unittests.cc index f38da10..dd509a39 100644 --- a/ash/app_list/test/run_all_unittests.cc +++ b/ash/app_list/test/run_all_unittests.cc
@@ -15,6 +15,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/env.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_paths.h" #include "ui/gl/test/gl_surface_test_support.h" @@ -35,7 +36,6 @@ base::TestSuite::Initialize(); gl::GLSurfaceTestSupport::InitializeOneOff(); - env_ = aura::Env::CreateInstance(); ui::RegisterPathProvider(); base::FilePath ui_test_pak_path; @@ -44,6 +44,9 @@ base::DiscardableMemoryAllocator::SetInstance( &discardable_memory_allocator_); + env_ = aura::Env::CreateInstance(features::IsSingleProcessMash() + ? aura::Env::Mode::MUS + : aura::Env::Mode::LOCAL); } void Shutdown() override {
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc index c0372451..8352b3f 100644 --- a/ash/app_list/views/search_box_view.cc +++ b/ash/app_list/views/search_box_view.cc
@@ -708,8 +708,10 @@ views::ImageButton* assistant = assistant_button(); assistant->SetImage( views::ImageButton::STATE_NORMAL, - gfx::CreateVectorIcon(ash::kAssistantIcon, kAssistantIconSize, - search_box_color())); + gfx::CreateVectorIcon(app_list_features::IsEmbeddedAssistantUIEnabled() + ? ash::kAssistantMicIcon + : ash::kAssistantIcon, + kAssistantIconSize, search_box_color())); assistant->SetAccessibleName( l10n_util::GetStringUTF16(IDS_APP_LIST_START_ASSISTANT)); }
diff --git a/ash/app_list/views/search_result_answer_card_view.cc b/ash/app_list/views/search_result_answer_card_view.cc index 8f619f0..709cd4a 100644 --- a/ash/app_list/views/search_result_answer_card_view.cc +++ b/ash/app_list/views/search_result_answer_card_view.cc
@@ -28,6 +28,7 @@ #include "ui/accessibility/ax_node.h" #include "ui/accessibility/ax_node_data.h" #include "ui/aura/window.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/canvas.h" #include "ui/views/background.h" #include "ui/views/layout/fill_layout.h" @@ -121,6 +122,8 @@ params->background_color = SK_ColorTRANSPARENT; contents_ = std::make_unique<content::NavigableContents>( contents_factory_.get(), std::move(params)); + if (features::IsUsingWindowService()) + contents_->ForceUseWindowService(); contents_->AddObserver(this); }
diff --git a/ash/assistant/assistant_interaction_controller.cc b/ash/assistant/assistant_interaction_controller.cc index 1fd07a2..55834e8 100644 --- a/ash/assistant/assistant_interaction_controller.cc +++ b/ash/assistant/assistant_interaction_controller.cc
@@ -618,10 +618,13 @@ DCHECK_EQ(AssistantVisibility::kVisible, assistant_controller_->ui_controller()->model()->visibility()); - const bool launch_with_mic_open = + bool launch_with_mic_open = Shell::Get()->voice_interaction_controller()->launch_with_mic_open(); switch (entry_point) { + case AssistantEntryPoint::kLauncherSearchBoxMic: + launch_with_mic_open = true; + FALLTHROUGH; case AssistantEntryPoint::kHotkey: case AssistantEntryPoint::kLauncherSearchBox: case AssistantEntryPoint::kLongPressLauncher: {
diff --git a/ash/assistant/assistant_view_delegate_impl.cc b/ash/assistant/assistant_view_delegate_impl.cc index 518bef1c4..3d9fa1f 100644 --- a/ash/assistant/assistant_view_delegate_impl.cc +++ b/ash/assistant/assistant_view_delegate_impl.cc
@@ -125,6 +125,13 @@ assistant_controller_->DownloadImage(url, std::move(callback)); } +mojom::ConsentStatus AssistantViewDelegateImpl::GetConsentStatus() const { + return Shell::Get() + ->voice_interaction_controller() + ->consent_status() + .value_or(mojom::ConsentStatus::kUnknown); +} + ::wm::CursorManager* AssistantViewDelegateImpl::GetCursorManager() { return Shell::Get()->cursor_manager(); } @@ -168,12 +175,4 @@ observer.OnDeepLinkReceived(type, params); } -bool AssistantViewDelegateImpl::VoiceInteractionControllerSetupCompleted() - const { - return Shell::Get() - ->voice_interaction_controller() - ->setup_completed() - .value_or(false); -} - } // namespace ash
diff --git a/ash/assistant/assistant_view_delegate_impl.h b/ash/assistant/assistant_view_delegate_impl.h index 253943a..0ca5c071 100644 --- a/ash/assistant/assistant_view_delegate_impl.h +++ b/ash/assistant/assistant_view_delegate_impl.h
@@ -54,6 +54,7 @@ void DownloadImage( const GURL& url, mojom::AssistantImageDownloader::DownloadCallback callback) override; + mojom::ConsentStatus GetConsentStatus() const override; ::wm::CursorManager* GetCursorManager() override; void GetNavigableContentsFactoryForView( content::mojom::NavigableContentsFactoryRequest request) override; @@ -63,7 +64,6 @@ int notification_button_index) override; void OnSuggestionChipPressed(const AssistantSuggestion* suggestion) override; void OpenUrlFromView(const GURL& url) override; - bool VoiceInteractionControllerSetupCompleted() const override; private: AssistantController* const assistant_controller_;
diff --git a/ash/assistant/model/assistant_ui_element.cc b/ash/assistant/model/assistant_ui_element.cc index b9762b59..1d7554b 100644 --- a/ash/assistant/model/assistant_ui_element.cc +++ b/ash/assistant/model/assistant_ui_element.cc
@@ -6,6 +6,7 @@ #include "ash/assistant/ui/assistant_ui_constants.h" #include "base/base64.h" +#include "ui/base/ui_base_features.h" namespace ash { @@ -65,6 +66,8 @@ contents_ = std::make_unique<content::NavigableContents>( contents_factory_, std::move(contents_params)); + if (features::IsUsingWindowService()) + contents_->ForceUseWindowService(); // Observe |contents_| so that we are notified when loading is complete. contents_->AddObserver(this);
diff --git a/ash/assistant/model/assistant_ui_model.h b/ash/assistant/model/assistant_ui_model.h index ee5bf68d..2e4b61c 100644 --- a/ash/assistant/model/assistant_ui_model.h +++ b/ash/assistant/model/assistant_ui_model.h
@@ -27,8 +27,9 @@ kSetup = 6, kStylus = 7, kLauncherSearchResult = 8, + kLauncherSearchBoxMic = 9, // Special enumerator value used by histogram macros. - kMaxValue = kLauncherSearchResult + kMaxValue = kLauncherSearchBoxMic }; // Enumeration of Assistant exit points. These values are persisted to logs.
diff --git a/ash/assistant/ui/assistant_view_delegate.h b/ash/assistant/ui/assistant_view_delegate.h index e6ebaae..6a2a72c9 100644 --- a/ash/assistant/ui/assistant_view_delegate.h +++ b/ash/assistant/ui/assistant_view_delegate.h
@@ -123,6 +123,9 @@ const GURL& url, mojom::AssistantImageDownloader::DownloadCallback callback) = 0; + // Returns the status of the user's consent. + virtual mojom::ConsentStatus GetConsentStatus() const = 0; + // Returns the cursor_manager. virtual ::wm::CursorManager* GetCursorManager() = 0; @@ -147,9 +150,6 @@ // Opens the specified |url| in a new browser tab. Special handling is applied // to deep links which may cause deviation from this behavior. virtual void OpenUrlFromView(const GURL& url) = 0; - - // Returns true if voice interaction controller setup completed. - virtual bool VoiceInteractionControllerSetupCompleted() const = 0; }; } // namespace ash
diff --git a/ash/assistant/ui/assistant_web_view.cc b/ash/assistant/ui/assistant_web_view.cc index 143883a..b3a7316 100644 --- a/ash/assistant/ui/assistant_web_view.cc +++ b/ash/assistant/ui/assistant_web_view.cc
@@ -15,6 +15,7 @@ #include "base/callback.h" #include "services/content/public/cpp/navigable_contents_view.h" #include "ui/aura/window.h" +#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -186,6 +187,8 @@ contents_ = std::make_unique<content::NavigableContents>( contents_factory_.get(), std::move(contents_params)); + if (features::IsUsingWindowService()) + contents_->ForceUseWindowService(); // We observe |contents_| so that we can handle events from the underlying // web contents.
diff --git a/ash/assistant/ui/main_stage/assistant_footer_view.cc b/ash/assistant/ui/main_stage/assistant_footer_view.cc index cd9ed13..be265a15 100644 --- a/ash/assistant/ui/main_stage/assistant_footer_view.cc +++ b/ash/assistant/ui/main_stage/assistant_footer_view.cc
@@ -68,47 +68,52 @@ SetLayoutManager(std::make_unique<views::FillLayout>()); // Initial view state is based on user consent state. - const bool setup_completed = - delegate_->VoiceInteractionControllerSetupCompleted(); + const bool consent_given = delegate_->GetConsentStatus() == + mojom::ConsentStatus::kActivityControlAccepted; + // Suggestion container. suggestion_container_ = new SuggestionContainerView(delegate_); - suggestion_container_->set_can_process_events_within_subtree(setup_completed); + suggestion_container_->set_can_process_events_within_subtree(consent_given); // Suggestion container will be animated on its own layer. suggestion_container_->SetPaintToLayer(); suggestion_container_->layer()->SetFillsBoundsOpaquely(false); - suggestion_container_->layer()->SetOpacity(setup_completed ? 1.f : 0.f); - suggestion_container_->SetVisible(setup_completed); + suggestion_container_->layer()->SetOpacity(consent_given ? 1.f : 0.f); + suggestion_container_->SetVisible(consent_given); AddChildView(suggestion_container_); // Opt in view. opt_in_view_ = new AssistantOptInView(); - opt_in_view_->set_can_process_events_within_subtree(!setup_completed); + opt_in_view_->set_can_process_events_within_subtree(!consent_given); opt_in_view_->set_delegate(delegate_->GetOptInDelegate()); // Opt in view will be animated on its own layer. opt_in_view_->SetPaintToLayer(); opt_in_view_->layer()->SetFillsBoundsOpaquely(false); - opt_in_view_->layer()->SetOpacity(setup_completed ? 0.f : 1.f); - opt_in_view_->SetVisible(!setup_completed); + opt_in_view_->layer()->SetOpacity(consent_given ? 0.f : 1.f); + opt_in_view_->SetVisible(!consent_given); AddChildView(opt_in_view_); } -void AssistantFooterView::OnVoiceInteractionSetupCompleted(bool completed) { +void AssistantFooterView::OnVoiceInteractionConsentStatusUpdated( + mojom::ConsentStatus consent_status) { using assistant::util::CreateLayerAnimationSequence; using assistant::util::CreateOpacityElement; using assistant::util::StartLayerAnimationSequence; + const bool consent_given = + consent_status == mojom::ConsentStatus::kActivityControlAccepted; + // When the consent state changes, we need to hide/show the appropriate views. views::View* hide_view = - completed ? static_cast<views::View*>(opt_in_view_) - : static_cast<views::View*>(suggestion_container_); + consent_given ? static_cast<views::View*>(opt_in_view_) + : static_cast<views::View*>(suggestion_container_); views::View* show_view = - completed ? static_cast<views::View*>(suggestion_container_) - : static_cast<views::View*>(opt_in_view_); + consent_given ? static_cast<views::View*>(suggestion_container_) + : static_cast<views::View*>(opt_in_view_); // Reset visibility to enable animation. hide_view->SetVisible(true); @@ -146,14 +151,14 @@ bool AssistantFooterView::OnAnimationEnded( const ui::CallbackLayerAnimationObserver& observer) { - const bool setup_completed = - delegate_->VoiceInteractionControllerSetupCompleted(); + const bool consent_given = delegate_->GetConsentStatus() == + mojom::ConsentStatus::kActivityControlAccepted; // Only the view relevant to our consent state should process events. - suggestion_container_->set_can_process_events_within_subtree(setup_completed); - suggestion_container_->SetVisible(setup_completed); - opt_in_view_->set_can_process_events_within_subtree(!setup_completed); - opt_in_view_->SetVisible(!setup_completed); + suggestion_container_->set_can_process_events_within_subtree(consent_given); + suggestion_container_->SetVisible(consent_given); + opt_in_view_->set_can_process_events_within_subtree(!consent_given); + opt_in_view_->SetVisible(!consent_given); // Return false to prevent the observer from destroying itself. return false;
diff --git a/ash/assistant/ui/main_stage/assistant_footer_view.h b/ash/assistant/ui/main_stage/assistant_footer_view.h index a7be0a45..29d174d 100644 --- a/ash/assistant/ui/main_stage/assistant_footer_view.h +++ b/ash/assistant/ui/main_stage/assistant_footer_view.h
@@ -37,7 +37,8 @@ int GetHeightForWidth(int width) const override; // mojom::VoiceInteractionObserver: - void OnVoiceInteractionSetupCompleted(bool completed) override; + void OnVoiceInteractionConsentStatusUpdated( + mojom::ConsentStatus consent_status) override; private: void InitLayout();
diff --git a/ash/assistant/util/assistant_util.cc b/ash/assistant/util/assistant_util.cc index c151b646..280e954 100644 --- a/ash/assistant/util/assistant_util.cc +++ b/ash/assistant/util/assistant_util.cc
@@ -25,6 +25,7 @@ entry_point == AssistantEntryPoint::kHotkey || entry_point == AssistantEntryPoint::kHotword || entry_point == AssistantEntryPoint::kLauncherSearchBox || + entry_point == AssistantEntryPoint::kLauncherSearchBoxMic || entry_point == AssistantEntryPoint::kLauncherSearchResult || entry_point == AssistantEntryPoint::kLongPressLauncher || entry_point == AssistantEntryPoint::kUnspecified;
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc index dd870ec2..eb2a2f9 100644 --- a/ash/display/window_tree_host_manager.cc +++ b/ash/display/window_tree_host_manager.cc
@@ -778,7 +778,7 @@ ui::EventDispatchDetails WindowTreeHostManager::DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) { + DispatchKeyEventPostIMECallback callback) { aura::Window* root_window = nullptr; if (event->target()) { root_window = static_cast<aura::Window*>(event->target())->GetRootWindow(); @@ -791,8 +791,8 @@ root_window = active_window ? active_window->GetRootWindow() : Shell::GetPrimaryRootWindow(); } - return root_window->GetHost()->DispatchKeyEventPostIME( - event, std::move(ack_callback)); + return root_window->GetHost()->DispatchKeyEventPostIME(event, + std::move(callback)); } AshWindowTreeHost* WindowTreeHostManager::AddWindowTreeHostForDisplay(
diff --git a/ash/display/window_tree_host_manager.h b/ash/display/window_tree_host_manager.h index e140cad..0d282c1 100644 --- a/ash/display/window_tree_host_manager.h +++ b/ash/display/window_tree_host_manager.h
@@ -176,7 +176,7 @@ // ui::internal::InputMethodDelegate overrides: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) override; + DispatchKeyEventPostIMECallback callback) override; private: FRIEND_TEST_ALL_PREFIXES(WindowTreeHostManagerTest, BoundsUpdated);
diff --git a/ash/public/cpp/assistant/assistant_state_base.h b/ash/public/cpp/assistant/assistant_state_base.h index b3033743..1c80fa0e 100644 --- a/ash/public/cpp/assistant/assistant_state_base.h +++ b/ash/public/cpp/assistant/assistant_state_base.h
@@ -31,8 +31,8 @@ return settings_enabled_; } - const base::Optional<bool>& setup_completed() const { - return setup_completed_; + const base::Optional<mojom::ConsentStatus>& consent_status() const { + return consent_status_; } const base::Optional<bool>& context_enabled() const { @@ -59,8 +59,8 @@ // Whether voice interaction is enabled in system settings. base::Optional<bool> settings_enabled_; - // Whether voice interaction setup flow has completed. - base::Optional<bool> setup_completed_; + // The status of the user's consent. + base::Optional<mojom::ConsentStatus> consent_status_; // Whether screen context is enabled. base::Optional<bool> context_enabled_;
diff --git a/ash/public/cpp/assistant/assistant_state_proxy.cc b/ash/public/cpp/assistant/assistant_state_proxy.cc index d241cd83..a41e69e 100644 --- a/ash/public/cpp/assistant/assistant_state_proxy.cc +++ b/ash/public/cpp/assistant/assistant_state_proxy.cc
@@ -35,8 +35,8 @@ observer->OnVoiceInteractionContextEnabled(context_enabled_.value()); if (hotword_enabled_.has_value()) observer->OnVoiceInteractionHotwordEnabled(hotword_enabled_.value()); - if (setup_completed_.has_value()) - observer->OnVoiceInteractionSetupCompleted(setup_completed_.value()); + if (consent_status_.has_value()) + observer->OnVoiceInteractionConsentStatusUpdated(consent_status_.value()); if (hotword_always_on_.has_value()) observer->OnVoiceInteractionHotwordAlwaysOn(hotword_always_on_.value()); if (allowed_state_.has_value()) @@ -77,10 +77,11 @@ observer.OnVoiceInteractionHotwordEnabled(hotword_enabled_.value()); } -void AssistantStateProxy::OnVoiceInteractionSetupCompleted(bool completed) { - setup_completed_ = completed; +void AssistantStateProxy::OnVoiceInteractionConsentStatusUpdated( + mojom::ConsentStatus consent_status) { + consent_status_ = consent_status; for (auto& observer : observers_) - observer.OnVoiceInteractionSetupCompleted(setup_completed_.value()); + observer.OnVoiceInteractionConsentStatusUpdated(consent_status_.value()); } void AssistantStateProxy::OnVoiceInteractionHotwordAlwaysOn(bool always_on) {
diff --git a/ash/public/cpp/assistant/assistant_state_proxy.h b/ash/public/cpp/assistant/assistant_state_proxy.h index 1c18337..51b8ff1c 100644 --- a/ash/public/cpp/assistant/assistant_state_proxy.h +++ b/ash/public/cpp/assistant/assistant_state_proxy.h
@@ -40,20 +40,21 @@ private: // mojom::VoiceInteractionObserver: void OnVoiceInteractionStatusChanged( - ash::mojom::VoiceInteractionState state) override; + mojom::VoiceInteractionState state) override; void OnVoiceInteractionSettingsEnabled(bool enabled) override; void OnVoiceInteractionContextEnabled(bool enabled) override; void OnVoiceInteractionHotwordEnabled(bool enabled) override; - void OnVoiceInteractionSetupCompleted(bool completed) override; + void OnVoiceInteractionConsentStatusUpdated( + mojom::ConsentStatus consent_status) override; void OnVoiceInteractionHotwordAlwaysOn(bool always_on) override; void OnAssistantFeatureAllowedChanged( - ash::mojom::AssistantAllowedState state) override; + mojom::AssistantAllowedState state) override; void OnLocaleChanged(const std::string& locale) override; base::ObserverList<DefaultVoiceInteractionObserver> observers_; - ash::mojom::VoiceInteractionControllerPtr voice_interaction_controller_; - mojo::Binding<ash::mojom::VoiceInteractionObserver> + mojom::VoiceInteractionControllerPtr voice_interaction_controller_; + mojo::Binding<mojom::VoiceInteractionObserver> voice_interaction_observer_binding_; DISALLOW_COPY_AND_ASSIGN(AssistantStateProxy);
diff --git a/ash/public/cpp/assistant/default_voice_interaction_observer.h b/ash/public/cpp/assistant/default_voice_interaction_observer.h index daa9827a..b70430f 100644 --- a/ash/public/cpp/assistant/default_voice_interaction_observer.h +++ b/ash/public/cpp/assistant/default_voice_interaction_observer.h
@@ -28,7 +28,8 @@ void OnVoiceInteractionSettingsEnabled(bool enabled) override {} void OnVoiceInteractionContextEnabled(bool enabled) override {} void OnVoiceInteractionHotwordEnabled(bool enabled) override {} - void OnVoiceInteractionSetupCompleted(bool completed) override {} + void OnVoiceInteractionConsentStatusUpdated( + ash::mojom::ConsentStatus consent_status) override {} void OnVoiceInteractionHotwordAlwaysOn(bool always_on) override {} void OnAssistantFeatureAllowedChanged( ash::mojom::AssistantAllowedState state) override {}
diff --git a/ash/public/cpp/vector_icons/BUILD.gn b/ash/public/cpp/vector_icons/BUILD.gn index addac85..350c537 100644 --- a/ash/public/cpp/vector_icons/BUILD.gn +++ b/ash/public/cpp/vector_icons/BUILD.gn
@@ -10,6 +10,7 @@ icons = [ "assistant.icon", + "assistant_mic.icon", "auto_launch_managed_guest_session.icon", "notification_assistant.icon", "notification_captive_portal.icon",
diff --git a/ash/public/cpp/vector_icons/assistant_mic.icon b/ash/public/cpp/vector_icons/assistant_mic.icon new file mode 100644 index 0000000..54f522a4 --- /dev/null +++ b/ash/public/cpp/vector_icons/assistant_mic.icon
@@ -0,0 +1,37 @@ +// Copyright 2019 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. + +CANVAS_DIMENSIONS, 24, +PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4, +MOVE_TO, 12, 15, +R_ARC_TO, 3, 3, 0, 0, 0, 3, -3, +V_LINE_TO, 5, +R_ARC_TO, 3, 3, 0, 0, 0, -6, 0, +R_V_LINE_TO, 7, +R_ARC_TO, 3, 3, 0, 0, 0, 3, 3, +CLOSE, +NEW_PATH, +PATH_COLOR_ARGB, 0xFF, 0x34, 0xA8, 0x53, +MOVE_TO, 11, 18.92f, +R_H_LINE_TO, 2, +V_LINE_TO, 22, +R_H_LINE_TO, -2, +CLOSE, +NEW_PATH, +PATH_COLOR_ARGB, 0xFF, 0xFA, 0xBB, 0x05, +MOVE_TO, 7, 12, +H_LINE_TO, 5, +R_ARC_TO, 7, 7, 0, 0, 0, 2, 4.95f, +R_LINE_TO, 1.41f, -1.41f, +ARC_TO, 5, 5, 0, 0, 1, 7, 12, +CLOSE, +NEW_PATH, +PATH_COLOR_ARGB, 0xFF, 0xE9, 0x42, 0x35, +MOVE_TO, 12, 17, +R_ARC_TO, 5, 5, 0, 0, 1, -3.54f, -1.47f, +R_LINE_TO, -1.41f, 1.42f, +ARC_TO, 7, 7, 0, 0, 0, 19, 12, +R_H_LINE_TO, -2, +R_ARC_TO, 5, 5, 0, 0, 1, -5, 5, +CLOSE
diff --git a/ash/public/interfaces/voice_interaction_controller.mojom b/ash/public/interfaces/voice_interaction_controller.mojom index 04589e3..79727c4 100644 --- a/ash/public/interfaces/voice_interaction_controller.mojom +++ b/ash/public/interfaces/voice_interaction_controller.mojom
@@ -65,8 +65,8 @@ // Called when hotword is set to always on/only with power source. OnVoiceInteractionHotwordAlwaysOn(bool always_on); - // Called when voice interaction setup flow completed. - OnVoiceInteractionSetupCompleted(bool completed); + // Called when consent status is updated. + OnVoiceInteractionConsentStatusUpdated(ConsentStatus consent_status); // Called when assistant feature allowed state has changed. OnAssistantFeatureAllowedChanged(AssistantAllowedState state); @@ -97,8 +97,8 @@ // Called when the hotword is set to always on/only with power source. NotifyHotwordAlwaysOn(bool enabled); - // Called when the voice interaction setup complete status is changed. - NotifySetupCompleted(bool completed); + // Called when the consent status is obtained from the server. + NotifyConsentStatus(ConsentStatus consent_status); // Notify if voice interaction feature is allowed or not. e.g. not allowed // if disabled by policy. @@ -116,3 +116,20 @@ // Add an observer. AddObserver(VoiceInteractionObserver observer); }; + +// The status of the user's consent. The enum values cannot be changed because +// they are persisted on disk. +enum ConsentStatus { + // The status is unknown. + kUnknown = 0, + + // The user accepted activity control access. + kActivityControlAccepted = 1, + + // The user is not authorized to give consent. + kUnauthorized = 2, + + // The user's consent information is not found. This is typically the case + // when consent from the user has never been requested. + kNotFound = 3, +};
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index 8f6c17e..bdda4de 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -60,6 +60,9 @@ } // namespace +// static +const char AppListButton::kViewClassName[] = "ash/AppListButton"; + AppListButton::AppListButton(ShelfView* shelf_view, Shelf* shelf) : ShelfControlButton(shelf_view), shelf_(shelf) { DCHECK(shelf_); @@ -178,6 +181,10 @@ } } +const char* AppListButton::GetClassName() const { + return kViewClassName; +} + std::unique_ptr<views::InkDropRipple> AppListButton::CreateInkDropRipple() const { const int app_list_button_radius = ShelfConstants::control_border_radius(); @@ -295,7 +302,8 @@ SchedulePaint(); } -void AppListButton::OnVoiceInteractionSetupCompleted(bool completed) { +void AppListButton::OnVoiceInteractionConsentStatusUpdated( + mojom::ConsentStatus consent_status) { SchedulePaint(); } @@ -321,11 +329,14 @@ VoiceInteractionController* controller = Shell::Get()->voice_interaction_controller(); bool settings_enabled = controller->settings_enabled().value_or(false); - bool setup_completed = controller->setup_completed().value_or(false); + + const bool consent_given = controller->consent_status() == + mojom::ConsentStatus::kActivityControlAccepted; + bool is_feature_allowed = controller->allowed_state() == mojom::AssistantAllowedState::ALLOWED; if (assistant_overlay_ && is_feature_allowed && - (settings_enabled || !setup_completed)) { + (settings_enabled || !consent_given)) { return true; } return false;
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h index ff97f08..c92b86c 100644 --- a/ash/shelf/app_list_button.h +++ b/ash/shelf/app_list_button.h
@@ -34,6 +34,8 @@ public TabletModeObserver, public DefaultVoiceInteractionObserver { public: + static const char kViewClassName[]; + AppListButton(ShelfView* shelf_view, Shelf* shelf); ~AppListButton() override; @@ -44,6 +46,7 @@ // views::Button: void OnGestureEvent(ui::GestureEvent* event) override; + const char* GetClassName() const override; protected: // views::Button: @@ -58,7 +61,8 @@ void OnVoiceInteractionStatusChanged( mojom::VoiceInteractionState state) override; void OnVoiceInteractionSettingsEnabled(bool enabled) override; - void OnVoiceInteractionSetupCompleted(bool completed) override; + void OnVoiceInteractionConsentStatusUpdated( + mojom::ConsentStatus consent_status) override; // SessionObserver: void OnActiveUserSessionChanged(const AccountId& account_id) override;
diff --git a/ash/shelf/back_button.cc b/ash/shelf/back_button.cc index 31e6522..4c1ba90 100644 --- a/ash/shelf/back_button.cc +++ b/ash/shelf/back_button.cc
@@ -27,6 +27,9 @@ namespace ash { +// static +const char BackButton::kViewClassName[] = "ash/BackButton"; + BackButton::BackButton(ShelfView* shelf_view) : ShelfControlButton(shelf_view) { SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_BACK_BUTTON_TITLE)); } @@ -60,6 +63,10 @@ GetCenterPoint().y() - img.height() / 2); } +const char* BackButton::GetClassName() const { + return kViewClassName; +} + void BackButton::GenerateAndSendBackEvent( const ui::EventType& original_event_type) { ui::EventType new_event_type;
diff --git a/ash/shelf/back_button.h b/ash/shelf/back_button.h index c07f2b0..272426f 100644 --- a/ash/shelf/back_button.h +++ b/ash/shelf/back_button.h
@@ -18,6 +18,8 @@ // in/out of the icon matches the movement of ShelfView's items. class ASH_EXPORT BackButton : public ShelfControlButton { public: + static const char kViewClassName[]; + explicit BackButton(ShelfView* shelf_view); ~BackButton() override; @@ -27,6 +29,7 @@ bool OnMousePressed(const ui::MouseEvent& event) override; void OnMouseReleased(const ui::MouseEvent& event) override; void PaintButtonContents(gfx::Canvas* canvas) override; + const char* GetClassName() const override; private: // Generate and send a VKEY_BROWSER_BACK key event when the back button
diff --git a/ash/shelf/overflow_button.cc b/ash/shelf/overflow_button.cc index 306b41c..2a4378b 100644 --- a/ash/shelf/overflow_button.cc +++ b/ash/shelf/overflow_button.cc
@@ -48,4 +48,8 @@ shelf_view()->ButtonPressed(this, event, nullptr); } +const char* OverflowButton::GetClassName() const { + return "ash/OverflowButton"; +} + } // namespace ash
diff --git a/ash/shelf/overflow_button.h b/ash/shelf/overflow_button.h index f3624345..bf9b6ed 100644 --- a/ash/shelf/overflow_button.h +++ b/ash/shelf/overflow_button.h
@@ -34,6 +34,7 @@ // views::Button: bool ShouldEnterPushedState(const ui::Event& event) override; void NotifyClick(const ui::Event& event) override; + const char* GetClassName() const override; const gfx::ImageSkia horizontal_dots_image_; views::ImageView* horizontal_dots_image_view_;
diff --git a/ash/shelf/shelf_button.cc b/ash/shelf/shelf_button.cc index 0c8527a..abd273dd 100644 --- a/ash/shelf/shelf_button.cc +++ b/ash/shelf/shelf_button.cc
@@ -93,4 +93,8 @@ return std::move(ink_drop); } +const char* ShelfButton::GetClassName() const { + return "ash/ShelfButton"; +} + } // namespace ash
diff --git a/ash/shelf/shelf_button.h b/ash/shelf/shelf_button.h index fd1963b..38da03c 100644 --- a/ash/shelf/shelf_button.h +++ b/ash/shelf/shelf_button.h
@@ -34,6 +34,7 @@ void NotifyClick(const ui::Event& event) override; bool ShouldEnterPushedState(const ui::Event& event) override; std::unique_ptr<views::InkDrop> CreateInkDrop() override; + const char* GetClassName() const override; private: // The shelf view hosting this button.
diff --git a/ash/shelf/shelf_control_button.cc b/ash/shelf/shelf_control_button.cc index 0597dfa..0143fb8 100644 --- a/ash/shelf/shelf_control_button.cc +++ b/ash/shelf/shelf_control_button.cc
@@ -47,6 +47,10 @@ size(), GetCenterPoint(), ShelfConstants::control_border_radius()); } +const char* ShelfControlButton::GetClassName() const { + return "ash/ShelfControlButton"; +} + gfx::Rect ShelfControlButton::CalculateButtonBounds() const { ShelfAlignment alignment = shelf_->alignment(); gfx::Rect content_bounds = GetContentsBounds();
diff --git a/ash/shelf/shelf_control_button.h b/ash/shelf/shelf_control_button.h index 93c27cd..ed1055c 100644 --- a/ash/shelf/shelf_control_button.h +++ b/ash/shelf/shelf_control_button.h
@@ -31,6 +31,7 @@ // views::Button: std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override; + const char* GetClassName() const override; void PaintBackground(gfx::Canvas* canvas, const gfx::Rect& bounds); void PaintButtonContents(gfx::Canvas* canvas) override;
diff --git a/ash/voice_interaction/voice_interaction_controller.cc b/ash/voice_interaction/voice_interaction_controller.cc index 19183fb..7ad9ada 100644 --- a/ash/voice_interaction/voice_interaction_controller.cc +++ b/ash/voice_interaction/voice_interaction_controller.cc
@@ -83,16 +83,17 @@ observer.OnVoiceInteractionHotwordAlwaysOn(always_on); } -void VoiceInteractionController::NotifySetupCompleted(bool completed) { - if (setup_completed_.has_value() && setup_completed_.value() == completed) +void VoiceInteractionController::NotifyConsentStatus( + mojom::ConsentStatus consent_status) { + if (consent_status_.has_value() && consent_status_.value() == consent_status) return; - setup_completed_ = completed; - observers_.ForAllPtrs([completed](auto* observer) { - observer->OnVoiceInteractionSetupCompleted(completed); + consent_status_ = consent_status; + observers_.ForAllPtrs([consent_status](auto* observer) { + observer->OnVoiceInteractionConsentStatusUpdated(consent_status); }); for (auto& observer : local_observers_) - observer.OnVoiceInteractionSetupCompleted(completed); + observer.OnVoiceInteractionConsentStatusUpdated(consent_status); } void VoiceInteractionController::NotifyFeatureAllowed( @@ -156,8 +157,8 @@ observer->OnVoiceInteractionContextEnabled(context_enabled_.value()); if (hotword_enabled_.has_value()) observer->OnVoiceInteractionHotwordEnabled(hotword_enabled_.value()); - if (setup_completed_.has_value()) - observer->OnVoiceInteractionSetupCompleted(setup_completed_.value()); + if (consent_status_.has_value()) + observer->OnVoiceInteractionConsentStatusUpdated(consent_status_.value()); if (hotword_always_on_.has_value()) observer->OnVoiceInteractionHotwordAlwaysOn(hotword_always_on_.value()); if (allowed_state_.has_value())
diff --git a/ash/voice_interaction/voice_interaction_controller.h b/ash/voice_interaction/voice_interaction_controller.h index c6ac68d..0b31a87 100644 --- a/ash/voice_interaction/voice_interaction_controller.h +++ b/ash/voice_interaction/voice_interaction_controller.h
@@ -32,7 +32,7 @@ void NotifyContextEnabled(bool enabled) override; void NotifyHotwordEnabled(bool enabled) override; void NotifyHotwordAlwaysOn(bool always_on) override; - void NotifySetupCompleted(bool completed) override; + void NotifyConsentStatus(mojom::ConsentStatus consent_status) override; void NotifyFeatureAllowed(mojom::AssistantAllowedState state) override; void NotifyNotificationEnabled(bool enabled) override; void NotifyLocaleChanged(const std::string& locale) override;
diff --git a/ash/voice_interaction/voice_interaction_controller_unittest.cc b/ash/voice_interaction/voice_interaction_controller_unittest.cc index fd33af05..e9da9ced 100644 --- a/ash/voice_interaction/voice_interaction_controller_unittest.cc +++ b/ash/voice_interaction/voice_interaction_controller_unittest.cc
@@ -37,8 +37,9 @@ void OnVoiceInteractionHotwordEnabled(bool enabled) override { hotword_enabled_ = enabled; } - void OnVoiceInteractionSetupCompleted(bool completed) override { - setup_completed_ = completed; + void OnVoiceInteractionConsentStatusUpdated( + mojom::ConsentStatus consent_status) override { + consent_status_ = consent_status; } void OnAssistantFeatureAllowedChanged( mojom::AssistantAllowedState state) override {} @@ -51,7 +52,7 @@ bool context_enabled() const { return context_enabled_; } bool hotword_always_on() const { return hotword_always_on_; } bool hotword_enabled() const { return hotword_enabled_; } - bool setup_completed() const { return setup_completed_; } + mojom::ConsentStatus consent_status() const { return consent_status_; } void SetVoiceInteractionController(VoiceInteractionController* controller) { mojom::VoiceInteractionObserverPtr ptr; @@ -65,7 +66,7 @@ bool context_enabled_ = false; bool hotword_always_on_ = false; bool hotword_enabled_ = false; - bool setup_completed_ = false; + mojom::ConsentStatus consent_status_ = mojom::ConsentStatus::kUnknown; mojo::Binding<mojom::VoiceInteractionObserver> voice_interaction_binding_; @@ -147,13 +148,16 @@ EXPECT_TRUE(observer()->hotword_enabled()); } -TEST_F(VoiceInteractionControllerTest, NotifySetupCompleted) { - controller()->NotifySetupCompleted(true); +TEST_F(VoiceInteractionControllerTest, NotifyConsentStatus) { + controller()->NotifyConsentStatus( + mojom::ConsentStatus::kActivityControlAccepted); controller()->FlushForTesting(); // The cached state should be updated. - EXPECT_TRUE(controller()->setup_completed()); + EXPECT_TRUE(controller()->consent_status() == + mojom::ConsentStatus::kActivityControlAccepted); // The observers should be notified. - EXPECT_TRUE(observer()->setup_completed()); + EXPECT_TRUE(observer()->consent_status() == + mojom::ConsentStatus::kActivityControlAccepted); } } // namespace ash
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 3d3e10e..18597d0 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -1918,8 +1918,12 @@ std::unique_ptr<WindowResizer> StartDrag(aura::Window* dragged_window, aura::Window* source_window) { SetIsInTabDragging(dragged_window, /*is_dragging=*/true, source_window); - return CreateResizerForTest(dragged_window, - dragged_window->bounds().origin(), HTCAPTION); + std::unique_ptr<WindowResizer> resizer = CreateResizerForTest( + dragged_window, dragged_window->bounds().origin(), HTCAPTION); + GetBrowserWindowDragController(resizer.get()) + ->drag_delegate_for_testing() + ->set_drag_start_deadline_for_testing(base::Time::Now()); + return resizer; } // Drags the window to |end_position|. @@ -1987,17 +1991,20 @@ } } - IndicatorState GetIndicatorState(WindowResizer* resizer) { + TabletModeWindowDragController* GetBrowserWindowDragController( + WindowResizer* resizer) { WindowResizer* real_window_resizer; // TODO(xdai): This piece of codes seems knowing too much impl details about // WindowResizer. Revisit the logic here later to see if there is anything // we can do to simplify the logic and hide impl details. real_window_resizer = static_cast<DragWindowResizer*>(resizer) ->next_window_resizer_for_testing(); - TabletModeWindowDragController* browser_controller = - static_cast<TabletModeWindowDragController*>(real_window_resizer); + return static_cast<TabletModeWindowDragController*>(real_window_resizer); + } - return browser_controller->drag_delegate_for_testing() + IndicatorState GetIndicatorState(WindowResizer* resizer) { + return GetBrowserWindowDragController(resizer) + ->drag_delegate_for_testing() ->split_view_drag_indicators_for_testing() ->current_indicator_state(); } @@ -3660,6 +3667,8 @@ ::wm::WINDOW_MOVE_SOURCE_TOUCH); controller_ = std::make_unique<TabletModeWindowDragController>( window_state, std::make_unique<TabletModeBrowserWindowDragDelegate>()); + controller_->drag_delegate_for_testing() + ->set_drag_start_deadline_for_testing(base::Time::Now()); controller_->Drag(location, 0); }
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc index dd2733b..c30a15a 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc
@@ -40,6 +40,10 @@ // tablet mode. constexpr float kIndicatorsThresholdRatio = 0.1; +// Duration of a drag that it will be considered as an intended drag. +constexpr base::TimeDelta kIsWindowMovedTimeoutMs = + base::TimeDelta::FromMilliseconds(300); + // Returns the overview session if overview mode is active, otherwise returns // nullptr. OverviewSession* GetOverviewSession() { @@ -97,6 +101,7 @@ dragged_window_ = dragged_window; initial_location_in_screen_ = location_in_screen; + drag_start_deadline_ = base::Time::Now() + kIsWindowMovedTimeoutMs; PrepareWindowDrag(location_in_screen); @@ -177,16 +182,7 @@ const gfx::Point& location_in_screen, UpdateDraggedWindowType type, const gfx::Rect& target_bounds) { - if (!did_move_) { - const gfx::Rect work_area_bounds = - display::Screen::GetScreen() - ->GetDisplayNearestWindow(dragged_window_) - .work_area(); - if (location_in_screen.y() >= - GetIndicatorsVerticalThreshold(work_area_bounds)) { - did_move_ = true; - } - } + UpdateIsWindowConsideredMoved(location_in_screen.y()); if (type == UpdateDraggedWindowType::UPDATE_BOUNDS) { // UPDATE_BOUNDS is used when dragging tab(s) out of a browser window. @@ -266,7 +262,7 @@ occlusion_excluder_.reset(); dragged_window_ = nullptr; - did_move_ = false; + is_window_considered_moved_ = false; } void TabletModeWindowDragDelegate::FlingOrSwipe(ui::GestureEvent* event) { @@ -299,16 +295,10 @@ if (split_view_controller_->IsSplitViewModeActive()) return IndicatorState::kNone; - // If the event location hasn't passed the indicator vertical threshold, do - // not show the drag indicators. - const gfx::Rect work_area_bounds = - display::Screen::GetScreen() - ->GetDisplayNearestWindow(dragged_window_) - .work_area(); - if (!did_move_ && location_in_screen.y() < - GetIndicatorsVerticalThreshold(work_area_bounds)) { + // Do not show the drag indicators if the window hasn't been considered as + // moved. + if (!is_window_considered_moved_) return IndicatorState::kNone; - } // No top drag indicator if in portrait screen orientation. if (IsCurrentScreenOrientationLandscape()) @@ -352,16 +342,13 @@ } } - // Otherwise, the user has to drag pass the indicator vertical threshold to - // snap the window. + // Do not snap the window if it hasn't be considered as moved. + if (!is_window_considered_moved_) + return SplitViewController::NONE; + gfx::Rect work_area_bounds = display::Screen::GetScreen() ->GetDisplayNearestWindow(dragged_window_) .work_area(); - if (!did_move_ && location_in_screen.y() < - GetIndicatorsVerticalThreshold(work_area_bounds)) { - return SplitViewController::NONE; - } - // Check to see if the current event location |location_in_screen|is within // the drag indicators bounds. if (is_landscape) { @@ -504,4 +491,21 @@ return event->details().velocity_y() > kFlingToOverviewThreshold; } +void TabletModeWindowDragDelegate::UpdateIsWindowConsideredMoved( + int y_location_in_screen) { + if (is_window_considered_moved_) + return; + + if (base::Time::Now() < drag_start_deadline_) + return; + + DCHECK(dragged_window_); + const gfx::Rect work_area_bounds = + display::Screen::GetScreen() + ->GetDisplayNearestWindow(dragged_window_) + .work_area(); + is_window_considered_moved_ = + y_location_in_screen >= GetIndicatorsVerticalThreshold(work_area_bounds); +} + } // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h index 4d9880c..239e44ac 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h +++ b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h
@@ -79,6 +79,10 @@ return split_view_drag_indicators_.get(); } + void set_drag_start_deadline_for_testing(base::Time time) { + drag_start_deadline_ = time; + } + protected: // These four methods are used by its child class to do its special handling // before/during/after dragging. @@ -115,6 +119,10 @@ // Returns true if fling event should drop the window into overview grid. bool ShouldFlingIntoOverview(const ui::GestureEvent* event) const; + // Updates |is_window_considered_moved_| on current time and + // |y_location_in_screen|. + void UpdateIsWindowConsideredMoved(int y_location_in_screen); + SplitViewController* const split_view_controller_; // A widget to display the drag indicators and preview window. @@ -137,11 +145,15 @@ // desired window transform during dragging. gfx::Rect bounds_of_selected_drop_target_; - // Flag to indicate whether a window is considered as moved. A window needs to - // be dragged vertically a small amount of distance to be considered as moved. - // The drag indicators will only show up after the window has been moved. Once - // the window is moved, it will stay as 'moved'. - bool did_move_ = false; + // True if the |dragged_window_| has been considered as moved. Only after it + // has been dragged longer than kIsWindowMovedTimeoutMs on time and further + // than GetIndicatorsVerticalThreshold on distance, it can be considered as + // moved. Only change its window state or show the drag indicators if it has + // been 'moved'. Once it has been 'moved', it will stay as 'moved'. + bool is_window_considered_moved_ = false; + + // Drag need to last later than the deadline here to be considered as 'moved'. + base::Time drag_start_deadline_; base::Optional<aura::WindowOcclusionTracker::ScopedExclude> occlusion_excluder_;
diff --git a/base/BUILD.gn b/base/BUILD.gn index 0125e5f..3dea978 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1139,8 +1139,8 @@ if (is_linux) { sources += [ "base_paths_posix.cc", - "debug/elf_reader_linux.cc", - "debug/elf_reader_linux.h", + "debug/elf_reader.cc", + "debug/elf_reader.h", ] } } @@ -1342,8 +1342,8 @@ # Android uses some Linux sources, put those back. set_sources_assignment_filter([]) sources += [ - "debug/elf_reader_linux.cc", - "debug/elf_reader_linux.h", + "debug/elf_reader.cc", + "debug/elf_reader.h", "debug/proc_maps_linux.cc", "debug/proc_maps_linux.h", "files/file_path_watcher_linux.cc", @@ -1401,6 +1401,8 @@ "base_paths_fuchsia.cc", "base_paths_fuchsia.h", "debug/debugger_posix.cc", + "debug/elf_reader.cc", + "debug/elf_reader.h", "debug/stack_trace_fuchsia.cc", "file_descriptor_posix.h", "files/dir_reader_posix.h", @@ -2330,7 +2332,6 @@ "debug/alias_unittest.cc", "debug/crash_logging_unittest.cc", "debug/debugger_unittest.cc", - "debug/elf_reader_linux_unittest.cc", "debug/leak_tracker_unittest.cc", "debug/proc_maps_linux_unittest.cc", "debug/stack_trace_unittest.cc", @@ -2759,6 +2760,8 @@ sources += [ "nix/xdg_util_unittest.cc" ] } + sources += [ "debug/elf_reader_unittest.cc" ] + deps += [ "//base/test:malloc_wrapper" ] defines += [ # This library is used by ElfReaderTest to test reading elf files. @@ -2782,6 +2785,7 @@ if (is_fuchsia) { sources += [ + "debug/elf_reader_unittest.cc", "files/dir_reader_posix_unittest.cc", "files/file_descriptor_watcher_posix_unittest.cc", "fuchsia/filtered_service_directory_unittest.cc", @@ -2815,7 +2819,7 @@ deps += [ "//testing/android/native_test:native_test_native_code" ] set_sources_assignment_filter([]) sources += [ - "debug/elf_reader_linux_unittest.cc", + "debug/elf_reader_unittest.cc", "debug/proc_maps_linux_unittest.cc", "trace_event/trace_event_android_unittest.cc", ]
diff --git a/base/debug/elf_reader.cc b/base/debug/elf_reader.cc new file mode 100644 index 0000000..a13c846 --- /dev/null +++ b/base/debug/elf_reader.cc
@@ -0,0 +1,166 @@ +// 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 "base/debug/elf_reader.h" + +#include <arpa/inet.h> +#include <elf.h> + +#include "base/bits.h" +#include "base/containers/span.h" +#include "base/sha1.h" +#include "base/strings/safe_sprintf.h" + +// NOTE: This code may be used in crash handling code, so the implementation +// must avoid dynamic memory allocation or using data structures which rely on +// dynamic allocation. + +namespace base { +namespace debug { +namespace { + +#if __SIZEOF_POINTER__ == 4 +using Ehdr = Elf32_Ehdr; +using Dyn = Elf32_Dyn; +using Half = Elf32_Half; +using Nhdr = Elf32_Nhdr; +using Word = Elf32_Word; +#else +using Ehdr = Elf64_Ehdr; +using Dyn = Elf64_Dyn; +using Half = Elf64_Half; +using Nhdr = Elf64_Nhdr; +using Word = Elf64_Word; +#endif + +constexpr char kGnuNoteName[] = "GNU"; + +// Returns a pointer to the header of the ELF binary mapped into memory, +// or a null pointer if the header is invalid. +const Ehdr* GetElfHeader(const void* elf_mapped_base) { + const char* elf_base = reinterpret_cast<const char*>(elf_mapped_base); + if (strncmp(elf_base, ELFMAG, SELFMAG) != 0) + return nullptr; + + const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); + return elf_header; +} + +} // namespace + +span<const Phdr> GetElfProgramHeaders(const void* elf_mapped_base) { + // NOTE: Function should use async signal safe calls only. + + const char* elf_base = reinterpret_cast<const char*>(elf_mapped_base); + const Ehdr* elf_header = GetElfHeader(elf_mapped_base); + if (!elf_header) + return {}; + + return span<const Phdr>( + reinterpret_cast<const Phdr*>(elf_base + elf_header->e_phoff), + elf_header->e_phnum); +} + +size_t ReadElfBuildId(const void* elf_mapped_base, + bool uppercase, + ElfBuildIdBuffer build_id) { + // NOTE: Function should use async signal safe calls only. + + const char* elf_base = reinterpret_cast<const char*>(elf_mapped_base); + const Ehdr* elf_header = GetElfHeader(elf_mapped_base); + if (!elf_header) + return 0; + + for (const Phdr& header : GetElfProgramHeaders(elf_mapped_base)) { + if (header.p_type != PT_NOTE) + continue; + + // Look for a NT_GNU_BUILD_ID note with name == "GNU". + const void* section_end = elf_base + header.p_offset + header.p_memsz; + const Nhdr* current_note = + reinterpret_cast<const Nhdr*>(elf_base + header.p_offset); + bool found = false; + while (current_note < section_end) { + if (current_note->n_type == NT_GNU_BUILD_ID) { + const char* note_name = + reinterpret_cast<const char*>(current_note) + sizeof(Nhdr); + if (current_note->n_namesz == 4 && + strncmp(note_name, kGnuNoteName, 4) == 0) { + found = true; + break; + } + } + + current_note = reinterpret_cast<const Nhdr*>( + reinterpret_cast<const char*>(current_note) + sizeof(Nhdr) + + bits::Align(current_note->n_namesz, 4) + + bits::Align(current_note->n_descsz, 4)); + } + if (!found) + continue; + + // Validate that the serialized build ID will fit inside |build_id|. + size_t note_size = current_note->n_descsz; + if (current_note >= section_end || + (note_size * 2) > kMaxBuildIdStringLength) { + continue; + } + + // Write out the build ID as a null-terminated hex string. + const uint8_t* build_id_raw = + reinterpret_cast<const uint8_t*>(current_note) + sizeof(Nhdr) + + bits::Align(current_note->n_namesz, 4); + size_t i = 0; + for (i = 0; i < current_note->n_descsz; ++i) { + strings::SafeSNPrintf(&build_id[i * 2], 3, (uppercase ? "%02X" : "%02x"), + build_id_raw[i]); + } + build_id[i * 2] = '\0'; + + // Return the length of the string. + return i * 2; + } + + return 0; +} + +Optional<StringPiece> ReadElfLibraryName(const void* elf_mapped_base) { + // NOTE: Function should use async signal safe calls only. + + const char* elf_base = reinterpret_cast<const char*>(elf_mapped_base); + const Ehdr* elf_header = GetElfHeader(elf_mapped_base); + if (!elf_header) + return {}; + + for (const Phdr& header : GetElfProgramHeaders(elf_mapped_base)) { + if (header.p_type != PT_DYNAMIC) + continue; + + // Read through the ELF dynamic sections to find the string table and + // SONAME offsets, which are used to compute the offset of the library + // name string. + const Dyn* dynamic_start = + reinterpret_cast<const Dyn*>(elf_base + header.p_offset); + const Dyn* dynamic_end = reinterpret_cast<const Dyn*>( + elf_base + header.p_offset + header.p_memsz); + Word soname_strtab_offset = 0; + const char* strtab_addr = 0; + for (const Dyn* dynamic_iter = dynamic_start; dynamic_iter < dynamic_end; + ++dynamic_iter) { + if (dynamic_iter->d_tag == DT_STRTAB) { + strtab_addr = + dynamic_iter->d_un.d_ptr + reinterpret_cast<const char*>(elf_base); + } else if (dynamic_iter->d_tag == DT_SONAME) { + soname_strtab_offset = dynamic_iter->d_un.d_val; + } + } + if (soname_strtab_offset && strtab_addr) + return StringPiece(strtab_addr + soname_strtab_offset); + } + + return nullopt; +} + +} // namespace debug +} // namespace base
diff --git a/base/debug/elf_reader.h b/base/debug/elf_reader.h new file mode 100644 index 0000000..8e0f48e6 --- /dev/null +++ b/base/debug/elf_reader.h
@@ -0,0 +1,50 @@ +// 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 BASE_DEBUG_ELF_READER_H_ +#define BASE_DEBUG_ELF_READER_H_ + +#include <elf.h> + +#include "base/base_export.h" +#include "base/containers/span.h" +#include "base/optional.h" +#include "base/sha1.h" +#include "base/strings/string_piece.h" + +// Functions for querying metadata from ELF binaries. +// All functions require that the file be fully memory mapped. + +#if __SIZEOF_POINTER__ == 4 +using Phdr = Elf32_Phdr; +#else +using Phdr = Elf64_Phdr; +#endif + +namespace base { +namespace debug { + +// Hex-encodes the build ID from the ELF binary located at |elf_base|. +// Returns the length of the build ID in bytes, or zero if the build ID couldn't +// be read. +// When |uppercase| is |true|, the output string is written using uppercase hex +// characters. Otherwise, the output is lowercased. +constexpr size_t kMaxBuildIdStringLength = kSHA1Length * 2; +using ElfBuildIdBuffer = char[kMaxBuildIdStringLength + 1]; +size_t BASE_EXPORT ReadElfBuildId(const void* elf_base, + bool uppercase, + ElfBuildIdBuffer build_id); + +// Returns the library name from the ELF file mapped at |elf_base|. +// Returns an empty result if the name could not be read. +Optional<StringPiece> BASE_EXPORT ReadElfLibraryName(const void* elf_base); + +// Returns a span of ELF program headers for the ELF file mapped at +// |elf_base|, or an empty span if the header couldn't be read. +span<const Phdr> BASE_EXPORT GetElfProgramHeaders(const void* elf_base); + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_ELF_READER_H_
diff --git a/base/debug/elf_reader_linux.cc b/base/debug/elf_reader_linux.cc deleted file mode 100644 index cdf8193..0000000 --- a/base/debug/elf_reader_linux.cc +++ /dev/null
@@ -1,132 +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. - -#include "base/debug/elf_reader_linux.h" - -#include <arpa/inet.h> -#include <elf.h> - -#include <vector> - -#include "base/bits.h" -#include "base/containers/span.h" -#include "base/sha1.h" -#include "base/strings/stringprintf.h" - -namespace base { -namespace debug { - -namespace { - -#if __SIZEOF_POINTER__ == 4 -using Ehdr = Elf32_Ehdr; -using Dyn = Elf32_Dyn; -using Half = Elf32_Half; -using Nhdr = Elf32_Nhdr; -using Phdr = Elf32_Phdr; -using Word = Elf32_Word; -#else -using Ehdr = Elf64_Ehdr; -using Dyn = Elf64_Dyn; -using Half = Elf64_Half; -using Nhdr = Elf64_Nhdr; -using Phdr = Elf64_Phdr; -using Word = Elf64_Word; -#endif - -using ElfSegment = span<const char>; - -Optional<std::string> ElfSegmentBuildIDNoteAsString(const ElfSegment& segment) { - const void* section_end = segment.data() + segment.size_bytes(); - const Nhdr* note_header = reinterpret_cast<const Nhdr*>(segment.data()); - while (note_header < section_end) { - if (note_header->n_type == NT_GNU_BUILD_ID) - break; - note_header = reinterpret_cast<const Nhdr*>( - reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) + - bits::Align(note_header->n_namesz, 4) + - bits::Align(note_header->n_descsz, 4)); - } - - if (note_header >= section_end || note_header->n_descsz != kSHA1Length) - return nullopt; - - const uint8_t* guid = reinterpret_cast<const uint8_t*>(note_header) + - sizeof(Nhdr) + bits::Align(note_header->n_namesz, 4); - - uint32_t dword = htonl(*reinterpret_cast<const int32_t*>(guid)); - uint16_t word1 = htons(*reinterpret_cast<const int16_t*>(guid + 4)); - uint16_t word2 = htons(*reinterpret_cast<const int16_t*>(guid + 6)); - std::string identifier; - identifier.reserve(kSHA1Length * 2); // as hex string - SStringPrintf(&identifier, "%08X%04X%04X", dword, word1, word2); - for (size_t i = 8; i < note_header->n_descsz; ++i) - StringAppendF(&identifier, "%02X", guid[i]); - - return identifier; -} - -std::vector<ElfSegment> FindElfSegments(const void* elf_mapped_base, - uint32_t segment_type) { - const char* elf_base = reinterpret_cast<const char*>(elf_mapped_base); - if (strncmp(elf_base, ELFMAG, SELFMAG) != 0) - return std::vector<ElfSegment>(); - - const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); - const Phdr* phdrs = - reinterpret_cast<const Phdr*>(elf_base + elf_header->e_phoff); - std::vector<ElfSegment> segments; - for (Half i = 0; i < elf_header->e_phnum; ++i) { - if (phdrs[i].p_type == segment_type) - segments.push_back({elf_base + phdrs[i].p_offset, phdrs[i].p_filesz}); - } - return segments; -} - -} // namespace - -Optional<std::string> ReadElfBuildId(const void* elf_base) { - // Elf program headers can have multiple PT_NOTE arrays. - std::vector<ElfSegment> segs = FindElfSegments(elf_base, PT_NOTE); - if (segs.empty()) - return nullopt; - Optional<std::string> id; - for (const ElfSegment& seg : segs) { - id = ElfSegmentBuildIDNoteAsString(seg); - if (id) - return id; - } - - return nullopt; -} - -Optional<std::string> ReadElfLibraryName(const void* elf_base) { - std::vector<ElfSegment> segs = FindElfSegments(elf_base, PT_DYNAMIC); - if (segs.empty()) - return nullopt; - DCHECK_EQ(1u, segs.size()); - - const ElfSegment& dynamic_seg = segs.front(); - const Dyn* dynamic_start = reinterpret_cast<const Dyn*>(dynamic_seg.data()); - const Dyn* dynamic_end = reinterpret_cast<const Dyn*>( - dynamic_seg.data() + dynamic_seg.size_bytes()); - Optional<std::string> soname; - Word soname_strtab_offset = 0; - const char* strtab_addr = 0; - for (const Dyn* dynamic_iter = dynamic_start; dynamic_iter < dynamic_end; - ++dynamic_iter) { - if (dynamic_iter->d_tag == DT_STRTAB) { - strtab_addr = - dynamic_iter->d_un.d_ptr + reinterpret_cast<const char*>(elf_base); - } else if (dynamic_iter->d_tag == DT_SONAME) { - soname_strtab_offset = dynamic_iter->d_un.d_val; - } - } - if (soname_strtab_offset && strtab_addr) - return std::string(strtab_addr + soname_strtab_offset); - return nullopt; -} - -} // namespace debug -} // namespace base
diff --git a/base/debug/elf_reader_linux.h b/base/debug/elf_reader_linux.h deleted file mode 100644 index 4086dfb..0000000 --- a/base/debug/elf_reader_linux.h +++ /dev/null
@@ -1,28 +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 BASE_DEBUG_ELF_READER_LINUX_H_ -#define BASE_DEBUG_ELF_READER_LINUX_H_ - -#include <string> - -#include "base/base_export.h" -#include "base/optional.h" - -namespace base { -namespace debug { - -// Returns the ELF section .note.gnu.build-id from the ELF file mapped at -// |elf_base|, if present. The caller must ensure that the file is fully mapped -// in memory. -Optional<std::string> BASE_EXPORT ReadElfBuildId(const void* elf_base); - -// Returns the library name from the ELF file mapped at |elf_base|, if present. -// The caller must ensure that the file is fully mapped in memory. -Optional<std::string> BASE_EXPORT ReadElfLibraryName(const void* elf_base); - -} // namespace debug -} // namespace base - -#endif // BASE_DEBUG_ELF_READER_LINUX_H_
diff --git a/base/debug/elf_reader_linux_unittest.cc b/base/debug/elf_reader_unittest.cc similarity index 60% rename from base/debug/elf_reader_linux_unittest.cc rename to base/debug/elf_reader_unittest.cc index 2c15299..38b14cb 100644 --- a/base/debug/elf_reader_linux_unittest.cc +++ b/base/debug/elf_reader_unittest.cc
@@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/elf_reader_linux.h" +#include "base/debug/elf_reader.h" #include <dlfcn.h> +#include <string> + #include "base/files/memory_mapped_file.h" #include "base/strings/string_util.h" #include "build/build_config.h" @@ -16,22 +18,44 @@ namespace base { namespace debug { -// The linker flag --build-id is passed only on official builds. Clang does not -// enable it by default and we do not have build id section in non-official +// The linker flag --build-id is passed only on official builds and Fuchsia // builds. -#if defined(OFFICIAL_BUILD) -TEST(ElfReaderTest, ReadElfBuildId) { - Optional<std::string> build_id = ReadElfBuildId(&__executable_start); - ASSERT_TRUE(build_id); - const size_t kGuidBytes = 20; - EXPECT_EQ(2 * kGuidBytes, build_id.value().size()); - for (char c : *build_id) { +#if defined(OFFICIAL_BUILD) || defined(OS_FUCHSIA) + +#if defined(OS_FUCHSIA) +constexpr size_t kExpectedBuildIdStringLength = 16; // 64-bit int in hex. +#else +constexpr size_t kExpectedBuildIdStringLength = 40; // SHA1 hash in hex. +#endif + +TEST(ElfReaderTest, ReadElfBuildIdUppercase) { + ElfBuildIdBuffer build_id; + size_t build_id_size = ReadElfBuildId(&__executable_start, true, build_id); + ASSERT_NE(build_id_size, 0u); + + EXPECT_EQ(kExpectedBuildIdStringLength, build_id_size); + for (size_t i = 0; i < build_id_size; ++i) { + char c = build_id[i]; EXPECT_TRUE(IsHexDigit(c)); EXPECT_FALSE(IsAsciiLower(c)); } } -#endif +TEST(ElfReaderTest, ReadElfBuildIdLowercase) { + ElfBuildIdBuffer build_id; + size_t build_id_size = ReadElfBuildId(&__executable_start, false, build_id); + ASSERT_NE(build_id_size, 0u); + + EXPECT_EQ(kExpectedBuildIdStringLength, build_id_size); + for (size_t i = 0; i < kExpectedBuildIdStringLength; ++i) { + char c = build_id[i]; + EXPECT_TRUE(IsHexDigit(c)); + EXPECT_TRUE(!IsAsciiAlpha(c) || IsAsciiLower(c)); + } +} +#endif // defined(OFFICIAL_BUILD) || defined(OS_FUCHSIA) + +#if !defined(OS_FUCHSIA) TEST(ElfReaderTest, ReadElfLibraryName) { #if defined(OS_ANDROID) // On Android the library loader memory maps the full so file. @@ -65,6 +89,7 @@ << "Library name " << *name << " doesn't contain expected " << kLibraryName; } +#endif // !defined(OS_FUCHSIA) } // namespace debug } // namespace base
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index 36a97fe..a5701c7 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -49,7 +49,7 @@ #endif #if defined(OS_ANDROID) -#include "base/debug/elf_reader_linux.h" +#include "base/debug/elf_reader.h" // The linker assigns the virtual address of the start of current library to // this symbol. @@ -1510,11 +1510,12 @@ AddMetadataEventWhileLocked(current_thread_id, "chrome_library_address", "start_address", base::StringPrintf("%p", &__executable_start)); - base::Optional<std::string> buildid = - base::debug::ReadElfBuildId(&__executable_start); - if (buildid) { + base::debug::ElfBuildIdBuffer build_id; + size_t build_id_length = + base::debug::ReadElfBuildId(&__executable_start, true, build_id); + if (build_id_length > 0) { AddMetadataEventWhileLocked(current_thread_id, "chrome_library_module", - "id", buildid.value()); + "id", build_id); } #endif
diff --git a/build/android/bytecode/BUILD.gn b/build/android/bytecode/BUILD.gn index 5aa1ae36..1584bec 100644 --- a/build/android/bytecode/BUILD.gn +++ b/build/android/bytecode/BUILD.gn
@@ -14,8 +14,9 @@ "java/org/chromium/bytecode/ClassPathValidator.java", "java/org/chromium/bytecode/CustomClassLoaderClassWriter.java", "java/org/chromium/bytecode/CustomResourcesClassAdapter.java", - "java/org/chromium/bytecode/TypeUtils.java", + "java/org/chromium/bytecode/SplitCompatClassAdapter.java", "java/org/chromium/bytecode/ThreadAssertionClassAdapter.java", + "java/org/chromium/bytecode/TypeUtils.java", ] main_class = "org.chromium.bytecode.ByteCodeProcessor" deps = [
diff --git a/build/android/bytecode/java/org/chromium/bytecode/ByteCodeProcessor.java b/build/android/bytecode/java/org/chromium/bytecode/ByteCodeProcessor.java index 2b03b8ff..11474216 100644 --- a/build/android/bytecode/java/org/chromium/bytecode/ByteCodeProcessor.java +++ b/build/android/bytecode/java/org/chromium/bytecode/ByteCodeProcessor.java
@@ -61,6 +61,7 @@ private static ClassLoader sDirectClassPathClassLoader; private static ClassLoader sFullClassPathClassLoader; private static Set<String> sFullClassPathJarPaths; + private static Set<String> sSplitCompatClassNames; private static ClassPathValidator sValidator; private static class EntryDataPair { @@ -129,6 +130,10 @@ chain = new CustomResourcesClassAdapter( chain, reader.getClassName(), reader.getSuperName(), sFullClassPathClassLoader); } + if (!sSplitCompatClassNames.isEmpty()) { + chain = new SplitCompatClassAdapter( + chain, sSplitCompatClassNames, sFullClassPathClassLoader); + } reader.accept(chain, 0); byte[] patchedByteCode = writer.toByteArray(); return EntryDataPair.create(entry.getName(), patchedByteCode); @@ -235,6 +240,13 @@ currIndex += directJarsLength; sDirectClassPathClassLoader = loadJars(directClassPathJarPaths); + // Load list of class names that need to be fixed. + int splitCompatClassNamesLength = Integer.parseInt(args[currIndex++]); + sSplitCompatClassNames = new HashSet<>(); + sSplitCompatClassNames.addAll(Arrays.asList( + Arrays.copyOfRange(args, currIndex, currIndex + splitCompatClassNamesLength))); + currIndex += splitCompatClassNamesLength; + // Load all jars that are on the classpath for the input jar for analyzing class hierarchy. sFullClassPathJarPaths = new HashSet<>(); sFullClassPathJarPaths.clear();
diff --git a/build/android/bytecode/java/org/chromium/bytecode/SplitCompatClassAdapter.java b/build/android/bytecode/java/org/chromium/bytecode/SplitCompatClassAdapter.java new file mode 100644 index 0000000..8d6ae69 --- /dev/null +++ b/build/android/bytecode/java/org/chromium/bytecode/SplitCompatClassAdapter.java
@@ -0,0 +1,149 @@ +// Copyright 2019 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.bytecode; + +import static org.objectweb.asm.Opcodes.ACC_PROTECTED; +import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.INVOKESPECIAL; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.RETURN; + +import static org.chromium.bytecode.TypeUtils.CONTEXT; +import static org.chromium.bytecode.TypeUtils.VOID; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.Set; + +/** + * A ClassVisitor for injecting ModuleInstaller.initActivity(activity) method call + * into Activity's attachBaseContext() method. The goal is to eventually invoke + * SplitCompat.install() method if running with the binary that has bundle support + * enabled. This needs to happen for activities that were not built with SplitCompat + * support. + */ +class SplitCompatClassAdapter extends ClassVisitor { + private static final String ANDROID_APP_ACTIVITY_CLASS_NAME = "android/app/Activity"; + private static final String ATTACH_BASE_CONTEXT_METHOD_NAME = "attachBaseContext"; + private static final String ATTACH_BASE_CONTEXT_DESCRIPTOR = + TypeUtils.getMethodDescriptor(VOID, CONTEXT); + + private static final String MODULE_INSTALLER_CLASS_NAME = + "org/chromium/components/module_installer/ModuleInstaller"; + private static final String INIT_ACTIVITY_METHOD_NAME = "initActivity"; + private static final String INIT_ACTIVITY_DESCRIPTOR = + TypeUtils.getMethodDescriptor(VOID, CONTEXT); + + private boolean mShouldTransform; + + private Set<String> mClassNames; + + private ClassLoader mClassLoader; + + /** + * Creates instance of SplitCompatClassAdapter. + * + * @param visitor + * @param classNames Names of classes into which the attachBaseContext method will be + * injected. Currently, we'll only consider classes for bytecode rewriting only if + * they inherit directly from android.app.Activity & not already contain + * attachBaseContext method. + * @param classLoader + */ + SplitCompatClassAdapter(ClassVisitor visitor, Set<String> classNames, ClassLoader classLoader) { + super(Opcodes.ASM5, visitor); + + mShouldTransform = false; + mClassNames = classNames; + mClassLoader = classLoader; + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, + String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces); + + if (mClassNames.contains(name)) { + if (!isSubclassOfActivity(name)) { + throw new RuntimeException(name + + " should be transformed but does not inherit from android.app.Activity"); + } + + mShouldTransform = true; + } + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + // Check if current method matches attachBaseContext & we're supposed to emit code - if so, + // fail. + if (mShouldTransform && name.equals(ATTACH_BASE_CONTEXT_METHOD_NAME)) { + throw new RuntimeException(ATTACH_BASE_CONTEXT_METHOD_NAME + " method already exists"); + } + + return super.visitMethod(access, name, descriptor, signature, exceptions); + } + + @Override + public void visitEnd() { + if (mShouldTransform) { + // If we reached this place, it means we're rewriting a class that inherits from + // Activity and there was no exception thrown due to existence of attachBaseContext + // method - emit code. + emitAttachBaseContext(); + } + + super.visitEnd(); + } + + /** + * Generates: + * + * <pre> + * protected void attachBaseContext(Context base) { + * super.attachBaseContext(base); + * ModuleInstaller.initActivity(this); + * } + * </pre> + */ + private void emitAttachBaseContext() { + MethodVisitor mv = super.visitMethod(ACC_PROTECTED, ATTACH_BASE_CONTEXT_METHOD_NAME, + ATTACH_BASE_CONTEXT_DESCRIPTOR, null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); // load "this" on stack + mv.visitVarInsn(ALOAD, 1); // load first method parameter on stack (Context) + mv.visitMethodInsn(INVOKESPECIAL, ANDROID_APP_ACTIVITY_CLASS_NAME, + ATTACH_BASE_CONTEXT_METHOD_NAME, + ATTACH_BASE_CONTEXT_DESCRIPTOR); // invoke super's attach base context + mv.visitVarInsn(ALOAD, 0); // load "this" on stack + mv.visitMethodInsn(INVOKESTATIC, MODULE_INSTALLER_CLASS_NAME, INIT_ACTIVITY_METHOD_NAME, + INIT_ACTIVITY_DESCRIPTOR); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 2); // max stack size - 2, max locals - 2 + mv.visitEnd(); + } + + /** + * Checks whether passed in class inherits from android.app.Activity. + * @param name Name of the class to be checked. + * @return true if class inherits from android.app.Activity, false otherwise. + */ + private boolean isSubclassOfActivity(String name) { + Class<?> activityClass = loadClass(ANDROID_APP_ACTIVITY_CLASS_NAME); + Class<?> candidateClass = loadClass(name); + return activityClass.isAssignableFrom(candidateClass); + } + + private Class<?> loadClass(String className) { + try { + return mClassLoader.loadClass(className.replace('/', '.')); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +}
diff --git a/build/android/gyp/bytecode_processor.py b/build/android/gyp/bytecode_processor.py index 76775d3..020b52f 100755 --- a/build/android/gyp/bytecode_processor.py +++ b/build/android/gyp/bytecode_processor.py
@@ -36,6 +36,11 @@ _AddSwitch(parser, '--enable-assert') _AddSwitch(parser, '--enable-thread-annotations') _AddSwitch(parser, '--enable-check-class-path') + parser.add_argument( + '--split-compat-class-names', + action='append', + default=[], + help='Names of classes that need to be made SplitCompat-enabled.') args = parser.parse_args(argv) sdk_jars = build_utils.ParseGnList(args.sdk_classpath_jars) @@ -48,6 +53,9 @@ for a in args.extra_jars: extra_classpath_jars.extend(build_utils.ParseGnList(a)) + split_compat_class_names = build_utils.ParseGnList( + args.split_compat_class_names) + if args.verbose: verbose = '--verbose' else: @@ -58,7 +66,9 @@ args.enable_assert, args.enable_custom_resources, args.enable_thread_annotations, args.enable_check_class_path, str(len(sdk_jars)) - ] + sdk_jars + [str(len(direct_jars))] + direct_jars + extra_classpath_jars) + ] + sdk_jars + [str(len(direct_jars))] + direct_jars + [ + str(len(split_compat_class_names)) + ] + split_compat_class_names + extra_classpath_jars) subprocess.check_call(cmd)
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py index 20ffbaa..9c9e7d38 100755 --- a/build/android/gyp/javac.py +++ b/build/android/gyp/javac.py
@@ -183,22 +183,6 @@ shutil.copystat(jar_path, path) -def _ConvertToJMakeArgs(javac_cmd, pdb_path): - new_args = ['bin/jmake', '-pdb', pdb_path, '-jcexec', javac_cmd[0]] - if md5_check.PRINT_EXPLANATIONS: - new_args.append('-Xtiming') - - do_not_prefix = ('-classpath', '-bootclasspath') - skip_next = False - for arg in javac_cmd[1:]: - if not skip_next and arg not in do_not_prefix: - arg = '-C' + arg - new_args.append(arg) - skip_next = arg in do_not_prefix - - return new_args - - def _ParsePackageAndClassNames(java_file): package_name = '' class_names = [] @@ -257,7 +241,7 @@ assert not chromium_code or len(class_names) == 1, ( 'Chromium java files must only have one class: {}'.format(source)) if chromium_code: - # This check is necessary to ensure JMake works. + # This check is not necessary but nice to check this somewhere. _CheckPathMatchesClassName(java_file, package_name, class_names[0]) @@ -307,11 +291,8 @@ logging.info('Completed jar file: %s', jar_path) -def _OnStaleMd5(changes, options, javac_cmd, java_files, classpath_inputs, - classpath): +def _OnStaleMd5(options, javac_cmd, java_files, classpath): logging.info('Starting _OnStaleMd5') - # Don't bother enabling incremental compilation for non-chromium code. - incremental = options.incremental and options.chromium_code # Compiles with Error Prone take twice as long to run as pure javac. Thus GN # rules run both in parallel, with Error Prone only used for checks. @@ -323,42 +304,12 @@ classes_dir = os.path.join(temp_dir, 'classes') os.makedirs(classes_dir) - changed_paths = None - # jmake can handle deleted files, but it's a rare case and it would - # complicate this script's logic. - if incremental and changes.AddedOrModifiedOnly(): - changed_paths = set(changes.IterChangedPaths()) - # Do a full compile if classpath has changed. - # jmake doesn't seem to do this on its own... Might be that ijars mess up - # its change-detection logic. - if any(p in changed_paths for p in classpath_inputs): - changed_paths = None - - if options.incremental: - pdb_path = options.jar_path + '.pdb' - - if incremental: - # jmake is a compiler wrapper that figures out the minimal set of .java - # files that need to be rebuilt given a set of .java files that have - # changed. - # jmake determines what files are stale based on timestamps between .java - # and .class files. Since we use .jars, .srcjars, and md5 checks, - # timestamp info isn't accurate for this purpose. Rather than use jmake's - # programatic interface (like we eventually should), we ensure that all - # .class files are newer than their .java files, and convey to jmake which - # sources are stale by having their .class files be missing entirely - # (by not extracting them). - javac_cmd = _ConvertToJMakeArgs(javac_cmd, pdb_path) - if save_outputs: generated_java_dir = options.generated_dir else: generated_java_dir = os.path.join(temp_dir, 'gen') - # Incremental means not all files will be extracted, so don't bother - # clearing out stale generated files. - if not incremental: - shutil.rmtree(generated_java_dir, True) + shutil.rmtree(generated_java_dir, True) srcjar_files = {} if srcjars: @@ -366,12 +317,8 @@ build_utils.MakeDirectory(generated_java_dir) jar_srcs = [] for srcjar in options.java_srcjars: - if changed_paths: - changed_paths.update(os.path.join(generated_java_dir, f) - for f in changes.IterChangedSubpaths(srcjar)) extracted_files = build_utils.ExtractAll( - srcjar, no_clobber=not incremental, path=generated_java_dir, - pattern='*.java') + srcjar, no_clobber=True, path=generated_java_dir, pattern='*.java') for path in extracted_files: # We want the path inside the srcjar so the viewer can have a tree # structure. @@ -380,28 +327,8 @@ jar_srcs.extend(extracted_files) logging.info('Done extracting srcjars') java_files.extend(jar_srcs) - if changed_paths: - # Set the mtime of all sources to 0 since we use the absence of .class - # files to tell jmake which files are stale. - for path in jar_srcs: - os.utime(path, (0, 0)) if java_files: - if changed_paths: - changed_java_files = [p for p in java_files if p in changed_paths] - if os.path.exists(options.jar_path): - _ExtractClassFiles(options.jar_path, classes_dir, changed_java_files) - # Add the extracted files to the classpath. This is required because - # when compiling only a subset of files, classes that haven't changed - # need to be findable. - classpath.append(classes_dir) - - # Can happen when a target goes from having no sources, to having sources. - # It's created by the call to build_utils.Touch() below. - if incremental: - if os.path.exists(pdb_path) and not os.path.getsize(pdb_path): - os.unlink(pdb_path) - # Don't include the output directory in the initial set of args since it # being in a temp dir makes it unstable (breaks md5 stamping). cmd = javac_cmd + ['-d', classes_dir] @@ -416,33 +343,14 @@ f.write(' '.join(java_files)) cmd += ['@' + java_files_rsp_path] - # JMake prints out some diagnostic logs that we want to ignore. - # This assumes that all compiler output goes through stderr. - stdout_filter = lambda s: '' - if md5_check.PRINT_EXPLANATIONS: - stdout_filter = None - logging.debug('Build command %s', cmd) - attempt_build = lambda: build_utils.CheckOutput( + build_utils.CheckOutput( cmd, print_stdout=options.chromium_code, - stdout_filter=stdout_filter, stderr_filter=ProcessJavacOutput) - try: - attempt_build() - except build_utils.CalledProcessError as e: - # Work-around for a bug in jmake (http://crbug.com/551449). - if ('project database corrupted' not in e.output - and 'jmake: internal Java exception' not in e.output): - raise - logging.error( - 'Applying work-around for jmake project database corrupted ' - '(http://crbug.com/551449).') - os.unlink(pdb_path) - attempt_build() logging.info('Finished build command') - if options.incremental or save_outputs: + if save_outputs: # Creating the jar file takes the longest, start it first on a separate # process to unblock the rest of the post-processing steps. jar_file_worker = multiprocessing.Process( @@ -460,10 +368,6 @@ else: build_utils.Touch(options.jar_path + '.info') - if options.incremental and (not java_files or not incremental): - # Make sure output exists. - build_utils.Touch(pdb_path) - if jar_file_worker: jar_file_worker.join() logging.info('Completed all steps in _OnStaleMd5') @@ -500,11 +404,6 @@ action='append', help='Classpath to use when no annotation processors are present.') parser.add_option( - '--incremental', - action='store_true', - help='Whether to re-use .class files rather than recompiling them ' - '(when possible).') - parser.add_option( '--processors', action='append', help='GN list of annotation processor main classes.') @@ -668,6 +567,7 @@ classpath_inputs = (options.bootclasspath + options.interface_classpath + options.processorpath) + # GN already knows of java_files, so listing them just make things worse when # they change. depfile_deps = [javac_path] + classpath_inputs + options.java_srcjars @@ -677,25 +577,16 @@ options.jar_path, options.jar_path + '.info', ] - if options.incremental: - output_paths.append(options.jar_path + '.pdb') - - # An escape hatch to be able to check if incremental compiles are causing - # problems. - force = int(os.environ.get('DISABLE_INCREMENTAL_JAVAC', 0)) # List python deps in input_strings rather than input_paths since the contents # of them does not change what gets written to the depsfile. build_utils.CallAndWriteDepfileIfStale( - lambda changes: _OnStaleMd5(changes, options, javac_cmd, java_files, - classpath_inputs, classpath), + lambda: _OnStaleMd5(options, javac_cmd, java_files, classpath), options, depfile_deps=depfile_deps, input_paths=input_paths, input_strings=javac_cmd + classpath, output_paths=output_paths, - force=force, - pass_changes=True, add_pydeps=False) logging.info('Script complete: %s', __file__)
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 7050374..77b9b770 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -288,6 +288,9 @@ For some Java related types, a list of extra `.jar` files to use at build time but not at runtime. +* `deps_info['extra_classpath_interface_jars']: +The interface jars corresponding to extra_classpath_jars. + ## <a name="target_java_binary">Target type `java_binary`</a>: This type corresponds to a Java binary, which is nothing more than a @@ -1219,6 +1222,7 @@ # These are .jars to add to javac classpath but not to runtime classpath. extra_jars = build_utils.ParseGnList(options.extra_classpath_jars) deps_info['extra_classpath_jars'] = extra_jars + deps_info['extra_classpath_interface_jars'] = extra_jars if is_java_target: # The classpath used to compile this target when annotation processors are @@ -1240,8 +1244,10 @@ for dep in group_deps: javac_classpath.extend(dep.get('extra_classpath_jars', [])) javac_full_classpath.extend(dep.get('extra_classpath_jars', [])) - javac_interface_classpath.extend(dep.get('extra_classpath_jars', [])) - javac_full_interface_classpath.extend(dep.get('extra_classpath_jars', [])) + javac_interface_classpath.extend( + dep.get('extra_classpath_interface_jars', [])) + javac_full_interface_classpath.extend( + dep.get('extra_classpath_interface_jars', [])) # Deps to add to the compile-time classpath (but not the runtime classpath). # TODO(agrieve): Might be less confusing to fold these into bootclasspath. @@ -1249,24 +1255,39 @@ for c in classpath_deps.Direct('java_library')] extra_jars = [c['jar_path'] for c in classpath_deps.Direct('java_library')] + interface_extra_jars = [ + c['interface_jar_path'] for c in classpath_deps.Direct('java_library') + ] + # These are jars specified by input_jars_paths that almost never change. + # Just add them directly to all the *extra_jars. if options.extra_classpath_jars: # These are .jars to add to javac classpath but not to runtime classpath. javac_extra_jars.extend( build_utils.ParseGnList(options.extra_classpath_jars)) extra_jars.extend(build_utils.ParseGnList(options.extra_classpath_jars)) + interface_extra_jars.extend( + build_utils.ParseGnList(options.extra_classpath_jars)) if extra_jars: deps_info['extra_classpath_jars'] = extra_jars + if interface_extra_jars: + deps_info['extra_classpath_interface_jars'] = interface_extra_jars + javac_extra_jars = [p for p in javac_extra_jars if p not in javac_classpath] javac_classpath.extend(javac_extra_jars) - javac_interface_classpath.extend(javac_extra_jars) - javac_full_interface_classpath.extend( - p for p in javac_extra_jars if p not in javac_full_classpath) javac_full_classpath.extend( p for p in javac_extra_jars if p not in javac_full_classpath) + interface_extra_jars = [ + p for p in interface_extra_jars if p not in javac_interface_classpath + ] + javac_interface_classpath.extend(interface_extra_jars) + javac_full_interface_classpath.extend( + p for p in interface_extra_jars + if p not in javac_full_interface_classpath) + if is_java_target or options.type == 'android_app_bundle': # The classpath to use to run this target (or as an input to ProGuard). java_full_classpath = []
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index 57d7e73..b4a8870 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -107,8 +107,6 @@ <ignore regexp="tools/android/audio_focus_grabber/java/res/drawable-xxxhdpi/notification_icon.png"/> </issue> <issue id="IconDensities"> - <!-- The large assets below only include a few densities to reduce APK size. --> - <ignore regexp="data_reduction_illustration.png"/> <!-- This is intentional to save on WebAPKs' size. --> <ignore regexp="chrome/android/webapk/shell_apk/res/drawable-*"/> <!-- crbug.com/457918 is tracking missing assets -->
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index f3001ac..59f6585 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -201,9 +201,6 @@ # Required for Android M+ due to SELinux policies (stronger sandboxing). disable_incremental_isolated_processes = false - # Speeds up incremental compiles by compiling only changed files. - enable_incremental_javac = false - # Build incremental targets whenever possible. # Ex. with this arg set to true, the chrome_public_apk target result in # chrome_public_apk_incremental being built. @@ -252,11 +249,9 @@ use_hashed_jni_names = !is_java_debug } - # Neither of these should ever be used for release builds since they are - # somewhat experimental and dx --incremental is known to not produce - # byte-for-byte identical output. + # This should not be used for release builds since dx --incremental is known + # to not produce byte-for-byte identical output. assert(!(enable_incremental_dx && !is_java_debug)) - assert(!(enable_incremental_javac && !is_java_debug)) # Path to where selected build variables are written to. android_build_vars = "$root_build_dir/build_vars.txt"
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index d7782ab..3b5b6dd 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -1486,8 +1486,10 @@ _desugar = defined(invoker.supports_android) && invoker.supports_android _emma_instrument = invoker.emma_instrument + _enable_split_compat = defined(invoker.split_compat_class_names) _enable_bytecode_rewriter = - _enable_assert || _enable_custom_resources || _enable_thread_annotations + _enable_assert || _enable_custom_resources || + _enable_thread_annotations || _enable_split_compat _is_prebuilt = defined(invoker.is_prebuilt) && invoker.is_prebuilt _enable_bytecode_checks = !defined(invoker.enable_bytecode_checks) || invoker.enable_bytecode_checks @@ -1570,6 +1572,10 @@ if (_enable_bytecode_checks) { args += [ "--enable-check-class-path" ] } + if (_enable_split_compat) { + args += [ "--split-compat-class-names" ] + + invoker.split_compat_class_names + } args += [ "--direct-classpath-jars", "@FileArg($_rebased_build_config:javac:classpath)", @@ -2756,10 +2762,6 @@ # additional_jar_files: Optional list of files to copy into the resulting # .jar file (by default, only .class files are put there). Each entry # has the 'srcPath:dstPath' format. - # enable_incremental_javac_override: Optional. If provided, determines - # whether incremental javac compilation (based on jmake) is enabled. - # Otherwise, decision is based on the global enable_incremental_javac - # build arg variable. # enable_errorprone: Optional. If True, use the errorprone compiler to # check for error-prone constructs in the language. If not provided, # whether this is enabled depends on chromium_code and the global @@ -2797,14 +2799,6 @@ _additional_jar_files = invoker.additional_jar_files } - if (defined(invoker.enable_incremental_javac_override)) { - # Use invoker-specified override. - _enable_incremental_javac = invoker.enable_incremental_javac_override - } else { - # Default to build arg if not overridden. - _enable_incremental_javac = enable_incremental_javac - } - _srcjar_deps = [] if (defined(invoker.srcjar_deps)) { _srcjar_deps += invoker.srcjar_deps @@ -2861,12 +2855,6 @@ if (defined(invoker.srcjar_filearg)) { args += [ "--java-srcjars=${invoker.srcjar_filearg}" ] } - if (_enable_incremental_javac) { - args += [ "--incremental" ] - deps += [ "//third_party/jmake($default_toolchain)" ] - inputs += [ "$root_build_dir/bin/jmake" ] - outputs += [ "${invoker.javac_jar_path}.pdb" ] - } if (invoker.requires_android) { args += [ "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_interface_jars)" ] } @@ -3401,7 +3389,6 @@ _compile_java_forward_variables = [ "additional_jar_files", "apk_name", - "enable_incremental_javac_override", "processor_args_javac", "provider_configurations", "javac_args", @@ -3493,6 +3480,7 @@ "enable_bytecode_rewriter", "jar_excluded_patterns", "jar_included_patterns", + "split_compat_class_names", ]) is_prebuilt = _is_prebuilt supports_android = _supports_android
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index bff3882..77596b9 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1383,8 +1383,6 @@ # # chromium_code: If true, extra analysis warning/errors will be enabled. # enable_errorprone: If true, enables the errorprone compiler. - # enable_incremental_javac_override: Overrides the global - # enable_incremental_javac. # # jar_excluded_patterns: List of patterns of .class files to exclude. # jar_included_patterns: List of patterns of .class files to include. @@ -3587,6 +3585,10 @@ # extract_native_libraries: Whether to extract .so files found in the .aar. # If the file contains .so, either extract_native_libraries or # ignore_native_libraries must be set. + # split_compat_class_names: Names of the classes that will have their + # bytecode rewritten to inject the call to SplitCompat.install(). + # Used to make dependencies compatible with SplitCompat to immediately + # access resources brought in by the modules. # create_srcjar: If false, does not create an R.java file. # TODO(jbudorick@): remove this arguments after crbug.com/522043 is fixed. # requires_android: Whether this target can only be used for compiling @@ -3763,6 +3765,7 @@ "jar_included_patterns", "proguard_configs", "requires_android", + "split_compat_class_names", "testonly", ]) if (!defined(deps)) {
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni index 063b964..b0aaabb 100644 --- a/build/config/ios/rules.gni +++ b/build/config/ios/rules.gni
@@ -1988,7 +1988,11 @@ "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework", ] - bundle_deps = [ + bundle_deps = [] + if (defined(invoker.bundle_deps)) { + bundle_deps += invoker.bundle_deps + } + bundle_deps += [ ":$_info_plist_bundle", ":$_pkginfo_bundle", ":$_xctest_bundle", @@ -2044,6 +2048,7 @@ ios_xcuitest_test_runner_bundle(_xcuitest_runner_target) { output_name = _xcuitest_runner_output xctest_bundle = _xcuitest_module_target + "_bundle" + forward_variables_from(invoker, [ "bundle_deps" ]) } }
diff --git a/build/config/linux/gtk/BUILD.gn b/build/config/linux/gtk/BUILD.gn index 6624d13..d78f740 100644 --- a/build/config/linux/gtk/BUILD.gn +++ b/build/config/linux/gtk/BUILD.gn
@@ -32,7 +32,7 @@ "//remoting/host/it2me:common", "//remoting/host/it2me:remote_assistance_host", "//remoting/host:common", - "//remoting/host/file_transfer:common", + "//remoting/host/file_transfer", "//remoting/host:remoting_me2me_host_static", "//remoting/test:it2me_standalone_host_main", "//webrtc/examples:peerconnection_client",
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index f8c9a30..43c6efe 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -81b54a7e2b2fff7f5dad246801c3c4b34486abdf \ No newline at end of file +a2ea5f5d6d67ba13062c98cf312f0887aea91cb3 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index eec3a7a4..d6437e4 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -f80285fb56fc829316c85929d34f5fbe9b15b4a9 \ No newline at end of file +8f16de2e93bdcb2442be4935500102658c60a330 \ No newline at end of file
diff --git a/build/toolchain/goma.gni b/build/toolchain/goma.gni index 0e1d815..2fbf572 100644 --- a/build/toolchain/goma.gni +++ b/build/toolchain/goma.gni
@@ -27,6 +27,3 @@ } } } - -assert(!(is_win && host_os != "win") || !use_goma, - "goma does not yet work in win cross builds, b/64390790")
diff --git a/build/util/lastchange.py b/build/util/lastchange.py index bf38785..81c7431 100755 --- a/build/util/lastchange.py +++ b/build/util/lastchange.py
@@ -7,23 +7,20 @@ lastchange.py -- Chromium revision fetching utility. """ -import argparse -import collections +import re import logging +import argparse import os import subprocess import sys -VersionInfo = collections.namedtuple("VersionInfo", - ("revision_id", "revision", "timestamp")) +class VersionInfo(object): + def __init__(self, revision_id, full_revision_string, timestamp): + self.revision_id = revision_id + self.revision = full_revision_string + self.timestamp = timestamp -class GitError(Exception): - pass -# This function exists for compatibility with logic outside this -# repository that uses this file as a library. -# TODO(eliribble) remove this function after it has been ported into -# the repositories that depend on it def RunGitCommand(directory, command): """ Launches git subcommand. @@ -52,95 +49,53 @@ return None -def _RunGitCommand(directory, command): - """Launches git subcommand. - - Returns: - The stripped stdout of the git command. - Raises: - GitError on failure, including a nonzero return code. - """ - command = ['git'] + command - # Force shell usage under cygwin. This is a workaround for - # mysterious loss of cwd while invoking cygwin's git. - # We can't just pass shell=True to Popen, as under win32 this will - # cause CMD to be used, while we explicitly want a cygwin shell. - if sys.platform == 'cygwin': - command = ['sh', '-c', ' '.join(command)] - try: - logging.info("Executing '%s' in %s", ' '.join(command), directory) - proc = subprocess.Popen(command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=directory, - shell=(sys.platform=='win32')) - stdout, stderr = proc.communicate() - stdout = stdout.strip() - logging.debug("returncode: %d", proc.returncode) - logging.debug("stdout: %s", stdout) - logging.debug("stderr: %s", stderr) - if proc.returncode != 0 or not stdout: - raise GitError(( - "Git command 'git {}' in {} failed: " - "rc={}, stdout='{}' stderr='{}'").format( - " ".join(command), directory, proc.returncode, stdout, stderr)) - return stdout - except OSError as e: - raise GitError("Git command 'git {}' in {} failed: {}".format( - " ".join(command), directory, e)) - - -def GetMergeBase(directory, ref): - """ - Return the merge-base of HEAD and ref. - - Args: - directory: The directory containing the .git directory. - ref: The ref to use to find the merge base. - Returns: - The git commit SHA of the merge-base as a string. - """ - logging.debug("Calculating merge base between HEAD and %s in %s", - ref, directory) - command = ['merge-base', 'HEAD', ref] - return _RunGitCommand(directory, command) - - -def FetchGitRevision(directory, commit_filter, start_commit="HEAD"): +def FetchGitRevision(directory, git_log_filter): """ Fetch the Git hash (and Cr-Commit-Position if any) for a given directory. + Errors are swallowed. + Args: - directory: The directory containing the .git directory. - commit_filter: A filter to supply to grep to filter commits - start_commit: A commit identifier. The result of this function - will be limited to only consider commits before the provided - commit. + git_log_filter: a string to be used for filtering git log result. + Returns: - A VersionInfo object. On error all values will be 0. + A VersionInfo object or None on error. """ - hash_ = '' - + hsh = '' git_args = ['log', '-1', '--format=%H %ct'] - if commit_filter is not None: - git_args.append('--grep=' + commit_filter) + if git_log_filter is not None: + git_args.append('--grep=' + git_log_filter) + proc = RunGitCommand(directory, git_args) + if proc: + output = proc.communicate()[0].strip() + if proc.returncode == 0 and output: + hsh, ct = output.split() + else: + logging.error('Git error: rc=%d, output=%r' % + (proc.returncode, output)) + if not hsh: + return None + pos = '' + proc = RunGitCommand(directory, ['cat-file', 'commit', hsh]) + if proc: + output = proc.communicate()[0] + if proc.returncode == 0 and output: + for line in reversed(output.splitlines()): + if line.startswith('Cr-Commit-Position:'): + pos = line.rsplit()[-1].strip() + break + return VersionInfo(hsh, '%s-%s' % (hsh, pos), int(ct)) - git_args.append(start_commit) - output = _RunGitCommand(directory, git_args) - hash_, commit_timestamp = output.split() - if not hash_: - return VersionInfo('0', '0', 0) - - revision = hash_ - output = _RunGitCommand(directory, ['cat-file', 'commit', hash_]) - for line in reversed(output.splitlines()): - if line.startswith('Cr-Commit-Position:'): - pos = line.rsplit()[-1].strip() - logging.debug("Found Cr-Commit-Position '%s'", pos) - revision = "{}-{}".format(hash_, pos) - break - return VersionInfo(hash_, revision, int(commit_timestamp)) +def FetchVersionInfo(directory=None, git_log_filter=None): + """ + Returns the last change (as a VersionInfo object) + from some appropriate revision control system. + """ + version_info = FetchGitRevision(directory, git_log_filter) + if not version_info: + version_info = VersionInfo('0', '0', 0) + return version_info def GetHeaderGuard(path): @@ -181,17 +136,6 @@ return header_contents -def GetGitTopDirectory(source_dir): - """Get the top git directory - the directory that contains the .git directory. - - Args: - source_dir: The directory to search. - Returns: - The output of "git rev-parse --show-toplevel" as a string - """ - return _RunGitCommand(source_dir, ['rev-parse', '--show-toplevel']) - - def WriteIfChanged(file_name, contents): """ Writes the specified contents to the specified file_name @@ -216,23 +160,20 @@ parser = argparse.ArgumentParser(usage="lastchange.py [options]") parser.add_argument("-m", "--version-macro", - help=("Name of C #define when using --header. Defaults to " - "LAST_CHANGE.")) + help="Name of C #define when using --header. Defaults to " + + "LAST_CHANGE.", + default="LAST_CHANGE") parser.add_argument("-o", "--output", metavar="FILE", - help=("Write last change to FILE. " - "Can be combined with --header to write both files.")) + help="Write last change to FILE. " + + "Can be combined with --header to write both files.") parser.add_argument("--header", metavar="FILE", help=("Write last change to FILE as a C/C++ header. " "Can be combined with --output to write both files.")) - parser.add_argument("--merge-base-ref", - default=None, - help=("Only consider changes since the merge " - "base between HEAD and the provided ref")) parser.add_argument("--revision-id-only", action='store_true', help=("Output the revision as a VCS revision ID only (in " "Git, a 40-character commit hash, excluding the " "Cr-Commit-Position).")) - parser.add_argument("--print-only", action="store_true", + parser.add_argument("--print-only", action='store_true', help=("Just print the revision string. Overrides any " "file-output-related options.")) parser.add_argument("-s", "--source-dir", metavar="DIR", @@ -242,14 +183,13 @@ "matches the supplied filter regex. Defaults to " "'^Change-Id:' to suppress local commits."), default='^Change-Id:') - args, extras = parser.parse_known_args(argv[1:]) logging.basicConfig(level=logging.WARNING) out_file = args.output header = args.header - commit_filter=args.filter + git_log_filter=args.filter while len(extras) and out_file is None: if out_file is None: @@ -259,37 +199,19 @@ parser.print_help() sys.exit(2) - source_dir = args.source_dir or os.path.dirname(os.path.abspath(__file__)) - try: - git_top_dir = GetGitTopDirectory(source_dir) - except GitError as e: - logging.error("Failed to get git top directory from '%s': %s", - source_dir, e) - return 2 - - if args.merge_base_ref: - try: - merge_base_sha = GetMergeBase(git_top_dir, args.merge_base_ref) - except GitError as e: - logging.error("You requested a --merge-base-ref value of '%s' but no " - "merge base could be found between it and HEAD. Git " - "reports: %s", args.merge_base_ref, e) - return 3 + if args.source_dir: + src_dir = args.source_dir else: - merge_base_sha = 'HEAD' + src_dir = os.path.dirname(os.path.abspath(__file__)) - try: - version_info = FetchGitRevision(git_top_dir, commit_filter, merge_base_sha) - except GitError as e: - logging.error("Failed to get version info: %s") - return 1 - + version_info = FetchVersionInfo(directory=src_dir, + git_log_filter=git_log_filter) revision_string = version_info.revision if args.revision_id_only: revision_string = version_info.revision_id if args.print_only: - print(revision_string) + print revision_string else: contents = "LASTCHANGE=%s\n" % revision_string if not out_file and not args.header:
diff --git a/buildtools/third_party/libc++/BUILD.gn b/buildtools/third_party/libc++/BUILD.gn index 1d17b3f..b6af43e 100644 --- a/buildtools/third_party/libc++/BUILD.gn +++ b/buildtools/third_party/libc++/BUILD.gn
@@ -123,7 +123,7 @@ ] } } - if (is_asan || is_tsan || is_msan) { + if (!is_mac && (is_asan || is_tsan || is_msan)) { # In {a,t,m}san configurations, operator new and operator delete will be # provided by the sanitizer runtime library. Since libc++ defines these # symbols with weak linkage, and the *san runtime uses strong linkage, it
diff --git a/cc/layers/scrollbar_layer_impl_base.cc b/cc/layers/scrollbar_layer_impl_base.cc index 24a855e2f..768048fe 100644 --- a/cc/layers/scrollbar_layer_impl_base.cc +++ b/cc/layers/scrollbar_layer_impl_base.cc
@@ -87,6 +87,12 @@ const auto* scroll_node = property_trees->scroll_tree.FindNodeFromElementId(scroll_element_id_); DCHECK(scroll_node); + // TODO(bokan): Looks like we sometimes get here without a ScrollNode. It + // should be safe to just return false here (we don't use scroll_element_id_ + // anywhere else) so we can merge the fix. Once merged, will investigate the + // underlying cause. https://crbug.com/924068. + if (!scroll_node) + return false; if (orientation() == ScrollbarOrientation::HORIZONTAL) { if (!scroll_node->user_scrollable_horizontal)
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc index 7611dd0..afe7d8e 100644 --- a/cc/layers/surface_layer.cc +++ b/cc/layers/surface_layer.cc
@@ -40,13 +40,14 @@ deadline_policy.use_existing_deadline()) { return; } - - TRACE_EVENT_WITH_FLOW2( - TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), - "LocalSurfaceId.Embed.Flow", - TRACE_ID_GLOBAL(surface_id.local_surface_id().embed_trace_id()), - TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step", - "SetSurfaceId", "surface_id", surface_id.ToString()); + if (surface_id.local_surface_id().is_valid()) { + TRACE_EVENT_WITH_FLOW2( + TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), + "LocalSurfaceId.Embed.Flow", + TRACE_ID_GLOBAL(surface_id.local_surface_id().embed_trace_id()), + TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step", + "SetSurfaceId", "surface_id", surface_id.ToString()); + } if (layer_tree_host() && surface_range_.IsValid()) layer_tree_host()->RemoveSurfaceRange(surface_range_);
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc index 3b411aa7..36c4dc3 100644 --- a/cc/layers/surface_layer_impl.cc +++ b/cc/layers/surface_layer_impl.cc
@@ -43,7 +43,8 @@ return; } - if (surface_range_.end() != surface_range.end()) { + if (surface_range_.end() != surface_range.end() && + surface_range.end().local_surface_id().is_valid()) { TRACE_EVENT_WITH_FLOW2( TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), "LocalSurfaceId.Embed.Flow", @@ -54,7 +55,8 @@ } if (surface_range.start() && - surface_range_.start() != surface_range.start()) { + surface_range_.start() != surface_range.start() && + surface_range.start()->local_surface_id().is_valid()) { TRACE_EVENT_WITH_FLOW2( TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), "LocalSurfaceId.Submission.Flow",
diff --git a/cc/paint/draw_image.cc b/cc/paint/draw_image.cc index 984ccd5c..f7d5cbe 100644 --- a/cc/paint/draw_image.cc +++ b/cc/paint/draw_image.cc
@@ -28,6 +28,14 @@ scale_(SkSize::Make(1.f, 1.f)), matrix_is_decomposable_(true) {} +DrawImage::DrawImage(PaintImage image) + : paint_image_(std::move(image)), + src_rect_( + SkIRect::MakeXYWH(0, 0, paint_image_.width(), paint_image_.height())), + filter_quality_(kNone_SkFilterQuality), + scale_(SkSize::Make(1.f, 1.f)), + matrix_is_decomposable_(true) {} + DrawImage::DrawImage(PaintImage image, const SkIRect& src_rect, SkFilterQuality filter_quality,
diff --git a/cc/paint/draw_image.h b/cc/paint/draw_image.h index 615b25e..6365379 100644 --- a/cc/paint/draw_image.h +++ b/cc/paint/draw_image.h
@@ -24,6 +24,7 @@ class CC_PAINT_EXPORT DrawImage { public: DrawImage(); + explicit DrawImage(PaintImage image); DrawImage(PaintImage image, const SkIRect& src_rect, SkFilterQuality filter_quality,
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index 1a6d63a7..654bdee 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -1205,8 +1205,22 @@ const PaintFlags* flags, SkCanvas* canvas, const PlaybackParams& params) { + // TODO(crbug.com/931704): make sure to support the case where paint worklet + // generated images are used in other raster work such as canvas2d. SkPaint paint = flags ? flags->ToSkPaint() : SkPaint(); + if (op->image.IsPaintWorklet()) { + DCHECK(params.image_provider); + ImageProvider::ScopedResult result = + params.image_provider->GetRasterContent(DrawImage(op->image)); + + DCHECK(IsScaleAdjustmentIdentity(op->scale_adjustment)); + SkAutoCanvasRestore save_restore(canvas, true); + canvas->translate(op->left, op->top); + result.paint_record()->Playback(canvas, params); + return; + } + if (!params.image_provider) { const bool needs_scale = !IsScaleAdjustmentIdentity(op->scale_adjustment); SkAutoCanvasRestore save_restore(canvas, needs_scale); @@ -1245,6 +1259,7 @@ canvas->drawImage(decoded_image.image().get(), op->left, op->top, &paint); } +// TODO(xidachen): ensure paint worklet generated images are correctly handled. void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op, const PaintFlags* flags, SkCanvas* canvas, @@ -2393,8 +2408,6 @@ PlaybackParams new_params(params.image_provider, canvas->getTotalMatrix(), params.custom_callback, params.did_draw_op_callback); - // TODO(xidachen): retrieve the PaintRecord stored in PaintWorkletImageCache, - // from the PaintWorkletImageProvider in the params. for (PlaybackFoldingIterator iter(this, offsets); iter; ++iter) { const PaintOp* op = *iter;
diff --git a/cc/paint/paint_op_buffer_serializer.cc b/cc/paint/paint_op_buffer_serializer.cc index f7f7f4f..fe4028b 100644 --- a/cc/paint/paint_op_buffer_serializer.cc +++ b/cc/paint/paint_op_buffer_serializer.cc
@@ -84,9 +84,9 @@ context_supports_distance_field_text), text_blob_canvas_(kMaxExtent, kMaxExtent, - SkMatrix::I(), ComputeSurfaceProps(can_use_lcd_text), strike_server, + nullptr, // colorspace MakeCanvasSettings(context_supports_distance_field_text, max_texture_size, max_texture_bytes)) {
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 22a3bbbc..e6204aaf 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -20,6 +20,7 @@ #include "cc/test/paint_op_helper.h" #include "cc/test/skia_common.h" #include "cc/test/test_options_provider.h" +#include "cc/test/test_paint_worklet_input.h" #include "cc/test/test_skcanvas.h" #include "cc/test/transfer_cache_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" @@ -429,6 +430,15 @@ EXPECT_TRUE(buffer.HasDiscardableImages()); } +TEST(PaintOpBufferTest, DiscardableImagesTracking_PaintWorkletImage) { + scoped_refptr<TestPaintWorkletInput> input = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(32.0f, 32.0f)); + PaintOpBuffer buffer; + PaintImage image = CreatePaintWorkletPaintImage(input); + buffer.push<DrawImageOp>(image, SkIntToScalar(0), SkIntToScalar(0), nullptr); + EXPECT_TRUE(buffer.HasDiscardableImages()); +} + TEST(PaintOpBufferTest, DiscardableImagesTracking_DrawImageRect) { PaintOpBuffer buffer; PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100)); @@ -2711,9 +2721,16 @@ ~MockImageProvider() override = default; + void DoNothing() {} + ImageProvider::ScopedResult GetRasterContent( const DrawImage& draw_image) override { - DCHECK(!draw_image.paint_image().IsPaintWorklet()); + if (draw_image.paint_image().IsPaintWorklet()) { + auto callback = + base::BindOnce(&MockImageProvider::DoNothing, base::Unretained(this)); + return ScopedResult(record_, std::move(callback)); + } + if (fail_all_decodes_) return ImageProvider::ScopedResult(); @@ -2726,12 +2743,15 @@ quality_[i], true)); } + void SetRecord(PaintRecord* record) { record_ = record; } + private: std::vector<SkSize> src_rect_offset_; std::vector<SkSize> scale_; std::vector<SkFilterQuality> quality_; size_t index_ = 0; bool fail_all_decodes_ = false; + PaintRecord* record_; }; TEST(PaintOpBufferTest, SkipsOpsOutsideClip) { @@ -2827,6 +2847,78 @@ return true; } +TEST(PaintOpBufferTest, RasterPaintWorkletImage1) { + PaintOpBuffer paint_worklet_buffer; + PaintFlags noop_flags; + SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 100, 100); + paint_worklet_buffer.push<TranslateOp>(8.0f, 8.0f); + paint_worklet_buffer.push<SaveLayerOp>(&savelayer_rect, &noop_flags); + PaintFlags draw_flags; + draw_flags.setColor(0u); + SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100); + paint_worklet_buffer.push<DrawRectOp>(rect, draw_flags); + + MockImageProvider provider; + provider.SetRecord(&paint_worklet_buffer); + + PaintOpBuffer blink_buffer; + scoped_refptr<TestPaintWorkletInput> input = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100, 100)); + PaintImage image = CreatePaintWorkletPaintImage(input); + blink_buffer.push<DrawImageOp>(image, 0.0f, 0.0f, nullptr); + + testing::StrictMock<MockCanvas> canvas; + testing::Sequence s; + + EXPECT_CALL(canvas, willSave()).InSequence(s); + EXPECT_CALL(canvas, didConcat(SkMatrix::MakeTrans(8.0f, 8.0f))); + EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s); + EXPECT_CALL(canvas, OnDrawRectWithColor(0u)); + EXPECT_CALL(canvas, willRestore()).InSequence(s); + EXPECT_CALL(canvas, willRestore()).InSequence(s); + + blink_buffer.Playback(&canvas, PlaybackParams(&provider)); +} + +TEST(PaintOpBufferTest, RasterPaintWorkletImage2) { + PaintOpBuffer paint_worklet_buffer; + PaintFlags noop_flags; + SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 10, 10); + paint_worklet_buffer.push<SaveLayerOp>(&savelayer_rect, &noop_flags); + PaintFlags draw_flags; + draw_flags.setFilterQuality(kLow_SkFilterQuality); + PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10)); + paint_worklet_buffer.push<DrawImageOp>(paint_image, 0.0f, 0.0f, &draw_flags); + + std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()}; + std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)}; + std::vector<SkFilterQuality> quality = {kHigh_SkFilterQuality}; + MockImageProvider provider(src_rect_offset, scale_adjustment, quality); + provider.SetRecord(&paint_worklet_buffer); + + PaintOpBuffer blink_buffer; + scoped_refptr<TestPaintWorkletInput> input = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100, 100)); + PaintImage image = CreatePaintWorkletPaintImage(input); + blink_buffer.push<DrawImageOp>(image, 5.0f, 7.0f, nullptr); + + testing::StrictMock<MockCanvas> canvas; + testing::Sequence s; + + EXPECT_CALL(canvas, willSave()).InSequence(s); + EXPECT_CALL(canvas, didConcat(SkMatrix::MakeTrans(5.0f, 7.0f))); + EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s); + EXPECT_CALL(canvas, willSave()).InSequence(s); + EXPECT_CALL(canvas, didConcat(MatchesInvScale(scale_adjustment[0]))); + EXPECT_CALL(canvas, onDrawImage(NonLazyImage(), 0.0f, 0.0f, + MatchesQuality(quality[0]))); + EXPECT_CALL(canvas, willRestore()).InSequence(s); + EXPECT_CALL(canvas, willRestore()).InSequence(s); + EXPECT_CALL(canvas, willRestore()).InSequence(s); + + blink_buffer.Playback(&canvas, PlaybackParams(&provider)); +} + TEST(PaintOpBufferTest, ReplacesImagesFromProvider) { std::vector<SkSize> src_rect_offset = { SkSize::MakeEmpty(), SkSize::Make(2.0f, 2.0f), SkSize::Make(3.0f, 3.0f)};
diff --git a/cc/tiles/paint_worklet_image_cache.cc b/cc/tiles/paint_worklet_image_cache.cc index 9565fb3..f9d9d42 100644 --- a/cc/tiles/paint_worklet_image_cache.cc +++ b/cc/tiles/paint_worklet_image_cache.cc
@@ -49,6 +49,8 @@ // Do check the cache first. If there is already a cache entry for this input, // then there is no need to call the Paint() function. void PaintWorkletImageCache::PaintImageInTask(const PaintImage& paint_image) { + // TODO(xidachen): ensure that the canvas operations in the PaintRecord + // matches the PaintGeneratedImage::Draw. sk_sp<PaintRecord> record = painter_->Paint(); records_[paint_image.paint_worklet_input()] = PaintWorkletImageCacheValue(std::move(record), 0);
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 1f18015..a1c0c47 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -147,8 +147,8 @@ enum MainOrder : int { MAIN_START = 1, MAIN_LAYOUT, - MAIN_COMMIT_COMPLETE, MAIN_DID_BEGIN_FRAME, + MAIN_COMMIT_COMPLETE, MAIN_END, };
diff --git a/cc/trees/layer_tree_mutator.h b/cc/trees/layer_tree_mutator.h index c3d6fbe..696b95c 100644 --- a/cc/trees/layer_tree_mutator.h +++ b/cc/trees/layer_tree_mutator.h
@@ -18,6 +18,17 @@ namespace cc { +enum class MutateQueuingStrategy { + kDrop, // Discard request if busy. + kQueueAndReplace // Queue request if busy replacing previously queued + // request. +}; + +enum class MutateStatus { + kCompleted, // Mutation cycle successfully ran to completion. + kCanceled // Mutation cycle dropped from the input queue. +}; + struct CC_EXPORT WorkletAnimationId { // Uniquely identifies the animation worklet with which this animation is // associated.
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc index e0683e5..7218721 100644 --- a/cc/trees/proxy_main.cc +++ b/cc/trees/proxy_main.cc
@@ -236,6 +236,8 @@ skip_commit |= defer_main_frame_update_ || defer_commits_; if (skip_commit) { + current_pipeline_stage_ = NO_PIPELINE_STAGE; + layer_tree_host_->DidBeginMainFrame(); TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame", TRACE_EVENT_SCOPE_THREAD); layer_tree_host_->RecordEndOfFrameMetrics(begin_main_frame_start_time); @@ -246,10 +248,8 @@ CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, begin_main_frame_start_time, base::Passed(&empty_swap_promises))); - current_pipeline_stage_ = NO_PIPELINE_STAGE; // We intentionally don't report CommitComplete() here since it was aborted // prematurely and we're waiting to do another commit in the future. - layer_tree_host_->DidBeginMainFrame(); // When we stop deferring commits, we should resume any previously requested // pipeline stages. deferred_final_pipeline_stage_ = final_pipeline_stage_; @@ -284,6 +284,8 @@ current_pipeline_stage_ = COMMIT_PIPELINE_STAGE; if (final_pipeline_stage_ < COMMIT_PIPELINE_STAGE) { + current_pipeline_stage_ = NO_PIPELINE_STAGE; + layer_tree_host_->DidBeginMainFrame(); TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD); layer_tree_host_->RecordEndOfFrameMetrics(begin_main_frame_start_time); std::vector<std::unique_ptr<SwapPromise>> swap_promises = @@ -298,9 +300,7 @@ // Although the commit is internally aborted, this is because it has been // detected to be a no-op. From the perspective of an embedder, this commit // went through, and input should no longer be throttled, etc. - current_pipeline_stage_ = NO_PIPELINE_STAGE; layer_tree_host_->CommitComplete(); - layer_tree_host_->DidBeginMainFrame(); return; } @@ -314,6 +314,9 @@ layer_tree_host_->QueueSwapPromise( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); + current_pipeline_stage_ = NO_PIPELINE_STAGE; + layer_tree_host_->DidBeginMainFrame(); + // Notify the impl thread that the main thread is ready to commit. This will // begin the commit process, which is blocking from the main thread's // point of view, but asynchronously performed on the impl thread, @@ -336,9 +339,7 @@ completion.Wait(); } - current_pipeline_stage_ = NO_PIPELINE_STAGE; layer_tree_host_->CommitComplete(); - layer_tree_host_->DidBeginMainFrame(); } void ProxyMain::DidPresentCompositorFrame(
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 874079d..056cfe70 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc
@@ -231,8 +231,8 @@ << "Activation is expected to have synchronously occurred by now."; DebugScopedSetMainThread main(task_runner_provider_); - layer_tree_host_->CommitComplete(); layer_tree_host_->DidBeginMainFrame(); + layer_tree_host_->CommitComplete(); next_frame_is_newly_committed_frame_ = true; }
diff --git a/chrome/android/java/res/drawable-mdpi/data_reduction_illustration.png b/chrome/android/java/res/drawable-mdpi/data_reduction_illustration.png deleted file mode 100644 index 1e04158..0000000 --- a/chrome/android/java/res/drawable-mdpi/data_reduction_illustration.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/data_reduction_illustration.png b/chrome/android/java/res/drawable-xxhdpi/data_reduction_illustration.png deleted file mode 100644 index 5261aef7..0000000 --- a/chrome/android/java/res/drawable-xxhdpi/data_reduction_illustration.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable/data_reduction_illustration.xml b/chrome/android/java/res/drawable/data_reduction_illustration.xml new file mode 100644 index 0000000..ec8e23f6 --- /dev/null +++ b/chrome/android/java/res/drawable/data_reduction_illustration.xml
@@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 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. --> + +<!-- VectorRaster warning is ignored because we intentionally want the width to + be greater than 200. --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + tools:targetApi="21" + tools:ignore="VectorRaster" + android:width="232dp" + android:height="107dp" + android:viewportWidth="232" + android:viewportHeight="107"> + <path + android:pathData="M156.91,3.733l18.155,31.59l-90.126,-1.508l12.968,-31.662z" + android:strokeWidth="1" + android:fillColor="#F1F3F4" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M227.729,52.338L225.928,52.338C224.703,52.338 223.694,51.333 223.694,50.113L223.694,44.369C223.694,43.149 224.703,42.144 225.928,42.144L227.729,42.144C228.954,42.144 229.962,43.149 229.962,44.369L229.962,50.113C230.034,51.333 229.026,52.338 227.729,52.338Z" + android:strokeWidth="1" + android:fillColor="#E1741F" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M115.125,1.149h2.089v39.056h-2.089z" + android:strokeWidth="1" + android:fillColor="#DADCE0" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M49.638,81.128L205.612,81.128C217.283,81.128 226.72,71.723 226.72,60.092L226.72,37.836C226.72,35.467 224.775,33.528 222.398,33.528L32.419,33.528C30.186,33.528 28.313,35.323 28.313,37.621L28.313,59.949C28.313,71.651 37.895,81.128 49.638,81.128Z" + android:strokeWidth="1" + android:fillColor="#F9BB2D" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M74.764,106.115a25.924,22.906 104.033,1 0,12.573 -50.301a25.924,22.906 104.033,1 0,-12.573 50.301z" + android:strokeWidth="1" + android:fillColor="#3C4043" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M78.334,91.832a11.203,9.94 104.033,1 0,5.433 -21.737a11.203,9.94 104.033,1 0,-5.433 21.737z" + android:strokeWidth="1" + android:fillColor="#DADCE0" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M175.629,106.111a25.924,22.906 104.033,1 0,12.573 -50.301a25.924,22.906 104.033,1 0,-12.573 50.301z" + android:strokeWidth="1" + android:fillColor="#3C4043" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M179.199,91.828a11.203,9.94 104.033,1 0,5.433 -21.737a11.203,9.94 104.033,1 0,-5.433 21.737z" + android:strokeWidth="1" + android:fillColor="#DADCE0" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M227.801,77.682L223.118,77.682C221.101,77.682 219.444,76.031 219.444,74.021L219.444,71.149C219.444,69.138 221.101,67.487 223.118,67.487L227.801,67.487C229.818,67.487 231.475,69.138 231.475,71.149L231.475,74.021C231.475,76.031 229.818,77.682 227.801,77.682Z" + android:strokeWidth="1" + android:fillColor="#BDC1C6" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M38.975,77.682L26.728,77.682C24.567,77.682 22.766,75.887 22.766,73.733L22.766,71.364C22.766,69.21 24.567,67.415 26.728,67.415L38.903,67.415C41.065,67.415 42.866,69.21 42.866,71.364L42.866,73.733C42.938,75.959 41.137,77.682 38.975,77.682Z" + android:strokeWidth="1" + android:fillColor="#BDC1C6" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M79.752,12.851L14.697,12.851C12.752,12.851 11.239,11.272 11.239,9.405L11.239,9.405C11.239,7.467 12.824,5.959 14.697,5.959L79.752,5.959C81.697,5.959 83.21,7.538 83.21,9.405L83.21,9.405C83.21,11.272 81.697,12.851 79.752,12.851Z" + android:strokeWidth="1" + android:fillColor="#DADCE0" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M12.608,30.872L3.962,30.872C2.017,30.872 0.504,29.292 0.504,27.426L0.504,27.426C0.504,25.487 2.089,23.979 3.962,23.979L12.608,23.979C14.553,23.979 16.066,25.559 16.066,27.426L16.066,27.426C16.138,29.292 14.553,30.872 12.608,30.872Z" + android:strokeWidth="1" + android:fillColor="#DADCE0" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M37.967,48.821L12.103,48.821C10.158,48.821 8.645,47.241 8.645,45.374L8.645,45.374C8.645,43.436 10.23,41.928 12.103,41.928L37.967,41.928C39.912,41.928 41.425,43.508 41.425,45.374L41.425,45.374C41.497,47.313 39.912,48.821 37.967,48.821Z" + android:strokeWidth="1" + android:fillColor="#DADCE0" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M98.267,48.821L52.664,48.821C50.718,48.821 49.206,47.241 49.206,45.374L49.206,45.374C49.206,43.436 50.791,41.928 52.664,41.928L98.267,41.928C100.212,41.928 101.725,43.508 101.725,45.374L101.725,45.374C101.725,47.313 100.212,48.821 98.267,48.821Z" + android:strokeWidth="1" + android:fillColor="#DADCE0" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M47.765,35.897C47.188,35.897 46.9,35.395 47.188,34.964L72.115,3.949C74.133,1.436 77.158,-0 80.328,-0L157.198,-0C158.207,-0 159,0.862 159,1.867L159,2.154C159,3.159 158.207,4.021 157.198,4.021L105.039,4.021C102.374,4.021 99.996,5.528 98.771,7.897L84.939,34.892C84.651,35.467 83.93,35.897 83.138,35.897L47.765,35.897L47.765,35.897Z" + android:strokeWidth="1" + android:fillColor="#3C4043" + android:fillType="nonZero" + android:strokeColor="#00000000"/> + <path + android:pathData="M96.394,30.872L26.584,30.872C24.639,30.872 23.126,29.292 23.126,27.426L23.126,27.426C23.126,25.487 24.711,23.979 26.584,23.979L96.394,23.979C98.339,23.979 99.852,25.559 99.852,27.426L99.852,27.426C99.924,29.292 98.339,30.872 96.394,30.872Z" + android:strokeWidth="1" + android:fillColor="#DADCE0" + android:fillType="nonZero" + android:strokeColor="#00000000"/> +</vector>
diff --git a/chrome/android/java/res/layout/bottom_toolbar.xml b/chrome/android/java/res/layout/bottom_toolbar.xml index a8e3ee1..cf50148 100644 --- a/chrome/android/java/res/layout/bottom_toolbar.xml +++ b/chrome/android/java/res/layout/bottom_toolbar.xml
@@ -15,7 +15,6 @@ android:layout_width="match_parent" android:layout_height="@dimen/bottom_toolbar_height_with_shadow" android:inflatedId="@+id/bottom_toolbar_tab_switcher_mode" - android:layout="@layout/bottom_toolbar_tab_switcher" - android:layout_gravity="bottom" /> + android:layout="@layout/bottom_toolbar_tab_switcher" /> </FrameLayout>
diff --git a/chrome/android/java/res/layout/bottom_toolbar_tab_switcher.xml b/chrome/android/java/res/layout/bottom_toolbar_tab_switcher.xml index d541959..80f8993 100644 --- a/chrome/android/java/res/layout/bottom_toolbar_tab_switcher.xml +++ b/chrome/android/java/res/layout/bottom_toolbar_tab_switcher.xml
@@ -3,11 +3,12 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<FrameLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/bottom_toolbar_tab_switcher" + android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone" @@ -29,8 +30,7 @@ android:layout_height="@dimen/bottom_toolbar_height" android:background="@color/modern_primary_color" android:paddingStart="@dimen/bottom_toolbar_start_padding" - android:paddingEnd="@dimen/bottom_toolbar_end_padding" - android:layout_marginTop="@dimen/toolbar_shadow_height" > + android:paddingEnd="@dimen/bottom_toolbar_end_padding" > <org.chromium.chrome.browser.toolbar.bottom.CloseAllTabsButton android:id="@+id/close_all_tabs_button" @@ -56,4 +56,13 @@ </LinearLayout> -</FrameLayout> + <ImageView + android:id="@+id/bottom_toolbar_bottom_shadow" + android:layout_width="match_parent" + android:layout_height="@dimen/toolbar_shadow_height" + android:src="@drawable/modern_toolbar_shadow" + android:scaleType="fitXY" + android:visibility="gone" + tools:ignore="ContentDescription" /> + +</LinearLayout>
diff --git a/chrome/android/java/res/layout/fre_data_reduction_proxy.xml b/chrome/android/java/res/layout/fre_data_reduction_proxy.xml index a8a61d57..7629239 100644 --- a/chrome/android/java/res/layout/fre_data_reduction_proxy.xml +++ b/chrome/android/java/res/layout/fre_data_reduction_proxy.xml
@@ -6,6 +6,7 @@ --> <org.chromium.chrome.browser.firstrun.FirstRunView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -27,7 +28,7 @@ android:id="@+id/title" android:text="@string/data_reduction_promo_title" style="@style/FreTitle"/> - + <!-- The orientation of this view is changed dynamically to give a nicer layout when in landscape mode on devices with small screens. --> <LinearLayout @@ -43,7 +44,7 @@ android:layout_width="wrap_content" android:layout_height="@dimen/fre_image_height" tools:ignore="ContentDescription" - android:src="@drawable/data_reduction_illustration" /> + app:srcCompat="@drawable/data_reduction_illustration" /> <LinearLayout android:id="@+id/fre_content_wrapper" @@ -89,4 +90,4 @@ android:paddingEnd="@dimen/fre_button_padding" android:text="@string/next" style="@style/FilledButton.Flat" /> -</org.chromium.chrome.browser.firstrun.FirstRunView> \ No newline at end of file +</org.chromium.chrome.browser.firstrun.FirstRunView>
diff --git a/chrome/android/java/res/layout/fre_data_reduction_proxy_lite_mode.xml b/chrome/android/java/res/layout/fre_data_reduction_proxy_lite_mode.xml index f2bbbe1..16abb25 100644 --- a/chrome/android/java/res/layout/fre_data_reduction_proxy_lite_mode.xml +++ b/chrome/android/java/res/layout/fre_data_reduction_proxy_lite_mode.xml
@@ -6,6 +6,7 @@ --> <org.chromium.chrome.browser.firstrun.FirstRunView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -43,7 +44,7 @@ android:layout_width="wrap_content" android:layout_height="@dimen/fre_image_height" tools:ignore="ContentDescription" - android:src="@drawable/data_reduction_illustration" /> + app:srcCompat="@drawable/data_reduction_illustration" /> <LinearLayout android:id="@+id/fre_content_wrapper"
diff --git a/chrome/android/java/res/layout/omnibox_answer_suggestion.xml b/chrome/android/java/res/layout/omnibox_answer_suggestion.xml index 1929e04..537fb5ba 100644 --- a/chrome/android/java/res/layout/omnibox_answer_suggestion.xml +++ b/chrome/android/java/res/layout/omnibox_answer_suggestion.xml
@@ -17,6 +17,7 @@ android:id="@+id/omnibox_answer" android:layout_alignParentStart="true" android:layout_centerVertical="true" + android:paddingVertical="10dp" android:layout_height="wrap_content" android:layout_toStartOf="@+id/omnibox_answer_refine_icon" android:layout_width="0dp"> @@ -25,7 +26,7 @@ android:contentDescription="@null" android:id="@+id/omnibox_answer_icon" android:layout_centerVertical="true" - android:layout_height="wrap_content" + android:layout_height="36dp" android:layout_marginEnd="10dp" android:layout_marginStart="@dimen/omnibox_answer_suggestion_icon_margin_start" android:layout_width="36dp"
diff --git a/chrome/android/java/res/layout/tab_grid_card_item.xml b/chrome/android/java/res/layout/tab_grid_card_item.xml index fe1a2e6..74847a2 100644 --- a/chrome/android/java/res/layout/tab_grid_card_item.xml +++ b/chrome/android/java/res/layout/tab_grid_card_item.xml
@@ -2,58 +2,58 @@ <!-- Copyright 2019 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. --> -<!-- TODO(crbug/928388): Spec issues with this layout: Handle elevation for KitKat. Touch target - for close button is too small. Text height needs to be verified for XL text while we are using - FrameLayout as parent --> +<!-- TODO(crbug/928388): Handle elevation for KitKat.--> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="200dp" - android:background="@drawable/tab_grid_card_background" - android:elevation="4dp" - android:layout_margin="8dp"> - <ImageView - android:id="@+id/tab_favicon" - android:layout_width="@dimen/tab_grid_favicon_size" - android:layout_height="@dimen/tab_grid_favicon_size" - android:padding="8dp" - android:importantForAccessibility="no" - android:src="@drawable/ic_omnibox_page"/> - - <TextView - android:id="@+id/tab_title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:minHeight="32dp" - android:layout_marginEnd="32dp" - android:layout_marginStart="32dp" - android:ellipsize="end" - android:maxLines="1" - android:paddingBottom="6dp" - android:paddingTop="6dp" - android:textAppearance="@style/TextAppearance.BlackTitle2"/> - <ImageView - android:id="@+id/close_button" - android:layout_width="32dp" - android:layout_height="32dp" - android:scaleType="center" - android:layout_gravity="end" - android:contentDescription="@string/accessibility_tabstrip_btn_close_tab" - android:src="@drawable/btn_delete_24dp"/> - - <org.chromium.ui.widget.RoundedCornerImageView - android:id="@+id/tab_thumbnail" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginTop="32dp" - android:gravity="center_horizontal" - android:scaleType="centerCrop" - android:importantForAccessibility="no" - android:src="@color/thumbnail_placeholder_on_primary_bg" - app:cornerRadiusBottomStart="@dimen/default_card_corner_radius" - app:cornerRadiusBottomEnd="@dimen/default_card_corner_radius"/> - - <View - style="@style/HorizontalDivider" - android:layout_marginTop="32dp"/> + android:layout_height="216dp"> + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:elevation="4dp" + android:background="@drawable/tab_grid_card_background" + android:layout_margin="8dp"> + <ImageView + android:id="@+id/tab_favicon" + android:layout_width="@dimen/tab_grid_favicon_size" + android:layout_height="@dimen/tab_grid_favicon_size" + android:padding="8dp" + android:importantForAccessibility="no" + android:src="@drawable/ic_omnibox_page"/> + <TextView + android:id="@+id/tab_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_toEndOf="@id/tab_favicon" + android:layout_marginEnd="32dp" + android:minHeight="32dp" + android:ellipsize="end" + android:maxLines="1" + android:paddingBottom="6dp" + android:paddingTop="6dp" + android:textAppearance="@style/TextAppearance.BlackTitle2"/> + <org.chromium.ui.widget.RoundedCornerImageView + android:id="@+id/tab_thumbnail" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_below="@id/tab_title" + android:gravity="center_horizontal" + android:scaleType="centerCrop" + android:importantForAccessibility="no" + android:src="@color/thumbnail_placeholder_on_primary_bg" + app:cornerRadiusBottomStart="@dimen/default_card_corner_radius" + app:cornerRadiusBottomEnd="@dimen/default_card_corner_radius"/> + <View + style="@style/HorizontalDivider" + android:layout_below="@id/tab_title"/> + </RelativeLayout> + <ImageView + android:id="@+id/close_button" + android:layout_width="48dp" + android:layout_height="48dp" + android:elevation="4dp" + android:scaleType="center" + android:layout_gravity="end" + android:contentDescription="@string/accessibility_tabstrip_btn_close_tab" + android:src="@drawable/btn_delete_24dp"/> </FrameLayout>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index eaa47a0..1ec0790 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -593,4 +593,5 @@ <dimen name="autofill_assistant_details_image_size">48dp</dimen> <dimen name="tab_grid_favicon_size">32dp</dimen> + <dimen name="tab_list_selected_inset">5dp</dimen> </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 7eb573c2..be80ee5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -322,7 +322,7 @@ private ActivityTabProvider mActivityTabProvider = new ActivityTabProvider(); /** A means of providing the theme color to different features. */ - private final TabThemeColorProvider mTabThemeColorProvider = new TabThemeColorProvider(); + private TabThemeColorProvider mTabThemeColorProvider; /** Whether or not the activity is in started state. */ private boolean mStarted; @@ -673,6 +673,7 @@ mTabModelSelector = createTabModelSelector(); mActivityTabProvider.setTabModelSelector(mTabModelSelector); + mTabThemeColorProvider = new TabThemeColorProvider(this); mTabThemeColorProvider.setActivityTabProvider(mActivityTabProvider); if (mTabModelSelector == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 018fb8b..72f6513 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -187,6 +187,7 @@ public static final String CCT_REPORT_PARALLEL_REQUEST_STATUS = "CCTReportParallelRequestStatus"; public static final String CHROME_DUET = "ChromeDuet"; + public static final String CHROME_DUET_ADAPTIVE = "ChromeDuetAdaptive"; public static final String CHROME_SMART_SELECTION = "ChromeSmartSelection"; public static final String CLEAR_OLD_BROWSING_DATA = "ClearOldBrowsingData"; public static final String CLIPBOARD_CONTENT_SETTING = "ClipboardContentSetting";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index af0e418..dc7b0d2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -739,8 +739,6 @@ public void onStopWithNative() { super.onStopWithNative(); - if (getActivityTab() != null) getActivityTab().setIsAllowedToReturnToExternalApp(false); - mTabModelSelectorImpl.saveState(); mActivityStopMetrics.onStopWithNative(this); @@ -1363,21 +1361,8 @@ */ private void openNewTab(String url, String referer, String headers, String externalAppId, Intent intent, boolean forceNewTab) { - boolean isAllowedToReturnToExternalApp = IntentUtils.safeGetBooleanExtra( - intent, LaunchIntentDispatcher.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT, true); - // Create a new tab. - Tab newTab = - launchIntent(url, referer, headers, externalAppId, forceNewTab, intent); - if (newTab != null) { - newTab.setIsAllowedToReturnToExternalApp(isAllowedToReturnToExternalApp); - } else { - // TODO(twellington): This should only happen for NTPs created in Chrome Home. See - // if we should be caching setIsAllowedToReturnToExternalApp - // in those cases. - assert NewTabPage.isNTPUrl(url); - assert getBottomSheet() != null; - } + launchIntent(url, referer, headers, externalAppId, forceNewTab, intent); logMobileReceivedExternalIntent(externalAppId, intent); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java index 50e7f90..624f0db 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -69,12 +69,6 @@ public static final String EXTRA_LAUNCH_MODE = "com.google.android.apps.chrome.EXTRA_LAUNCH_MODE"; - /** - * Whether or not the toolbar should indicate that a tab was spawned by another Activity. - */ - public static final String EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT = - "org.chromium.chrome.browser.document.IS_ALLOWED_TO_RETURN_TO_PARENT"; - private static final String TAG = "ActivitiyDispatcher"; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabThemeColorProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/TabThemeColorProvider.java index 219a7bd..b757a50 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/TabThemeColorProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/TabThemeColorProvider.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser; +import android.content.Context; + import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabThemeColorHelper; @@ -13,7 +15,9 @@ /** The {@link sActivityTabTabObserver} used to know when the active tab color changed. */ private ActivityTabTabObserver mActivityTabTabObserver; - public TabThemeColorProvider() {} + public TabThemeColorProvider(Context context) { + super(context); + } /** * @param provider A means of getting the activity's tab.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ThemeColorProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/ThemeColorProvider.java index 26732b9..5b2efad 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ThemeColorProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ThemeColorProvider.java
@@ -8,7 +8,6 @@ import android.content.res.ColorStateList; import android.support.v7.content.res.AppCompatResources; -import org.chromium.base.ContextUtils; import org.chromium.base.ObserverList; import org.chromium.chrome.R; import org.chromium.chrome.browser.util.ColorUtils; @@ -57,10 +56,12 @@ /** List of {@link TintObserver}s. These are used to broadcast events to listeners. */ private final ObserverList<TintObserver> mTintObservers; - public ThemeColorProvider() { + /** + * @param context The {@link Context} that is used to retrieve color related resources. + */ + public ThemeColorProvider(Context context) { mThemeColorObservers = new ObserverList<ThemeColorObserver>(); mTintObservers = new ObserverList<TintObserver>(); - final Context context = ContextUtils.getApplicationContext(); mLightModeTint = AppCompatResources.getColorStateList(context, R.color.light_mode_tint); mDarkModeTint = AppCompatResources.getColorStateList(context, R.color.dark_mode_tint); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java index aa65d15..1394442 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java
@@ -16,7 +16,6 @@ import org.chromium.base.Log; import org.chromium.chrome.browser.IntentHandler; -import org.chromium.chrome.browser.LaunchIntentDispatcher; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.offlinepages.OfflinePageOrigin; import org.chromium.chrome.browser.profiles.Profile; @@ -63,7 +62,6 @@ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkUrl)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setPackage(mActivity.getPackageName()); - intent.putExtra(LaunchIntentDispatcher.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT, false); intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true); intent.putExtra(Browser.EXTRA_APPLICATION_ID, mActivity.getPackageName()); IntentHandler.addTrustedIntentExtras(intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index b38b0978..714fd0200 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -940,7 +940,6 @@ if (TextUtils.isEmpty(url)) url = mIntentDataProvider.getUrlToLoad(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(LaunchIntentDispatcher.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT, false); boolean willChromeHandleIntent = getIntentDataProvider().isOpenedByChrome() || getIntentDataProvider().isIncognito();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java index 3d71630..cef14d1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
@@ -27,6 +27,7 @@ import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.browserservices.PostMessageHandler; import org.chromium.chrome.browser.customtabs.CloseButtonNavigator; +import org.chromium.chrome.browser.customtabs.CloseButtonNavigator.PageCriteria; import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.customtabs.CustomTabTopBarDelegate; @@ -154,6 +155,8 @@ new DynamicModuleNavigationEventObserver(); private final DynamicModulePageLoadObserver mPageLoadObserver; + private final PageCriteria mPageCriteria; + @Inject public DynamicModuleCoordinator(CustomTabIntentDataProvider intentDataProvider, CloseButtonNavigator closeButtonNavigator, @@ -184,8 +187,8 @@ mBottomBarDelegate = bottomBarDelegate; mFullscreenManager = fullscreenManager; - closeButtonNavigator.setLandingPageCriteria(url -> - (isModuleLoading() || isModuleLoaded()) && isModuleManagedUrl(url)); + mPageCriteria = url -> (isModuleLoading() || isModuleLoaded()) && isModuleManagedUrl(url); + closeButtonNavigator.setLandingPageCriteria(mPageCriteria); activityLifecycleDispatcher.register(this); } @@ -385,6 +388,10 @@ return mModuleCallback != null; } + /* package */ boolean hasModuleFailedToLoad() { + return mActivityDelegate == null; + } + private boolean isModuleManagedUrl(String url) { if (TextUtils.isEmpty(url)) { return false; @@ -445,9 +452,9 @@ mIntentDataProvider.getSession()); } - private View getProgressBarAnchorView(boolean isModuleManagedUrl) { + private View getProgressBarAnchorView(boolean showTopBar) { View anchorView = null; - if (isModuleManagedUrl) { + if (showTopBar) { View topBarContentView = mTopBarDelegate.get().getTopBarContentView(); if (topBarContentView != null && topBarContentView.getVisibility() == View.VISIBLE) { anchorView = topBarContentView; @@ -459,19 +466,19 @@ } private void maybeCustomizeCctHeader(String url) { - if (!isModuleLoaded() && !isModuleLoading()) return; + if (!isModuleLoaded() && !isModuleLoading() && !hasModuleFailedToLoad()) return; - boolean isModuleManagedUrl = isModuleManagedUrl(url); - mTopBarDelegate.get().showTopBarIfNecessary(isModuleManagedUrl); + boolean showTopBar = mPageCriteria.matches(url); + mTopBarDelegate.get().showTopBarIfNecessary(showTopBar); if (shouldHideCctHeaderOnModuleManagedUrls()) { mActivity.getToolbarManager().setToolbarVisibility( - isModuleManagedUrl ? View.GONE : mDefaultToolbarVisibility); + showTopBar ? View.GONE : mDefaultToolbarVisibility); mActivity.getToolbarManager().setToolbarShadowVisibility( - isModuleManagedUrl ? View.GONE : mDefaultToolbarShadowVisibility); + showTopBar ? View.GONE : mDefaultToolbarShadowVisibility); mFullscreenManager.get().setTopControlsHeight( - isModuleManagedUrl ? getTopBarHeight() : mDefaultTopControlContainerHeight); + showTopBar ? getTopBarHeight() : mDefaultTopControlContainerHeight); mActivity.getToolbarManager().setProgressBarAnchorView( - getProgressBarAnchorView(isModuleManagedUrl)); + getProgressBarAnchorView(showTopBar)); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gsa/ContextReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/gsa/ContextReporter.java index 01a9f3f5..37f154d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gsa/ContextReporter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gsa/ContextReporter.java
@@ -19,7 +19,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.components.sync.ModelType; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; import java.util.concurrent.atomic.AtomicBoolean; @@ -216,7 +216,7 @@ reportStatus(STATUS_SYNC_NOT_INITIALIZED); } else if (!syncService.getActiveDataTypes().contains(ModelType.TYPED_URLS)) { reportStatus(STATUS_SYNC_NOT_SYNCING_URLS); - } else if (!syncService.getPassphraseType().equals(PassphraseType.KEYSTORE_PASSPHRASE)) { + } else if (syncService.getPassphraseType() != Passphrase.Type.KEYSTORE) { reportStatus(STATUS_SYNC_NOT_KEYSTORE_PASSPHRASE); } else { reportStatus(STATUS_SYNC_OTHER);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java index b3b64e55..dd14ba3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
@@ -64,12 +64,14 @@ @Override public int getViewTypeId() { - return OmniboxSuggestionUiType.DEFAULT; + return mEnableNewAnswerLayout ? OmniboxSuggestionUiType.ANSWER_SUGGESTION + : OmniboxSuggestionUiType.DEFAULT; } @Override public PropertyModel createModelForSuggestion(OmniboxSuggestion suggestion) { - return new PropertyModel(SuggestionViewProperties.ALL_KEYS); + return mEnableNewAnswerLayout ? new PropertyModel(AnswerSuggestionViewProperties.ALL_KEYS) + : new PropertyModel(SuggestionViewProperties.ALL_KEYS); } @Override @@ -78,7 +80,11 @@ SuggestionViewDelegate delegate = mSuggestionHost.createSuggestionViewDelegate(suggestion, position); - setStateForClassicSuggestion(model, suggestion.getAnswer(), delegate); + if (mEnableNewAnswerLayout) { + setStateForNewSuggestion(model, suggestion.getAnswer(), delegate); + } else { + setStateForClassicSuggestion(model, suggestion.getAnswer(), delegate); + } } @Override @@ -117,7 +123,12 @@ for (int i = 0; i < models.size(); i++) { PropertyModel model = models.get(i); if (!mSuggestionHost.isActiveModel(model)) continue; - model.set(SuggestionViewProperties.ANSWER_IMAGE, bitmap); + + if (mEnableNewAnswerLayout) { + model.set(AnswerSuggestionViewProperties.ANSWER_IMAGE, bitmap); + } else { + model.set(SuggestionViewProperties.ANSWER_IMAGE, bitmap); + } didUpdate = true; } if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged(); @@ -132,8 +143,6 @@ PropertyModel model, SuggestionAnswer answer, SuggestionViewDelegate delegate) { SuggestionAnswer.ImageLine firstLine = answer.getFirstLine(); SuggestionAnswer.ImageLine secondLine = answer.getSecondLine(); - int numAnswerLines = parseNumAnswerLines(secondLine.getTextFields()); - if (numAnswerLines == -1) numAnswerLines = 1; model.set(SuggestionViewProperties.IS_ANSWER, true); @@ -170,8 +179,6 @@ PropertyModel model, SuggestionAnswer answer, SuggestionViewDelegate delegate) { SuggestionAnswer.ImageLine firstLine = answer.getFirstLine(); SuggestionAnswer.ImageLine secondLine = answer.getSecondLine(); - int numAnswerLines = parseNumAnswerLines(secondLine.getTextFields()); - if (numAnswerLines == -1) numAnswerLines = 1; AnswerText[] details = AnswerTextNewLayout.from(mContext, answer); @@ -220,13 +227,4 @@ model.set(AnswerSuggestionViewProperties.ANSWER_ICON_TYPE, icon); } - - private static int parseNumAnswerLines(List<SuggestionAnswer.TextField> textFields) { - for (int i = 0; i < textFields.size(); i++) { - if (textFields.get(i).hasNumLines()) { - return Math.min(3, textFields.get(i).getNumLines()); - } - } - return -1; - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionView.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionView.java index 4d27562..1ad3822 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionView.java
@@ -6,13 +6,19 @@ import android.content.Context; import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.support.annotation.DrawableRes; +import android.support.v4.graphics.drawable.DrawableCompat; import android.text.Spannable; import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewDelegate; @@ -21,9 +27,11 @@ */ public class AnswerSuggestionView extends RelativeLayout { private SuggestionViewDelegate mSuggestionDelegate; + private View mAnswerView; private TextView mTextView1; private TextView mTextView2; - private ImageView mAnswerIcon; + private ImageView mAnswerIconView; + private ImageView mRefineView; /** Creates new instance of AnswerSuggestionView. */ public AnswerSuggestionView(Context context, AttributeSet attributes) { @@ -35,19 +43,57 @@ super.onFinishInflate(); mTextView1 = findViewById(R.id.omnibox_answer_line_1); mTextView2 = findViewById(R.id.omnibox_answer_line_2); - mAnswerIcon = findViewById(R.id.omnibox_answer_icon); + mAnswerIconView = findViewById(R.id.omnibox_answer_icon); + mAnswerView = findViewById(R.id.omnibox_answer); + mRefineView = findViewById(R.id.omnibox_answer_refine_icon); + } + + @Override + public void setSelected(boolean selected) { + super.setSelected(selected); + if (selected && !isInTouchMode()) { + postDelegateAction(() -> mSuggestionDelegate.onSetUrlToSuggestion()); + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + // Whenever the suggestion dropdown is touched, we dispatch onGestureDown which is + // used to let autocomplete controller know that it should stop updating suggestions. + switch (ev.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mSuggestionDelegate.onGestureDown(); + break; + case MotionEvent.ACTION_UP: + mSuggestionDelegate.onGestureUp(ev.getEventTime()); + break; + } + return super.dispatchTouchEvent(ev); } /** Specify delegate receiving click/refine events. */ void setDelegate(SuggestionViewDelegate delegate) { mSuggestionDelegate = delegate; + mAnswerView.setOnClickListener( + (View v) -> postDelegateAction(() -> mSuggestionDelegate.onSelection())); + mAnswerView.setOnLongClickListener((View v) -> { + postDelegateAction(() -> mSuggestionDelegate.onLongPress()); + return true; + }); + mRefineView.setOnClickListener( + (View v) -> postDelegateAction(() -> mSuggestionDelegate.onRefineSuggestion())); } /** * Toggles theme. * @param useDarkColors specifies whether UI should use dark theme. */ - void setUseDarkColors(boolean useDarkColors) {} + void setUseDarkColors(boolean useDarkColors) { + Drawable drawable = mRefineView.getDrawable(); + DrawableCompat.setTint(drawable, + ApiCompatibilityUtils.getColor(getContext().getResources(), + useDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint)); + } /** * Specifies text content of the first text line. @@ -69,13 +115,25 @@ * Specifies image bitmap to be displayed as an answer icon. * @param bitmap Decoded image to be displayed as an answer icon. */ - void setIconBitmap(Bitmap bitmap) {} + void setIconBitmap(Bitmap bitmap) { + BitmapDrawable drawable = new BitmapDrawable(bitmap); + mAnswerIconView.setImageDrawable(drawable); + } /** * Specifies fallback image to be presented if no image is available. * @param res Drawable resource ID to be used in place of answer image. */ void setFallbackIconRes(@DrawableRes int res) { - mAnswerIcon.setImageResource(res); + mAnswerIconView.setImageResource(res); + } + + /** + * Post delegate action to main thread. Invoked only if delegate is specified. + * @param action Delegate action to invoke on the UI thread. + */ + private void postDelegateAction(Runnable action) { + if (mSuggestionDelegate == null) return; + if (!post(action)) action.run(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ManageSyncPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ManageSyncPreferences.java index 3205e22..9007801f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ManageSyncPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ManageSyncPreferences.java
@@ -38,7 +38,7 @@ import org.chromium.chrome.browser.sync.ui.PassphraseTypeDialogFragment; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.sync.ModelType; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; import org.chromium.content_public.browser.UiThreadTaskTraits; import java.util.HashSet; @@ -365,7 +365,7 @@ /** Callback for PassphraseTypeDialogFragment.Listener */ @Override - public void onPassphraseTypeSelected(PassphraseType type) { + public void onPassphraseTypeSelected(@Passphrase.Type int type) { if (!mProfileSyncService.isEngineInitialized()) { // If the engine was shut down since the dialog was opened, do nothing. return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java index f80768e..7d6089d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java
@@ -51,7 +51,7 @@ @Override protected DialogParams getDialogParams() { PromoDialog.DialogParams params = new PromoDialog.DialogParams(); - params.drawableResource = R.drawable.data_reduction_illustration; + params.vectorDrawableResource = R.drawable.data_reduction_illustration; params.headerStringResource = DataReductionBrandingResourceProvider.getDataSaverBrandedString( R.string.data_reduction_promo_title);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java index 8995813..9e88137 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java
@@ -13,7 +13,7 @@ import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.components.sync.ModelType; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; import java.util.HashSet; import java.util.List; @@ -170,10 +170,13 @@ * This method should only be used if you want to know the raw value. For checking whether * we should ask the user for a passphrase, use isPassphraseRequiredForDecryption(). */ - public PassphraseType getPassphraseType() { + public @Passphrase.Type int getPassphraseType() { assert isEngineInitialized(); int passphraseType = nativeGetPassphraseType(mNativeProfileSyncServiceAndroid); - return PassphraseType.fromInternalValue(passphraseType); + if (passphraseType < 0 || passphraseType >= Passphrase.Type.NUM_ENTRIES) { + throw new IllegalArgumentException(); + } + return passphraseType; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java index 3f088af..099d6bac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
@@ -24,7 +24,7 @@ import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.sync.AndroidSyncSettings; import org.chromium.components.sync.ModelType; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; import org.chromium.components.sync.StopSource; /** @@ -221,8 +221,7 @@ public boolean isSyncingUrlsWithKeystorePassphrase() { return mProfileSyncService.isEngineInitialized() && mProfileSyncService.getPreferredDataTypes().contains(ModelType.TYPED_URLS) - && mProfileSyncService.getPassphraseType().equals( - PassphraseType.KEYSTORE_PASSPHRASE); + && mProfileSyncService.getPassphraseType() == Passphrase.Type.KEYSTORE; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java index 339d40b..3d3d62d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.sync.GoogleServiceAuthError.State; import org.chromium.chrome.browser.sync.ui.PassphraseActivity; import org.chromium.components.sync.AndroidSyncSettings; +import org.chromium.components.sync.Passphrase; /** * {@link SyncNotificationController} provides functionality for displaying Android notifications @@ -68,12 +69,12 @@ return; } switch (mProfileSyncService.getPassphraseType()) { - case IMPLICIT_PASSPHRASE: // Falling through intentionally. - case FROZEN_IMPLICIT_PASSPHRASE: // Falling through intentionally. - case CUSTOM_PASSPHRASE: + case Passphrase.Type.IMPLICIT: // Falling through intentionally. + case Passphrase.Type.FROZEN_IMPLICIT: // Falling through intentionally. + case Passphrase.Type.CUSTOM: showSyncNotification(R.string.sync_need_passphrase, createPasswordIntent()); break; - case KEYSTORE_PASSPHRASE: // Falling through intentionally. + case Passphrase.Type.KEYSTORE: // Falling through intentionally. default: mNotificationManager.cancel(NotificationConstants.NOTIFICATION_ID_SYNC); return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java index dab49ce..247e639 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
@@ -39,7 +39,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.chrome.browser.util.IntentUtils; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; import org.chromium.ui.text.SpanApplier; import org.chromium.ui.text.SpanApplier.SpanInfo; @@ -190,21 +190,22 @@ private SpannableString getPromptText() { ProfileSyncService pss = ProfileSyncService.get(); String accountName = pss.getCurrentSignedInAccountText() + "\n\n"; - PassphraseType passphraseType = pss.getPassphraseType(); + @Passphrase.Type + int passphraseType = pss.getPassphraseType(); if (pss.hasExplicitPassphraseTime()) { String syncPassphraseHelpContext = getString(R.string.help_context_change_sync_passphrase); switch (passphraseType) { - case FROZEN_IMPLICIT_PASSPHRASE: + case Passphrase.Type.FROZEN_IMPLICIT: return applyInProductHelpSpan( accountName + pss.getSyncEnterGooglePassphraseBodyWithDateText(), syncPassphraseHelpContext); - case CUSTOM_PASSPHRASE: + case Passphrase.Type.CUSTOM: return applyInProductHelpSpan( accountName + pss.getSyncEnterCustomPassphraseBodyWithDateText(), syncPassphraseHelpContext); - case IMPLICIT_PASSPHRASE: // Falling through intentionally. - case KEYSTORE_PASSPHRASE: // Falling through intentionally. + case Passphrase.Type.IMPLICIT: // Falling through intentionally. + case Passphrase.Type.KEYSTORE: // Falling through intentionally. default: Log.w(TAG, "Found incorrect passphrase type " + passphraseType + ". Falling back to default string.");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java index 1cdf8df0..a1de874 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java
@@ -30,16 +30,14 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeStringConstants; import org.chromium.chrome.browser.util.IntentUtils; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; import org.chromium.ui.text.SpanApplier; import org.chromium.ui.text.SpanApplier.SpanInfo; import org.chromium.ui.widget.TextViewWithClickableSpans; import java.text.DateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.List; -import java.util.Set; /** * Dialog to ask the user select what type of password to use for encryption. @@ -48,9 +46,9 @@ DialogInterface.OnClickListener, OnItemClickListener { private static final String TAG = "PassphraseTypeDialogFragment"; - public interface Listener { void onPassphraseTypeSelected(PassphraseType type); } + public interface Listener { void onPassphraseTypeSelected(@Passphrase.Type int type); } - private String[] getDisplayNames(List<PassphraseType> passphraseTypes) { + private String[] getDisplayNames(List<Integer /* @Passphrase.Type */> passphraseTypes) { String[] displayNames = new String[passphraseTypes.size()]; for (int i = 0; i < displayNames.length; i++) { displayNames[i] = textForPassphraseType(passphraseTypes.get(i)); @@ -58,25 +56,25 @@ return displayNames; } - private String textForPassphraseType(PassphraseType type) { + private String textForPassphraseType(@Passphrase.Type int type) { switch (type) { - case IMPLICIT_PASSPHRASE: // Intentional fall through. - case KEYSTORE_PASSPHRASE: + case Passphrase.Type.IMPLICIT: // Intentional fall through. + case Passphrase.Type.KEYSTORE: return getString(R.string.sync_passphrase_type_keystore); - case FROZEN_IMPLICIT_PASSPHRASE: + case Passphrase.Type.FROZEN_IMPLICIT: String passphraseDate = getPassphraseDateStringFromArguments(); String frozenPassphraseString = getString(R.string.sync_passphrase_type_frozen); return String.format(frozenPassphraseString, passphraseDate); - case CUSTOM_PASSPHRASE: + case Passphrase.Type.CUSTOM: return getString(R.string.sync_passphrase_type_custom); default: return ""; } } - private Adapter createAdapter(PassphraseType currentType) { - List<PassphraseType> passphraseTypes = - new ArrayList<PassphraseType>(currentType.getVisibleTypes()); + private Adapter createAdapter(@Passphrase.Type int currentType) { + List<Integer /* @Passphrase.Type */> passphraseTypes = + Passphrase.getVisibleTypes(currentType); return new Adapter(passphraseTypes, getDisplayNames(passphraseTypes)); } @@ -85,14 +83,14 @@ */ @VisibleForTesting public class Adapter extends ArrayAdapter<String> { - - private final List<PassphraseType> mPassphraseTypes; + private final List<Integer /* @PassphraseType */> mPassphraseTypes; /** * Do not call this constructor directly. Instead use * {@link PassphraseTypeDialogFragment#createAdapter}. */ - private Adapter(List<PassphraseType> passphraseTypes, String[] displayStrings) { + private Adapter( + List<Integer /* @Passphrase.Type */> passphraseTypes, String[] displayStrings) { super(getActivity(), R.layout.passphrase_type_item, displayStrings); mPassphraseTypes = passphraseTypes; } @@ -104,24 +102,26 @@ @Override public long getItemId(int position) { - return getType(position).internalValue(); + return getType(position); } - public PassphraseType getType(int position) { + public @Passphrase.Type int getType(int position) { return mPassphraseTypes.get(position); } - public int getPositionForType(PassphraseType type) { + public int getPositionForType(@Passphrase.Type int type) { return mPassphraseTypes.indexOf(type); } @Override public View getView(int position, View convertView, ViewGroup parent) { CheckedTextView view = (CheckedTextView) super.getView(position, convertView, parent); - PassphraseType positionType = getType(position); - PassphraseType currentType = getCurrentTypeFromArguments(); - Set<PassphraseType> allowedTypes = - currentType.getAllowedTypes(getIsEncryptEverythingAllowedFromArguments()); + @Passphrase.Type + int positionType = getType(position); + @Passphrase.Type + int currentType = getCurrentTypeFromArguments(); + List<Integer /* @Passphrase.Type */> allowedTypes = Passphrase.getAllowedTypes( + currentType, getIsEncryptEverythingAllowedFromArguments()); // Set the item to checked it if it is the currently selected encryption type. view.setChecked(positionType == currentType); @@ -132,7 +132,7 @@ } /** - * This argument should contain a single value of type {@link PassphraseType}. + * This argument should contain a single value of type {@link Passphrase.Type}. */ private static final String ARG_CURRENT_TYPE = "arg_current_type"; @@ -141,11 +141,11 @@ private static final String ARG_IS_ENCRYPT_EVERYTHING_ALLOWED = "arg_is_encrypt_everything_allowed"; - public static PassphraseTypeDialogFragment create( - PassphraseType currentType, long passphraseTime, boolean isEncryptEverythingAllowed) { + public static PassphraseTypeDialogFragment create(@Passphrase.Type int currentType, + long passphraseTime, boolean isEncryptEverythingAllowed) { PassphraseTypeDialogFragment dialog = new PassphraseTypeDialogFragment(); Bundle args = new Bundle(); - args.putParcelable(ARG_CURRENT_TYPE, currentType); + args.putInt(ARG_CURRENT_TYPE, currentType); args.putLong(ARG_PASSPHRASE_TIME, passphraseTime); args.putBoolean(ARG_IS_ENCRYPT_EVERYTHING_ALLOWED, isEncryptEverythingAllowed); dialog.setArguments(args); @@ -160,11 +160,12 @@ // Configure the passphrase type list ListView list = (ListView) v.findViewById(R.id.passphrase_types); - PassphraseType currentType = getCurrentTypeFromArguments(); + @Passphrase.Type + int currentType = getCurrentTypeFromArguments(); // Configure the hint to reset the passphrase settings // Only show this hint if encryption has been set to use sync passphrase - if (currentType == PassphraseType.CUSTOM_PASSPHRASE) { + if (currentType == Passphrase.Type.CUSTOM) { TextViewWithClickableSpans instructionsView = new TextViewWithClickableSpans(getActivity()); instructionsView.setPadding(0, @@ -217,13 +218,15 @@ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long typeId) { - PassphraseType currentType = getCurrentTypeFromArguments(); - // We know this conversion from long to int is safe, because it represents very small - // enum values. - PassphraseType type = PassphraseType.fromInternalValue((int) typeId); + @Passphrase.Type + int currentType = getCurrentTypeFromArguments(); + // We know that typeId conversion from long to int is safe, because it represents very + // small enum values. + @Passphrase.Type + int type = (int) typeId; boolean isEncryptEverythingAllowed = getIsEncryptEverythingAllowedFromArguments(); - if (currentType.getAllowedTypes(isEncryptEverythingAllowed).contains(type)) { - if (typeId != currentType.internalValue()) { + if (Passphrase.getAllowedTypes(currentType, isEncryptEverythingAllowed).contains(type)) { + if (type != currentType) { Listener listener = (Listener) getTargetFragment(); listener.onPassphraseTypeSelected(type); } @@ -232,9 +235,10 @@ } @VisibleForTesting - public PassphraseType getCurrentTypeFromArguments() { - PassphraseType currentType = getArguments().getParcelable(ARG_CURRENT_TYPE); - if (currentType == null) { + public @Passphrase.Type int getCurrentTypeFromArguments() { + // NUM_ENTRIES is used to find when value doesn't exist. + int currentType = getArguments().getInt(ARG_CURRENT_TYPE, Passphrase.Type.NUM_ENTRIES); + if (currentType == Passphrase.Type.NUM_ENTRIES) { throw new IllegalStateException("Unable to find argument with current type."); } return currentType;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java index 579b6e8..8d3ac2a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java
@@ -50,7 +50,7 @@ import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.sync.AndroidSyncSettings; import org.chromium.components.sync.ModelType; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; import org.chromium.components.sync.ProtocolErrorClientAction; import org.chromium.content_public.browser.UiThreadTaskTraits; @@ -470,7 +470,7 @@ * Callback for PassphraseTypeDialogFragment.Listener */ @Override - public void onPassphraseTypeSelected(PassphraseType type) { + public void onPassphraseTypeSelected(@Passphrase.Type int type) { if (!mProfileSyncService.isEngineInitialized()) { // If the engine was shut down since the dialog was opened, do nothing. return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index 9e89dab..05991ca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -327,9 +327,6 @@ */ private boolean mIsDetached; - /** Whether or not the tab closing the tab can send the user back to the app that opened it. */ - private boolean mIsAllowedToReturnToExternalApp; - /** * The publisher URL for pages hosted on a trusted CDN, or null otherwise. */ @@ -581,7 +578,6 @@ if ((params.getTransitionType() & PageTransition.FROM_ADDRESS_BAR) == PageTransition.FROM_ADDRESS_BAR) { mAppAssociatedWith = null; - setIsAllowedToReturnToExternalApp(false); } if ("chrome://java-crash/".equals(params.getUrl())) { return handleJavaCrash(); @@ -2653,20 +2649,6 @@ } /** - * Set whether closing this Tab should return the user to the app that spawned Chrome. - */ - public void setIsAllowedToReturnToExternalApp(boolean state) { - mIsAllowedToReturnToExternalApp = state; - } - - /** - * @return Whether closing this Tab should return the user to the app that spawned Chrome. - */ - public boolean isAllowedToReturnToExternalApp() { - return mIsAllowedToReturnToExternalApp; - } - - /** * @return Whether or not the tab was opened by an app other than Chrome. */ public boolean isCreatedForExternalApp() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java index 9699f9f..78548bd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
@@ -17,7 +17,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.DefaultBrowserInfo; import org.chromium.chrome.browser.IntentHandler; -import org.chromium.chrome.browser.LaunchIntentDispatcher; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.contextmenu.ContextMenuItemDelegate; import org.chromium.chrome.browser.document.ChromeLauncherActivity; @@ -243,10 +242,6 @@ if (packageManager.queryIntentActivities(chromeIntent, 0).isEmpty()) return; } - // For "Open in Chrome" from the context menu in WebappActivity we want to bypass - // CustomTab, and this flag ensures we open in TabbedChrome. - chromeIntent.putExtra(LaunchIntentDispatcher.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT, false); - boolean activityStarted = false; if (pageUrl != null) { try { @@ -274,7 +269,6 @@ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkUrl)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClass(mTab.getApplicationContext(), ChromeLauncherActivity.class); - intent.putExtra(LaunchIntentDispatcher.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT, false); if (isIncognito) { intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true); intent.putExtra(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabGridViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabGridViewBinder.java index 5bd9cb1..7121d6a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabGridViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabGridViewBinder.java
@@ -4,6 +4,9 @@ package org.chromium.chrome.browser.tasks.tab_list_ui; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.InsetDrawable; import android.support.annotation.Nullable; import android.support.v4.content.res.ResourcesCompat; import android.support.v7.widget.RecyclerView.ViewHolder; @@ -37,12 +40,13 @@ holder.closeButton.setContentDescription(holder.itemView.getResources().getString( R.string.accessibility_tabstrip_btn_close_tab, title)); } else if (TabProperties.IS_SELECTED == propertyKey) { + Resources res = holder.itemView.getResources(); + Drawable drawable = new InsetDrawable( + ResourcesCompat.getDrawable(res, R.drawable.selected_tab_background, + holder.itemView.getContext().getTheme()), + (int) res.getDimension(R.dimen.tab_list_selected_inset)); ((FrameLayout) holder.itemView) - .setForeground(item.get(TabProperties.IS_SELECTED) - ? ResourcesCompat.getDrawable(holder.itemView.getResources(), - R.drawable.selected_tab_background, - holder.itemView.getContext().getTheme()) - : null); + .setForeground(item.get(TabProperties.IS_SELECTED) ? drawable : null); } else if (TabProperties.TAB_SELECTED_LISTENER == propertyKey) { holder.itemView.setOnClickListener(view -> { item.get(TabProperties.TAB_SELECTED_LISTENER).run(holder.getTabId());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java index 8e80a46..d1acafc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
@@ -31,15 +31,19 @@ * The home button. */ public class HomeButton extends ChromeImageButton - implements TintObserver, OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener { + implements TintObserver, OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener, + HomepageManager.HomepageStateListener { private static final int ID_REMOVE = 0; /** A provider that notifies components when the theme color changes.*/ private ThemeColorProvider mThemeColorProvider; - /** The {@link sActivityTabTabObserver} used to know when the active page changed. */ + /** The {@link ActivityTabTabObserver} used to know when the active page changed. */ private ActivityTabTabObserver mActivityTabTabObserver; + /** The {@link ActivityTabProvider} used to know if the active tab is on the NTP. */ + private ActivityTabProvider mActivityTabProvider; + public HomeButton(Context context, AttributeSet attrs) { super(context, attrs); @@ -51,6 +55,8 @@ && !FeatureUtilities.isBottomToolbarEnabled()) { setOnCreateContextMenuListener(this); } + + HomepageManager.getInstance().addListener(this); } public void destroy() { @@ -58,10 +64,13 @@ mThemeColorProvider.removeTintObserver(this); mThemeColorProvider = null; } + if (mActivityTabTabObserver != null) { mActivityTabTabObserver.destroy(); mActivityTabTabObserver = null; } + + HomepageManager.getInstance().removeListener(this); } public void setThemeColorProvider(ThemeColorProvider themeColorProvider) { @@ -86,23 +95,37 @@ return true; } + @Override + public void onHomepageStateUpdated() { + updateButtonEnabledState(); + } + public void setActivityTabProvider(ActivityTabProvider activityTabProvider) { + mActivityTabProvider = activityTabProvider; mActivityTabTabObserver = new ActivityTabTabObserver(activityTabProvider) { @Override public void onObservingDifferentTab(Tab tab) { if (tab == null) return; - setEnabled(shouldEnableHome(tab.getUrl())); + updateButtonEnabledState(); } @Override public void onUpdateUrl(Tab tab, String url) { - setEnabled(shouldEnableHome(url)); + updateButtonEnabledState(); } }; } - private static boolean shouldEnableHome(String url) { - if (!FeatureUtilities.isBottomToolbarEnabled()) return true; - return !NewTabPage.isNTPUrl(url); + private void updateButtonEnabledState() { + if (FeatureUtilities.isNewTabPageButtonEnabled() || !HomepageManager.isHomepageEnabled()) { + setEnabled(!isActiveTabNTP()); + } else { + setEnabled(true); + } + } + + private boolean isActiveTabNTP() { + if (mActivityTabProvider == null) return false; + return NewTabPage.isNTPUrl(mActivityTabProvider.getActivityTab().getUrl()); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 11d30c4..1424c775 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -31,6 +31,7 @@ import org.chromium.base.task.PostTask; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.TabLoadStatus; import org.chromium.chrome.browser.ThemeColorProvider; @@ -976,7 +977,7 @@ wrapBottomToolbarClickListenerForIPH(newTabClickHandler), closeTabsClickListener, mAppMenuButtonHelper, mTabModelSelector, mOverviewModeBehavior, mActivity.getWindowAndroid(), mTabCountProvider, - mIncognitoStateProvider); + mIncognitoStateProvider, mActivity.findViewById(R.id.control_container)); // Allow the bottom toolbar to be focused in accessibility after the top toolbar. ApiCompatibilityUtils.setAccessibilityTraversalBefore( @@ -1212,6 +1213,15 @@ public void onOrientationChange() { if (mActionModeController == null) return; mActionModeController.showControlsOnOrientationChange(); + if (mBottomToolbarCoordinator != null + && ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_DUET_ADAPTIVE)) { + final boolean isLandscape = mActivity.getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE; + mBottomToolbarCoordinator.setBottomToolbarHidden(isLandscape); + if (mAppMenuButtonHelper != null) { + mAppMenuButtonHelper.setMenuShowsFromBottom(!isLandscape); + } + } } /** @@ -1681,7 +1691,6 @@ if (previousTab != tab) { if (previousTab != null) { previousTab.removeObserver(mTabObserver); - previousTab.setIsAllowedToReturnToExternalApp(false); } if (tab != null) tab.addObserver(mTabObserver); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java index 9ba378eb..3bfc3c14 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java
@@ -6,6 +6,7 @@ import android.view.View; import android.view.View.OnClickListener; +import android.view.ViewGroup; import android.view.ViewStub; import org.chromium.chrome.R; @@ -59,7 +60,7 @@ mTabSwitcherModeStub = root.findViewById(R.id.bottom_toolbar_tab_switcher_mode_stub); - mBottomToolbarThemeColorProvider = new BottomToolbarThemeColorProvider(); + mBottomToolbarThemeColorProvider = new BottomToolbarThemeColorProvider(root.getContext()); } /** @@ -82,13 +83,14 @@ * @param tabCountProvider Updates the tab count number in the tab switcher button and in the * incognito toggle tab layout. * @param incognitoStateProvider Notifies components when incognito mode is entered or exited. + * @param topToolbarRoot The root {@link ViewGroup} of the top toolbar. */ public void initializeWithNative(ResourceManager resourceManager, LayoutManager layoutManager, OnClickListener tabSwitcherListener, OnClickListener newTabClickListener, OnClickListener closeTabsClickListener, AppMenuButtonHelper menuButtonHelper, TabModelSelector tabModelSelector, OverviewModeBehavior overviewModeBehavior, WindowAndroid windowAndroid, TabCountProvider tabCountProvider, - IncognitoStateProvider incognitoStateProvider) { + IncognitoStateProvider incognitoStateProvider, ViewGroup topToolbarRoot) { mBottomToolbarThemeColorProvider.setIncognitoStateProvider(incognitoStateProvider); mBottomToolbarThemeColorProvider.setOverviewModeBehavior(overviewModeBehavior); @@ -96,9 +98,18 @@ tabSwitcherListener, menuButtonHelper, overviewModeBehavior, windowAndroid, tabCountProvider, mBottomToolbarThemeColorProvider, tabModelSelector); mTabSwitcherModeCoordinator = new TabSwitcherBottomToolbarCoordinator(mTabSwitcherModeStub, - incognitoStateProvider, mBottomToolbarThemeColorProvider, newTabClickListener, - closeTabsClickListener, menuButtonHelper, tabModelSelector, overviewModeBehavior, - tabCountProvider); + topToolbarRoot, incognitoStateProvider, mBottomToolbarThemeColorProvider, + newTabClickListener, closeTabsClickListener, menuButtonHelper, tabModelSelector, + overviewModeBehavior, tabCountProvider); + } + + /** + * @param shouldHide Whether the bottom toolbar should be hidden. + */ + public void setBottomToolbarHidden(boolean shouldHide) { + if (mTabSwitcherModeCoordinator != null) { + mTabSwitcherModeCoordinator.showToolbarOnTop(shouldHide); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarThemeColorProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarThemeColorProvider.java index 69cdb44..9f7c29c9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarThemeColorProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarThemeColorProvider.java
@@ -7,7 +7,6 @@ import android.content.Context; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.ContextUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ThemeColorProvider; @@ -45,8 +44,8 @@ /** Whether app is in overview mode. */ private boolean mIsOverviewVisible; - public BottomToolbarThemeColorProvider() { - final Context context = ContextUtils.getApplicationContext(); + public BottomToolbarThemeColorProvider(Context context) { + super(context); mLightPrimaryColor = ApiCompatibilityUtils.getColor( context.getResources(), R.color.modern_primary_color); mDarkPrimaryColor = ApiCompatibilityUtils.getColor(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java index e2e221f..7cc9487 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java
@@ -6,6 +6,7 @@ import android.view.View; import android.view.View.OnClickListener; +import android.view.ViewGroup; import android.view.ViewStub; import org.chromium.chrome.R; @@ -38,6 +39,7 @@ /** * Build the coordinator that manages the tab switcher bottom toolbar. * @param stub The tab switcher bottom toolbar {@link ViewStub} to inflate. + * @param topToolbarRoot The root {@link ViewGroup} of the top toolbar. * @param incognitoStateProvider Notifies components when incognito mode is entered or exited. * @param themeColorProvider Notifies components when the theme color changes. * @param newTabClickListener An {@link OnClickListener} that is triggered when the @@ -52,7 +54,7 @@ * @param tabCountProvider Updates the tab count number in the tab switcher button and in the * incognito toggle tab layout. */ - public TabSwitcherBottomToolbarCoordinator(ViewStub stub, + public TabSwitcherBottomToolbarCoordinator(ViewStub stub, ViewGroup topToolbarRoot, IncognitoStateProvider incognitoStateProvider, ThemeColorProvider themeColorProvider, OnClickListener newTabClickListener, OnClickListener closeTabsClickListener, AppMenuButtonHelper menuButtonHelper, TabModelSelector tabModelSelector, @@ -61,7 +63,9 @@ TabSwitcherBottomToolbarModel model = new TabSwitcherBottomToolbarModel(); - PropertyModelChangeProcessor.create(model, root, new TabSwitcherBottomToolbarViewBinder()); + PropertyModelChangeProcessor.create(model, root, + new TabSwitcherBottomToolbarViewBinder( + topToolbarRoot, (ViewGroup) root.getParent())); mMediator = new TabSwitcherBottomToolbarMediator( model, themeColorProvider, overviewModeBehavior); @@ -84,6 +88,13 @@ } /** + * @param showOnTop Whether to show the tab switcher bottom toolbar on the top of the screen. + */ + public void showToolbarOnTop(boolean showOnTop) { + mMediator.showToolbarOnTop(showOnTop); + } + + /** * Clean up any state when the bottom toolbar is destroyed. */ public void destroy() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java index aa8769f4..93d5b407 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java
@@ -43,6 +43,13 @@ } /** + * @param showOnTop Whether to show the tab switcher bottom toolbar on the top of the screen. + */ + void showToolbarOnTop(boolean showOnTop) { + mModel.set(TabSwitcherBottomToolbarModel.SHOW_ON_TOP, showOnTop); + } + + /** * Clean up anything that needs to be when the tab switcher bottom toolbar is destroyed. */ void destroy() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarModel.java index 3eb5413..03a43a3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarModel.java
@@ -17,8 +17,11 @@ /** Whether the tab switcher bottom toolbar is visible */ public static final WritableBooleanPropertyKey IS_VISIBLE = new WritableBooleanPropertyKey(); + /** Whether the tab switcher bottom toolbar shows on top of the screen. */ + public static final WritableBooleanPropertyKey SHOW_ON_TOP = new WritableBooleanPropertyKey(); + /** Default constructor. */ public TabSwitcherBottomToolbarModel() { - super(PRIMARY_COLOR, IS_VISIBLE); + super(PRIMARY_COLOR, IS_VISIBLE, SHOW_ON_TOP); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarViewBinder.java index ee635ca9..7fe4bbe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarViewBinder.java
@@ -5,8 +5,10 @@ package org.chromium.chrome.browser.toolbar.bottom; import android.view.View; +import android.view.ViewGroup; import org.chromium.chrome.R; +import org.chromium.ui.UiUtils; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -18,11 +20,17 @@ public class TabSwitcherBottomToolbarViewBinder implements PropertyModelChangeProcessor .ViewBinder<TabSwitcherBottomToolbarModel, View, PropertyKey> { + private final ViewGroup mTopRoot; + private final ViewGroup mBottomRoot; + /** * Build a binder that handles interaction between the model and the tab switcher bottom toolbar * view. */ - public TabSwitcherBottomToolbarViewBinder() {} + public TabSwitcherBottomToolbarViewBinder(ViewGroup topRoot, ViewGroup bottomRoot) { + mTopRoot = topRoot; + mBottomRoot = bottomRoot; + } @Override public final void bind( @@ -33,8 +41,20 @@ } else if (TabSwitcherBottomToolbarModel.PRIMARY_COLOR == propertyKey) { view.findViewById(R.id.bottom_toolbar_buttons) .setBackgroundColor(model.get(TabSwitcherBottomToolbarModel.PRIMARY_COLOR)); + } else if (TabSwitcherBottomToolbarModel.SHOW_ON_TOP == propertyKey) { + final boolean showOnTop = model.get(TabSwitcherBottomToolbarModel.SHOW_ON_TOP); + view.findViewById(R.id.bottom_toolbar_top_shadow) + .setVisibility(showOnTop ? View.GONE : View.VISIBLE); + view.findViewById(R.id.bottom_toolbar_bottom_shadow) + .setVisibility(showOnTop ? View.VISIBLE : View.GONE); + reparentView(view, showOnTop ? mTopRoot : mBottomRoot); } else { assert false : "Unhandled property detected in TabSwitcherBottomToolbarViewBinder!"; } } + + private static void reparentView(View v, ViewGroup newParent) { + UiUtils.removeViewFromParent(v); + newParent.addView(v); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java index 3e75871..9ed6b4c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java
@@ -193,7 +193,8 @@ // onFinishNativeInitialization() call happens before therefore if we instantiate // DynamicModuleCoordinator now, the module will not be loaded. DynamicModuleCoordinator coordinator = getModuleCoordinator(); - assertFalse(coordinator.isModuleLoading() || coordinator.isModuleLoaded()); + assertFalse(coordinator.isModuleLoading() || coordinator.isModuleLoaded() + || coordinator.hasModuleFailedToLoad()); // We shouldn't be able to open a channel or post messages yet. assertFalse(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleUITest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleUITest.java index 015b870..ba93c53 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleUITest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleUITest.java
@@ -318,7 +318,7 @@ @Test @SmallTest @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE) - public void testSetTopBarContentView_moduleLoadingFailed_noTopBar() throws Exception { + public void testSetTopBarContentView_moduleLoadingFailed_cctHeaderVisible() throws Exception { Intent intent = new IntentBuilder(mTestPage).setModuleFailToLoadComponentName().build(); mActivityRule.startCustomTabActivityWithIntent(intent); @@ -327,9 +327,13 @@ runOnUiThreadBlocking(() -> { View anyView = new View(getActivity()); getModuleCoordinator().setTopBarContentView(anyView); + ViewGroup topBar = getActivity().findViewById(R.id.topbar); + Assert.assertNotNull(topBar); + Assert.assertThat(anyView.getParent(), equalTo(topBar)); + assertEquals(View.GONE, anyView.getVisibility()); }); - assertNoTopBar(); + assertCCTHeaderIsVisible(); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java index 523d1916..5c577071 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
@@ -45,7 +45,7 @@ import org.chromium.chrome.test.util.browser.sync.SyncTestUtil; import org.chromium.components.sync.AndroidSyncSettings; import org.chromium.components.sync.ModelType; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; import org.chromium.components.sync.protocol.AutofillWalletSpecifics; import org.chromium.components.sync.protocol.EntitySpecifics; import org.chromium.components.sync.protocol.SyncEntity; @@ -521,10 +521,8 @@ final PassphraseTypeDialogFragment typeFragment = getPassphraseTypeDialogFragment(); mSyncTestRule.stopSync(); - ThreadUtils.runOnUiThreadBlocking(() -> { - typeFragment.onItemClick( - null, null, 0, PassphraseType.CUSTOM_PASSPHRASE.internalValue()); - }); + ThreadUtils.runOnUiThreadBlocking( + () -> { typeFragment.onItemClick(null, null, 0, Passphrase.Type.CUSTOM); }); // No crash means we passed. } @@ -588,7 +586,7 @@ SyncTestUtil.waitForSyncActive(); final SyncCustomizationFragment fragment = startSyncCustomizationFragment(); ThreadUtils.runOnUiThreadBlocking( - () -> fragment.onPassphraseTypeSelected(PassphraseType.CUSTOM_PASSPHRASE)); + () -> fragment.onPassphraseTypeSelected(Passphrase.Type.CUSTOM)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); PassphraseCreationDialogFragment pcdf = getPassphraseCreationDialogFragment(); AlertDialog dialog = (AlertDialog) pcdf.getDialog();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java index fc5879b..191956d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java
@@ -22,7 +22,7 @@ import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.sync.SyncTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.components.sync.PassphraseType; +import org.chromium.components.sync.Passphrase; /** * Tests to make sure that PassphraseTypeDialogFragment presents the correct options. @@ -41,10 +41,10 @@ private static final boolean UNCHECKED = false; private static class TypeOptions { - public final PassphraseType type; + public final @Passphrase.Type int type; public final boolean isEnabled; public final boolean isChecked; - public TypeOptions(PassphraseType type, boolean isEnabled, boolean isChecked) { + public TypeOptions(@Passphrase.Type int type, boolean isEnabled, boolean isChecked) { this.type = type; this.isEnabled = isEnabled; this.isChecked = isChecked; @@ -57,20 +57,20 @@ @SmallTest @Feature({"Sync"}) public void testKeystoreEncryptionOptions() throws Exception { - createFragment(PassphraseType.KEYSTORE_PASSPHRASE, true); + createFragment(Passphrase.Type.KEYSTORE, true); assertPassphraseTypeOptions(false, - new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, ENABLED, UNCHECKED), - new TypeOptions(PassphraseType.KEYSTORE_PASSPHRASE, ENABLED, CHECKED)); + new TypeOptions(Passphrase.Type.CUSTOM, ENABLED, UNCHECKED), + new TypeOptions(Passphrase.Type.KEYSTORE, ENABLED, CHECKED)); } @Test @SmallTest @Feature({"Sync"}) public void testCustomEncryptionOptions() throws Exception { - createFragment(PassphraseType.CUSTOM_PASSPHRASE, true); + createFragment(Passphrase.Type.CUSTOM, true); assertPassphraseTypeOptions(true, - new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, DISABLED, CHECKED), - new TypeOptions(PassphraseType.KEYSTORE_PASSPHRASE, DISABLED, UNCHECKED)); + new TypeOptions(Passphrase.Type.CUSTOM, DISABLED, CHECKED), + new TypeOptions(Passphrase.Type.KEYSTORE, DISABLED, UNCHECKED)); } /* @@ -80,43 +80,43 @@ @Test @FlakyTest(message = "crbug.com/588050") public void testFrozenImplicitEncryptionOptions() throws Exception { - createFragment(PassphraseType.FROZEN_IMPLICIT_PASSPHRASE, true); + createFragment(Passphrase.Type.FROZEN_IMPLICIT, true); assertPassphraseTypeOptions(true, - new TypeOptions(PassphraseType.FROZEN_IMPLICIT_PASSPHRASE, DISABLED, CHECKED), - new TypeOptions(PassphraseType.KEYSTORE_PASSPHRASE, DISABLED, UNCHECKED)); + new TypeOptions(Passphrase.Type.FROZEN_IMPLICIT, DISABLED, CHECKED), + new TypeOptions(Passphrase.Type.KEYSTORE, DISABLED, UNCHECKED)); } @Test @SmallTest @Feature({"Sync"}) public void testImplicitEncryptionOptions() throws Exception { - createFragment(PassphraseType.IMPLICIT_PASSPHRASE, true); + createFragment(Passphrase.Type.IMPLICIT, true); assertPassphraseTypeOptions(false, - new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, ENABLED, UNCHECKED), - new TypeOptions(PassphraseType.IMPLICIT_PASSPHRASE, ENABLED, CHECKED)); + new TypeOptions(Passphrase.Type.CUSTOM, ENABLED, UNCHECKED), + new TypeOptions(Passphrase.Type.IMPLICIT, ENABLED, CHECKED)); } @Test @SmallTest @Feature({"Sync"}) public void testKeystoreEncryptionOptionsEncryptEverythingDisallowed() throws Exception { - createFragment(PassphraseType.KEYSTORE_PASSPHRASE, false); + createFragment(Passphrase.Type.KEYSTORE, false); assertPassphraseTypeOptions(false, - new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, DISABLED, UNCHECKED), - new TypeOptions(PassphraseType.KEYSTORE_PASSPHRASE, ENABLED, CHECKED)); + new TypeOptions(Passphrase.Type.CUSTOM, DISABLED, UNCHECKED), + new TypeOptions(Passphrase.Type.KEYSTORE, ENABLED, CHECKED)); } @Test @SmallTest @Feature({"Sync"}) public void testImplicitEncryptionOptionsEncryptEverythingDisallowed() throws Exception { - createFragment(PassphraseType.IMPLICIT_PASSPHRASE, false); + createFragment(Passphrase.Type.IMPLICIT, false); assertPassphraseTypeOptions(false, - new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, DISABLED, UNCHECKED), - new TypeOptions(PassphraseType.IMPLICIT_PASSPHRASE, ENABLED, CHECKED)); + new TypeOptions(Passphrase.Type.CUSTOM, DISABLED, UNCHECKED), + new TypeOptions(Passphrase.Type.IMPLICIT, ENABLED, CHECKED)); } - public void createFragment(PassphraseType type, boolean isEncryptEverythingAllowed) { + public void createFragment(@Passphrase.Type int type, boolean isEncryptEverythingAllowed) { mTypeFragment = PassphraseTypeDialogFragment.create(type, 0, isEncryptEverythingAllowed); mTypeFragment.show(mSyncTestRule.getActivity().getFragmentManager(), TAG); InstrumentationRegistry.getInstrumentation().waitForIdleSync();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java index ac67229b..5da01e14 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java
@@ -121,7 +121,7 @@ public void testBasic_Visibility() throws Exception { // Create a full dialog. DialogParams dialogParams = new DialogParams(); - dialogParams.drawableResource = R.drawable.data_reduction_illustration; + dialogParams.vectorDrawableResource = R.drawable.data_reduction_illustration; dialogParams.headerStringResource = R.string.data_reduction_promo_title; dialogParams.subheaderStringResource = R.string.data_reduction_promo_summary; dialogParams.primaryButtonStringResource = R.string.ok; @@ -150,7 +150,7 @@ View footer = promoDialogLayout.findViewById(R.id.footer); // Any controls not specified by the DialogParams won't exist. - checkControlVisibility(illustration, dialogParams.drawableResource != 0); + checkControlVisibility(illustration, dialogParams.vectorDrawableResource != 0); checkControlVisibility(header, dialogParams.headerStringResource != 0); checkControlVisibility(subheader, dialogParams.subheaderStringResource != 0); checkControlVisibility(primary, dialogParams.primaryButtonStringResource != 0); @@ -171,7 +171,7 @@ @SmallTest public void testBasic_Orientation() throws Exception { DialogParams dialogParams = new DialogParams(); - dialogParams.drawableResource = R.drawable.data_reduction_illustration; + dialogParams.vectorDrawableResource = R.drawable.data_reduction_illustration; dialogParams.headerStringResource = R.string.data_reduction_promo_title; dialogParams.subheaderStringResource = R.string.data_reduction_promo_summary; dialogParams.primaryButtonStringResource = R.string.ok; @@ -249,7 +249,7 @@ public void testBasic_HeaderBehavior_WithIllustration() throws Exception { // With an illustration, the header View is part of the scrollable content. DialogParams dialogParams = new DialogParams(); - dialogParams.drawableResource = R.drawable.data_reduction_illustration; + dialogParams.drawableResource = R.drawable.data_reduction_main_menu_chart; dialogParams.headerStringResource = R.string.data_reduction_promo_title; dialogParams.primaryButtonStringResource = R.string.data_reduction_enable_button;
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 35fc5b68..fd6a571 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -3703,7 +3703,7 @@ </message> <message name="IDS_EXTENSION_PROMPT_WARNING_CONTENT_SETTINGS" desc="Permission string for access to content settings."> - Change your settings that control websites' access to features such as cookies, JavaScript, plugins, geolocation, microphone, camera etc. + Change your settings that control websites' access to features such as cookies, JavaScript, plugins, geolocation, microphone, camera, etc. </message> <message name="IDS_EXTENSION_PROMPT_WARNING_PRIVACY" desc="Permission string for access to privacy settings."> Change your privacy-related settings
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 5fc7de7..c112b5b 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -652,6 +652,10 @@ "lookalikes/lookalike_url_controller_client.h", "lookalikes/lookalike_url_interstitial_page.cc", "lookalikes/lookalike_url_interstitial_page.h", + "lookalikes/lookalike_url_navigation_throttle.cc", + "lookalikes/lookalike_url_navigation_throttle.h", + "lookalikes/lookalike_url_service.cc", + "lookalikes/lookalike_url_service.h", "mac/bluetooth_utility.h", "mac/bluetooth_utility.mm", "mac/dock.h", @@ -2068,7 +2072,6 @@ "//ui/accessibility", "//ui/base", "//ui/base:ui_data_pack", - "//ui/base/idle", "//ui/base/ime", "//ui/events:events_base", "//ui/gfx", @@ -2841,10 +2844,6 @@ "lifetime/browser_close_manager.h", "lifetime/termination_notification.cc", "lifetime/termination_notification.h", - "lookalikes/lookalike_url_navigation_observer.cc", - "lookalikes/lookalike_url_navigation_observer.h", - "lookalikes/lookalike_url_service.cc", - "lookalikes/lookalike_url_service.h", "media/capture_access_handler_base.cc", "media/capture_access_handler_base.h", "media/unified_autoplay_config.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 6c9ccd2..c23579d 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -266,8 +266,4 @@ # The following is used to build FakeSigninManager instances for testing. "+components/signin/core/browser/fake_signin_manager.h", ], - # To share values of UMA enums between product code and tests. - "translate_manager_browsertest.cc": [ - "+services/network/initiator_lock_compatibility.h", - ], }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0fe1aba..af610d04 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2264,6 +2264,9 @@ {"force-update-menu-type", flag_descriptions::kUpdateMenuTypeName, flag_descriptions::kUpdateMenuTypeDescription, kOsAndroid, MULTI_VALUE_TYPE(kForceUpdateMenuTypeChoices)}, + {"enable-inline-update-flow", flag_descriptions::kInlineUpdateFlowName, + flag_descriptions::kInlineUpdateFlowDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kInlineUpdateFlow)}, {"update-menu-item-custom-summary", flag_descriptions::kUpdateMenuItemCustomSummaryName, flag_descriptions::kUpdateMenuItemCustomSummaryDescription, kOsAndroid, @@ -3628,12 +3631,6 @@ flag_descriptions::kExperimentalProductivityFeaturesDescription, kOsAll, FEATURE_VALUE_TYPE(features::kExperimentalProductivityFeatures)}, -#if defined(OS_ANDROID) - {"enable-display-cutout-api", flag_descriptions::kDisplayCutoutAPIName, - flag_descriptions::kDisplayCutoutAPIDescription, kOsAndroid, - FEATURE_VALUE_TYPE(features::kDisplayCutoutAPI)}, -#endif // OS_ANDROID - #if defined(USE_AURA) {"touchpad-overscroll-history-navigation", flag_descriptions::kTouchpadOverscrollHistoryNavigationName, @@ -4207,6 +4204,11 @@ password_manager::features::kManualPasswordGenerationAndroid)}, #endif // defined(OS_ANDROID) + {"autofill-show-full-disclosure-label", + flag_descriptions::kAutofillShowFullDisclosureLabelName, + flag_descriptions::kAutofillShowFullDisclosureLabelDescription, kOsAll, + FEATURE_VALUE_TYPE(autofill::features::kAutofillShowFullDisclosureLabel)}, + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index cc0a6b0c..dc351700 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -108,6 +108,7 @@ &kCCTReportParallelRequestStatus, &kCCTResourcePrefetch, &kChromeDuetFeature, + &kChromeDuetAdaptive, &kChromeSmartSelection, &kCommandLineOnNonRooted, &kContentSuggestionsScrollToLoad, @@ -290,6 +291,9 @@ const base::Feature kChromeDuetFeature{"ChromeDuet", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kChromeDuetAdaptive{"ChromeDuetAdaptive", + base::FEATURE_ENABLED_BY_DEFAULT}; + const base::Feature kChromeSmartSelection{"ChromeSmartSelection", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index ad395a3..93796ca 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -38,6 +38,7 @@ extern const base::Feature kCCTReportParallelRequestStatus; extern const base::Feature kCCTResourcePrefetch; extern const base::Feature kChromeDuetFeature; +extern const base::Feature kChromeDuetAdaptive; extern const base::Feature kChromeSmartSelection; extern const base::Feature kCommandLineOnNonRooted; extern const base::Feature kContentSuggestionsScrollToLoad;
diff --git a/chrome/browser/android/download/local_media_data_source_factory.cc b/chrome/browser/android/download/local_media_data_source_factory.cc index 201874d..90081573 100644 --- a/chrome/browser/android/download/local_media_data_source_factory.cc +++ b/chrome/browser/android/download/local_media_data_source_factory.cc
@@ -6,12 +6,14 @@ #include <vector> +#include "base/android/content_uri_utils.h" #include "base/bind.h" #include "base/callback.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop_current.h" +#include "build/build_config.h" #include "mojo/public/cpp/bindings/binding.h" namespace { @@ -20,6 +22,15 @@ SafeMediaMetadataParser::MediaDataSourceFactory::MediaDataCallback; using ReadFileCallback = base::OnceCallback<void(bool, std::vector<char>)>; +// Helper method to post |cb| on the |main_task_runner| with read result. +void OnReadComplete(scoped_refptr<base::SequencedTaskRunner> main_task_runner, + ReadFileCallback cb, + bool success, + std::vector<char> data) { + main_task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(cb), success, std::move(data))); +} + // Reads a chunk of the file on a file thread, and reply the data or error to // main thread. void ReadFile(const base::FilePath& file_path, @@ -27,30 +38,38 @@ int64_t length, scoped_refptr<base::SequencedTaskRunner> main_task_runner, ReadFileCallback cb) { - base::File file(file_path, - base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ); + base::File file; +#if defined(OS_ANDROID) + if (file_path.IsContentUri()) { + file = base::OpenContentUriForRead(file_path); + if (!file.IsValid()) { + OnReadComplete(main_task_runner, std::move(cb), false /*success*/, + std::vector<char>()); + return; + } + } +#endif // defined(OS_ANDROID) + if (!file.IsValid()) + file = base::File(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); if (!file.IsValid()) { - main_task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(cb), false /*success*/, std::vector<char>())); + OnReadComplete(main_task_runner, std::move(cb), false /*success*/, + std::vector<char>()); return; } auto buffer = std::vector<char>(length); int bytes_read = file.Read(position, buffer.data(), length); if (bytes_read == -1) { - main_task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(cb), false /*success*/, std::vector<char>())); + OnReadComplete(main_task_runner, std::move(cb), false /*success*/, + std::vector<char>()); return; } DCHECK_GE(bytes_read, 0); if (bytes_read < length) buffer.resize(bytes_read); - main_task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(cb), true /*success*/, std::move(buffer))); + OnReadComplete(main_task_runner, std::move(cb), true /*success*/, + std::move(buffer)); } // Read media file incrementally and send data to the utility process to parse
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc index da74cfc1..001e6701 100644 --- a/chrome/browser/android/vr/vr_shell.cc +++ b/chrome/browser/android/vr/vr_shell.cc
@@ -149,9 +149,7 @@ int display_height_pixels, bool pause_content, bool low_density) - : web_vr_autopresentation_expected_( - ui_initial_state.web_vr_autopresentation_expected), - delegate_provider_(delegate), + : delegate_provider_(delegate), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), reprojected_rendering_(reprojected_rendering), display_size_meters_(display_width_meters, display_height_meters), @@ -181,12 +179,6 @@ gl_thread_->Start(); - if (ui_initial_state.in_web_vr || - ui_initial_state.web_vr_autopresentation_expected) { - UMA_HISTOGRAM_BOOLEAN("VRAutopresentedWebVR", - ui_initial_state.web_vr_autopresentation_expected); - } - can_load_new_assets_ = AssetsLoader::GetInstance()->ComponentReady(); if (!can_load_new_assets_) { waiting_for_assets_component_timer_.Start( @@ -259,8 +251,7 @@ if (web_contents_ && !SessionMetricsHelper::FromWebContents(web_contents_)) { SessionMetricsHelper::CreateForWebContents( web_contents_, - webvr_mode_ ? Mode::kWebXrVrPresentation : Mode::kVrBrowsingRegular, - web_vr_autopresentation_expected_); + webvr_mode_ ? Mode::kWebXrVrPresentation : Mode::kVrBrowsingRegular); } } @@ -542,11 +533,11 @@ CreatePageInfo(); ui_->SetWebVrMode(enabled); - if (!webvr_mode_ && !web_vr_autopresentation_expected_) { - AssetsLoader::GetInstance()->GetMetricsHelper()->OnEnter(Mode::kVrBrowsing); - } else { + if (webvr_mode_) { AssetsLoader::GetInstance()->GetMetricsHelper()->OnEnter( Mode::kWebXrVrPresentation); + } else { + AssetsLoader::GetInstance()->GetMetricsHelper()->OnEnter(Mode::kVrBrowsing); } }
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h index 0e1f68f..9c7965b 100644 --- a/chrome/browser/android/vr/vr_shell.h +++ b/chrome/browser/android/vr/vr_shell.h
@@ -333,7 +333,6 @@ std::unique_ptr<PageInfo> CreatePageInfo(); bool webvr_mode_ = false; - bool web_vr_autopresentation_expected_ = false; content::WebContents* web_contents_ = nullptr; bool web_contents_is_native_page_ = false;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 9f61d79e..783a2969 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -60,6 +60,7 @@ #include "chrome/browser/language/translate_frame_binder.h" #include "chrome/browser/lifetime/browser_shutdown.h" #include "chrome/browser/loader/chrome_navigation_data.h" +#include "chrome/browser/lookalikes/lookalike_url_navigation_throttle.h" #include "chrome/browser/media/router/media_router_feature.h" #include "chrome/browser/media/router/presentation/presentation_service_delegate_impl.h" #include "chrome/browser/media/router/presentation/receiver_presentation_service_delegate_impl.h" @@ -4205,6 +4206,14 @@ } #endif +#if !defined(OS_ANDROID) + std::unique_ptr<content::NavigationThrottle> + lookalike_url_navigation_throttle = + LookalikeUrlNavigationThrottle::MaybeCreateNavigationThrottle(handle); + if (lookalike_url_navigation_throttle) + throttles.push_back(std::move(lookalike_url_navigation_throttle)); +#endif + std::unique_ptr<content::NavigationThrottle> pdf_iframe_throttle = PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle); if (pdf_iframe_throttle)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index bf0e175..dc1a26d 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -227,7 +227,6 @@ "//ui/accessibility", "//ui/aura", "//ui/base", - "//ui/base/idle", "//ui/chromeos", "//ui/chromeos/events", "//ui/compositor", @@ -580,6 +579,8 @@ "arc/voice_interaction/voice_interaction_controller_client.h", "arc/wallpaper/arc_wallpaper_service.cc", "arc/wallpaper/arc_wallpaper_service.h", + "assistant/assistant_util.cc", + "assistant/assistant_util.h", "attestation/attestation_ca_client.cc", "attestation/attestation_ca_client.h", "attestation/attestation_policy_observer.cc", @@ -2210,6 +2211,7 @@ "arc/voice_interaction/fake_voice_interaction_controller.cc", "arc/voice_interaction/voice_interaction_controller_client_unittest.cc", "arc/wallpaper/arc_wallpaper_service_unittest.cc", + "assistant/assistant_util_unittest.cc", "attestation/attestation_ca_client_unittest.cc", "attestation/attestation_policy_observer_unittest.cc", "attestation/enrollment_policy_observer_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_panel.cc b/chrome/browser/chromeos/accessibility/accessibility_panel.cc index 37502bc..83b7f4e2 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_panel.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_panel.cc
@@ -127,6 +127,7 @@ } bool AccessibilityPanel::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { // Eat all requests as context menus are disallowed. return true;
diff --git a/chrome/browser/chromeos/accessibility/accessibility_panel.h b/chrome/browser/chromeos/accessibility/accessibility_panel.h index 4cfcdcf..6f39b0d 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_panel.h +++ b/chrome/browser/chromeos/accessibility/accessibility_panel.h
@@ -54,7 +54,8 @@ class AccessibilityPanelWebContentsObserver; // content::WebContentsDelegate: - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; // Indirectly invoked by the component extension. void DidFirstVisuallyNonEmptyPaint();
diff --git a/chrome/browser/chromeos/arc/arc_util.cc b/chrome/browser/chromeos/arc/arc_util.cc index 536ab84..338ae5a2 100644 --- a/chrome/browser/chromeos/arc/arc_util.cc +++ b/chrome/browser/chromeos/arc/arc_util.cc
@@ -41,12 +41,10 @@ #include "components/arc/arc_features.h" #include "components/arc/arc_prefs.h" #include "components/arc/arc_util.h" -#include "components/language/core/browser/pref_names.h" #include "components/prefs/pref_service.h" #include "components/user_manager/known_user.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" -#include "third_party/icu/source/common/unicode/locid.h" namespace arc { @@ -583,48 +581,6 @@ std::move(callback))); } -ash::mojom::AssistantAllowedState IsAssistantAllowedForProfile( - const Profile* profile) { - if (!chromeos::switches::IsAssistantEnabled()) { - return ash::mojom::AssistantAllowedState::DISALLOWED_BY_FLAG; - } - - if (!chromeos::ProfileHelper::IsPrimaryProfile(profile)) - return ash::mojom::AssistantAllowedState::DISALLOWED_BY_NONPRIMARY_USER; - - if (profile->IsOffTheRecord()) - return ash::mojom::AssistantAllowedState::DISALLOWED_BY_INCOGNITO; - - if (profile->IsLegacySupervised()) - return ash::mojom::AssistantAllowedState::DISALLOWED_BY_SUPERVISED_USER; - - if (chromeos::DemoSession::IsDeviceInDemoMode()) - return ash::mojom::AssistantAllowedState::DISALLOWED_BY_DEMO_MODE; - - if (user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()) - return ash::mojom::AssistantAllowedState::DISALLOWED_BY_PUBLIC_SESSION; - - const std::string kAllowedLocales[] = {ULOC_US, ULOC_UK, ULOC_CANADA, - ULOC_CANADA_FRENCH}; - - const PrefService* prefs = profile->GetPrefs(); - std::string pref_locale = - prefs->GetString(language::prefs::kApplicationLocale); - // Also accept runtime locale which maybe an approximation of user's pref - // locale. - const std::string kRuntimeLocale = icu::Locale::getDefault().getName(); - if (!pref_locale.empty()) { - base::ReplaceChars(pref_locale, "-", "_", &pref_locale); - bool disallowed = !base::ContainsValue(kAllowedLocales, pref_locale) && - !base::ContainsValue(kAllowedLocales, kRuntimeLocale); - - if (disallowed) - return ash::mojom::AssistantAllowedState::DISALLOWED_BY_LOCALE; - } - - return ash::mojom::AssistantAllowedState::ALLOWED; -} - ArcSupervisionTransition GetSupervisionTransition(const Profile* profile) { DCHECK(profile); DCHECK(profile->GetPrefs());
diff --git a/chrome/browser/chromeos/arc/arc_util.h b/chrome/browser/chromeos/arc/arc_util.h index fe4b1cb..c913e34 100644 --- a/chrome/browser/chromeos/arc/arc_util.h +++ b/chrome/browser/chromeos/arc/arc_util.h
@@ -7,7 +7,6 @@ #include <stdint.h> -#include "ash/public/interfaces/voice_interaction_controller.mojom.h" #include "base/callback_forward.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "components/arc/arc_supervision_transition.h" @@ -160,10 +159,6 @@ const base::FilePath& profile_path, base::OnceClosure callback); -// Returns whether Google Assistant feature is allowed for given |profile|. -ash::mojom::AssistantAllowedState IsAssistantAllowedForProfile( - const Profile* profile); - // Returns the supervision transition status as stored in profile prefs. ArcSupervisionTransition GetSupervisionTransition(const Profile* profile);
diff --git a/chrome/browser/chromeos/arc/arc_util_unittest.cc b/chrome/browser/chromeos/arc/arc_util_unittest.cc index 3be5cae..42f53e4 100644 --- a/chrome/browser/chromeos/arc/arc_util_unittest.cc +++ b/chrome/browser/chromeos/arc/arc_util_unittest.cc
@@ -12,7 +12,6 @@ #include "base/test/icu_test_util.h" #include "base/test/scoped_command_line.h" #include "base/test/scoped_feature_list.h" -#include "base/test/scoped_locale.h" #include "base/values.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h" @@ -37,7 +36,6 @@ #include "chromeos/dbus/fake_oobe_configuration_client.h" #include "components/account_id/account_id.h" #include "components/arc/arc_prefs.h" -#include "components/language/core/browser/pref_names.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/prefs/pref_service.h" #include "components/prefs/testing_pref_service.h" @@ -50,7 +48,6 @@ #include "content/public/common/content_switches.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/icu/source/common/unicode/locid.h" namespace arc { namespace util { @@ -173,7 +170,6 @@ void SetUp() override { command_line_ = std::make_unique<base::test::ScopedCommandLine>(); - feature_list_.InitAndEnableFeature(chromeos::switches::kAssistantFeature); ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); profile_manager_ = std::make_unique<TestingProfileManager>( @@ -510,63 +506,6 @@ EXPECT_FALSE(IsArcPlayStoreEnabledPreferenceManagedForProfile(profile())); } -TEST_F(ChromeArcUtilTest, IsAssistantAllowedForProfile_SecondaryUser) { - ScopedLogIn login2( - GetFakeUserManager(), - AccountId::FromUserEmailGaiaId("user2@gmail.com", "0123456789")); - ScopedLogIn login(GetFakeUserManager(), - AccountId::FromUserEmailGaiaId( - profile()->GetProfileUserName(), kTestGaiaId)); - - EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_NONPRIMARY_USER, - IsAssistantAllowedForProfile(profile())); -} - -TEST_F(ChromeArcUtilTest, IsAssistantAllowedForProfile_SupervisedUser) { - ScopedLogIn login(GetFakeUserManager(), - AccountId::FromUserEmailGaiaId( - profile()->GetProfileUserName(), kTestGaiaId)); - profile()->SetSupervisedUserId("foo"); - EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_SUPERVISED_USER, - IsAssistantAllowedForProfile(profile())); -} - -TEST_F(ChromeArcUtilTest, IsAssistantAllowedForProfile_Locale) { - profile()->GetTestingPrefService()->SetString( - language::prefs::kApplicationLocale, "he"); - UErrorCode error_code = U_ZERO_ERROR; - const icu::Locale& old_locale = icu::Locale::getDefault(); - icu::Locale::setDefault(icu::Locale("he"), error_code); - ScopedLogIn login(GetFakeUserManager(), - AccountId::FromUserEmailGaiaId( - profile()->GetProfileUserName(), kTestGaiaId)); - - EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_LOCALE, - IsAssistantAllowedForProfile(profile())); - icu::Locale::setDefault(old_locale, error_code); -} - -TEST_F(ChromeArcUtilTest, IsAssistantAllowedForProfile_DemoMode) { - chromeos::DemoSession::SetDemoConfigForTesting( - chromeos::DemoSession::DemoModeConfig::kOnline); - ScopedLogIn login(GetFakeUserManager(), - AccountId::FromUserEmail(profile()->GetProfileUserName()), - user_manager::USER_TYPE_PUBLIC_ACCOUNT); - EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_DEMO_MODE, - IsAssistantAllowedForProfile(profile())); - - chromeos::DemoSession::SetDemoConfigForTesting( - chromeos::DemoSession::DemoModeConfig::kNone); -} - -TEST_F(ChromeArcUtilTest, IsAssistantAllowedForProfile_PublicSession) { - ScopedLogIn login(GetFakeUserManager(), - AccountId::FromUserEmail(profile()->GetProfileUserName()), - user_manager::USER_TYPE_PUBLIC_ACCOUNT); - EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_PUBLIC_SESSION, - IsAssistantAllowedForProfile(profile())); -} - // Test the AreArcAllOptInPreferencesIgnorableForProfile() function. TEST_F(ChromeArcUtilTest, AreArcAllOptInPreferencesIgnorableForProfile) { base::CommandLine::ForCurrentProcess()->InitFromArgv(
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc index 5340715..6f1f6e0 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc
@@ -343,8 +343,7 @@ if (state_ != State::kDisabled) { DLOG(WARNING) << "Cannot start tracing, it is already enabled."; - if (callback) - std::move(callback).Run(false /*success*/); + std::move(callback).Run(false /*success*/); return; } state_ = State::kStarting; @@ -391,8 +390,7 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(State::kStarting, state_); state_ = success ? State::kEnabled : State::kDisabled; - if (callback) - std::move(callback).Run(success); + std::move(callback).Run(success); } void ArcTracingBridge::StopAndFlush(TraceDataCallback callback) { @@ -463,9 +461,10 @@ void ArcTracingBridge::ArcTracingAgent::StartTracing( const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - bridge_->StartTracing(config, SuccessCallback()); + bridge_->StartTracing(config, std::move(callback)); } void ArcTracingBridge::ArcTracingAgent::StopAndFlush(
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h index e77f8a4..dc321c2 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h
@@ -78,7 +78,8 @@ // tracing::mojom::Agent. void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) override; void StopAndFlush(tracing::mojom::RecorderPtr recorder) override; void OnTraceData(const std::string& data);
diff --git a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc index 295b6c4..1280a28 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc
@@ -39,8 +39,9 @@ voice_interaction_hotword_enabled_ = enabled; } -void FakeVoiceInteractionController::NotifySetupCompleted(bool completed) { - voice_interaction_setup_completed_ = completed; +void FakeVoiceInteractionController::NotifyConsentStatus( + ash::mojom::ConsentStatus consent_status) { + consent_status_ = consent_status; } void FakeVoiceInteractionController::NotifyFeatureAllowed(
diff --git a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h index a14b993..36a4228 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h +++ b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h
@@ -26,7 +26,7 @@ void NotifyContextEnabled(bool enabled) override; void NotifyHotwordAlwaysOn(bool enabled) override; void NotifyHotwordEnabled(bool enabled) override; - void NotifySetupCompleted(bool completed) override; + void NotifyConsentStatus(ash::mojom::ConsentStatus consent_status) override; void NotifyFeatureAllowed(ash::mojom::AssistantAllowedState state) override; void NotifyNotificationEnabled(bool enabled) override; void NotifyLocaleChanged(const std::string& locale) override; @@ -45,8 +45,8 @@ bool voice_interaction_hotword_enabled() const { return voice_interaction_hotword_enabled_; } - bool voice_interaction_setup_completed() const { - return voice_interaction_setup_completed_; + ash::mojom::ConsentStatus voice_interaction_consent_status() const { + return consent_status_; } ash::mojom::AssistantAllowedState assistant_allowed_state() const { return assistant_allowed_state_; @@ -64,7 +64,8 @@ bool voice_interaction_context_enabled_ = false; bool voice_interaction_hotword_always_on_ = false; bool voice_interaction_hotword_enabled_ = false; - bool voice_interaction_setup_completed_ = false; + ash::mojom::ConsentStatus consent_status_ = + ash::mojom::ConsentStatus::kUnknown; bool voice_interaction_notification_enabled_ = false; std::string locale_; ash::mojom::AssistantAllowedState assistant_allowed_state_ =
diff --git a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.cc b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.cc index 834b6b0..8d4b196 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.cc
@@ -11,9 +11,10 @@ #include "ash/public/interfaces/constants.mojom.h" #include "base/bind.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/ash/assistant/assistant_pref_util.h" #include "chromeos/constants/chromeos_switches.h" #include "components/arc/arc_prefs.h" #include "components/arc/arc_util.h" @@ -116,18 +117,17 @@ voice_interaction_controller_->NotifyHotwordAlwaysOn(always_on); } -void VoiceInteractionControllerClient::NotifySetupCompleted() { +void VoiceInteractionControllerClient::NotifyConsentStatus() { DCHECK(profile_); PrefService* prefs = profile_->GetPrefs(); - bool completed = - prefs->GetBoolean(prefs::kVoiceInteractionActivityControlAccepted); - voice_interaction_controller_->NotifySetupCompleted(completed); + voice_interaction_controller_->NotifyConsentStatus( + assistant::prefs::GetConsentStatus(prefs)); } void VoiceInteractionControllerClient::NotifyFeatureAllowed() { DCHECK(profile_); ash::mojom::AssistantAllowedState state = - IsAssistantAllowedForProfile(profile_); + assistant::IsAssistantAllowedForProfile(profile_); voice_interaction_controller_->NotifyFeatureAllowed(state); } @@ -182,9 +182,9 @@ pref_change_registrar_->Init(prefs); pref_change_registrar_->Add( - prefs::kVoiceInteractionActivityControlAccepted, + assistant::prefs::kAssistantConsentStatus, base::BindRepeating( - &VoiceInteractionControllerClient::NotifySetupCompleted, + &VoiceInteractionControllerClient::NotifyConsentStatus, base::Unretained(this))); pref_change_registrar_->Add( language::prefs::kApplicationLocale, @@ -222,7 +222,7 @@ &VoiceInteractionControllerClient::NotifyLaunchWithMicOpen, base::Unretained(this))); - NotifySetupCompleted(); + NotifyConsentStatus(); NotifySettingsEnabled(); NotifyContextEnabled(); NotifyLocaleChanged();
diff --git a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h index 008ce13..7e64737 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h +++ b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h
@@ -56,7 +56,7 @@ void NotifyContextEnabled(); void NotifyHotwordEnabled(); void NotifyHotwordAlwaysOn(); - void NotifySetupCompleted(); + void NotifyConsentStatus(); void NotifyFeatureAllowed(); void NotifyNotificationEnabled(); void NotifyLocaleChanged();
diff --git a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc index 5d428d1..5e658eb 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/arc/arc_session_manager.h" #include "chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ui/ash/assistant/assistant_pref_util.h" #include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/testing_profile.h" #include "components/arc/arc_prefs.h" @@ -138,15 +139,17 @@ false, voice_interaction_controller()->voice_interaction_notification_enabled()); - ASSERT_EQ(false, - prefs->GetBoolean(prefs::kVoiceInteractionActivityControlAccepted)); - prefs->SetBoolean(prefs::kVoiceInteractionActivityControlAccepted, true); - ASSERT_EQ(true, - prefs->GetBoolean(prefs::kVoiceInteractionActivityControlAccepted)); + ASSERT_EQ(static_cast<int>(ash::mojom::ConsentStatus::kUnknown), + prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); + prefs->SetInteger( + assistant::prefs::kAssistantConsentStatus, + static_cast<int>(ash::mojom::ConsentStatus::kActivityControlAccepted)); + ASSERT_EQ( + static_cast<int>(ash::mojom::ConsentStatus::kActivityControlAccepted), + prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); voice_interaction_controller_client()->FlushMojoForTesting(); - EXPECT_EQ( - true, - voice_interaction_controller()->voice_interaction_setup_completed()); + EXPECT_EQ(ash::mojom::ConsentStatus::kActivityControlAccepted, + voice_interaction_controller()->voice_interaction_consent_status()); ASSERT_EQ("", prefs->GetString(language::prefs::kApplicationLocale)); prefs->SetString(language::prefs::kApplicationLocale, "en-CA");
diff --git a/chrome/browser/chromeos/assistant/OWNERS b/chrome/browser/chromeos/assistant/OWNERS new file mode 100644 index 0000000..1f575b1 --- /dev/null +++ b/chrome/browser/chromeos/assistant/OWNERS
@@ -0,0 +1,3 @@ +file://chromeos/assistant/OWNERS + +# COMPONENTS: UI>Shell>Assistant
diff --git a/chrome/browser/chromeos/assistant/assistant_util.cc b/chrome/browser/chromeos/assistant/assistant_util.cc new file mode 100644 index 0000000..25ad631 --- /dev/null +++ b/chrome/browser/chromeos/assistant/assistant_util.cc
@@ -0,0 +1,62 @@ +// Copyright 2019 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/assistant/assistant_util.h" + +#include <string> + +#include "chrome/browser/chromeos/login/demo_mode/demo_session.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chromeos/constants/chromeos_switches.h" +#include "components/language/core/browser/pref_names.h" +#include "components/prefs/pref_service.h" +#include "components/user_manager/user_manager.h" +#include "third_party/icu/source/common/unicode/locid.h" + +namespace assistant { + +ash::mojom::AssistantAllowedState IsAssistantAllowedForProfile( + const Profile* profile) { + if (!chromeos::switches::IsAssistantEnabled()) { + return ash::mojom::AssistantAllowedState::DISALLOWED_BY_FLAG; + } + + if (!chromeos::ProfileHelper::IsPrimaryProfile(profile)) + return ash::mojom::AssistantAllowedState::DISALLOWED_BY_NONPRIMARY_USER; + + if (profile->IsOffTheRecord()) + return ash::mojom::AssistantAllowedState::DISALLOWED_BY_INCOGNITO; + + if (profile->IsLegacySupervised()) + return ash::mojom::AssistantAllowedState::DISALLOWED_BY_SUPERVISED_USER; + + if (chromeos::DemoSession::IsDeviceInDemoMode()) + return ash::mojom::AssistantAllowedState::DISALLOWED_BY_DEMO_MODE; + + if (user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()) + return ash::mojom::AssistantAllowedState::DISALLOWED_BY_PUBLIC_SESSION; + + const std::string kAllowedLocales[] = {ULOC_US, ULOC_UK, ULOC_CANADA, + ULOC_CANADA_FRENCH}; + + const PrefService* prefs = profile->GetPrefs(); + std::string pref_locale = + prefs->GetString(language::prefs::kApplicationLocale); + // Also accept runtime locale which maybe an approximation of user's pref + // locale. + const std::string kRuntimeLocale = icu::Locale::getDefault().getName(); + if (!pref_locale.empty()) { + base::ReplaceChars(pref_locale, "-", "_", &pref_locale); + bool disallowed = !base::ContainsValue(kAllowedLocales, pref_locale) && + !base::ContainsValue(kAllowedLocales, kRuntimeLocale); + + if (disallowed) + return ash::mojom::AssistantAllowedState::DISALLOWED_BY_LOCALE; + } + + return ash::mojom::AssistantAllowedState::ALLOWED; +} + +} // namespace assistant
diff --git a/chrome/browser/chromeos/assistant/assistant_util.h b/chrome/browser/chromeos/assistant/assistant_util.h new file mode 100644 index 0000000..8ddacb1 --- /dev/null +++ b/chrome/browser/chromeos/assistant/assistant_util.h
@@ -0,0 +1,20 @@ +// Copyright 2019 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_ASSISTANT_ASSISTANT_UTIL_H_ +#define CHROME_BROWSER_CHROMEOS_ASSISTANT_ASSISTANT_UTIL_H_ + +#include "ash/public/interfaces/voice_interaction_controller.mojom.h" + +class Profile; + +namespace assistant { + +// Returns whether Google Assistant feature is allowed for given |profile|. +ash::mojom::AssistantAllowedState IsAssistantAllowedForProfile( + const Profile* profile); + +} // namespace assistant + +#endif // CHROME_BROWSER_CHROMEOS_ASSISTANT_ASSISTANT_UTIL_H_
diff --git a/chrome/browser/chromeos/assistant/assistant_util_unittest.cc b/chrome/browser/chromeos/assistant/assistant_util_unittest.cc new file mode 100644 index 0000000..144544e --- /dev/null +++ b/chrome/browser/chromeos/assistant/assistant_util_unittest.cc
@@ -0,0 +1,237 @@ +// Copyright 2019 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/assistant/assistant_util.h" + +#include <memory> + +#include "base/files/scoped_temp_dir.h" +#include "base/test/scoped_command_line.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_session.h" +#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/constants/chromeos_switches.h" +#include "components/account_id/account_id.h" +#include "components/language/core/browser/pref_names.h" +#include "components/prefs/testing_pref_service.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/user_manager.h" +#include "components/user_manager/user_type.h" +#include "content/public/common/content_switches.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/icu/source/common/unicode/locid.h" + +namespace assistant { +namespace { + +constexpr char kTestProfileName[] = "user@gmail.com"; +constexpr char kTestGaiaId[] = "1234567890"; + +class FakeUserManagerWithLocalState : public chromeos::FakeChromeUserManager { + public: + explicit FakeUserManagerWithLocalState( + TestingProfileManager* testing_profile_manager) + : testing_profile_manager_(testing_profile_manager), + test_local_state_(std::make_unique<TestingPrefServiceSimple>()) { + RegisterPrefs(test_local_state_->registry()); + } + + PrefService* GetLocalState() const override { + return test_local_state_.get(); + } + + TestingProfileManager* testing_profile_manager() { + return testing_profile_manager_; + } + + private: + // Unowned pointer. + TestingProfileManager* const testing_profile_manager_; + + std::unique_ptr<TestingPrefServiceSimple> test_local_state_; + + DISALLOW_COPY_AND_ASSIGN(FakeUserManagerWithLocalState); +}; + +class ScopedLogIn { + public: + ScopedLogIn( + FakeUserManagerWithLocalState* fake_user_manager, + const AccountId& account_id, + user_manager::UserType user_type = user_manager::USER_TYPE_REGULAR) + : fake_user_manager_(fake_user_manager), account_id_(account_id) { + // Prevent access to DBus. This switch is reset in case set from test SetUp + // due massive usage of InitFromArgv. + base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + if (!command_line.HasSwitch(switches::kTestType)) + command_line.AppendSwitch(switches::kTestType); + + switch (user_type) { + case user_manager::USER_TYPE_REGULAR: // fallthrough + case user_manager::USER_TYPE_ACTIVE_DIRECTORY: + LogIn(); + break; + case user_manager::USER_TYPE_PUBLIC_ACCOUNT: + LogInAsPublicAccount(); + break; + case user_manager::USER_TYPE_ARC_KIOSK_APP: + LogInArcKioskApp(); + break; + default: + NOTREACHED(); + } + fake_user_manager_->testing_profile_manager()->SetLoggedIn(true); + } + + ~ScopedLogIn() { + fake_user_manager_->testing_profile_manager()->SetLoggedIn(false); + LogOut(); + } + + private: + void LogIn() { + fake_user_manager_->AddUser(account_id_); + fake_user_manager_->LoginUser(account_id_); + } + + void LogInAsPublicAccount() { + fake_user_manager_->AddPublicAccountUser(account_id_); + fake_user_manager_->LoginUser(account_id_); + } + + void LogInArcKioskApp() { + fake_user_manager_->AddArcKioskAppUser(account_id_); + fake_user_manager_->LoginUser(account_id_); + } + + void LogOut() { fake_user_manager_->RemoveUserFromList(account_id_); } + + FakeUserManagerWithLocalState* fake_user_manager_; + const AccountId account_id_; + + DISALLOW_COPY_AND_ASSIGN(ScopedLogIn); +}; + +} // namespace + +class ChromeAssistantUtilTest : public testing::Test { + public: + ChromeAssistantUtilTest() = default; + ~ChromeAssistantUtilTest() override = default; + + void SetUp() override { + command_line_ = std::make_unique<base::test::ScopedCommandLine>(); + feature_list_.InitAndEnableFeature(chromeos::switches::kAssistantFeature); + + ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); + profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(profile_manager_->SetUp()); + + user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>( + std::make_unique<FakeUserManagerWithLocalState>( + profile_manager_.get())); + + profile_ = profile_manager_->CreateTestingProfile(kTestProfileName); + } + + void TearDown() override { + // Avoid retries, let the next test start safely. + profile_manager_->DeleteTestingProfile(kTestProfileName); + profile_ = nullptr; + user_manager_enabler_.reset(); + profile_manager_.reset(); + command_line_.reset(); + } + + TestingProfile* profile() { return profile_; } + + FakeUserManagerWithLocalState* GetFakeUserManager() const { + return static_cast<FakeUserManagerWithLocalState*>( + user_manager::UserManager::Get()); + } + + void LogIn() { + const auto account_id = AccountId::FromUserEmailGaiaId( + profile()->GetProfileUserName(), kTestGaiaId); + GetFakeUserManager()->AddUser(account_id); + GetFakeUserManager()->LoginUser(account_id); + } + + private: + std::unique_ptr<base::test::ScopedCommandLine> command_line_; + base::test::ScopedFeatureList feature_list_; + content::TestBrowserThreadBundle thread_bundle_; + base::ScopedTempDir data_dir_; + std::unique_ptr<TestingProfileManager> profile_manager_; + std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_; + // Owned by |profile_manager_| + TestingProfile* profile_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(ChromeAssistantUtilTest); +}; + +TEST_F(ChromeAssistantUtilTest, IsAssistantAllowedForProfile_SecondaryUser) { + ScopedLogIn login2( + GetFakeUserManager(), + AccountId::FromUserEmailGaiaId("user2@gmail.com", "0123456789")); + ScopedLogIn login(GetFakeUserManager(), + AccountId::FromUserEmailGaiaId( + profile()->GetProfileUserName(), kTestGaiaId)); + + EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_NONPRIMARY_USER, + IsAssistantAllowedForProfile(profile())); +} + +TEST_F(ChromeAssistantUtilTest, IsAssistantAllowedForProfile_SupervisedUser) { + ScopedLogIn login(GetFakeUserManager(), + AccountId::FromUserEmailGaiaId( + profile()->GetProfileUserName(), kTestGaiaId)); + profile()->SetSupervisedUserId("foo"); + EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_SUPERVISED_USER, + IsAssistantAllowedForProfile(profile())); +} + +TEST_F(ChromeAssistantUtilTest, IsAssistantAllowedForProfile_Locale) { + profile()->GetTestingPrefService()->SetString( + language::prefs::kApplicationLocale, "he"); + UErrorCode error_code = U_ZERO_ERROR; + const icu::Locale& old_locale = icu::Locale::getDefault(); + icu::Locale::setDefault(icu::Locale("he"), error_code); + ScopedLogIn login(GetFakeUserManager(), + AccountId::FromUserEmailGaiaId( + profile()->GetProfileUserName(), kTestGaiaId)); + + EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_LOCALE, + IsAssistantAllowedForProfile(profile())); + icu::Locale::setDefault(old_locale, error_code); +} + +TEST_F(ChromeAssistantUtilTest, IsAssistantAllowedForProfile_DemoMode) { + chromeos::DemoSession::SetDemoConfigForTesting( + chromeos::DemoSession::DemoModeConfig::kOnline); + ScopedLogIn login(GetFakeUserManager(), + AccountId::FromUserEmail(profile()->GetProfileUserName()), + user_manager::USER_TYPE_PUBLIC_ACCOUNT); + EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_DEMO_MODE, + IsAssistantAllowedForProfile(profile())); + + chromeos::DemoSession::SetDemoConfigForTesting( + chromeos::DemoSession::DemoModeConfig::kNone); +} + +TEST_F(ChromeAssistantUtilTest, IsAssistantAllowedForProfile_PublicSession) { + ScopedLogIn login(GetFakeUserManager(), + AccountId::FromUserEmail(profile()->GetProfileUserName()), + user_manager::USER_TYPE_PUBLIC_ACCOUNT); + EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_PUBLIC_SESSION, + IsAssistantAllowedForProfile(profile())); +} + +} // namespace assistant
diff --git a/chrome/browser/chromeos/crostini/OWNERS b/chrome/browser/chromeos/crostini/OWNERS index 48eb7f2..3e30dd2 100644 --- a/chrome/browser/chromeos/crostini/OWNERS +++ b/chrome/browser/chromeos/crostini/OWNERS
@@ -1,5 +1,4 @@ benwells@chromium.org +joelhockey@chromium.org nverne@chromium.org timloh@chromium.org - -per-file crostini_share_path*=joelhockey@chromium.org
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index 473bb64..aa05209 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -26,6 +26,7 @@ #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_pref_names.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" @@ -176,7 +177,7 @@ if (pref_name == arc::prefs::kVoiceInteractionHotwordEnabled) { DCHECK(value.is_bool()); - if (arc::IsAssistantAllowedForProfile(profile) != + if (assistant::IsAssistantAllowedForProfile(profile) != ash::mojom::AssistantAllowedState::ALLOWED) { return "Assistant is not available for the current user"; } @@ -1212,7 +1213,7 @@ EXTENSION_FUNCTION_VALIDATE(params); Profile* profile = Profile::FromBrowserContext(browser_context()); - if (arc::IsAssistantAllowedForProfile(profile) != + if (assistant::IsAssistantAllowedForProfile(profile) != ash::mojom::AssistantAllowedState::ALLOWED) { return RespondNow(Error("Assistant is not available for the current user")); } @@ -1278,7 +1279,7 @@ EXTENSION_FUNCTION_VALIDATE(params); Profile* profile = Profile::FromBrowserContext(browser_context()); - if (!profile || arc::IsAssistantAllowedForProfile(profile) != + if (!profile || assistant::IsAssistantAllowedForProfile(profile) != ash::mojom::AssistantAllowedState::ALLOWED) { return RespondNow(Error("Assistant is not available for the current user")); }
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 c25e9b4..1b79531 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -13,6 +13,7 @@ #include "ash/public/interfaces/shell_test_api.test-mojom-test-utils.h" #include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/containers/circular_deque.h" #include "base/files/file_path.h" #include "base/json/json_reader.h" @@ -1803,7 +1804,7 @@ extensions::AppWindowRegistry::Get(profile())->app_windows(); ASSERT_FALSE(app_windows.empty()); app_windows.front()->GetNativeWindow()->GetHost()->DispatchKeyEventPostIME( - &key_event, base::BindOnce([](bool) {})); + &key_event, base::NullCallback()); *output = "mediaKeyDispatched"; return; } @@ -1827,7 +1828,7 @@ host = app_windows.front()->GetNativeWindow()->GetHost(); } ASSERT_TRUE(host); - host->DispatchKeyEventPostIME(&key_event, base::BindOnce([](bool) {})); + host->DispatchKeyEventPostIME(&key_event, base::NullCallback()); *output = "tabKeyDispatched"; return; }
diff --git a/chrome/browser/chromeos/first_run/first_run_view.cc b/chrome/browser/chromeos/first_run/first_run_view.cc index 5533b3d0..287b521 100644 --- a/chrome/browser/chromeos/first_run/first_run_view.cc +++ b/chrome/browser/chromeos/first_run/first_run_view.cc
@@ -60,6 +60,7 @@ } bool FirstRunView::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { // Discards context menu. return true;
diff --git a/chrome/browser/chromeos/first_run/first_run_view.h b/chrome/browser/chromeos/first_run/first_run_view.h index ff2ebf89..d8b86c2 100644 --- a/chrome/browser/chromeos/first_run/first_run_view.h +++ b/chrome/browser/chromeos/first_run/first_run_view.h
@@ -38,7 +38,8 @@ private: // Overriden from content::WebContentsDelegate. - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; content::KeyboardEventProcessingResult PreHandleKeyboardEvent( content::WebContents* source, const content::NativeWebKeyboardEvent& event) override;
diff --git a/chrome/browser/chromeos/hats/hats_dialog.cc b/chrome/browser/chromeos/hats/hats_dialog.cc index f5676fb..5e35ee8 100644 --- a/chrome/browser/chromeos/hats/hats_dialog.cc +++ b/chrome/browser/chromeos/hats/hats_dialog.cc
@@ -190,7 +190,8 @@ return false; } -bool HatsDialog::HandleContextMenu(const content::ContextMenuParams& params) { +bool HatsDialog::HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) { // Disable context menu. return true; }
diff --git a/chrome/browser/chromeos/hats/hats_dialog.h b/chrome/browser/chromeos/hats/hats_dialog.h index 9041cec..52e2697 100644 --- a/chrome/browser/chromeos/hats/hats_dialog.h +++ b/chrome/browser/chromeos/hats/hats_dialog.h
@@ -42,7 +42,8 @@ void OnCloseContents(content::WebContents* source, bool* out_close_dialog) override; bool ShouldShowDialogTitle() const override; - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; std::string html_data_;
diff --git a/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen.cc b/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen.cc index d91e207..c6b8a10 100644 --- a/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen.cc +++ b/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/chromeos/login/screens/assistant_optin_flow_screen.h" -#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_view.h" #include "chrome/browser/chromeos/login/screens/base_screen_delegate.h" #include "chrome/browser/profiles/profile.h" @@ -40,7 +40,7 @@ #if BUILDFLAG(ENABLE_CROS_ASSISTANT) if (chromeos::switches::IsAssistantEnabled() && - arc::IsAssistantAllowedForProfile( + assistant::IsAssistantAllowedForProfile( ProfileManager::GetActiveUserProfile()) == ash::mojom::AssistantAllowedState::ALLOWED) { view_->Show();
diff --git a/chrome/browser/chromeos/login/ui/login_web_dialog.cc b/chrome/browser/chromeos/login/ui/login_web_dialog.cc index 5b831b6..406554f9 100644 --- a/chrome/browser/chromeos/login/ui/login_web_dialog.cc +++ b/chrome/browser/chromeos/login/ui/login_web_dialog.cc
@@ -146,6 +146,7 @@ } bool LoginWebDialog::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { // Disable context menu. return true;
diff --git a/chrome/browser/chromeos/login/ui/login_web_dialog.h b/chrome/browser/chromeos/login/ui/login_web_dialog.h index e4b4fb5..571ba7c 100644 --- a/chrome/browser/chromeos/login/ui/login_web_dialog.h +++ b/chrome/browser/chromeos/login/ui/login_web_dialog.h
@@ -76,7 +76,8 @@ void OnCloseContents(content::WebContents* source, bool* out_close_dialog) override; bool ShouldShowDialogTitle() const override; - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; bool HandleOpenURLFromTab(content::WebContents* source, const content::OpenURLParams& params, content::WebContents** out_new_contents) override;
diff --git a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc index 1133ad36..c4f1938 100644 --- a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc +++ b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc
@@ -408,6 +408,7 @@ } bool OobeUIDialogDelegate::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { return true; }
diff --git a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h index eae80b8..50c1319 100644 --- a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h +++ b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h
@@ -110,7 +110,8 @@ void OnCloseContents(content::WebContents* source, bool* out_close_dialog) override; bool ShouldShowDialogTitle() const override; - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; std::vector<ui::Accelerator> GetAccelerators() override; bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc index 3cbeae8..0273d8e 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_view.cc +++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -420,6 +420,7 @@ // WebUILoginView private: ----------------------------------------------------- bool WebUILoginView::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { #ifndef NDEBUG // Do not show the context menu.
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.h b/chrome/browser/chromeos/login/ui/webui_login_view.h index cc29db4..0824a24 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_view.h +++ b/chrome/browser/chromeos/login/ui/webui_login_view.h
@@ -149,7 +149,8 @@ void OnKeyboardVisibilityChanged(bool visible) override; // Overridden from content::WebContentsDelegate. - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; bool HandleKeyboardEvent( content::WebContents* source, const content::NativeWebKeyboardEvent& event) override;
diff --git a/chrome/browser/conflicts/DEPS b/chrome/browser/conflicts/DEPS index acd5f432..4a806f9 100644 --- a/chrome/browser/conflicts/DEPS +++ b/chrome/browser/conflicts/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+chrome/services/util_win/util_win_service.h", "+chrome_elf/sha1/sha1.h", "+chrome_elf/third_party_dlls", ]
diff --git a/chrome/browser/conflicts/module_inspector_win.cc b/chrome/browser/conflicts/module_inspector_win.cc index 0adab09..d97f4e1 100644 --- a/chrome/browser/conflicts/module_inspector_win.cc +++ b/chrome/browser/conflicts/module_inspector_win.cc
@@ -22,9 +22,6 @@ namespace { -constexpr base::Feature kWinOOPInspectModuleFeature = { - "WinOOPInspectModule", base::FEATURE_DISABLED_BY_DEFAULT}; - // The maximum amount of time a stale entry is kept in the cache before it is // deleted. constexpr base::TimeDelta kMaxEntryAge = base::TimeDelta::FromDays(30); @@ -38,21 +35,6 @@ }); } -// Returns a bound pointer to the UtilWin service. -chrome::mojom::UtilWinPtr ConnectToUtilWinService( - base::OnceClosure connection_error_handler) { - chrome::mojom::UtilWinPtr util_win_ptr; - - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(chrome::mojom::kUtilWinServiceName, &util_win_ptr); - - util_win_ptr.set_connection_error_handler( - std::move(connection_error_handler)); - - return util_win_ptr; -} - void ReportConnectionError(bool value) { base::UmaHistogramBoolean("Windows.InspectModule.ConnectionError", value); } @@ -95,6 +77,9 @@ // static constexpr base::Feature ModuleInspector::kEnableBackgroundModuleInspection; +// static +constexpr base::Feature ModuleInspector::kWinOOPInspectModuleFeature; + ModuleInspector::ModuleInspector( const OnModuleInspectedCallback& on_module_inspected_callback) : on_module_inspected_callback_(on_module_inspected_callback), @@ -110,6 +95,7 @@ connection_error_retry_count_(kConnectionErrorRetryCount), background_inspection_enabled_( base::FeatureList::IsEnabled(kEnableBackgroundModuleInspection)), + test_connector_(nullptr), weak_ptr_factory_(this) { // Use AfterStartupTaskUtils to be notified when startup is finished. AfterStartupTaskUtils::PostTask( @@ -165,6 +151,31 @@ inspection_results_cache_)); } +void ModuleInspector::EnsureUtilWinServiceBound() { + DCHECK(base::FeatureList::IsEnabled(kWinOOPInspectModuleFeature)); + + // Use the |test_connector_| if set. + service_manager::Connector* connector = test_connector_; + if (!connector) { + // The ServiceManagerConnection can be null during shutdown. + content::ServiceManagerConnection* service_manager_connection = + content::ServiceManagerConnection::GetForProcess(); + if (!service_manager_connection) + return; + + connector = service_manager_connection->GetConnector(); + } + + connector->BindInterface(chrome::mojom::kUtilWinServiceName, &util_win_ptr_); + util_win_ptr_.set_connection_error_handler( + base::BindOnce(&ModuleInspector::OnUtilWinServiceConnectionError, + base::Unretained(this))); + + // Emit a false value to the connection error histogram to serve as a + // baseline. + ReportConnectionError(false); +} + void ModuleInspector::OnStartupFinished() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -231,31 +242,31 @@ return; } - // There is a small priority inversion that happens when - // IncreaseInspectionPriority() is called while a module is currently being - // inspected. - // - // This is because all the subsequent tasks will be posted at a higher - // priority, but they are waiting on the current task that is currently - // running at a lower priority. - // - // In practice, this is not an issue because the only caller of - // IncreaseInspectionPriority() (chrome://conflicts) does not depend on the - // inspection to finish synchronously and is not blocking anything else. if (base::FeatureList::IsEnabled(kWinOOPInspectModuleFeature)) { - // Make sure the pointer is bound to the service first. - if (!util_win_ptr_) { - util_win_ptr_ = ConnectToUtilWinService( - base::BindOnce(&ModuleInspector::OnUtilWinServiceConnectionError, - base::Unretained(this))); - ReportConnectionError(false); - } + EnsureUtilWinServiceBound(); + + // An unbound InterfacePtr at this point means the service is not available. + // This is only possible during shutdown. In this case, just dropping the + // request and stop processing new modules is fine. + if (!util_win_ptr_) + return; util_win_ptr_->InspectModule( module_key.module_path, base::BindOnce(&ModuleInspector::OnModuleNewlyInspected, weak_ptr_factory_.GetWeakPtr(), module_key)); } else { + // There is a small priority inversion that happens when + // IncreaseInspectionPriority() is called while a module is currently being + // inspected. + // + // This is because all the subsequent tasks on |inspection_task_runner_| + // will be posted at a higher priority, but they are waiting on the current + // task that is currently running at a lower priority. + // + // In practice, this is not an issue because the only caller of + // IncreaseInspectionPriority() (chrome://conflicts) does not depend on the + // inspection to finish synchronously and is not blocking anything else. base::PostTaskAndReplyWithResult( inspection_task_runner_.get(), FROM_HERE, base::BindOnce(&InspectModule, module_key.module_path),
diff --git a/chrome/browser/conflicts/module_inspector_win.h b/chrome/browser/conflicts/module_inspector_win.h index 73637be..542c97f 100644 --- a/chrome/browser/conflicts/module_inspector_win.h +++ b/chrome/browser/conflicts/module_inspector_win.h
@@ -24,6 +24,10 @@ class SequencedTaskRunner; } +namespace service_manager { +class Connector; +} + // This class takes care of inspecting several modules (identified by their // ModuleInfoKey) and returning the result via the OnModuleInspectedCallback on // the SequencedTaskRunner where it was created. @@ -43,6 +47,10 @@ static constexpr base::Feature kEnableBackgroundModuleInspection = { "EnableBackgroundModuleInspection", base::FEATURE_ENABLED_BY_DEFAULT}; + // Controls whether or not module inspection is done out of process. + static constexpr base::Feature kWinOOPInspectModuleFeature = { + "WinOOPInspectModule", base::FEATURE_DISABLED_BY_DEFAULT}; + using OnModuleInspectedCallback = base::Callback<void(const ModuleInfoKey& module_key, ModuleInspectionResult inspection_result)>; @@ -64,7 +72,15 @@ // ModuleDatabaseObserver: void OnModuleDatabaseIdle() override; + void SetConnectorForTesting(service_manager::Connector* connector) { + test_connector_ = connector; + } + private: + // Ensures the |util_win_ptr_| instance is bound to the UtilWin service. This + // may result in an unbounded pointer if Chrome is currently shutting down. + void EnsureUtilWinServiceBound(); + // Invoked when Chrome has finished starting up to initiate the inspection of // queued modules. void OnStartupFinished(); @@ -135,6 +151,9 @@ // to true if IncreaseInspectionPriority() is called. bool background_inspection_enabled_; + // Used to connect to the UtilWin service during tests. + service_manager::Connector* test_connector_; + SEQUENCE_CHECKER(sequence_checker_); // Weak pointers are used to safely post the inspection result back to the
diff --git a/chrome/browser/conflicts/module_inspector_win_unittest.cc b/chrome/browser/conflicts/module_inspector_win_unittest.cc index 59fbeaa..05c6029b 100644 --- a/chrome/browser/conflicts/module_inspector_win_unittest.cc +++ b/chrome/browser/conflicts/module_inspector_win_unittest.cc
@@ -14,7 +14,10 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/test/scoped_feature_list.h" +#include "chrome/services/util_win/public/mojom/constants.mojom.h" +#include "chrome/services/util_win/util_win_service.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "services/service_manager/public/cpp/test/test_connector_factory.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -117,3 +120,29 @@ EXPECT_EQ(2u, inspected_modules().size()); } + +TEST_F(ModuleInspectorTest, OOPInspectModule) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + ModuleInspector::kWinOOPInspectModuleFeature); + + service_manager::TestConnectorFactory test_connector_factory_; + UtilWinService util_win_service(test_connector_factory_.RegisterInstance( + chrome::mojom::kUtilWinServiceName)); + + ModuleInfoKey kTestCases[] = { + {base::FilePath(), 0, 0}, + {base::FilePath(), 0, 0}, + }; + + ModuleInspector module_inspector(base::Bind( + &ModuleInspectorTest::OnModuleInspected, base::Unretained(this))); + module_inspector.SetConnectorForTesting( + test_connector_factory_.GetDefaultConnector()); + + for (const auto& module : kTestCases) + module_inspector.AddModule(module); + + RunUntilIdle(); + EXPECT_EQ(2u, inspected_modules().size()); +}
diff --git a/chrome/browser/download/notification/download_notification_browsertest.cc b/chrome/browser/download/notification/download_notification_browsertest.cc index 1cb4575..4ed9fc8 100644 --- a/chrome/browser/download/notification/download_notification_browsertest.cc +++ b/chrome/browser/download/notification/download_notification_browsertest.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/stl_util.h" @@ -1058,11 +1059,19 @@ IN_PROC_BROWSER_TEST_F(MultiProfileDownloadNotificationTest, PRE_DownloadMultipleFiles) { + // TODO(crbug.com/933963): Flaky with network service. + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + AddAllUsers(); } IN_PROC_BROWSER_TEST_F(MultiProfileDownloadNotificationTest, DownloadMultipleFiles) { + // TODO(crbug.com/933963): Flaky with network service. + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + AddAllUsers(); GURL url(SlowDownloadInterceptor::kUnknownSizeUrl);
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc index 6b0e7408..7d1001e 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -606,12 +606,11 @@ } } -// Tests that the separator character '^' correctly matches the end of the url. -// TODO(crbug.com/772260): Enable once the bug is fixed. IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, - DISABLED_BlockRequests_SeparatorMatchesEndOfURL) { + BlockRequests_SeparatorMatchesEndOfURL) { TestRule rule = CreateGenericRule(); rule.condition->url_filter = std::string("page2.html^"); + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({rule}));
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 2b804c2..f28d285 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -52,6 +52,7 @@ #include "chrome/browser/chromeos/system/timezone_util.h" #include "chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.h" #include "chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.h" +#include "chrome/browser/ui/ash/assistant/assistant_pref_util.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/settings/cros_settings_names.h" #include "components/arc/arc_prefs.h" @@ -380,8 +381,8 @@ settings_api::PrefType::PREF_TYPE_BOOLEAN; // Google Assistant. - (*s_whitelist)[arc::prefs::kVoiceInteractionActivityControlAccepted] = - settings_api::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[::assistant::prefs::kAssistantConsentStatus] = + settings_api::PrefType::PREF_TYPE_NUMBER; (*s_whitelist)[arc::prefs::kVoiceInteractionEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[arc::prefs::kVoiceInteractionContextEnabled] =
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 2fb5740..e29488f 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -282,6 +282,11 @@ "expiry_milestone": 75 }, { + "name": "autofill-show-full-disclosure-label", + "owners": [ "ftirelo", "tmartino" ], + "expiry_milestone": 77 + }, + { "name": "automatic-password-generation", "owners": [ "ioanap", "fhorschig" ], "expiry_milestone": 76 @@ -1072,11 +1077,6 @@ "expiry_milestone": -1 }, { - "name": "enable-display-cutout-api", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "enable-downloads-location-change", // "owners": [ "your-team" ], "expiry_milestone": 76 @@ -1300,6 +1300,11 @@ "expiry_milestone": 76 }, { + "name": "enable-inline-update-flow", + "owners": [ "nyquist", "dtrainor" ], + "expiry_milestone": 76 + }, + { "name": "enable-input-ime-api", // "owners": [ "your-team" ], "expiry_milestone": 76 @@ -3033,7 +3038,7 @@ }, { "name": "unfiltered-bluetooth-devices", - // "owners": [ "your-team" ], + "owners": [ "sonnysasaka", "qiyuh@google.com" ], "expiry_milestone": 76 }, {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index e5e731c..e872ed2a 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -134,6 +134,12 @@ const char kAutofillProfileServerValidationDescription[] = "Allows autofill to use server side validation"; +const char kAutofillShowFullDisclosureLabelName[] = + "Autofill Show Full Disclosure Label"; +const char kAutofillShowFullDisclosureLabelDescription[] = + "When enabled, the Autofill dropdown's labels are displayed in the full " + "disclosure format."; + const char kAutofillPreviewStyleExperimentName[] = "Autofill Preview Style Experiment"; const char kAutofillPreviewStyleExperimentDescription[] = @@ -2273,11 +2279,6 @@ const char kContextualSearchUnityIntegrationDescription[] = "Enables integration of Tap to Search with Unified Consent."; -const char kDisplayCutoutAPIName[] = - "Enable support for the Display Cutout API"; -const char kDisplayCutoutAPIDescription[] = - "Enables developers to support devices that have a display cutout."; - const char kDontPrefetchLibrariesName[] = "Don't Prefetch Libraries"; const char kDontPrefetchLibrariesDescription[] = "Don't prefetch libraries after loading."; @@ -2699,6 +2700,13 @@ const char kUpdateMenuTypeInlineUpdateInstallFailed[] = "Inline Update Error: Install Failed"; +const char kInlineUpdateFlowName[] = "Enable Google Play inline update flow"; +const char kInlineUpdateFlowDescription[] = + "When this flag is set, instead of taking the user to the Google Play " + "Store when an update is available, the user is presented with an inline " + "flow where they do not have to leave Chrome until the update is ready " + "to install."; + const char kThirdPartyDoodlesName[] = "Enable Doodles for third-party search engines"; const char kThirdPartyDoodlesDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index b115c7d..e6ccf52 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -119,6 +119,9 @@ extern const char kAutofillProfileServerValidationName[]; extern const char kAutofillProfileServerValidationDescription[]; +extern const char kAutofillShowFullDisclosureLabelName[]; +extern const char kAutofillShowFullDisclosureLabelDescription[]; + extern const char kAutofillPreviewStyleExperimentName[]; extern const char kAutofillPreviewStyleExperimentDescription[]; @@ -1347,9 +1350,6 @@ extern const char kContextualSearchUnityIntegrationName[]; extern const char kContextualSearchUnityIntegrationDescription[]; -extern const char kDisplayCutoutAPIName[]; -extern const char kDisplayCutoutAPIDescription[]; - extern const char kDontPrefetchLibrariesName[]; extern const char kDontPrefetchLibrariesDescription[]; @@ -1588,6 +1588,9 @@ extern const char kUpdateMenuTypeInlineUpdateDownloadCanceled[]; extern const char kUpdateMenuTypeInlineUpdateInstallFailed[]; +extern const char kInlineUpdateFlowName[]; +extern const char kInlineUpdateFlowDescription[]; + extern const char kThirdPartyDoodlesName[]; extern const char kThirdPartyDoodlesDescription[];
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc index e16c7d4..f1ada4fc 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -231,7 +231,7 @@ const content::ResourceRequestInfo::FrameTreeNodeIdGetter& frame_tree_node_id_getter, const GURL& url, - const net::HostPortPair& host_port_pair, + const net::IPEndPoint& remote_endpoint, const content::GlobalRequestID& request_id, int render_process_id, int render_frame_id, @@ -279,7 +279,7 @@ content::RenderFrameHost* render_frame_host_or_null = content::RenderFrameHost::FromID(render_process_id, render_frame_id); metrics_observer->OnRequestComplete( - url, host_port_pair, frame_tree_node_id_getter.Run(), request_id, + url, remote_endpoint, frame_tree_node_id_getter.Run(), request_id, render_frame_host_or_null, resource_type, was_cached, std::move(data_reduction_proxy_data), raw_body_bytes, original_content_length, request_creation_time, net_error, @@ -547,19 +547,14 @@ lofi_decider) : url_request->GetRawBodyBytes(); - net::HostPortPair request_host_port; + net::IPEndPoint remote_endpoint; // We want to get the IP address of the response if it was returned, and the // last endpoint that was checked if it failed. - if (url_request->response_headers()) { - request_host_port = url_request->GetSocketAddress(); - } - if (request_host_port.IsEmpty()) { - net::IPEndPoint request_ip_endpoint; - bool was_successful = url_request->GetRemoteEndpoint(&request_ip_endpoint); - if (was_successful) { - request_host_port = - net::HostPortPair::FromIPEndPoint(request_ip_endpoint); - } + if (url_request->response_headers()) + remote_endpoint = url_request->GetResponseRemoteEndpoint(); + if (!remote_endpoint.address().IsValid() && + !url_request->GetTransactionRemoteEndpoint(&remote_endpoint)) { + remote_endpoint = net::IPEndPoint(); } auto load_timing_info = std::make_unique<net::LoadTimingInfo>(); @@ -571,7 +566,7 @@ &NotifyUIThreadOfRequestComplete, info->GetWebContentsGetterForRequest(), info->GetFrameTreeNodeIdGetterForRequest(), url_request->url(), - request_host_port, info->GetGlobalRequestID(), info->GetChildID(), + remote_endpoint, info->GetGlobalRequestID(), info->GetChildID(), info->GetRenderFrameID(), info->GetResourceType(), info->IsDownload(), url_request->was_cached(), std::move(data_reduction_proxy_data), net_error, url_request->GetTotalReceivedBytes(),
diff --git a/chrome/browser/lookalikes/lookalike_url_controller_client.cc b/chrome/browser/lookalikes/lookalike_url_controller_client.cc index e436ab2..299b6be 100644 --- a/chrome/browser/lookalikes/lookalike_url_controller_client.cc +++ b/chrome/browser/lookalikes/lookalike_url_controller_client.cc
@@ -16,14 +16,23 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/referrer.h" +// static +std::unique_ptr<security_interstitials::MetricsHelper> +LookalikeUrlControllerClient::GetMetricsHelper(const GURL& url) { + security_interstitials::MetricsHelper::ReportDetails settings; + settings.metric_prefix = "lookalike"; + + return std::make_unique<security_interstitials::MetricsHelper>(url, settings, + nullptr); +} + LookalikeUrlControllerClient::LookalikeUrlControllerClient( content::WebContents* web_contents, - std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper, const GURL& request_url, const GURL& safe_url) : SecurityInterstitialControllerClient( web_contents, - std::move(metrics_helper), + GetMetricsHelper(request_url), Profile::FromBrowserContext(web_contents->GetBrowserContext()) ->GetPrefs(), g_browser_process->GetApplicationLocale(),
diff --git a/chrome/browser/lookalikes/lookalike_url_controller_client.h b/chrome/browser/lookalikes/lookalike_url_controller_client.h index a764230..0a37a25 100644 --- a/chrome/browser/lookalikes/lookalike_url_controller_client.h +++ b/chrome/browser/lookalikes/lookalike_url_controller_client.h
@@ -19,9 +19,11 @@ class LookalikeUrlControllerClient : public security_interstitials::SecurityInterstitialControllerClient { public: + static std::unique_ptr<security_interstitials::MetricsHelper> + GetMetricsHelper(const GURL& url); + LookalikeUrlControllerClient( content::WebContents* web_contents, - std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper, const GURL& request_url, const GURL& safe_url);
diff --git a/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc b/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc index aad1c9a..232101f 100644 --- a/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc +++ b/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc
@@ -9,12 +9,21 @@ #include "components/grit/components_resources.h" #include "components/security_interstitials/content/security_interstitial_controller_client.h" #include "components/security_interstitials/core/common_string_util.h" +#include "components/security_interstitials/core/metrics_helper.h" #include "components/strings/grit/components_strings.h" +#include "content/public/browser/interstitial_page_delegate.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" #include "net/base/net_errors.h" #include "ui/base/l10n/l10n_util.h" +using security_interstitials::MetricsHelper; + +// static +const content::InterstitialPageDelegate::TypeID + LookalikeUrlInterstitialPage::kTypeForTesting = + &LookalikeUrlInterstitialPage::kTypeForTesting; + LookalikeUrlInterstitialPage::LookalikeUrlInterstitialPage( content::WebContents* web_contents, const GURL& request_url, @@ -24,10 +33,19 @@ : security_interstitials::SecurityInterstitialPage( web_contents, request_url, - std::move(controller_client)) {} + std::move(controller_client)) { + controller()->metrics_helper()->RecordUserDecision(MetricsHelper::SHOW); + controller()->metrics_helper()->RecordUserInteraction( + MetricsHelper::TOTAL_VISITS); +} LookalikeUrlInterstitialPage::~LookalikeUrlInterstitialPage() {} +content::InterstitialPageDelegate::TypeID +LookalikeUrlInterstitialPage::GetTypeForTesting() const { + return LookalikeUrlInterstitialPage::kTypeForTesting; +} + bool LookalikeUrlInterstitialPage::ShouldCreateNewNavigation() const { return true; } @@ -69,9 +87,13 @@ switch (cmd) { case security_interstitials::CMD_DONT_PROCEED: + controller()->metrics_helper()->RecordUserDecision( + MetricsHelper::DONT_PROCEED); controller()->GoBack(); break; case security_interstitials::CMD_PROCEED: + controller()->metrics_helper()->RecordUserDecision( + MetricsHelper::PROCEED); controller()->Proceed(); break; case security_interstitials::CMD_DO_REPORT:
diff --git a/chrome/browser/lookalikes/lookalike_url_interstitial_page.h b/chrome/browser/lookalikes/lookalike_url_interstitial_page.h index 0eaf47c..aeeb0b5 100644 --- a/chrome/browser/lookalikes/lookalike_url_interstitial_page.h +++ b/chrome/browser/lookalikes/lookalike_url_interstitial_page.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/time/time.h" #include "components/security_interstitials/content/security_interstitial_page.h" +#include "content/public/browser/interstitial_page_delegate.h" class GURL; @@ -21,7 +22,7 @@ : public security_interstitials::SecurityInterstitialPage { public: // Interstitial type, used in tests. - static const InterstitialPageDelegate::TypeID kTypeForTesting; + static const content::InterstitialPageDelegate::TypeID kTypeForTesting; LookalikeUrlInterstitialPage( content::WebContents* web_contents, @@ -32,6 +33,9 @@ ~LookalikeUrlInterstitialPage() override; + // InterstitialPageDelegate method: + InterstitialPageDelegate::TypeID GetTypeForTesting() const override; + protected: // InterstitialPageDelegate implementation: void CommandReceived(const std::string& command) override; @@ -44,6 +48,8 @@ int GetHTMLTemplateId() override; private: + friend class LookalikeUrlNavigationThrottleBrowserTest; + // Values added to get our shared interstitial HTML to play nice. void PopulateStringsForSharedHTML(base::DictionaryValue* load_time_data);
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_observer.h b/chrome/browser/lookalikes/lookalike_url_navigation_observer.h deleted file mode 100644 index ba011be..0000000 --- a/chrome/browser/lookalikes/lookalike_url_navigation_observer.h +++ /dev/null
@@ -1,116 +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_LOOKALIKES_LOOKALIKE_URL_NAVIGATION_OBSERVER_H_ -#define CHROME_BROWSER_LOOKALIKES_LOOKALIKE_URL_NAVIGATION_OBSERVER_H_ - -#include <string> -#include <vector> - -#include "base/memory/weak_ptr.h" -#include "chrome/browser/engagement/site_engagement_details.mojom.h" -#include "components/url_formatter/url_formatter.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" - -namespace content { -class NavigationHandle; -} - -class Profile; - -// Observes navigations and shows an infobar if the navigated domain name -// is visually similar to a top domain or a domain with a site engagement score. -class LookalikeUrlNavigationObserver - : public content::WebContentsObserver, - public content::WebContentsUserData<LookalikeUrlNavigationObserver> { - public: - // Used for metrics. Multiple events can occur per navigation. - enum class NavigationSuggestionEvent { - kNone = 0, - kInfobarShown = 1, - kLinkClicked = 2, - kMatchTopSite = 3, - kMatchSiteEngagement = 4, - kMatchEditDistance = 5, - - // Append new items to the end of the list above; do not modify or - // replace existing values. Comment out obsolete items. - kMaxValue = kMatchEditDistance, - }; - - // Used for UKM. There is only a single MatchType per navigation. - enum class MatchType { - kNone = 0, - kTopSite = 1, - kSiteEngagement = 2, - kEditDistance = 3, - - // Append new items to the end of the list above; do not modify or replace - // existing values. Comment out obsolete items. - kMaxValue = kEditDistance, - }; - - struct DomainInfo { - const std::string domain_and_registry; - const url_formatter::IDNConversionResult idn_result; - const url_formatter::Skeletons skeletons; - DomainInfo(const std::string& arg_domain_and_registry, - const url_formatter::IDNConversionResult& arg_idn_result, - const url_formatter::Skeletons& arg_skeletons); - ~DomainInfo(); - DomainInfo(const DomainInfo& other); - }; - - static const char kHistogramName[]; - - static void CreateForWebContents(content::WebContents* web_contents); - - explicit LookalikeUrlNavigationObserver(content::WebContents* web_contents); - ~LookalikeUrlNavigationObserver() override; - - // content::WebContentsObserver: - void DidFinishNavigation( - content::NavigationHandle* navigation_handle) override; - - private: - friend class content::WebContentsUserData<LookalikeUrlNavigationObserver>; - FRIEND_TEST_ALL_PREFIXES(LookalikeUrlNavigationObserverTest, - IsEditDistanceAtMostOne); - - DomainInfo GetDomainInfo(const GURL& url); - - // Performs top domain and engaged site checks on the navigated |url|. Uses - // |engaged_sites| for the engaged site checks. - void PerformChecks(const GURL& url, - const DomainInfo& navigated_domain, - const std::vector<GURL>& engaged_sites); - - // Returns true if a domain is visually similar to the hostname of |url|. The - // matching domain can be a top domain or an engaged site. Similarity check - // is made using both visual skeleton and edit distance comparison. If this - // returns true, match details will be written into |matched_domain| and - // |match_type|. They cannot be nullptr. - bool GetMatchingDomain(const DomainInfo& navigated_domain, - const std::vector<GURL>& engaged_sites, - std::string* matched_domain, - MatchType* match_type); - - // Returns if the Levenshtein distance between |str1| and |str2| is at most 1. - // This has O(max(n,m)) complexity as opposed to O(n*m) of the usual edit - // distance computation. - static bool IsEditDistanceAtMostOne(const base::string16& str1, - const base::string16& str2); - - // Returns the first matching top domain with an edit distance of at most one - // to |domain_and_registry|. - static std::string GetSimilarDomainFromTop500(const DomainInfo& domain_info); - - Profile* profile_; - base::WeakPtrFactory<LookalikeUrlNavigationObserver> weak_factory_; - - WEB_CONTENTS_USER_DATA_KEY_DECL(); -}; - -#endif // CHROME_BROWSER_LOOKALIKES_LOOKALIKE_URL_NAVIGATION_OBSERVER_H_
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_observer_browsertest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_observer_browsertest.cc deleted file mode 100644 index c8176a12..0000000 --- a/chrome/browser/lookalikes/lookalike_url_navigation_observer_browsertest.cc +++ /dev/null
@@ -1,560 +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. - -#include "base/bind.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/simple_test_clock.h" -#include "chrome/browser/engagement/site_engagement_score.h" -#include "chrome/browser/engagement/site_engagement_service.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/history/history_test_utils.h" -#include "chrome/browser/infobars/infobar_observer.h" -#include "chrome/browser/infobars/infobar_service.h" -#include "chrome/browser/lookalikes/lookalike_url_navigation_observer.h" -#include "chrome/browser/lookalikes/lookalike_url_service.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/chrome_features.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/infobars/core/infobar.h" -#include "components/infobars/core/infobar_delegate.h" -#include "components/ukm/test_ukm_recorder.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/test_navigation_observer.h" -#include "net/dns/mock_host_resolver.h" -#include "net/test/embedded_test_server/http_request.h" -#include "net/test/embedded_test_server/http_response.h" -#include "services/metrics/public/cpp/ukm_builders.h" -#include "services/metrics/public/cpp/ukm_source.h" -#include "ui/base/window_open_disposition.h" - -namespace { - -using UkmEntry = ukm::builders::LookalikeUrl_NavigationSuggestion; -using NavigationSuggestionEvent = - LookalikeUrlNavigationObserver::NavigationSuggestionEvent; - -enum class UIEnabled { kDisabled, kEnabled }; - -// An engagement score above MEDIUM. -const int kHighEngagement = 20; - -// An engagement score below MEDIUM. -const int kLowEngagement = 1; - -// The domains here should not private domains (e.g. site.test), otherwise they -// might test the wrong thing. Also note that site5.com is in the top domain -// list, so it shouldn't be used here. -struct SiteEngagementTestCase { - const char* const navigated; - const char* const suggested; -} kSiteEngagementTestCases[] = { - {"sité1.com", "site1.com"}, - {"mail.www.sité1.com", "site1.com"}, - - // These should match since the comparison uses eTLD+1s. - {"sité2.com", "www.site2.com"}, - {"mail.sité2.com", "www.site2.com"}, - - {"síté3.com", "sité3.com"}, - {"mail.síté3.com", "sité3.com"}, - - {"síté4.com", "www.sité4.com"}, - {"mail.síté4.com", "www.sité4.com"}, -}; - -static std::unique_ptr<net::test_server::HttpResponse> -NetworkErrorResponseHandler(const net::test_server::HttpRequest& request) { - return std::unique_ptr<net::test_server::HttpResponse>( - new net::test_server::RawHttpResponse("", "")); -} - -} // namespace - -class LookalikeUrlNavigationObserverBrowserTest - : public InProcessBrowserTest, - public testing::WithParamInterface<UIEnabled> { - protected: - // Sets the absolute Site Engagement |score| for the testing origin. - static void SetEngagementScore(Browser* browser, - const GURL& url, - double score) { - SiteEngagementService::Get(browser->profile()) - ->ResetBaseScoreForURL(url, score); - } - - void SetUp() override { - if (ui_enabled()) { - feature_list_.InitAndEnableFeature( - features::kLookalikeUrlNavigationSuggestionsUI); - } else { - feature_list_.InitAndDisableFeature( - features::kLookalikeUrlNavigationSuggestionsUI); - } - InProcessBrowserTest::SetUp(); - } - - void SetUpOnMainThread() override { - host_resolver()->AddRule("*", "127.0.0.1"); - ASSERT_TRUE(embedded_test_server()->Start()); - test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); - - const base::Time kNow = base::Time::FromDoubleT(1000); - test_clock_.SetNow(kNow); - - LookalikeUrlService* lookalike_service = - LookalikeUrlService::Get(browser()->profile()); - lookalike_service->SetClockForTesting(&test_clock_); - lookalike_service->ClearEngagedSitesForTesting(); - } - - GURL GetURL(const char* hostname) const { - return embedded_test_server()->GetURL(hostname, "/title1.html"); - } - - // Checks that UKM recorded a metric for each URL in |navigated_urls|. - void CheckUkm(const std::vector<GURL>& navigated_urls, - LookalikeUrlNavigationObserver::MatchType match_type) { - auto entries = test_ukm_recorder()->GetEntriesByName(UkmEntry::kEntryName); - ASSERT_EQ(navigated_urls.size(), entries.size()); - int entry_count = 0; - for (const auto* const entry : entries) { - test_ukm_recorder()->ExpectEntrySourceHasUrl(entry, - navigated_urls[entry_count]); - test_ukm_recorder()->ExpectEntryMetric(entry, "MatchType", - static_cast<int>(match_type)); - entry_count++; - } - } - - // Checks that UKM did not record any lookalike URL metrics. - void CheckNoUkm() { - EXPECT_TRUE( - test_ukm_recorder()->GetEntriesByName(UkmEntry::kEntryName).empty()); - } - - void TestInfobarNotShown(Browser* browser, const GURL& navigated_url) { - content::WebContents* web_contents = - browser->tab_strip_model()->GetActiveWebContents(); - InfoBarService* infobar_service = - InfoBarService::FromWebContents(web_contents); - { - content::TestNavigationObserver navigation_observer(web_contents, 1); - NavigateToURL(browser, navigated_url); - navigation_observer.Wait(); - EXPECT_EQ(0u, infobar_service->infobar_count()); - } - { - // Navigate to an empty page. This will happen after any - // LookalikeUrlService tasks, so will effectively wait for those tasks to - // finish. - content::TestNavigationObserver navigation_observer(web_contents, 1); - NavigateToURL(browser, GURL("about:blank")); - navigation_observer.Wait(); - EXPECT_EQ(0u, infobar_service->infobar_count()); - } - } - - // Tests that the histogram event |expected_event| is recorded. If the UI is - // enabled, additinal events for infobar display and link click will also be - // tested. - void TestHistogramEventsRecordedAndInfobarVisibility( - Browser* browser, - base::HistogramTester* histograms, - const GURL& navigated_url, - const GURL& expected_suggested_url, - LookalikeUrlNavigationObserver::NavigationSuggestionEvent - expected_event) { - if (ui_enabled()) { - // If the feature is enabled, the UI will be displayed. Expect extra - // histogram entries for kInfobarShown and kLinkClicked events. - TestInfobarShown(browser, navigated_url, expected_suggested_url); - histograms->ExpectTotalCount( - LookalikeUrlNavigationObserver::kHistogramName, 3); - histograms->ExpectBucketCount( - LookalikeUrlNavigationObserver::kHistogramName, - LookalikeUrlNavigationObserver::NavigationSuggestionEvent:: - kInfobarShown, - 1); - histograms->ExpectBucketCount( - LookalikeUrlNavigationObserver::kHistogramName, - LookalikeUrlNavigationObserver::NavigationSuggestionEvent:: - kLinkClicked, - 1); - histograms->ExpectBucketCount( - LookalikeUrlNavigationObserver::kHistogramName, expected_event, 1); - return; - } - - TestInfobarNotShown(browser, navigated_url); - histograms->ExpectTotalCount(LookalikeUrlNavigationObserver::kHistogramName, - 1); - histograms->ExpectBucketCount( - LookalikeUrlNavigationObserver::kHistogramName, expected_event, 1); - } - - ukm::TestUkmRecorder* test_ukm_recorder() { return test_ukm_recorder_.get(); } - - base::SimpleTestClock* test_clock() { return &test_clock_; } - - private: - bool ui_enabled() const { return GetParam() == UIEnabled::kEnabled; } - - // Simulates a link click navigation. We don't use - // ui_test_utils::NavigateToURL(const GURL&) because it simulates the user - // typing the URL, causing the site to have a site engagement score of at - // least LOW. - static void NavigateToURL(Browser* browser, const GURL& url) { - NavigateParams params(browser, url, ui::PAGE_TRANSITION_LINK); - params.initiator_origin = url::Origin::Create(GURL("about:blank")); - params.disposition = WindowOpenDisposition::CURRENT_TAB; - params.is_renderer_initiated = true; - ui_test_utils::NavigateToURL(¶ms); - } - - // Checks that navigating to |navigated_url| results in displaying a - // navigation suggesting that says "Did you mean to go to - // |expected_suggested_url|?". Both |navigated_url| and - // |expected_suggested_url| can be ASCII or IDN. - static void TestInfobarShown(Browser* browser, - const GURL& navigated_url, - const GURL& expected_suggested_url) { - history::HistoryService* const history_service = - HistoryServiceFactory::GetForProfile( - browser->profile(), ServiceAccessType::EXPLICIT_ACCESS); - ui_test_utils::WaitForHistoryToLoad(history_service); - - content::WebContents* web_contents = - browser->tab_strip_model()->GetActiveWebContents(); - InfoBarService* infobar_service = - InfoBarService::FromWebContents(web_contents); - InfoBarObserver infobar_added_observer( - infobar_service, InfoBarObserver::Type::kInfoBarAdded); - NavigateToURL(browser, navigated_url); - infobar_added_observer.Wait(); - - infobars::InfoBar* infobar = infobar_service->infobar_at(0); - EXPECT_EQ(infobars::InfoBarDelegate::ALTERNATE_NAV_INFOBAR_DELEGATE, - infobar->delegate()->GetIdentifier()); - - // Clicking the link in the infobar should remove the infobar and navigate - // to the suggested URL. - InfoBarObserver infobar_removed_observer( - infobar_service, InfoBarObserver::Type::kInfoBarRemoved); - AlternateNavInfoBarDelegate* infobar_delegate = - static_cast<AlternateNavInfoBarDelegate*>(infobar->delegate()); - infobar_delegate->LinkClicked(WindowOpenDisposition::CURRENT_TAB); - infobar_removed_observer.Wait(); - - EXPECT_EQ(0u, infobar_service->infobar_count()); - EXPECT_EQ(expected_suggested_url, web_contents->GetURL()); - - // Clicking the link in the infobar should also remove the original URL from - // history. - ui_test_utils::HistoryEnumerator enumerator(browser->profile()); - EXPECT_FALSE(base::ContainsValue(enumerator.urls(), navigated_url)); - } - - base::test::ScopedFeatureList feature_list_; - std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_; - base::SimpleTestClock test_clock_; -}; - -INSTANTIATE_TEST_SUITE_P(, - LookalikeUrlNavigationObserverBrowserTest, - ::testing::Values(UIEnabled::kDisabled, - UIEnabled::kEnabled)); - -// Navigating to a non-IDN shouldn't show an infobar or record metrics. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - NonIdn_NoMatch) { - TestInfobarNotShown(browser(), GetURL("google.com")); - CheckNoUkm(); -} - -// Navigating to a domain whose visual representation does not look like a -// top domain shouldn't show an infobar or record metrics. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - NonTopDomainIdn_NoInfobar) { - TestInfobarNotShown(browser(), GetURL("éxample.com")); - CheckNoUkm(); -} - -// If the user has engaged with the domain before, metrics shouldn't be recorded -// and the infobar shouldn't be shown, even if the domain is visually similar -// to a top domain. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - Idn_TopDomain_EngagedSite_NoMatch) { - const GURL url = GetURL("googlé.com"); - SetEngagementScore(browser(), url, kHighEngagement); - TestInfobarNotShown(browser(), url); - CheckNoUkm(); -} - -// Navigate to a domain whose visual representation looks like a top domain. -// This should record metrics. It should also show a "Did you mean to go to ..." -// infobar if configured via a feature param. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - Idn_TopDomain_Match) { - base::HistogramTester histograms; - - const GURL kNavigatedUrl = GetURL("googlé.com"); - const GURL kExpectedSuggestedUrl = GetURL("google.com"); - // Even if the navigated site has a low engagement score, it should be - // considered for lookalike suggestions. - SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); - - TestHistogramEventsRecordedAndInfobarVisibility( - browser(), &histograms, kNavigatedUrl, kExpectedSuggestedUrl, - NavigationSuggestionEvent::kMatchTopSite); - - CheckUkm({kNavigatedUrl}, - LookalikeUrlNavigationObserver::MatchType::kTopSite); -} - -// The navigated domain itself is a top domain or a subdomain of a top domain. -// Should not record metrics. The top domain list doesn't contain any IDN, so -// this only tests the case where the subdomains are IDNs. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - TopDomainIdnSubdomain_NoMatch) { - TestInfobarNotShown(browser(), GetURL("tést.google.com")); - CheckNoUkm(); - - // blogspot.com is a private registry, so the eTLD+1 of "tést.blogspot.com" is - // itself, instead of just "blogspot.com". This is different than - // tést.google.com whose eTLD+1 is google.com, and it should be handled - // correctly. - TestInfobarNotShown(browser(), GetURL("tést.blogspot.com")); - CheckNoUkm(); -} - -// Schemes other than HTTP and HTTPS should be ignored. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - TopDomainChromeUrl_NoMatch) { - TestInfobarNotShown(browser(), GURL("chrome://googlé.com")); - CheckNoUkm(); -} - -// Navigate to a domain within an edit distance of 1 to a top domain. -// This should record metrics. It should also show a "Did you mean to go to ..." -// infobar if configured via a feature param. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - EditDistance_TopDomain_Match) { - base::HistogramTester histograms; - - // The skeleton of this domain, gooogle.corn, is one 1 edit away from - // google.corn, the skeleton of google.com. - const GURL kNavigatedUrl = GetURL("goooglé.com"); - const GURL kExpectedSuggestedUrl = GetURL("google.com"); - // Even if the navigated site has a low engagement score, it should be - // considered for lookalike suggestions. - SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); - - TestHistogramEventsRecordedAndInfobarVisibility( - browser(), &histograms, kNavigatedUrl, kExpectedSuggestedUrl, - NavigationSuggestionEvent::kMatchEditDistance); - - CheckUkm({kNavigatedUrl}, - LookalikeUrlNavigationObserver::MatchType::kEditDistance); -} - -// Tests negative examples for the edit distance. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - EditDistance_TopDomain_NoMatch) { - // Matches google.com.tr but only differs in registry. - TestInfobarNotShown(browser(), GetURL("google.com.tw")); - CheckNoUkm(); - - // Matches bing.com but is a top domain itself. - TestInfobarNotShown(browser(), GetURL("ning.com")); - CheckNoUkm(); - - // Matches ask.com but is too short. - TestInfobarNotShown(browser(), GetURL("bsk.com")); - CheckNoUkm(); -} - -// Test that the heuristics aren't triggered on net errors. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - NetError_NoMatch) { - // Create a test server that returns invalid responses. - net::EmbeddedTestServer custom_test_server; - custom_test_server.RegisterRequestHandler( - base::BindRepeating(&NetworkErrorResponseHandler)); - ASSERT_TRUE(custom_test_server.Start()); - - // Matches google.com but page returns an invalid response. - TestInfobarNotShown(browser(), - custom_test_server.GetURL("gooogle.com", "/title1.html")); - CheckNoUkm(); - - TestInfobarNotShown(browser(), - custom_test_server.GetURL("googlé.com", "/title1.html")); - CheckNoUkm(); - - SetEngagementScore(browser(), GURL("http://site1.com"), kHighEngagement); - TestInfobarNotShown(browser(), - custom_test_server.GetURL("sité1.com", "/title1.html")); - CheckNoUkm(); -} - -// Navigate to a domain whose visual representation looks like a domain with a -// site engagement score above a certain threshold. This should record metrics. -// It should also show a "Did you mean to go to ..." infobar if configured via -// a feature param. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - Idn_SiteEngagement_Match) { - const char* const kEngagedSites[] = { - "http://site1.com", "http://www.site2.com", "http://sité3.com", - "http://www.sité4.com"}; - - for (const char* const kSite : kEngagedSites) { - SetEngagementScore(browser(), GURL(kSite), kHighEngagement); - } - - std::vector<GURL> ukm_urls; - for (const auto& test_case : kSiteEngagementTestCases) { - base::HistogramTester histograms; - const GURL kNavigatedUrl = GetURL(test_case.navigated); - const GURL kExpectedSuggestedUrl = GetURL(test_case.suggested); - - // Even if the navigated site has a low engagement score, it should be - // considered for lookalike suggestions. - SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); - // Advance the clock to force LookalikeUrlService to fetch a new engaged - // site list. - test_clock()->Advance(base::TimeDelta::FromHours(1)); - - TestHistogramEventsRecordedAndInfobarVisibility( - browser(), &histograms, kNavigatedUrl, kExpectedSuggestedUrl, - NavigationSuggestionEvent::kMatchSiteEngagement); - - ukm_urls.push_back(kNavigatedUrl); - CheckUkm(ukm_urls, - LookalikeUrlNavigationObserver::MatchType::kSiteEngagement); - } -} - -// Similar to Idn_SiteEngagement_Match, but tests a single domain. Also checks -// that the list of engaged sites in incognito and the main profile don't affect -// each other. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - Idn_SiteEngagement_Match_Incognito) { - const GURL kNavigatedUrl = GetURL("sité1.com"); - const GURL kEngagedUrl = GetURL("site1.com"); - - // Set high engagement scores in the main profile and low engagement scores - // in incognito. Main profile should record metrics, incognito shouldn't. - Browser* incognito = CreateIncognitoBrowser(); - LookalikeUrlService::Get(incognito->profile()) - ->SetClockForTesting(test_clock()); - SetEngagementScore(browser(), kEngagedUrl, kHighEngagement); - SetEngagementScore(incognito, kEngagedUrl, kLowEngagement); - - std::vector<GURL> ukm_urls; - // Main profile should record metrics because there are engaged sites. - { - base::HistogramTester histograms; - // Advance the clock to force LookalikeUrlService to fetch a new engaged - // site list. - test_clock()->Advance(base::TimeDelta::FromHours(1)); - TestHistogramEventsRecordedAndInfobarVisibility( - browser(), &histograms, kNavigatedUrl, kEngagedUrl, - NavigationSuggestionEvent::kMatchSiteEngagement); - - ukm_urls.push_back(kNavigatedUrl); - CheckUkm(ukm_urls, - LookalikeUrlNavigationObserver::MatchType::kSiteEngagement); - } - - // Incognito shouldn't record metrics because there are no engaged sites. - { - base::HistogramTester histograms; - test_clock()->Advance(base::TimeDelta::FromHours(1)); - TestInfobarNotShown(incognito, kNavigatedUrl); - histograms.ExpectTotalCount(LookalikeUrlNavigationObserver::kHistogramName, - 0); - } - - // Now reverse the scores: Set low engagement in the main profile and high - // engagement in incognito. - SetEngagementScore(browser(), kEngagedUrl, kLowEngagement); - SetEngagementScore(incognito, kEngagedUrl, kHighEngagement); - - // Incognito should start recording metrics and main profile should stop. - { - base::HistogramTester histograms; - test_clock()->Advance(base::TimeDelta::FromHours(1)); - - TestHistogramEventsRecordedAndInfobarVisibility( - incognito, &histograms, kNavigatedUrl, kEngagedUrl, - NavigationSuggestionEvent::kMatchSiteEngagement); - ukm_urls.push_back(kNavigatedUrl); - CheckUkm(ukm_urls, - LookalikeUrlNavigationObserver::MatchType::kSiteEngagement); - } - - // Main profile shouldn't record metrics because there are no engaged sites. - { - base::HistogramTester histograms; - test_clock()->Advance(base::TimeDelta::FromHours(1)); - TestInfobarNotShown(browser(), kNavigatedUrl); - histograms.ExpectTotalCount(LookalikeUrlNavigationObserver::kHistogramName, - 0); - } -} - -// Test that navigations to a site with a high engagement score shouldn't -// record metrics or show infobar. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - Idn_SiteEngagement_Match_IgnoreHighlyEngagedSite) { - base::HistogramTester histograms; - SetEngagementScore(browser(), GURL("http://site-not-in-top-domain-list.com"), - kHighEngagement); - const GURL high_engagement_url = GetURL("síte-not-ín-top-domaín-líst.com"); - SetEngagementScore(browser(), high_engagement_url, kHighEngagement); - TestInfobarNotShown(browser(), high_engagement_url); - histograms.ExpectTotalCount(LookalikeUrlNavigationObserver::kHistogramName, - 0); -} - -// Test that an engaged site with a scheme other than HTTP or HTTPS should be -// ignored. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - Idn_SiteEngagement_IgnoreChromeUrl) { - base::HistogramTester histograms; - SetEngagementScore(browser(), - GURL("chrome://site-not-in-top-domain-list.com"), - kHighEngagement); - const GURL low_engagement_url("http://síte-not-ín-top-domaín-líst.com"); - SetEngagementScore(browser(), low_engagement_url, kLowEngagement); - TestInfobarNotShown(browser(), low_engagement_url); - histograms.ExpectTotalCount(LookalikeUrlNavigationObserver::kHistogramName, - 0); -} - -// IDNs with a single label should be properly handled. There are two cases -// where this might occur: -// 1. The navigated URL is an IDN with a single label. -// 2. One of the engaged sites is an IDN with a single label. -// Neither of these should cause a crash. -IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationObserverBrowserTest, - IdnWithSingleLabelShouldNotCauseACrash) { - base::HistogramTester histograms; - - // Case 1: Navigating to an IDN with a single label shouldn't cause a crash. - TestInfobarNotShown(browser(), GetURL("é")); - - // Case 2: An IDN with a single label with a site engagement score shouldn't - // cause a crash. - SetEngagementScore(browser(), GURL("http://tést"), kHighEngagement); - TestInfobarNotShown(browser(), GetURL("tést.com")); - - histograms.ExpectTotalCount(LookalikeUrlNavigationObserver::kHistogramName, - 0); - CheckNoUkm(); -}
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_observer.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc similarity index 60% rename from chrome/browser/lookalikes/lookalike_url_navigation_observer.cc rename to chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc index f89be4df..480b131 100644 --- a/chrome/browser/lookalikes/lookalike_url_navigation_observer.cc +++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
@@ -1,22 +1,29 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 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/lookalikes/lookalike_url_navigation_observer.h" +#include "chrome/browser/lookalikes/lookalike_url_navigation_throttle.h" + +#include <map> +#include <memory> +#include <set> +#include <string> +#include <utility> +#include <vector> #include "base/bind.h" -#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/engagement/site_engagement_service.h" +#include "chrome/browser/lookalikes/lookalike_url_allowlist.h" +#include "chrome/browser/lookalikes/lookalike_url_controller_client.h" +#include "chrome/browser/lookalikes/lookalike_url_interstitial_page.h" #include "chrome/browser/lookalikes/lookalike_url_service.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h" #include "chrome/common/chrome_features.h" -#include "components/omnibox/browser/autocomplete_match.h" +#include "components/security_interstitials/content/security_interstitial_tab_helper.h" #include "components/ukm/content/source_url_recorder.h" -#include "components/url_formatter/idn_spoof_checker.h" #include "components/url_formatter/top_domains/top_domain_util.h" #include "content/public/browser/navigation_handle.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" @@ -27,13 +34,14 @@ #include "components/url_formatter/top_domains/top500-domains-inc.cc" -using MatchType = LookalikeUrlNavigationObserver::MatchType; +using MatchType = LookalikeUrlNavigationThrottle::MatchType; using NavigationSuggestionEvent = - LookalikeUrlNavigationObserver::NavigationSuggestionEvent; + LookalikeUrlNavigationThrottle::NavigationSuggestionEvent; +typedef content::NavigationThrottle::ThrottleCheckResult ThrottleCheckResult; void RecordEvent( - LookalikeUrlNavigationObserver::NavigationSuggestionEvent event) { - UMA_HISTOGRAM_ENUMERATION(LookalikeUrlNavigationObserver::kHistogramName, + LookalikeUrlNavigationThrottle::NavigationSuggestionEvent event) { + UMA_HISTOGRAM_ENUMERATION(LookalikeUrlNavigationThrottle::kHistogramName, event); } @@ -42,15 +50,16 @@ DCHECK(!skeletons1.empty()); DCHECK(!skeletons2.empty()); for (const std::string& skeleton1 : skeletons1) { - if (base::ContainsKey(skeletons2, skeleton1)) + if (base::ContainsKey(skeletons2, skeleton1)) { return true; + } } return false; } // Returns true if the domain given by |domain_info| is a top domain. bool IsTopDomain( - const LookalikeUrlNavigationObserver::DomainInfo& domain_info) { + const LookalikeUrlNavigationThrottle::DomainInfo& domain_info) { // Top domains are only accessible through their skeletons, so query the top // domains trie for each skeleton of this domain. for (const std::string& skeleton : domain_info.skeletons) { @@ -77,8 +86,8 @@ // |domain_and_registry| may be attempting to spoof, based on skeleton // comparison. std::string GetMatchingSiteEngagementDomain( - const std::vector<GURL>& engaged_sites, - const LookalikeUrlNavigationObserver::DomainInfo& navigated_domain) { + const std::set<GURL>& engaged_sites, + const LookalikeUrlNavigationThrottle::DomainInfo& navigated_domain) { DCHECK(!navigated_domain.domain_and_registry.empty()); std::map<std::string, url_formatter::Skeletons> domain_and_registry_to_skeleton; @@ -93,11 +102,13 @@ const std::string engaged_domain_and_registry = GetETLDPlusOne(engaged_site); // eTLD+1 can be empty for private domains (e.g. http://test). - if (engaged_domain_and_registry.empty()) + if (engaged_domain_and_registry.empty()) { continue; + } - if (navigated_domain.domain_and_registry == engaged_domain_and_registry) + if (navigated_domain.domain_and_registry == engaged_domain_and_registry) { return std::string(); + } // Multiple domains can map to the same eTLD+1, avoid skeleton generation // when possible. @@ -118,8 +129,9 @@ skeletons = it->second; } - if (SkeletonsMatch(navigated_domain.skeletons, skeletons)) + if (SkeletonsMatch(navigated_domain.skeletons, skeletons)) { return engaged_site.host(); + } } return std::string(); } @@ -127,10 +139,10 @@ } // namespace // static -const char LookalikeUrlNavigationObserver::kHistogramName[] = +const char LookalikeUrlNavigationThrottle::kHistogramName[] = "NavigationSuggestion.Event"; -LookalikeUrlNavigationObserver::DomainInfo::DomainInfo( +LookalikeUrlNavigationThrottle::DomainInfo::DomainInfo( const std::string& arg_domain_and_registry, const url_formatter::IDNConversionResult& arg_idn_result, const url_formatter::Skeletons& arg_skeletons) @@ -138,56 +150,122 @@ idn_result(arg_idn_result), skeletons(arg_skeletons) {} -LookalikeUrlNavigationObserver::DomainInfo::~DomainInfo() = default; +LookalikeUrlNavigationThrottle::DomainInfo::~DomainInfo() = default; -LookalikeUrlNavigationObserver::DomainInfo::DomainInfo(const DomainInfo&) = +LookalikeUrlNavigationThrottle::DomainInfo::DomainInfo(const DomainInfo&) = default; -LookalikeUrlNavigationObserver::LookalikeUrlNavigationObserver( - content::WebContents* web_contents) - : WebContentsObserver(web_contents), - profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), +LookalikeUrlNavigationThrottle::LookalikeUrlNavigationThrottle( + content::NavigationHandle* navigation_handle) + : content::NavigationThrottle(navigation_handle), + interstitials_enabled_(base::FeatureList::IsEnabled( + features::kLookalikeUrlNavigationSuggestionsUI)), + profile_(Profile::FromBrowserContext( + navigation_handle->GetWebContents()->GetBrowserContext())), weak_factory_(this) {} -LookalikeUrlNavigationObserver::~LookalikeUrlNavigationObserver() {} +LookalikeUrlNavigationThrottle::~LookalikeUrlNavigationThrottle() {} -void LookalikeUrlNavigationObserver::DidFinishNavigation( - content::NavigationHandle* navigation_handle) { +ThrottleCheckResult LookalikeUrlNavigationThrottle::HandleThrottleRequest( + const GURL& url) { + content::NavigationHandle* handle = navigation_handle(); + content::WebContents* web_contents = handle->GetWebContents(); + // Ignore subframe and same document navigations. - if (!navigation_handle->IsInMainFrame() || - navigation_handle->IsSameDocument()) - return; + if (!handle->IsInMainFrame() || handle->IsSameDocument()) { + return content::NavigationThrottle::PROCEED; + } - // If the navigation was not committed, it means either the page was a - // download or error 204/205, or the navigation never left the previous - // URL. Basically, this isn't a problem since we stayed at the existing URL. - // Also ignore any navigation errors. - if (!navigation_handle->HasCommitted() || - navigation_handle->GetNetErrorCode() != net::OK) - return; + if (!url.SchemeIsHTTPOrHTTPS()) { + return content::NavigationThrottle::PROCEED; + } - const GURL url = navigation_handle->GetURL(); - if (!url.SchemeIsHTTPOrHTTPS()) - return; - - // If the user has engaged with this site, don't show any lookalike - // navigation suggestions. - if (SiteEngagementService::Get(profile_)->IsEngagementAtLeast( - url, blink::mojom::EngagementLevel::MEDIUM)) - return; + // If the URL is in the allowlist, don't show any warning. + LookalikeUrlAllowlist* allowlist = + LookalikeUrlAllowlist::GetOrCreateAllowlist(web_contents); + if (allowlist->IsDomainInList(url.host())) { + return content::NavigationThrottle::PROCEED; + } const DomainInfo navigated_domain = GetDomainInfo(url); if (navigated_domain.domain_and_registry.empty() || - IsTopDomain(navigated_domain)) - return; + IsTopDomain(navigated_domain)) { + return content::NavigationThrottle::PROCEED; + } - LookalikeUrlService::Get(profile_)->GetEngagedSites( - base::BindOnce(&LookalikeUrlNavigationObserver::PerformChecks, - weak_factory_.GetWeakPtr(), url, navigated_domain)); + LookalikeUrlService* service = LookalikeUrlService::Get(profile_); + if (service->UpdateEngagedSites( + base::BindOnce(&LookalikeUrlNavigationThrottle::PerformChecksDeferred, + weak_factory_.GetWeakPtr(), url, navigated_domain))) { + // If we're not going to show an interstitial, there's no reason to delay + // the navigation any further. + if (!interstitials_enabled_) { + return content::NavigationThrottle::PROCEED; + } + return content::NavigationThrottle::DEFER; + } + + return PerformChecks(url, navigated_domain, service->GetLatestEngagedSites()); } -LookalikeUrlNavigationObserver::DomainInfo -LookalikeUrlNavigationObserver::GetDomainInfo(const GURL& url) { +ThrottleCheckResult LookalikeUrlNavigationThrottle::WillProcessResponse() { + if (navigation_handle()->GetNetErrorCode() != net::OK) { + return content::NavigationThrottle::PROCEED; + } + return HandleThrottleRequest(navigation_handle()->GetURL()); +} + +ThrottleCheckResult LookalikeUrlNavigationThrottle::WillRedirectRequest() { + const std::vector<GURL>& chain = navigation_handle()->GetRedirectChain(); + + // WillRedirectRequest is called after a redirect occurs, so the end of the + // chain is the URL that was redirected to. We need to check the preceding URL + // that caused the redirection. The final URL in the chain is checked either: + // - after the next redirection (when there is a longer chain), or + // - by WillProcessResponse (before content is rendered). + if (chain.size() < 2) { + return content::NavigationThrottle::PROCEED; + } + return HandleThrottleRequest(chain[chain.size() - 2]); +} + +const char* LookalikeUrlNavigationThrottle::GetNameForLogging() { + return "LookalikeUrlNavigationThrottle"; +} + +ThrottleCheckResult LookalikeUrlNavigationThrottle::ShowInterstitial( + const GURL& safe_url, + const GURL& url) { + content::NavigationHandle* handle = navigation_handle(); + content::WebContents* web_contents = handle->GetWebContents(); + + auto controller = std::make_unique<LookalikeUrlControllerClient>( + web_contents, url, safe_url); + + std::unique_ptr<LookalikeUrlInterstitialPage> blocking_page( + new LookalikeUrlInterstitialPage(web_contents, safe_url, + std::move(controller))); + + base::Optional<std::string> error_page_contents = + blocking_page->GetHTMLContents(); + + security_interstitials::SecurityInterstitialTabHelper::AssociateBlockingPage( + web_contents, handle->GetNavigationId(), std::move(blocking_page)); + + return ThrottleCheckResult(content::NavigationThrottle::CANCEL, + net::ERR_BLOCKED_BY_CLIENT, error_page_contents); +} + +std::unique_ptr<LookalikeUrlNavigationThrottle> +LookalikeUrlNavigationThrottle::MaybeCreateNavigationThrottle( + content::NavigationHandle* navigation_handle) { + // For metrics, we always insert the throttle + return std::make_unique<LookalikeUrlNavigationThrottle>(navigation_handle); +} + +// static +LookalikeUrlNavigationThrottle::DomainInfo +LookalikeUrlNavigationThrottle::GetDomainInfo(const GURL& url) { // Perform all computations on eTLD+1. const std::string domain_and_registry = GetETLDPlusOne(url); // eTLD+1 can be empty for private domains. @@ -203,15 +281,42 @@ return DomainInfo(domain_and_registry, idn_result, skeletons); } -void LookalikeUrlNavigationObserver::PerformChecks( +void LookalikeUrlNavigationThrottle::PerformChecksDeferred( const GURL& url, const DomainInfo& navigated_domain, - const std::vector<GURL>& engaged_sites) { + const std::set<GURL>& engaged_sites) { + ThrottleCheckResult result = LookalikeUrlNavigationThrottle::PerformChecks( + url, navigated_domain, engaged_sites); + + if (!interstitials_enabled_) { + return; + } + + if (result.action() == content::NavigationThrottle::PROCEED) { + Resume(); + return; + } + + CancelDeferredNavigation(result); +} + +ThrottleCheckResult LookalikeUrlNavigationThrottle::PerformChecks( + const GURL& url, + const DomainInfo& navigated_domain, + const std::set<GURL>& engaged_sites) { std::string matched_domain; MatchType match_type; + + // Ensure that this URL is not already engaged. We can't use the synchronous + // SiteEngagementService::IsEngagementAtLeast as it has side effects. We check + // in PerformChecks to ensure we have up-to-date engaged_sites. + if (base::ContainsKey(engaged_sites, url.GetOrigin())) { + return content::NavigationThrottle::PROCEED; + } + if (!GetMatchingDomain(navigated_domain, engaged_sites, &matched_domain, &match_type)) { - return; + return content::NavigationThrottle::PROCEED; } DCHECK(!matched_domain.empty()); @@ -222,24 +327,22 @@ ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get(); CHECK(ukm_recorder); - ukm::SourceId source_id = - ukm::GetSourceIdForWebContentsDocument(web_contents()); + ukm::SourceId source_id = ukm::ConvertToSourceId( + navigation_handle()->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID); ukm::builders::LookalikeUrl_NavigationSuggestion(source_id) .SetMatchType(static_cast<int>(match_type)) .Record(ukm_recorder); - if (base::FeatureList::IsEnabled( - features::kLookalikeUrlNavigationSuggestionsUI)) { - RecordEvent(NavigationSuggestionEvent::kInfobarShown); - AlternateNavInfoBarDelegate::CreateForLookalikeUrlNavigation( - web_contents(), base::UTF8ToUTF16(matched_domain), suggested_url, url, - base::BindOnce(RecordEvent, NavigationSuggestionEvent::kLinkClicked)); + if (interstitials_enabled_) { + return ShowInterstitial(suggested_url, url); } + + return content::NavigationThrottle::PROCEED; } -bool LookalikeUrlNavigationObserver::GetMatchingDomain( +bool LookalikeUrlNavigationThrottle::GetMatchingDomain( const DomainInfo& navigated_domain, - const std::vector<GURL>& engaged_sites, + const std::set<GURL>& engaged_sites, std::string* matched_domain, MatchType* match_type) { DCHECK(!navigated_domain.domain_and_registry.empty()); @@ -286,7 +389,7 @@ } // static -bool LookalikeUrlNavigationObserver::IsEditDistanceAtMostOne( +bool LookalikeUrlNavigationThrottle::IsEditDistanceAtMostOne( const base::string16& str1, const base::string16& str2) { if (str1.size() > str2.size() + 1 || str2.size() > str1.size() + 1) { @@ -329,7 +432,7 @@ } // static -std::string LookalikeUrlNavigationObserver::GetSimilarDomainFromTop500( +std::string LookalikeUrlNavigationThrottle::GetSimilarDomainFromTop500( const DomainInfo& navigated_domain) { if (!url_formatter::top_domains::IsEditDistanceCandidate( navigated_domain.domain_and_registry)) { @@ -361,16 +464,3 @@ } return std::string(); } - -// static -void LookalikeUrlNavigationObserver::CreateForWebContents( - content::WebContents* web_contents) { - DCHECK(web_contents); - if (!FromWebContents(web_contents)) { - web_contents->SetUserData( - UserDataKey(), - std::make_unique<LookalikeUrlNavigationObserver>(web_contents)); - } -} - -WEB_CONTENTS_USER_DATA_KEY_IMPL(LookalikeUrlNavigationObserver)
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h new file mode 100644 index 0000000..4746c3c4 --- /dev/null +++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h
@@ -0,0 +1,126 @@ +// Copyright 2019 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_LOOKALIKES_LOOKALIKE_URL_NAVIGATION_THROTTLE_H_ +#define CHROME_BROWSER_LOOKALIKES_LOOKALIKE_URL_NAVIGATION_THROTTLE_H_ + +#include <memory> +#include <set> +#include <string> + +#include "base/memory/weak_ptr.h" +#include "chrome/browser/engagement/site_engagement_details.mojom.h" +#include "components/url_formatter/url_formatter.h" +#include "content/public/browser/navigation_throttle.h" + +namespace content { +class NavigationHandle; +} // namespace content + +class Profile; + +// Observes navigations and shows an interstitial if the navigated domain name +// is visually similar to a top domain or a domain with a site engagement score. +class LookalikeUrlNavigationThrottle : public content::NavigationThrottle { + public: + // Used for metrics. Multiple events can occur per navigation. + enum class NavigationSuggestionEvent { + kNone = 0, + // Interstitial results recorded using security_interstitials::MetricsHelper + // kInfobarShown = 1, + // kLinkClicked = 2, + kMatchTopSite = 3, + kMatchSiteEngagement = 4, + kMatchEditDistance = 5, + + // Append new items to the end of the list above; do not modify or + // replace existing values. Comment out obsolete items. + kMaxValue = kMatchEditDistance, + }; + + // Used for UKM. There is only a single MatchType per navigation. + enum class MatchType { + kNone = 0, + kTopSite = 1, + kSiteEngagement = 2, + kEditDistance = 3, + + // Append new items to the end of the list above; do not modify or replace + // existing values. Comment out obsolete items. + kMaxValue = kEditDistance, + }; + + struct DomainInfo { + const std::string domain_and_registry; + const url_formatter::IDNConversionResult idn_result; + const url_formatter::Skeletons skeletons; + DomainInfo(const std::string& arg_domain_and_registry, + const url_formatter::IDNConversionResult& arg_idn_result, + const url_formatter::Skeletons& arg_skeletons); + ~DomainInfo(); + DomainInfo(const DomainInfo& other); + }; + + static const char kHistogramName[]; + + explicit LookalikeUrlNavigationThrottle(content::NavigationHandle* handle); + ~LookalikeUrlNavigationThrottle() override; + + // content::NavigationThrottle: + ThrottleCheckResult WillProcessResponse() override; + ThrottleCheckResult WillRedirectRequest() override; + const char* GetNameForLogging() override; + + static std::unique_ptr<LookalikeUrlNavigationThrottle> + MaybeCreateNavigationThrottle(content::NavigationHandle* navigation_handle); + + private: + FRIEND_TEST_ALL_PREFIXES(LookalikeUrlNavigationThrottleTest, + IsEditDistanceAtMostOne); + + ThrottleCheckResult HandleThrottleRequest(const GURL& url); + + static DomainInfo GetDomainInfo(const GURL& url); + + // Performs synchronous top domain and engaged site checks on the navigated + // |url|. Uses |engaged_sites| for the engaged site checks. + ThrottleCheckResult PerformChecks(const GURL& url, + const DomainInfo& navigated_domain, + const std::set<GURL>& engaged_sites); + + // A void-returning variant, only used with deferred throttle results. + void PerformChecksDeferred(const GURL& url, + const DomainInfo& navigated_domain, + const std::set<GURL>& engaged_sites); + + // Returns true if a domain is visually similar to the hostname of |url|. The + // matching domain can be a top domain or an engaged site. Similarity check + // is made using both visual skeleton and edit distance comparison. If this + // returns true, match details will be written into |matched_domain| and + // |match_type|. They cannot be nullptr. + bool GetMatchingDomain(const DomainInfo& navigated_domain, + const std::set<GURL>& engaged_sites, + std::string* matched_domain, + MatchType* match_type); + + // Returns if the Levenshtein distance between |str1| and |str2| is at most 1. + // This has O(max(n,m)) complexity as opposed to O(n*m) of the usual edit + // distance computation. + static bool IsEditDistanceAtMostOne(const base::string16& str1, + const base::string16& str2); + + // Returns the first matching top domain with an edit distance of at most one + // to |domain_and_registry|. + static std::string GetSimilarDomainFromTop500(const DomainInfo& domain_info); + + ThrottleCheckResult ShowInterstitial(const GURL& safe_domain, + const GURL& url); + + bool interstitials_enabled_; + + Profile* profile_; + base::WeakPtrFactory<LookalikeUrlNavigationThrottle> weak_factory_; +}; + +#endif // CHROME_BROWSER_LOOKALIKES_LOOKALIKE_URL_NAVIGATION_THROTTLE_H_
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc new file mode 100644 index 0000000..8173894 --- /dev/null +++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
@@ -0,0 +1,733 @@ +// 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 "base/bind.h" +#include "base/strings/string_number_conversions.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/simple_test_clock.h" +#include "chrome/browser/engagement/site_engagement_score.h" +#include "chrome/browser/engagement/site_engagement_service.h" +#include "chrome/browser/history/history_service_factory.h" +#include "chrome/browser/history/history_test_utils.h" +#include "chrome/browser/lookalikes/lookalike_url_interstitial_page.h" +#include "chrome/browser/lookalikes/lookalike_url_navigation_throttle.h" +#include "chrome/browser/lookalikes/lookalike_url_service.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/common/chrome_features.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/security_interstitials/content/security_interstitial_page.h" +#include "components/security_interstitials/content/security_interstitial_tab_helper.h" +#include "components/security_interstitials/core/metrics_helper.h" +#include "components/ukm/test_ukm_recorder.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/test_navigation_observer.h" +#include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_source.h" +#include "ui/base/window_open_disposition.h" + +namespace { + +using security_interstitials::MetricsHelper; +using security_interstitials::SecurityInterstitialCommand; +using UkmEntry = ukm::builders::LookalikeUrl_NavigationSuggestion; +using NavigationSuggestionEvent = + LookalikeUrlNavigationThrottle::NavigationSuggestionEvent; + +enum class UIEnabled { kDisabled, kEnabled }; + +// An engagement score above MEDIUM. +const int kHighEngagement = 20; + +// An engagement score below MEDIUM. +const int kLowEngagement = 1; + +// The UMA metric names registered by metrics_helper +const char kInterstitialDecisionMetric[] = "interstitial.lookalike.decision"; +const char kInterstitialInteractionMetric[] = + "interstitial.lookalike.interaction"; + +// The domains here should not private domains (e.g. site.test), otherwise they +// might test the wrong thing. Also note that site5.com is in the top domain +// list, so it shouldn't be used here. +struct SiteEngagementTestCase { + const char* const navigated; + const char* const suggested; +} kSiteEngagementTestCases[] = { + {"sité1.com", "site1.com"}, + {"mail.www.sité1.com", "site1.com"}, + + // These should match since the comparison uses eTLD+1s. + {"sité2.com", "www.site2.com"}, + {"mail.sité2.com", "www.site2.com"}, + + {"síté3.com", "sité3.com"}, + {"mail.síté3.com", "sité3.com"}, + + {"síté4.com", "www.sité4.com"}, + {"mail.síté4.com", "www.sité4.com"}, +}; + +static std::unique_ptr<net::test_server::HttpResponse> +NetworkErrorResponseHandler(const net::test_server::HttpRequest& request) { + return std::unique_ptr<net::test_server::HttpResponse>( + new net::test_server::RawHttpResponse("", "")); +} + +security_interstitials::SecurityInterstitialPage* GetCurrentInterstitial( + content::WebContents* web_contents) { + security_interstitials::SecurityInterstitialTabHelper* helper = + security_interstitials::SecurityInterstitialTabHelper::FromWebContents( + web_contents); + if (!helper) { + return nullptr; + } + return helper->GetBlockingPageForCurrentlyCommittedNavigationForTesting(); +} + +security_interstitials::SecurityInterstitialPage::TypeID GetInterstitialType( + content::WebContents* web_contents) { + security_interstitials::SecurityInterstitialPage* page = + GetCurrentInterstitial(web_contents); + if (!page) { + return nullptr; + } + return page->GetTypeForTesting(); +} + +void SendInterstitialCommand(content::WebContents* web_contents, + SecurityInterstitialCommand command) { + GetCurrentInterstitial(web_contents) + ->CommandReceived(base::NumberToString(command)); +} + +} // namespace + +class LookalikeUrlNavigationThrottleBrowserTest + : public InProcessBrowserTest, + public testing::WithParamInterface<UIEnabled> { + protected: + // Sets the absolute Site Engagement |score| for the testing origin. + static void SetEngagementScore(Browser* browser, + const GURL& url, + double score) { + SiteEngagementService::Get(browser->profile()) + ->ResetBaseScoreForURL(url, score); + } + + void SetUp() override { + if (ui_enabled()) { + feature_list_.InitAndEnableFeature( + features::kLookalikeUrlNavigationSuggestionsUI); + } else { + feature_list_.InitAndDisableFeature( + features::kLookalikeUrlNavigationSuggestionsUI); + } + InProcessBrowserTest::SetUp(); + } + + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + ASSERT_TRUE(embedded_test_server()->Start()); + test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); + + const base::Time kNow = base::Time::FromDoubleT(1000); + test_clock_.SetNow(kNow); + + LookalikeUrlService* lookalike_service = + LookalikeUrlService::Get(browser()->profile()); + lookalike_service->SetClockForTesting(&test_clock_); + } + + GURL GetURL(const char* hostname) const { + return embedded_test_server()->GetURL(hostname, "/title1.html"); + } + + GURL GetLongRedirect(const char* via_hostname1, + const char* via_hostname2, + const char* dest_hostname) const { + GURL dest = GetURL(dest_hostname); + GURL mid = embedded_test_server()->GetURL( + via_hostname2, "/server-redirect?" + dest.spec()); + return embedded_test_server()->GetURL(via_hostname1, + "/server-redirect?" + mid.spec()); + } + + // Checks that UKM recorded a metric for each URL in |navigated_urls|. + void CheckUkm(const std::vector<GURL>& navigated_urls, + LookalikeUrlNavigationThrottle::MatchType match_type) { + auto entries = test_ukm_recorder()->GetEntriesByName(UkmEntry::kEntryName); + ASSERT_EQ(navigated_urls.size(), entries.size()); + int entry_count = 0; + for (const auto* const entry : entries) { + test_ukm_recorder()->ExpectEntrySourceHasUrl(entry, + navigated_urls[entry_count]); + test_ukm_recorder()->ExpectEntryMetric(entry, "MatchType", + static_cast<int>(match_type)); + entry_count++; + } + } + + // Checks that UKM did not record any lookalike URL metrics. + void CheckNoUkm() { + EXPECT_TRUE( + test_ukm_recorder()->GetEntriesByName(UkmEntry::kEntryName).empty()); + } + + void TestInterstitialNotShown(Browser* browser, const GURL& navigated_url) { + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + { + content::TestNavigationObserver navigation_observer(web_contents, 1); + NavigateToURL(browser, navigated_url); + navigation_observer.Wait(); + EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents)); + } + { + // Navigate to an empty page. This will happen after any + // LookalikeUrlService tasks, so will effectively wait for those tasks to + // finish. + content::TestNavigationObserver navigation_observer(web_contents, 1); + NavigateToURL(browser, GURL("about:blank")); + navigation_observer.Wait(); + EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents)); + } + } + + // Tests only that the interstitial is shown (when enabled) when the user + // tries to visit the provided URL. + void TestOnlyInterstitialShown(Browser* browser, const GURL& navigated_url) { + if (!ui_enabled()) { + return; + } + + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + + content::TestNavigationObserver navigation_observer(web_contents, 1); + NavigateToURL(browser, navigated_url); + navigation_observer.Wait(); + + EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting, + GetInterstitialType(web_contents)); + } + + // Tests that the histogram event |expected_event| is recorded. If the UI is + // enabled, additinal events for interstitial display and link click will also + // be tested. + void TestHistogramEventsRecordedAndInterstitialShown( + Browser* browser, + base::HistogramTester* histograms, + const GURL& navigated_url, + const GURL& expected_suggested_url, + LookalikeUrlNavigationThrottle::NavigationSuggestionEvent + expected_event) { + if (ui_enabled()) { + // If the feature is enabled, the UI will be displayed. + TestInterstitialShown(browser, navigated_url, expected_suggested_url); + histograms->ExpectTotalCount( + LookalikeUrlNavigationThrottle::kHistogramName, 1); + histograms->ExpectBucketCount( + LookalikeUrlNavigationThrottle::kHistogramName, expected_event, 1); + + histograms->ExpectTotalCount(kInterstitialDecisionMetric, 2); + histograms->ExpectBucketCount(kInterstitialDecisionMetric, + MetricsHelper::SHOW, 1); + histograms->ExpectBucketCount(kInterstitialDecisionMetric, + MetricsHelper::DONT_PROCEED, 1); + + histograms->ExpectTotalCount(kInterstitialInteractionMetric, 1); + histograms->ExpectBucketCount(kInterstitialInteractionMetric, + MetricsHelper::TOTAL_VISITS, 1); + return; + } + + TestInterstitialNotShown(browser, navigated_url); + histograms->ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName, + 1); + histograms->ExpectBucketCount( + LookalikeUrlNavigationThrottle::kHistogramName, expected_event, 1); + } + + // Tests that the histogram event |expected_event| is recorded. If the UI is + // enabled, additional events for interstitial display and dismissal will also + // be tested. + void TestHistogramEventsRecordedWhenInterstitialIgnored( + Browser* browser, + base::HistogramTester* histograms, + const GURL& navigated_url, + LookalikeUrlNavigationThrottle::NavigationSuggestionEvent + expected_event) { + if (ui_enabled()) { + // If the feature is enabled, the UI will be displayed. + DisplayThenIgnoreInterstitial(browser, navigated_url); + histograms->ExpectTotalCount( + LookalikeUrlNavigationThrottle::kHistogramName, 1); + histograms->ExpectBucketCount( + LookalikeUrlNavigationThrottle::kHistogramName, expected_event, 1); + + histograms->ExpectTotalCount(kInterstitialDecisionMetric, 2); + histograms->ExpectBucketCount(kInterstitialDecisionMetric, + MetricsHelper::SHOW, 1); + histograms->ExpectBucketCount(kInterstitialDecisionMetric, + MetricsHelper::PROCEED, 1); + + histograms->ExpectTotalCount(kInterstitialInteractionMetric, 1); + histograms->ExpectBucketCount(kInterstitialInteractionMetric, + MetricsHelper::TOTAL_VISITS, 1); + + TestInterstitialNotShown(browser, navigated_url); + + return; + } + + TestInterstitialNotShown(browser, navigated_url); + histograms->ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName, + 1); + histograms->ExpectBucketCount( + LookalikeUrlNavigationThrottle::kHistogramName, expected_event, 1); + } + + ukm::TestUkmRecorder* test_ukm_recorder() { return test_ukm_recorder_.get(); } + + base::SimpleTestClock* test_clock() { return &test_clock_; } + + private: + bool ui_enabled() const { return GetParam() == UIEnabled::kEnabled; } + + // Simulates a link click navigation. We don't use + // ui_test_utils::NavigateToURL(const GURL&) because it simulates the user + // typing the URL, causing the site to have a site engagement score of at + // least LOW. + static void NavigateToURL(Browser* browser, const GURL& url) { + NavigateParams params(browser, url, ui::PAGE_TRANSITION_LINK); + params.initiator_origin = url::Origin::Create(GURL("about:blank")); + params.disposition = WindowOpenDisposition::CURRENT_TAB; + params.is_renderer_initiated = true; + ui_test_utils::NavigateToURL(¶ms); + } + + // Checks that navigating to |navigated_url| results in displaying an + // interstitial suggesting navigation to |expected_suggestion_url|. + // Both |navigated_url| and |expected_suggested_url| can be ASCII or IDN. + static void TestInterstitialShown(Browser* browser, + const GURL& navigated_url, + const GURL& expected_suggested_url) { + history::HistoryService* const history_service = + HistoryServiceFactory::GetForProfile( + browser->profile(), ServiceAccessType::EXPLICIT_ACCESS); + ui_test_utils::WaitForHistoryToLoad(history_service); + + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + + EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents)); + { + content::TestNavigationObserver navigation_observer(web_contents, 1); + NavigateToURL(browser, navigated_url); + navigation_observer.Wait(); + } + + EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting, + GetInterstitialType(web_contents)); + + // Clicking the link in the interstitial should remove the interstitial and + // navigate to the suggested URL. + { + content::TestNavigationObserver navigation_observer(web_contents, 1); + SendInterstitialCommand(web_contents, + SecurityInterstitialCommand::CMD_DONT_PROCEED); + navigation_observer.Wait(); + } + + EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents)); + EXPECT_EQ(expected_suggested_url, web_contents->GetURL()); + + // Clicking the link in the interstitial should also remove the original URL + // from history. + ui_test_utils::HistoryEnumerator enumerator(browser->profile()); + EXPECT_FALSE(base::ContainsValue(enumerator.urls(), navigated_url)); + } + + // Checks that navigating to |navigated_url| results in displaying an + // interstitial, that, when ignored, proceeds to |navigated_url|. + // |navigated_url| can be ASCII or IDN. + static void DisplayThenIgnoreInterstitial(Browser* browser, + const GURL& navigated_url) { + history::HistoryService* const history_service = + HistoryServiceFactory::GetForProfile( + browser->profile(), ServiceAccessType::EXPLICIT_ACCESS); + ui_test_utils::WaitForHistoryToLoad(history_service); + + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + + EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents)); + { + content::TestNavigationObserver navigation_observer(web_contents, 1); + NavigateToURL(browser, navigated_url); + navigation_observer.Wait(); + } + + EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting, + GetInterstitialType(web_contents)); + + // Clicking the ignore button in the interstitial should remove the + // interstitial and navigate to the original URL. + { + content::TestNavigationObserver navigation_observer(web_contents, 1); + SendInterstitialCommand(web_contents, + SecurityInterstitialCommand::CMD_PROCEED); + navigation_observer.Wait(); + } + + EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents)); + EXPECT_EQ(navigated_url, web_contents->GetURL()); + + // Clicking the link should result in the original URL appearing in history. + ui_test_utils::HistoryEnumerator enumerator(browser->profile()); + EXPECT_TRUE(base::ContainsValue(enumerator.urls(), navigated_url)); + } + + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_; + base::SimpleTestClock test_clock_; +}; + +INSTANTIATE_TEST_SUITE_P(, + LookalikeUrlNavigationThrottleBrowserTest, + ::testing::Values(UIEnabled::kDisabled, + UIEnabled::kEnabled)); + +// Navigating to a non-IDN shouldn't show an interstitial or record metrics. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + NonIdn_NoMatch) { + TestInterstitialNotShown(browser(), GetURL("google.com")); + CheckNoUkm(); +} + +// Navigating to a domain whose visual representation does not look like a +// top domain shouldn't show an interstitial or record metrics. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + NonTopDomainIdn_NoInterstitial) { + TestInterstitialNotShown(browser(), GetURL("éxample.com")); + CheckNoUkm(); +} + +// If the user has engaged with the domain before, metrics shouldn't be recorded +// and the interstitial shouldn't be shown, even if the domain is visually +// similar to a top domain. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + Idn_TopDomain_EngagedSite_NoMatch) { + const GURL url = GetURL("googlé.com"); + SetEngagementScore(browser(), url, kHighEngagement); + TestInterstitialNotShown(browser(), url); + CheckNoUkm(); +} + +// Navigate to a domain whose visual representation looks like a top domain. +// This should record metrics. It should also show a lookalike warning +// interstitial if configured via a feature param. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + Idn_TopDomain_Match) { + base::HistogramTester histograms; + + const GURL kNavigatedUrl = GetURL("googlé.com"); + const GURL kExpectedSuggestedUrl = GetURL("google.com"); + // Even if the navigated site has a low engagement score, it should be + // considered for lookalike suggestions. + SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); + + TestHistogramEventsRecordedAndInterstitialShown( + browser(), &histograms, kNavigatedUrl, kExpectedSuggestedUrl, + NavigationSuggestionEvent::kMatchTopSite); + + CheckUkm({kNavigatedUrl}, + LookalikeUrlNavigationThrottle::MatchType::kTopSite); +} + +// The navigated domain itself is a top domain or a subdomain of a top domain. +// Should not record metrics. The top domain list doesn't contain any IDN, so +// this only tests the case where the subdomains are IDNs. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + TopDomainIdnSubdomain_NoMatch) { + TestInterstitialNotShown(browser(), GetURL("tést.google.com")); + CheckNoUkm(); + + // blogspot.com is a private registry, so the eTLD+1 of "tést.blogspot.com" is + // itself, instead of just "blogspot.com". This is different than + // tést.google.com whose eTLD+1 is google.com, and it should be handled + // correctly. + TestInterstitialNotShown(browser(), GetURL("tést.blogspot.com")); + CheckNoUkm(); +} + +// Schemes other than HTTP and HTTPS should be ignored. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + TopDomainChromeUrl_NoMatch) { + TestInterstitialNotShown(browser(), GURL("chrome://googlé.com")); + CheckNoUkm(); +} + +// Navigate to a domain within an edit distance of 1 to a top domain. +// This should record metrics. It should also show a lookalike warning +// interstitial if configured via a feature param. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + EditDistance_TopDomain_Match) { + base::HistogramTester histograms; + + // The skeleton of this domain, gooogle.corn, is one 1 edit away from + // google.corn, the skeleton of google.com. + const GURL kNavigatedUrl = GetURL("goooglé.com"); + const GURL kExpectedSuggestedUrl = GetURL("google.com"); + // Even if the navigated site has a low engagement score, it should be + // considered for lookalike suggestions. + SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); + + TestHistogramEventsRecordedAndInterstitialShown( + browser(), &histograms, kNavigatedUrl, kExpectedSuggestedUrl, + NavigationSuggestionEvent::kMatchEditDistance); + + CheckUkm({kNavigatedUrl}, + LookalikeUrlNavigationThrottle::MatchType::kEditDistance); +} + +// Tests negative examples for the edit distance. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + EditDistance_TopDomain_NoMatch) { + // Matches google.com.tr but only differs in registry. + TestInterstitialNotShown(browser(), GetURL("google.com.tw")); + CheckNoUkm(); + + // Matches bing.com but is a top domain itself. + TestInterstitialNotShown(browser(), GetURL("ning.com")); + CheckNoUkm(); + + // Matches ask.com but is too short. + TestInterstitialNotShown(browser(), GetURL("bsk.com")); + CheckNoUkm(); +} + +// Test that the heuristics aren't triggered on net errors. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + NetError_NoMatch) { + // Create a test server that returns invalid responses. + net::EmbeddedTestServer custom_test_server; + custom_test_server.RegisterRequestHandler( + base::BindRepeating(&NetworkErrorResponseHandler)); + ASSERT_TRUE(custom_test_server.Start()); + + // Matches google.com but page returns an invalid response. + TestInterstitialNotShown( + browser(), custom_test_server.GetURL("gooogle.com", "/title1.html")); + CheckNoUkm(); + + TestInterstitialNotShown( + browser(), custom_test_server.GetURL("googlé.com", "/title1.html")); + CheckNoUkm(); + + SetEngagementScore(browser(), GURL("http://site1.com"), kHighEngagement); + TestInterstitialNotShown( + browser(), custom_test_server.GetURL("sité1.com", "/title1.html")); + CheckNoUkm(); +} + +// Navigate to a domain whose visual representation looks like a domain with a +// site engagement score above a certain threshold. This should record metrics. +// It should also show lookalike warning interstitial if configured via +// a feature param. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + Idn_SiteEngagement_Match) { + const char* const kEngagedSites[] = { + "http://site1.com", "http://www.site2.com", "http://sité3.com", + "http://www.sité4.com"}; + + for (const char* const kSite : kEngagedSites) { + SetEngagementScore(browser(), GURL(kSite), kHighEngagement); + } + + std::vector<GURL> ukm_urls; + for (const auto& test_case : kSiteEngagementTestCases) { + base::HistogramTester histograms; + const GURL kNavigatedUrl = GetURL(test_case.navigated); + const GURL kExpectedSuggestedUrl = GetURL(test_case.suggested); + + // Even if the navigated site has a low engagement score, it should be + // considered for lookalike suggestions. + SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); + // Advance the clock to force LookalikeUrlService to fetch a new engaged + // site list. + test_clock()->Advance(base::TimeDelta::FromHours(1)); + + TestHistogramEventsRecordedAndInterstitialShown( + browser(), &histograms, kNavigatedUrl, kExpectedSuggestedUrl, + NavigationSuggestionEvent::kMatchSiteEngagement); + + ukm_urls.push_back(kNavigatedUrl); + CheckUkm(ukm_urls, + LookalikeUrlNavigationThrottle::MatchType::kSiteEngagement); + } +} + +// Similar to Idn_SiteEngagement_Match, but tests a single domain. Also checks +// that the list of engaged sites in incognito and the main profile don't affect +// each other. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + Idn_SiteEngagement_Match_Incognito) { + const GURL kNavigatedUrl = GetURL("sité1.com"); + const GURL kEngagedUrl = GetURL("site1.com"); + + // Set high engagement scores in the main profile and low engagement scores + // in incognito. Main profile should record metrics, incognito shouldn't. + Browser* incognito = CreateIncognitoBrowser(); + LookalikeUrlService::Get(incognito->profile()) + ->SetClockForTesting(test_clock()); + SetEngagementScore(browser(), kEngagedUrl, kHighEngagement); + SetEngagementScore(incognito, kEngagedUrl, kLowEngagement); + + std::vector<GURL> ukm_urls; + // Main profile should record metrics because there are engaged sites. + { + base::HistogramTester histograms; + // Advance the clock to force LookalikeUrlService to fetch a new engaged + // site list. + test_clock()->Advance(base::TimeDelta::FromHours(1)); + TestHistogramEventsRecordedAndInterstitialShown( + browser(), &histograms, kNavigatedUrl, kEngagedUrl, + NavigationSuggestionEvent::kMatchSiteEngagement); + + ukm_urls.push_back(kNavigatedUrl); + CheckUkm(ukm_urls, + LookalikeUrlNavigationThrottle::MatchType::kSiteEngagement); + } + + // Incognito shouldn't record metrics because there are no engaged sites. + { + base::HistogramTester histograms; + test_clock()->Advance(base::TimeDelta::FromHours(1)); + TestInterstitialNotShown(incognito, kNavigatedUrl); + histograms.ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName, + 0); + } + + // Now reverse the scores: Set low engagement in the main profile and high + // engagement in incognito. + SetEngagementScore(browser(), kEngagedUrl, kLowEngagement); + SetEngagementScore(incognito, kEngagedUrl, kHighEngagement); + + // Incognito should start recording metrics and main profile should stop. + { + base::HistogramTester histograms; + test_clock()->Advance(base::TimeDelta::FromHours(1)); + + TestHistogramEventsRecordedAndInterstitialShown( + incognito, &histograms, kNavigatedUrl, kEngagedUrl, + NavigationSuggestionEvent::kMatchSiteEngagement); + ukm_urls.push_back(kNavigatedUrl); + CheckUkm(ukm_urls, + LookalikeUrlNavigationThrottle::MatchType::kSiteEngagement); + } + + // Main profile shouldn't record metrics because there are no engaged sites. + { + base::HistogramTester histograms; + test_clock()->Advance(base::TimeDelta::FromHours(1)); + TestInterstitialNotShown(browser(), kNavigatedUrl); + histograms.ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName, + 0); + } +} + +// Test that navigations to a site with a high engagement score shouldn't +// record metrics or show interstitial. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + Idn_SiteEngagement_Match_IgnoreHighlyEngagedSite) { + base::HistogramTester histograms; + SetEngagementScore(browser(), GURL("http://site-not-in-top-domain-list.com"), + kHighEngagement); + const GURL high_engagement_url = GetURL("síte-not-ín-top-domaín-líst.com"); + SetEngagementScore(browser(), high_engagement_url, kHighEngagement); + TestInterstitialNotShown(browser(), high_engagement_url); + histograms.ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName, + 0); +} + +// Test that an engaged site with a scheme other than HTTP or HTTPS should be +// ignored. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + Idn_SiteEngagement_IgnoreChromeUrl) { + base::HistogramTester histograms; + SetEngagementScore(browser(), + GURL("chrome://site-not-in-top-domain-list.com"), + kHighEngagement); + const GURL low_engagement_url("http://síte-not-ín-top-domaín-líst.com"); + SetEngagementScore(browser(), low_engagement_url, kLowEngagement); + TestInterstitialNotShown(browser(), low_engagement_url); + histograms.ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName, + 0); +} + +// IDNs with a single label should be properly handled. There are two cases +// where this might occur: +// 1. The navigated URL is an IDN with a single label. +// 2. One of the engaged sites is an IDN with a single label. +// Neither of these should cause a crash. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + IdnWithSingleLabelShouldNotCauseACrash) { + base::HistogramTester histograms; + + // Case 1: Navigating to an IDN with a single label shouldn't cause a crash. + TestInterstitialNotShown(browser(), GetURL("é")); + + // Case 2: An IDN with a single label with a site engagement score shouldn't + // cause a crash. + SetEngagementScore(browser(), GURL("http://tést"), kHighEngagement); + TestInterstitialNotShown(browser(), GetURL("tést.com")); + + histograms.ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName, + 0); + CheckNoUkm(); +} + +// Ensure that dismissing the interstitial works, and the result is remembered +// in the current tab. This should record metrics on the first visit, but not +// the second. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + Interstitial_Dismiss) { + base::HistogramTester histograms; + + const GURL kNavigatedUrl = GetURL("goooglé.com"); + SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); + + TestHistogramEventsRecordedWhenInterstitialIgnored( + browser(), &histograms, kNavigatedUrl, + NavigationSuggestionEvent::kMatchEditDistance); + + CheckUkm({kNavigatedUrl}, + LookalikeUrlNavigationThrottle::MatchType::kEditDistance); +} + +// Navigate to lookalike domains that redirect to benign domains. Ensure that +// we display an interstitial along the way if configured via a feature param. +IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, + Interstitial_CapturesRedirects) { + { + // Verify it works when the lookalike domain is the first in the chain + const GURL kNavigatedUrl = + GetLongRedirect("goooglé.com", "example.net", "example.com"); + SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); + TestOnlyInterstitialShown(browser(), kNavigatedUrl); + } + { + // ...or when it's later in the chain + const GURL kNavigatedUrl = + GetLongRedirect("example.net", "goooglé.com", "example.com"); + SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement); + TestOnlyInterstitialShown(browser(), kNavigatedUrl); + } +}
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_observer_unittest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_unittest.cc similarity index 89% rename from chrome/browser/lookalikes/lookalike_url_navigation_observer_unittest.cc rename to chrome/browser/lookalikes/lookalike_url_navigation_throttle_unittest.cc index 4308806..32d9263a 100644 --- a/chrome/browser/lookalikes/lookalike_url_navigation_observer_unittest.cc +++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_unittest.cc
@@ -2,12 +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/lookalikes/lookalike_url_navigation_observer.h" +#include "chrome/browser/lookalikes/lookalike_url_navigation_throttle.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" -TEST(LookalikeUrlNavigationObserverTest, IsEditDistanceAtMostOne) { +TEST(LookalikeUrlNavigationThrottleTest, IsEditDistanceAtMostOne) { const struct TestCase { const wchar_t* domain; const wchar_t* top_domain; @@ -59,7 +59,7 @@ {L"google.com", L"goooglé.com", false}, }; for (const TestCase& test_case : kTestCases) { - bool result = LookalikeUrlNavigationObserver::IsEditDistanceAtMostOne( + bool result = LookalikeUrlNavigationThrottle::IsEditDistanceAtMostOne( base::WideToUTF16(test_case.domain), base::WideToUTF16(test_case.top_domain)); EXPECT_EQ(test_case.expected, result);
diff --git a/chrome/browser/lookalikes/lookalike_url_service.cc b/chrome/browser/lookalikes/lookalike_url_service.cc index 8acd77f..e157ebef 100644 --- a/chrome/browser/lookalikes/lookalike_url_service.cc +++ b/chrome/browser/lookalikes/lookalike_url_service.cc
@@ -77,20 +77,20 @@ return LookalikeUrlServiceFactory::GetForProfile(profile); } -void LookalikeUrlService::GetEngagedSites(EngagedSitesCallback callback) { +bool LookalikeUrlService::UpdateEngagedSites(EngagedSitesCallback callback) { const base::Time now = clock_->Now(); if (!last_engagement_fetch_time_.is_null()) { const base::TimeDelta elapsed = now - last_engagement_fetch_time_; if (elapsed < base::TimeDelta::FromSeconds(kEngagedSiteUpdateIntervalInSeconds)) { - std::move(callback).Run(engaged_sites_); - return; + return false; } } + base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, - {base::TaskPriority::BEST_EFFORT, + {base::TaskPriority::USER_BLOCKING, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::BindOnce( &SiteEngagementService::GetAllDetailsInBackground, now, @@ -98,17 +98,17 @@ HostContentSettingsMapFactory::GetForProfile(profile_))), base::BindOnce(&LookalikeUrlService::OnFetchEngagedSites, weak_factory_.GetWeakPtr(), std::move(callback))); + return true; +} + +const std::set<GURL> LookalikeUrlService::GetLatestEngagedSites() const { + return engaged_sites_; } void LookalikeUrlService::SetClockForTesting(base::Clock* clock) { clock_ = clock; } -void LookalikeUrlService::ClearEngagedSitesForTesting() { - engaged_sites_.clear(); - last_engagement_fetch_time_ = clock_->Now(); -} - void LookalikeUrlService::OnFetchEngagedSites( EngagedSitesCallback callback, std::vector<mojom::SiteEngagementDetails> details) { @@ -120,7 +120,7 @@ blink::mojom::EngagementLevel::MEDIUM)) { continue; } - engaged_sites_.push_back(detail.origin); + engaged_sites_.insert(detail.origin); } last_engagement_fetch_time_ = clock_->Now();
diff --git a/chrome/browser/lookalikes/lookalike_url_service.h b/chrome/browser/lookalikes/lookalike_url_service.h index 6a6fcfe..ca2d29d 100644 --- a/chrome/browser/lookalikes/lookalike_url_service.h +++ b/chrome/browser/lookalikes/lookalike_url_service.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_LOOKALIKES_LOOKALIKE_URL_SERVICE_H_ #define CHROME_BROWSER_LOOKALIKES_LOOKALIKE_URL_SERVICE_H_ +#include <set> #include <vector> #include "base/callback_forward.h" @@ -30,19 +31,22 @@ explicit LookalikeUrlService(Profile* profile); ~LookalikeUrlService() override; - using EngagedSitesCallback = - base::OnceCallback<void(const std::vector<GURL>&)>; + using EngagedSitesCallback = base::OnceCallback<void(const std::set<GURL>&)>; static LookalikeUrlService* Get(Profile* profile); - // Triggers an update to engaged site list and passes the most recent result - // |callback|. The list is updated only after a certain amount of time passes - // after the last update. As a result, calling this method may or may not - // change the contents of engaged_sites, depending on the timing. - void GetEngagedSites(EngagedSitesCallback callback); + // Checks whether the engaged site list is recently updated, and triggers + // an update to the list if not. This method will not update the contents of + // engaged_sites nor call |callback| if an update is not required. The method + // returns whether or not an update was triggered (and thus whether the + // callback will be called). + bool UpdateEngagedSites(EngagedSitesCallback callback); + + // Returns the _current_ list of engaged sites, without updating them if + // they're out of date. + const std::set<GURL> GetLatestEngagedSites() const; void SetClockForTesting(base::Clock* clock); - void ClearEngagedSitesForTesting(); private: void OnFetchEngagedSites(EngagedSitesCallback callback, @@ -51,7 +55,7 @@ Profile* profile_; base::Clock* clock_; base::Time last_engagement_fetch_time_; - std::vector<GURL> engaged_sites_; + std::set<GURL> engaged_sites_; base::WeakPtrFactory<LookalikeUrlService> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LookalikeUrlService);
diff --git a/chrome/browser/media/offscreen_tab.cc b/chrome/browser/media/offscreen_tab.cc index 69ea13f..648f3d6 100644 --- a/chrome/browser/media/offscreen_tab.cc +++ b/chrome/browser/media/offscreen_tab.cc
@@ -245,7 +245,9 @@ callback.Run(false); } -bool OffscreenTab::HandleContextMenu(const content::ContextMenuParams& params) { +bool OffscreenTab::HandleContextMenu( + content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) { // Context menus should never be shown. Do nothing, but indicate the context // menu was shown so that default implementation in libcontent does not // attempt to do so on its own.
diff --git a/chrome/browser/media/offscreen_tab.h b/chrome/browser/media/offscreen_tab.h index 5dee093..acb56a4 100644 --- a/chrome/browser/media/offscreen_tab.h +++ b/chrome/browser/media/offscreen_tab.h
@@ -91,7 +91,8 @@ void CanDownload(const GURL& url, const std::string& request_method, const base::RepeatingCallback<void(bool)>& callback) final; - bool HandleContextMenu(const content::ContextMenuParams& params) final; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) final; content::KeyboardEventProcessingResult PreHandleKeyboardEvent( content::WebContents* source, const content::NativeWebKeyboardEvent& event) final;
diff --git a/chrome/browser/metrics/assistant_service_metrics_provider.cc b/chrome/browser/metrics/assistant_service_metrics_provider.cc index 5df7017..758c241 100644 --- a/chrome/browser/metrics/assistant_service_metrics_provider.cc +++ b/chrome/browser/metrics/assistant_service_metrics_provider.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/metrics/assistant_service_metrics_provider.h" #include "base/metrics/histogram_macros.h" -#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/profiles/profile_manager.h" #include "components/arc/arc_prefs.h" #include "components/prefs/pref_service.h" @@ -15,7 +15,7 @@ void AssistantServiceMetricsProvider::ProvideCurrentSessionData( metrics::ChromeUserMetricsExtension* uma_proto_unused) { - if (arc::IsAssistantAllowedForProfile( + if (assistant::IsAssistantAllowedForProfile( ProfileManager::GetActiveUserProfile()) != ash::mojom::AssistantAllowedState::ALLOWED) { return;
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc index 84aefa86..b8e0c70 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -30,6 +30,7 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "content/public/common/resource_load_info.mojom.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "services/network/public/cpp/features.h" #include "ui/base/page_transition_types.h" @@ -319,7 +320,7 @@ const content::mojom::CommonNetworkInfoPtr& network_info = resource_load_info.network_info; ExtraRequestCompleteInfo extra_request_complete_info( - resource_load_info.url, network_info->ip_port_pair.value(), + resource_load_info.url, network_info->remote_endpoint.value(), render_frame_host->GetFrameTreeNodeId(), resource_load_info.was_cached, resource_load_info.raw_body_bytes, original_content_length, std::move(data_reduction_proxy_data), resource_load_info.resource_type, @@ -353,7 +354,7 @@ void MetricsWebContentsObserver::OnRequestComplete( const GURL& url, - const net::HostPortPair& host_port_pair, + const net::IPEndPoint& remote_endpoint, int frame_tree_node_id, const content::GlobalRequestID& request_id, content::RenderFrameHost* render_frame_host_or_null, @@ -376,7 +377,7 @@ request_id, render_frame_host_or_null, resource_type, creation_time); if (tracker) { ExtraRequestCompleteInfo extra_request_complete_info( - url, host_port_pair, frame_tree_node_id, was_cached, raw_body_bytes, + url, remote_endpoint, frame_tree_node_id, was_cached, raw_body_bytes, was_cached ? 0 : original_content_length, std::move(data_reduction_proxy_data), resource_type, net_error, std::move(load_timing_info));
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h index 15021396..ba06b973 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -24,6 +24,10 @@ #include "content/public/common/resource_type.h" #include "third_party/blink/public/platform/web_input_event.h" +namespace net { +class IPEndPoint; +} // namespace net + namespace content { class NavigationHandle; class RenderFrameHost; @@ -126,7 +130,7 @@ // frame requests when browser-side navigation is enabled. void OnRequestComplete( const GURL& url, - const net::HostPortPair& host_port_pair, + const net::IPEndPoint& remote_endpoint, int frame_tree_node_id, const content::GlobalRequestID& request_id, content::RenderFrameHost* render_frame_host_or_null,
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc index 9b51a90..85c286b 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
@@ -26,6 +26,7 @@ #include "content/public/test/test_renderer_host.h" #include "content/public/test/web_contents_tester.h" #include "extensions/buildflags/buildflags.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -1467,7 +1468,7 @@ const auto request_id = navigation_simulator->GetGlobalRequestID(); observer()->OnRequestComplete( - main_resource_url, net::HostPortPair(), frame_tree_node_id, request_id, + main_resource_url, net::IPEndPoint(), frame_tree_node_id, request_id, web_contents()->GetMainFrame(), content::ResourceType::RESOURCE_TYPE_MAIN_FRAME, false, nullptr, 0, 0, base::TimeTicks::Now(), net::OK, nullptr); @@ -1479,7 +1480,7 @@ // Deliver a second main frame resource. This one should be ignored, since the // specified |request_id| is no longer associated with any tracked page loads. observer()->OnRequestComplete( - main_resource_url, net::HostPortPair(), frame_tree_node_id, request_id, + main_resource_url, net::IPEndPoint(), frame_tree_node_id, request_id, web_contents()->GetMainFrame(), content::ResourceType::RESOURCE_TYPE_MAIN_FRAME, false, nullptr, 0, 0, base::TimeTicks::Now(), net::OK, nullptr); @@ -1493,7 +1494,7 @@ web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); GURL loaded_resource_url("http://www.other.com/"); observer()->OnRequestComplete( - loaded_resource_url, net::HostPortPair(), + loaded_resource_url, net::IPEndPoint(), web_contents()->GetMainFrame()->GetFrameTreeNodeId(), content::GlobalRequestID(), web_contents()->GetMainFrame(), content::RESOURCE_TYPE_SCRIPT, false, nullptr, 0, 0, @@ -1519,7 +1520,7 @@ content::WebContentsTester::CreateTestWebContents(browser_context(), nullptr)); observer()->OnRequestComplete( - GURL("http://www.other.com/"), net::HostPortPair(), + GURL("http://www.other.com/"), net::IPEndPoint(), other_web_contents->GetMainFrame()->GetFrameTreeNodeId(), content::GlobalRequestID(), other_web_contents->GetMainFrame(), content::RESOURCE_TYPE_SCRIPT, false, nullptr, 0, 0, @@ -1535,7 +1536,7 @@ web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); GURL loaded_resource_url("data:text/html,Hello world"); observer()->OnRequestComplete( - loaded_resource_url, net::HostPortPair(), + loaded_resource_url, net::IPEndPoint(), web_contents()->GetMainFrame()->GetFrameTreeNodeId(), content::GlobalRequestID(), web_contents()->GetMainFrame(), content::RESOURCE_TYPE_SCRIPT, false, nullptr, 0, 0,
diff --git a/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer_unittest.cc index 1240a0b1..594f0fcc 100644 --- a/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h" #include "content/public/browser/web_contents.h" #include "content/public/test/navigation_simulator.h" +#include "net/base/ip_endpoint.h" #include "services/network/public/cpp/network_quality_tracker.h" #include "testing/gmock/include/gmock/gmock.h" @@ -194,7 +195,7 @@ const base::TimeTicks kNow = base::TimeTicks::Now(); load_timing_info->connect_timing.dns_start = kNow; page_load_metrics::ExtraRequestCompleteInfo info( - GURL("https://ignored.com"), net::HostPortPair(), frame_tree_node_id, + GURL("https://ignored.com"), net::IPEndPoint(), frame_tree_node_id, false, /* cached */ 10 * 1024 /* size */, 0 /* original_network_content_length */, nullptr
diff --git a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_base_unittest.cc b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_base_unittest.cc index 59d41aa..6911881c 100644 --- a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_base_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_base_unittest.cc
@@ -27,6 +27,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/previews/content/previews_user_data.h" #include "content/public/test/web_contents_tester.h" +#include "net/base/ip_endpoint.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" #include "third_party/blink/public/platform/web_input_event.h" @@ -179,7 +180,7 @@ // Verify LoFi is tracked when a LoFi response is received. page_load_metrics::ExtraRequestCompleteInfo resource = { GURL(kResourceUrl), - net::HostPortPair(), + net::IPEndPoint(), -1 /* frame_tree_node_id */, true /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
diff --git a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc index c931b48..55c569e4 100644 --- a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc
@@ -8,8 +8,7 @@ #include "base/metrics/histogram_macros.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/page_load_metrics/page_load_metrics_util.h" -#include "net/base/host_port_pair.h" -#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/url_util.h" #include "services/metrics/public/cpp/ukm_builders.h" @@ -105,7 +104,7 @@ } // Attempts to get the IP address of a resource request from -// |extra_request_info.host_port_pair|, trying to get it from the URL string in +// |extra_request_info.remote_endpoint|, trying to get it from the URL string in // |extra_request_info.url| if that fails. // Sets the values of |resource_ip| and |port| with the extracted IP address and // port, respectively. @@ -116,9 +115,9 @@ int* resource_port) { // If the request was successful, then the IP address should be in // |extra_request_info|. - bool ip_exists = net::ParseURLHostnameToAddress( - extra_request_info.host_port_pair.host(), resource_ip); - *resource_port = extra_request_info.host_port_pair.port(); + bool ip_exists = extra_request_info.remote_endpoint.address().IsValid(); + *resource_ip = extra_request_info.remote_endpoint.address(); + *resource_port = extra_request_info.remote_endpoint.port(); // If the request failed, it's possible we didn't receive the IP address, // possibly because domain resolution failed. As a backup, try getting the IP @@ -307,22 +306,17 @@ ukm::SourceId source_id) { // Upon page load, we want to determine whether the page loaded was a public // domain or private domain and generate an event describing the domain type. - net::HostPortPair address = navigation_handle->GetSocketAddress(); + net::IPEndPoint remote_endpoint = navigation_handle->GetSocketAddress(); + page_ip_address_ = remote_endpoint.address(); // In cases where the page loaded does not have a socket address or was not a // network resource, we don't want to track the page load. Such resources will // fail to parse or return an empty IP address. - if (!net::ParseURLHostnameToAddress(address.host(), &page_ip_address_) || - page_ip_address_.IsZero()) { + if (!page_ip_address_.IsValid()) { return STOP_OBSERVING; } - // |HostStringIsLocalhost| assumes (and doesn't verify) that any IPv6 host - // passed to it does not have square brackets around it, but - // |HostPortPair::host| retains the brackets, so we need to separately check - // for IPv6 localhost here. - if (net::HostStringIsLocalhost(address.host()) || - page_ip_address_ == net::IPAddress::IPv6Localhost()) { + if (page_ip_address_.IsLoopback()) { page_domain_type_ = internal::DOMAIN_TYPE_LOCALHOST; } else if (!page_ip_address_.IsPubliclyRoutable()) { page_domain_type_ = internal::DOMAIN_TYPE_PRIVATE; @@ -377,7 +371,7 @@ // We can't track anything if we don't have an IP address for the resource. // We also don't want to track any requests to the page's IP address itself. if (!GetIPAndPort(extra_request_info, &resource_ip, &resource_port) || - resource_ip.IsZero() || resource_ip == page_ip_address_) { + !resource_ip.IsValid() || resource_ip == page_ip_address_) { return; }
diff --git a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc index 256fcbd..0dfc3116 100644 --- a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc
@@ -14,8 +14,7 @@ #include "content/public/browser/global_request_id.h" #include "content/public/common/resource_type.h" #include "content/public/test/navigation_simulator.h" -#include "net/base/host_port_pair.h" -#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_source.h" @@ -38,10 +37,10 @@ static const PageAddressInfo kPublicPage = {(char*)"https://foo.com/", (char*)"216.58.195.78", 443}, kPublicPageIPv6 = {(char*)"https://google.com/", - (char*)"[2607:f8b0:4005:809::200e]", 443}, + (char*)"2607:f8b0:4005:809::200e", 443}, kPrivatePage = {(char*)"http://test.local/", (char*)"192.168.10.123", 80}, kLocalhostPage = {(char*)"http://localhost/", (char*)"127.0.0.1", 80}, - kLocalhostPageIPv6 = {(char*)"http://[::1]/", (char*)"[::1]", 80}, + kLocalhostPageIPv6 = {(char*)"http://[::1]/", (char*)"::1", 80}, kPublicRequest1 = {(char*)"http://bar.com/", (char*)"100.150.200.250", 80}, kPublicRequest2 = {(char*)"https://www.baz.com/", (char*)"192.10.20.30", 443}, @@ -89,12 +88,14 @@ void SimulateNavigateAndCommit(const internal::PageAddressInfo& page) { GURL url(page.url); - net::HostPortPair socket_address(page.host_ip, page.port); + net::IPAddress address; + ASSERT_TRUE(address.AssignFromIPLiteral(page.host_ip)); + net::IPEndPoint remote_endpoint(address, page.port); navigation_simulator_ = content::NavigationSimulator::CreateRendererInitiated(url, main_rfh()); navigation_simulator_->Start(); - navigation_simulator_->SetSocketAddress(socket_address); + navigation_simulator_->SetSocketAddress(remote_endpoint); navigation_simulator_->Commit(); } @@ -109,8 +110,10 @@ void SimulateLoadedResource(const internal::PageAddressInfo& resource, const int net_error) { + net::IPAddress address; + ASSERT_TRUE(address.AssignFromIPLiteral(resource.host_ip)); page_load_metrics::ExtraRequestCompleteInfo request_info( - GURL(resource.url), net::HostPortPair(resource.host_ip, resource.port), + GURL(resource.url), net::IPEndPoint(address, resource.port), -1 /* frame_tree_node_id */, !net_error /* was_cached */, (net_error ? 1024 * 20 : 0) /* raw_body_bytes */, 0 /* original_network_content_length */, @@ -775,7 +778,7 @@ // Load a resource that has the IP address in the URL but returned an empty // socket address for some reason. PageLoadMetricsObserverTestHarness::SimulateLoadedResource( - {GURL(internal::kDiffSubnetRequest2.url), net::HostPortPair(), + {GURL(internal::kDiffSubnetRequest2.url), net::IPEndPoint(), -1 /* frame_tree_node_id */, true /* was_cached */, 1024 * 20 /* raw_body_bytes */, 0 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, @@ -803,7 +806,7 @@ // Load a resource that doesn't have the IP address in the URL and returned an // empty socket address (e.g., failed DNS resolution). PageLoadMetricsObserverTestHarness::SimulateLoadedResource( - {GURL(internal::kPrivatePage.url), net::HostPortPair(), + {GURL(internal::kPrivatePage.url), net::IPEndPoint(), -1 /* frame_tree_node_id */, false /* was_cached */, 0 /* raw_body_bytes */, 0 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */,
diff --git a/chrome/browser/page_load_metrics/observers/lofi_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/lofi_page_load_metrics_observer_unittest.cc index cd79f4a1..ebb2a7e0 100644 --- a/chrome/browser/page_load_metrics/observers/lofi_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/lofi_page_load_metrics_observer_unittest.cc
@@ -17,6 +17,7 @@ #include "chrome/common/page_load_metrics/page_load_timing.h" #include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" +#include "net/base/ip_endpoint.h" namespace data_reduction_proxy { @@ -136,26 +137,26 @@ // LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { // Cached request. - {GURL(kResourceUrl), net::HostPortPair(), -1, true /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, true /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 0 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, content::ResourceType::RESOURCE_TYPE_SCRIPT, 0, nullptr /* load_timing_info */}, // Uncached non-proxied request. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .1 compression ratio. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 10 /* original_network_content_length */, data->DeepCopy(), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .5 compression ratio. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, @@ -200,26 +201,26 @@ // client LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { // Cached request. - {GURL(kResourceUrl), net::HostPortPair(), -1, true /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, true /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 0 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, content::ResourceType::RESOURCE_TYPE_SCRIPT, 0, nullptr /* load_timing_info */}, // Uncached non-proxied request. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .1 compression ratio. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 10 /* original_network_content_length */, data->DeepCopy(), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .5 compression ratio. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, @@ -265,26 +266,26 @@ // server LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { // Cached request. - {GURL(kResourceUrl), net::HostPortPair(), -1, true /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, true /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 0 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, content::ResourceType::RESOURCE_TYPE_SCRIPT, 0, nullptr /* load_timing_info */}, // Uncached non-proxied request. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .1 compression ratio. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 10 /* original_network_content_length */, data->DeepCopy(), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .5 compression ratio. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, @@ -335,26 +336,26 @@ // 1 has Server LoFi. page_load_metrics::ExtraRequestCompleteInfo resources[] = { // Cached request. - {GURL(kResourceUrl), net::HostPortPair(), -1, true /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, true /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 0 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, content::ResourceType::RESOURCE_TYPE_SCRIPT, 0, nullptr /* load_timing_info */}, // Uncached non-proxied request. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .1 compression ratio. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 10 /* original_network_content_length */, std::move(data1), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .5 compression ratio. - {GURL(kResourceUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kResourceUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data2), content::ResourceType::RESOURCE_TYPE_IMAGE, 0,
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc index d8bba72d..93a5d04 100644 --- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc +++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
@@ -17,6 +17,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/resource_type.h" +#include "net/base/ip_endpoint.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/web_input_event.h" #include "url/gurl.h" @@ -156,7 +157,7 @@ : web_contents()->GetMainFrame(); observer_->OnRequestComplete( - info.url, info.host_port_pair, info.frame_tree_node_id, request_id, + info.url, info.remote_endpoint, info.frame_tree_node_id, request_id, render_frame_host_or_null, info.resource_type, info.was_cached, info.data_reduction_proxy_data ? info.data_reduction_proxy_data->DeepCopy()
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc index b6700cf4..9cd408a2 100644 --- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
@@ -21,6 +21,7 @@ #include "components/ukm/test_ukm_recorder.h" #include "content/public/common/previews_state.h" #include "content/public/test/web_contents_tester.h" +#include "net/base/ip_endpoint.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_source.h" @@ -570,13 +571,13 @@ // Prepare 3 resources of varying size and configurations, 2 of which have // client LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached non-proxied request. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, @@ -619,13 +620,13 @@ // Prepare 3 resources of varying size and configurations, 2 of which have // client LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached non-proxied request. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, @@ -667,13 +668,13 @@ // Prepare 3 resources of varying size and configurations, 2 of which have // client LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached non-proxied request. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, @@ -711,12 +712,12 @@ // Prepare 3 resources of varying size and configurations, 2 of which have // client LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, @@ -760,12 +761,12 @@ // Prepare 3 resources of varying size and configurations, 2 of which have // client LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, @@ -809,12 +810,12 @@ // Prepare 3 resources of varying size and configurations, 2 of which have // client LoFi set. page_load_metrics::ExtraRequestCompleteInfo resources[] = { - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 /* original_network_content_length */, nullptr /* data_reduction_proxy_data */, @@ -859,13 +860,13 @@ // 1 has Server LoFi. page_load_metrics::ExtraRequestCompleteInfo resources[] = { // Uncached proxied request with .1 compression ratio. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 10 /* original_network_content_length */, std::move(data1), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .5 compression ratio. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data2), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, @@ -913,13 +914,13 @@ // 1 has Server LoFi. page_load_metrics::ExtraRequestCompleteInfo resources[] = { // Uncached proxied request with .1 compression ratio. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 10 /* original_network_content_length */, std::move(data1), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .5 compression ratio. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data2), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, @@ -966,13 +967,13 @@ // 1 has Server LoFi. page_load_metrics::ExtraRequestCompleteInfo resources[] = { // Uncached proxied request with .1 compression ratio. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 10 /* original_network_content_length */, std::move(data1), content::ResourceType::RESOURCE_TYPE_IMAGE, 0, nullptr /* load_timing_info */}, // Uncached proxied request with .5 compression ratio. - {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/, + {GURL(kDefaultTestUrl), net::IPEndPoint(), -1, false /*was_cached*/, 1024 * 40 /* raw_body_bytes */, 1024 * 40 * 5 /* original_network_content_length */, std::move(data2), content::ResourceType::RESOURCE_TYPE_IMAGE, 0,
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc index cae25b0..3570b6ed 100644 --- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
@@ -16,6 +16,7 @@ #include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h" #include "content/public/browser/web_contents.h" #include "content/public/test/navigation_simulator.h" +#include "net/base/ip_endpoint.h" #include "net/nqe/effective_connection_type.h" #include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" @@ -822,7 +823,7 @@ page_load_metrics::ExtraRequestCompleteInfo resources[] = { // Cached request. {GURL(kResourceUrl), - net::HostPortPair(), + net::IPEndPoint(), -1 /* frame_tree_node_id */, true /* was_cached */, 1024 * 20 /* raw_body_bytes */, @@ -833,7 +834,7 @@ {} /* load_timing_info */}, // Uncached non-proxied request. {GURL(kResourceUrl), - net::HostPortPair(), + net::IPEndPoint(), -1 /* frame_tree_node_id */, false /* was_cached */, 1024 * 40 /* raw_body_bytes */,
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/page_load_metrics_observer.cc index 5f08cd3..20817fb 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.cc
@@ -63,7 +63,7 @@ ExtraRequestCompleteInfo::ExtraRequestCompleteInfo( const GURL& url, - const net::HostPortPair& host_port_pair, + const net::IPEndPoint& remote_endpoint, int frame_tree_node_id, bool was_cached, int64_t raw_body_bytes, @@ -74,7 +74,7 @@ int net_error, std::unique_ptr<net::LoadTimingInfo> load_timing_info) : url(url), - host_port_pair(host_port_pair), + remote_endpoint(remote_endpoint), frame_tree_node_id(frame_tree_node_id), was_cached(was_cached), raw_body_bytes(raw_body_bytes), @@ -87,7 +87,7 @@ ExtraRequestCompleteInfo::ExtraRequestCompleteInfo( const ExtraRequestCompleteInfo& other) : url(other.url), - host_port_pair(other.host_port_pair), + remote_endpoint(other.remote_endpoint), frame_tree_node_id(other.frame_tree_node_id), was_cached(other.was_cached), raw_body_bytes(other.raw_body_bytes),
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h index fc8f72e..8fafe0d 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -16,6 +16,7 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/common/resource_type.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "services/metrics/public/cpp/ukm_source.h" #include "third_party/blink/public/platform/web_input_event.h" #include "url/gurl.h" @@ -225,7 +226,7 @@ struct ExtraRequestCompleteInfo { ExtraRequestCompleteInfo( const GURL& url, - const net::HostPortPair& host_port_pair, + const net::IPEndPoint& remote_endpoint, int frame_tree_node_id, bool was_cached, int64_t raw_body_bytes, @@ -244,7 +245,7 @@ const GURL url; // The host (IP address) and port for the request. - const net::HostPortPair host_port_pair; + const net::IPEndPoint remote_endpoint; // The frame tree node id that initiated the request. const int frame_tree_node_id;
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index d193b20..3a14537 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -286,6 +286,7 @@ #include "chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" +#include "chromeos/assistant/buildflags.h" #include "chromeos/audio/audio_devices_pref_handler_impl.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/network/fast_transition_observer.h" @@ -297,6 +298,11 @@ #include "components/onc/onc_pref_names.h" #include "components/quirks/quirks_manager.h" #include "extensions/browser/api/lock_screen_data/lock_screen_item_storage.h" + +#if BUILDFLAG(ENABLE_CROS_ASSISTANT) +#include "chrome/browser/ui/ash/assistant/assistant_pref_util.h" +#endif + #else #include "chrome/browser/extensions/default_apps.h" #endif @@ -394,6 +400,10 @@ const char kNextUpdateCheck[] = "extensions.autoupdate.next_check"; const char kLastUpdateCheck[] = "extensions.autoupdate.last_check"; +// Deprecated 2/2019. +const char kVoiceInteractionActivityControlAcceptedDeprecated[] = + "settings.voice_interaction.activity_control.accepted"; + // Register prefs used only for migration (clearing or moving to a new key). void RegisterProfilePrefsForMigration( user_prefs::PrefRegistrySyncable* registry) { @@ -423,6 +433,9 @@ PrefRegistry::LOSSY_PREF); registry->RegisterIntegerPref(kLastUpdateCheck, 0); registry->RegisterIntegerPref(kNextUpdateCheck, 0); + + registry->RegisterBooleanPref( + kVoiceInteractionActivityControlAcceptedDeprecated, false); } } // namespace @@ -760,6 +773,11 @@ policy::AppInstallEventLogManagerWrapper::RegisterProfilePrefs(registry); policy::DeviceStatusCollector::RegisterProfilePrefs(registry); ::onc::RegisterProfilePrefs(registry); + +#if BUILDFLAG(ENABLE_CROS_ASSISTANT) + assistant::prefs::RegisterProfilePrefs(registry); +#endif + #endif #if defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_APP_LIST) @@ -834,6 +852,29 @@ void RegisterLoginProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { RegisterProfilePrefs(registry); } + +#if BUILDFLAG(ENABLE_CROS_ASSISTANT) + +bool MigrateVoiceInteractionActivityControlAccepted( + PrefService* profile_prefs) { + const base::Value* activity_control_accepted = + profile_prefs->GetUserPrefValue( + kVoiceInteractionActivityControlAcceptedDeprecated); + + if (!activity_control_accepted) + return false; + + ash::mojom::ConsentStatus consent_status = + activity_control_accepted->GetBool() + ? ash::mojom::ConsentStatus::kActivityControlAccepted + : ash::mojom::ConsentStatus::kUnknown; + + assistant::prefs::SetConsentStatus(profile_prefs, consent_status); + return true; +} + +#endif + #endif // This method should be periodically pruned of year+ old migrations. @@ -908,11 +949,21 @@ #if defined(OS_CHROMEOS) // Added 12/2018. profile_prefs->ClearPref(prefs::kDataSaverPromptsShown); + +#if BUILDFLAG(ENABLE_CROS_ASSISTANT) + // Added 2/2019. + if (MigrateVoiceInteractionActivityControlAccepted(profile_prefs)) { + profile_prefs->ClearPref( + kVoiceInteractionActivityControlAcceptedDeprecated); + } +#endif + #endif // Added 1/2019. profile_prefs->ClearPref(kLastUpdateCheck); profile_prefs->ClearPref(kNextUpdateCheck); + syncer::MigrateSessionsToProxyTabsPrefs(profile_prefs); syncer::ClearObsoleteUserTypePrefs(profile_prefs);
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn index df605581..b6707a26 100644 --- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -124,6 +124,7 @@ "cvox2/background/base_automation_handler.js", "cvox2/background/braille_command_data.js", "cvox2/background/braille_command_handler.js", + "cvox2/background/color.js", "cvox2/background/chromevox_state.js", "cvox2/background/command_handler.js", "cvox2/background/console_tts.js", @@ -618,6 +619,7 @@ "braille/liblouis_test.extjs", "cvox2/background/automation_util_test.extjs", "cvox2/background/background_test.extjs", + "cvox2/background/color_test.extjs", "cvox2/background/cursors_test.extjs", "cvox2/background/editing_test.extjs", "cvox2/background/i_search_test.extjs",
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json b/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json index 08eaef21..ddee7a20 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json
@@ -1005,6 +1005,15 @@ "keyCode": [79, 66] } } + }, + { + "command": "getRichTextDescription", + "sequence": { + "cvoxModifier": true, + "keys": { + "keyCode": [65, 70] + } + } } ] }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/color.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/color.js new file mode 100644 index 0000000..312c361c --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/color.js
@@ -0,0 +1,237 @@ +// Copyright 2019 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. + +/** + * @fileoverview Provides color matching services for ChromeVox. + */ + +goog.provide('Color'); + +/** + * Returns a string representation of a color. + * @param {number|undefined} color The argb value represented as an integer. + * @return {string} + */ +Color.getColorDescription = function(color) { + if (!color) + return ''; + // Convert to unsigned integer. + color = color >>> 0; + // The following 24 bits represent the rgb value. Filter out first 8 bits. + var rgb = color & 0x00ffffff; + var optSubs = + [Color.findClosestMatchingColor(rgb), Color.getOpacityPercentage(color)]; + return Msgs.getMsg('color_description', optSubs); +}; + +/** + * Extracts the opacity of the color, which is encoded within the first 8 bits. + * @param {number} color An integer representation of a color. + * @return {number} + */ +Color.getOpacityPercentage = function(color) { + return Math.round(((color >>> 24) / 256) * 100); +}; + +/** + * Finds the most similar stored color given an rgb value. + * @param {number} target The rgb value as an integer. + * @return {string} + */ +Color.findClosestMatchingColor = function(target) { + var bestMessageId; + var bestDistance = Number.MAX_VALUE; + + Color.ColorObjectArray.forEach(function(obj) { + var val = obj.value; + var distance = Color.findDistance(target, val); + if (distance < bestDistance) { + bestMessageId = obj.colorMessageId; + bestDistance = distance; + } + }); + // Do not report color if most similar color is too inaccurate. + if (bestDistance > Color.DISTANCE_THRESHOLD) + return ''; + return Msgs.getMsg(bestMessageId); +}; + +/** + * Calculates the distance between two 3-D points, encoded as numbers, + * that represent colors. + * The first 8 bits are unused as they have either been shifted off or are + * simply filled by zeros. The x component is designated by the second + * 8 bits. The y component is designated by the third 8 bits. + * The z component is designated by the last 8 bits. + * @param {number} firstColor + * @param {number} secondColor + * @return {number} + */ +Color.findDistance = function(firstColor, secondColor) { + // Extract x, y, and z components. + var firstColorX = (firstColor & 0xff0000) >> 16; + var firstColorY = (firstColor & 0x00ff00) >> 8; + var firstColorZ = (firstColor & 0x0000ff); + var secondColorX = (secondColor & 0xff0000) >> 16; + var secondColorY = (secondColor & 0x00ff00) >> 8; + var secondColorZ = (secondColor & 0x0000ff); + + return Math.pow(secondColorX - firstColorX, 2) + + Math.pow(secondColorY - firstColorY, 2) + + Math.pow(secondColorZ - firstColorZ, 2); +}; + +/** + * The distance between black and dark grey is the threshold. + * @const {number} + */ +Color.DISTANCE_THRESHOLD = Color.findDistance(0X000000, 0X181818); + +/** + * Holds objects that contain hexadecimal RGB values of colors and their + * corresponding ChromeVox message IDs. + * @private {!Array<{colorMessageId: string, value: number}>} + * Obtained from url: https://www.w3schools.com/lib/w3color.js + */ +Color.ColorObjectArray = [ + {'value': 0x0, 'colorMessageId': 'color_black'}, + {'value': 0x6400, 'colorMessageId': 'color_dark_green'}, + {'value': 0x8000, 'colorMessageId': 'color_green'}, + {'value': 0x800080, 'colorMessageId': 'color_purple'}, + {'value': 0xb8860b, 'colorMessageId': 'color_dark_golden_rod'}, + {'value': 0xfffacd, 'colorMessageId': 'color_lemon_chiffon'}, + {'value': 0xa0522d, 'colorMessageId': 'color_sienna'}, + {'value': 0xffa500, 'colorMessageId': 'color_orange'}, + {'value': 0x8b4513, 'colorMessageId': 'color_saddle_brown'}, + {'value': 0xffff, 'colorMessageId': 'color_cyan'}, + {'value': 0xadff2f, 'colorMessageId': 'color_green_yellow'}, + {'value': 0xd2691e, 'colorMessageId': 'color_chocolate'}, + {'value': 0x800000, 'colorMessageId': 'color_maroon'}, + {'value': 0xdaa520, 'colorMessageId': 'color_golden_rod'}, + {'value': 0x228b22, 'colorMessageId': 'color_forest_green'}, + {'value': 0x6b8e23, 'colorMessageId': 'color_olive_drab'}, + {'value': 0xfffff0, 'colorMessageId': 'color_ivory'}, + {'value': 0xf5f5dc, 'colorMessageId': 'color_beige'}, + {'value': 0xa52a2a, 'colorMessageId': 'color_brown'}, + {'value': 0x9acd32, 'colorMessageId': 'color_yellow_green'}, + {'value': 0xff4500, 'colorMessageId': 'color_orange_red'}, + {'value': 0x556b2f, 'colorMessageId': 'color_dark_olive_green'}, + {'value': 0x32cd32, 'colorMessageId': 'color_lime_green'}, + {'value': 0xff00, 'colorMessageId': 'color_lime'}, + {'value': 0xeee8aa, 'colorMessageId': 'color_pale_golden_rod'}, + {'value': 0xff69b4, 'colorMessageId': 'color_hot_pink'}, + {'value': 0xdc143c, 'colorMessageId': 'color_crimson'}, + {'value': 0xb0e0e6, 'colorMessageId': 'color_powder_blue'}, + {'value': 0x808000, 'colorMessageId': 'color_olive'}, + {'value': 0xffffe0, 'colorMessageId': 'color_light_yellow'}, + {'value': 0xfaf0e6, 'colorMessageId': 'color_linen'}, + {'value': 0x8b, 'colorMessageId': 'color_dark_blue'}, + {'value': 0xf8f8ff, 'colorMessageId': 'color_ghost_white'}, + {'value': 0xff6347, 'colorMessageId': 'color_tomato'}, + {'value': 0xf0e68c, 'colorMessageId': 'color_khaki'}, + {'value': 0x2f4f4f, 'colorMessageId': 'color_dark_slate_grey'}, + {'value': 0xff7f50, 'colorMessageId': 'color_coral'}, + {'value': 0xf5fffa, 'colorMessageId': 'color_mint_cream'}, + {'value': 0x8080, 'colorMessageId': 'color_teal'}, + {'value': 0x8b008b, 'colorMessageId': 'color_dark_magenta'}, + {'value': 0xffa07a, 'colorMessageId': 'color_light_salmon'}, + {'value': 0x2e8b57, 'colorMessageId': 'color_sea_green'}, + {'value': 0xff0000, 'colorMessageId': 'color_red'}, + {'value': 0xbc8f8f, 'colorMessageId': 'color_rosy_brown'}, + {'value': 0xcd5c5c, 'colorMessageId': 'color_indian_red'}, + {'value': 0xd3d3d3, 'colorMessageId': 'color_light_grey'}, + {'value': 0xf4a460, 'colorMessageId': 'color_sandy_brown'}, + {'value': 0x90ee90, 'colorMessageId': 'color_light_green'}, + {'value': 0xadd8e6, 'colorMessageId': 'color_light_blue'}, + {'value': 0xff8c00, 'colorMessageId': 'color_dark_orange'}, + {'value': 0x696969, 'colorMessageId': 'color_dim_grey'}, + {'value': 0xffebcd, 'colorMessageId': 'color_blanched_almond'}, + {'value': 0xbdb76b, 'colorMessageId': 'color_dark_khaki'}, + {'value': 0xff00ff, 'colorMessageId': 'color_magenta'}, + {'value': 0x191970, 'colorMessageId': 'color_midnight_blue'}, + {'value': 0x3cb371, 'colorMessageId': 'color_medium_sea_green'}, + {'value': 0xfa8072, 'colorMessageId': 'color_salmon'}, + {'value': 0xff1493, 'colorMessageId': 'color_deep_pink'}, + {'value': 0xe9967a, 'colorMessageId': 'color_dark_salmon'}, + {'value': 0xcd853f, 'colorMessageId': 'color_peru'}, + {'value': 0xff7f, 'colorMessageId': 'color_spring_green'}, + {'value': 0x80, 'colorMessageId': 'color_navy'}, + {'value': 0xf08080, 'colorMessageId': 'color_light_coral'}, + {'value': 0x4b0082, 'colorMessageId': 'color_indigo'}, + {'value': 0xffffff, 'colorMessageId': 'color_white'}, + {'value': 0xc71585, 'colorMessageId': 'color_medium_violet_red'}, + {'value': 0xdeb887, 'colorMessageId': 'color_burly_wood'}, + {'value': 0xe6e6fa, 'colorMessageId': 'color_lavender'}, + {'value': 0x483d8b, 'colorMessageId': 'color_dark_slate_blue'}, + {'value': 0xd2b48c, 'colorMessageId': 'color_tan'}, + {'value': 0x8fbc8f, 'colorMessageId': 'color_dark_sea_green'}, + {'value': 0x708090, 'colorMessageId': 'color_slate_grey'}, + {'value': 0xdb7093, 'colorMessageId': 'color_pale_violet_red'}, + {'value': 0xfff8dc, 'colorMessageId': 'color_cornsilk'}, + {'value': 0xafeeee, 'colorMessageId': 'color_pale_turquoise'}, + {'value': 0x778899, 'colorMessageId': 'color_light_slate_grey'}, + {'value': 0x98fb98, 'colorMessageId': 'color_pale_green'}, + {'value': 0x663399, 'colorMessageId': 'color_rebecca_purple'}, + {'value': 0xfa9a, 'colorMessageId': 'color_medium_spring_green'}, + {'value': 0xffc0cb, 'colorMessageId': 'color_pink'}, + {'value': 0x5f9ea0, 'colorMessageId': 'color_cadet_blue'}, + {'value': 0x808080, 'colorMessageId': 'color_grey'}, + {'value': 0xee82ee, 'colorMessageId': 'color_violet'}, + {'value': 0xa9a9a9, 'colorMessageId': 'color_dark_grey'}, + {'value': 0x20b2aa, 'colorMessageId': 'color_light_sea_green'}, + {'value': 0x8b8b, 'colorMessageId': 'color_dark_cyan'}, + {'value': 0xffdead, 'colorMessageId': 'color_navajo_white'}, + {'value': 0xf0f8ff, 'colorMessageId': 'color_alice_blue'}, + {'value': 0xfffaf0, 'colorMessageId': 'color_floral_white'}, + {'value': 0xffe4e1, 'colorMessageId': 'color_misty_rose'}, + {'value': 0xf5deb3, 'colorMessageId': 'color_wheat'}, + {'value': 0x4682b4, 'colorMessageId': 'color_steel_blue'}, + {'value': 0xffe4b5, 'colorMessageId': 'color_moccasin'}, + {'value': 0xffdab9, 'colorMessageId': 'color_peach_puff'}, + {'value': 0xffd700, 'colorMessageId': 'color_gold'}, + {'value': 0xfff0f5, 'colorMessageId': 'color_lavender_blush'}, + {'value': 0xc0c0c0, 'colorMessageId': 'color_silver'}, + {'value': 0xffb6c1, 'colorMessageId': 'color_light_pink'}, + {'value': 0xf0ffff, 'colorMessageId': 'color_azure'}, + {'value': 0xffe4c4, 'colorMessageId': 'color_bisque'}, + {'value': 0x9932cc, 'colorMessageId': 'color_dark_orchid'}, + {'value': 0xfdf5e6, 'colorMessageId': 'color_old_lace'}, + {'value': 0x48d1cc, 'colorMessageId': 'color_medium_turquoise'}, + {'value': 0x6a5acd, 'colorMessageId': 'color_slate_blue'}, + {'value': 0xcd, 'colorMessageId': 'color_medium_blue'}, + {'value': 0x40e0d0, 'colorMessageId': 'color_turquoise'}, + {'value': 0xced1, 'colorMessageId': 'color_dark_turquoise'}, + {'value': 0xfafad2, 'colorMessageId': 'color_light_golden_rod_yellow'}, + {'value': 0x9400d3, 'colorMessageId': 'color_dark_violet'}, + {'value': 0x7fffd4, 'colorMessageId': 'color_aquamarine'}, + {'value': 0xffefd5, 'colorMessageId': 'color_papaya_whip'}, + {'value': 0xda70d6, 'colorMessageId': 'color_orchid'}, + {'value': 0xfaebd7, 'colorMessageId': 'color_antique_white'}, + {'value': 0xd8bfd8, 'colorMessageId': 'color_thistle'}, + {'value': 0x9370db, 'colorMessageId': 'color_medium_purple'}, + {'value': 0xdcdcdc, 'colorMessageId': 'color_gainsboro'}, + {'value': 0xdda0dd, 'colorMessageId': 'color_plum'}, + {'value': 0xb0c4de, 'colorMessageId': 'color_light_steel_blue'}, + {'value': 0x8b0000, 'colorMessageId': 'color_dark_red'}, + {'value': 0xfff5ee, 'colorMessageId': 'color_sea_shell'}, + {'value': 0x4169e1, 'colorMessageId': 'color_royal_blue'}, + {'value': 0x8a2be2, 'colorMessageId': 'color_blue_violet'}, + {'value': 0x7cfc00, 'colorMessageId': 'color_lawn_green'}, + {'value': 0xe0ffff, 'colorMessageId': 'color_light_cyan'}, + {'value': 0xb22222, 'colorMessageId': 'color_fire_brick'}, + {'value': 0x87ceeb, 'colorMessageId': 'color_sky_blue'}, + {'value': 0x6495ed, 'colorMessageId': 'color_cornflower_blue'}, + {'value': 0x7b68ee, 'colorMessageId': 'color_medium_slate_blue'}, + {'value': 0xff, 'colorMessageId': 'color_blue'}, + {'value': 0xf0fff0, 'colorMessageId': 'color_honeydew'}, + {'value': 0xba55d3, 'colorMessageId': 'color_medium_orchid'}, + {'value': 0xf5f5f5, 'colorMessageId': 'color_white_smoke'}, + {'value': 0xffff00, 'colorMessageId': 'color_yellow'}, + {'value': 0x87cefa, 'colorMessageId': 'color_light_sky_blue'}, + {'value': 0xbfff, 'colorMessageId': 'color_deep_sky_blue'}, + {'value': 0xfffafa, 'colorMessageId': 'color_snow'}, + {'value': 0x66cdaa, 'colorMessageId': 'color_medium_aqua_marine'}, + {'value': 0x7fff00, 'colorMessageId': 'color_chartreuse'}, + {'value': 0x1e90ff, 'colorMessageId': 'color_dodger_blue'}, +];
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/color_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/color_test.extjs new file mode 100644 index 0000000..8eee010 --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/color_test.extjs
@@ -0,0 +1,69 @@ +// Copyright 2019 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 test fixture. +GEN_INCLUDE(['../../testing/chromevox_next_e2e_test_base.js']); + +/** + * Test fixture for Color. + * @constructor + * @extends {ChromeVoxE2ETest} + */ +function ChromeVoxColorTest() { + ChromeVoxNextE2ETest.call(this); +} + +ChromeVoxColorTest.prototype = { + __proto__: ChromeVoxNextE2ETest.prototype, +}; + +SYNC_TEST_F('ChromeVoxColorTest', 'FindDistanceTest', function() { + // Hexadecimal representations of colors. + var red = 0xff0000; + var lime = 0x00ff00; + var blue = 0x0000ff; + var opaqueRed = 0xffff0000; + var transparentLime = 0x0000ff00; + + assertEquals(Color.findDistance(red,lime), Color.findDistance(lime, blue)); + // Opacity should not factor into this calculation. + assertEquals(Color.findDistance(red,lime), Color.findDistance(opaqueRed, transparentLime)); +}); + +SYNC_TEST_F('ChromeVoxColorTest', 'FindClosestMatchingColorTest', function() { + var white = 0xffffff; + var red = 0xff0000; + var lime = 0x00ff00; + var blue = 0x0000ff; + var black = 0x000000; + + var looksLikePink = 0xF4CCCC; + var looksLikeGreen = 0x38761D; + + var unknownColor = 0x0C343D; + + // Exact matches. + assertEquals('White', Color.findClosestMatchingColor(white)); + assertEquals('Red', Color.findClosestMatchingColor(red)); + assertEquals('Lime', Color.findClosestMatchingColor(lime)); + assertEquals('Blue', Color.findClosestMatchingColor(blue)); + assertEquals('Black', Color.findClosestMatchingColor(black)); + + // Inexact matches. + assertEquals('Pink', Color.findClosestMatchingColor(looksLikePink)); + assertEquals('Forest Green', Color.findClosestMatchingColor(looksLikeGreen)); + + // No match. + assertEquals('', Color.findClosestMatchingColor(unknownColor)); +}); + +SYNC_TEST_F('ChromeVoxColorTest', 'GetOpacityPercentageTest', function() { + var opaqueRed = 0xffff0000; + var transparentLime = 0x0000ff00; + var translucentBlue = 0x800000ff; + + assertEquals(100, Color.getOpacityPercentage(opaqueRed)); + assertEquals(0, Color.getOpacityPercentage(transparentLime)); + assertEquals(50, Color.getOpacityPercentage(translucentBlue)); +});
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js index ff2fed6..09b80f9 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js
@@ -17,6 +17,7 @@ goog.require('cvox.ChromeVoxKbHandler'); goog.require('cvox.ChromeVoxPrefs'); goog.require('cvox.CommandStore'); +goog.require('Color'); goog.scope(function() { var AutomationEvent = chrome.automation.AutomationEvent; @@ -868,6 +869,28 @@ .go(); }); break; + case 'getRichTextDescription': + var node = ChromeVoxState.instance.currentRange.start.node; + var optSubs = []; + node.fontSize ? optSubs.push('font size: ' + node.fontSize) : + optSubs.push(''); + node.color ? optSubs.push(Color.getColorDescription(node.color)) : + optSubs.push(''); + node.bold ? optSubs.push(Msgs.getMsg('bold')) : optSubs.push(''); + node.italic ? optSubs.push(Msgs.getMsg('italic')) : optSubs.push(''); + node.underline ? optSubs.push(Msgs.getMsg('underline')) : + optSubs.push(''); + node.lineThrough ? optSubs.push(Msgs.getMsg('linethrough')) : + optSubs.push(''); + node.fontFamily ? optSubs.push('font family: ' + node.fontFamily) : + optSubs.push(''); + + var richTextDescription = Msgs.getMsg('rich_text_attributes', optSubs); + new Output() + .withString(richTextDescription) + .withQueueMode(cvox.QueueMode.CATEGORY_FLUSH) + .go(); + return false; default: return true; }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js index b552849..9da4a9af 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
@@ -234,6 +234,19 @@ root.anchorObject, root.anchorOffset, root.focusObject, root.focusOffset); this.updateIntraLineState_(this.line_); + + /** + * @private {string|undefined} + */ + this.fontFamily_; + /** + * @private {number|undefined} + */ + this.fontSize_; + /** + * @private {string|undefined} + */ + this.fontColor_; } AutomationRichEditableText.prototype = { @@ -550,25 +563,57 @@ */ speakTextStyle_: function(style, opt_end) { var msgs = []; - if (style.state.linked) - msgs.push(opt_end ? 'link_end' : 'link_start'); - if (style.subscript) - msgs.push(opt_end ? 'subscript_end' : 'subscript_start'); - if (style.superscript) - msgs.push(opt_end ? 'superscript_end' : 'superscript_start'); - if (style.bold) - msgs.push(opt_end ? 'bold_end' : 'bold_start'); - if (style.italic) - msgs.push(opt_end ? 'italic_end' : 'italic_start'); - if (style.underline) - msgs.push(opt_end ? 'underline_end' : 'underline_start'); - if (style.lineThrough) - msgs.push(opt_end ? 'line_through_end' : 'line_through_start'); + var fontFamily = style.fontFamily; + var fontSize = style.fontSize; + var fontColor = Color.getColorDescription(style.color); + var msg; + + if (fontSize && (fontSize !== this.fontSize_)) { + this.fontSize_ = fontSize; + msg = opt_end ? 'font_size_end' : 'font_size_start'; + msgs.push({'msg': msg, 'opt_subs': [this.fontSize_]}); + } + if (fontColor && (fontColor !== this.fontColor_)) { + this.fontColor_ = fontColor; + msg = opt_end ? 'font_color_end' : 'font_color_start'; + msgs.push({'msg': msg, 'opt_subs': [this.fontColor_]}); + } + if (style.state.linked) { + msgs.push(opt_end ? {'msg': 'link_end'} : {'msg': 'link_start'}); + } + if (style.subscript) { + msgs.push( + opt_end ? {'msg': 'subscript_end'} : {'msg': 'subscript_start'}); + } + if (style.superscript) { + msgs.push( + opt_end ? {'msg': 'superscript_end'} : {'msg': 'superscript_start'}); + } + if (style.bold) { + msgs.push(opt_end ? {'msg': 'bold_end'} : {'msg': 'bold_start'}); + } + if (style.italic) { + msgs.push(opt_end ? {'msg': 'italic_end'} : {'msg': 'italic_start'}); + } + if (style.underline) { + msgs.push( + opt_end ? {'msg': 'underline_end'} : {'msg': 'underline_start'}); + } + if (style.lineThrough) { + msgs.push( + opt_end ? {'msg': 'line_through_end'} : + {'msg': 'line_through_start'}); + } + if (fontFamily && (fontFamily !== this.fontFamily_)) { + this.fontFamily_ = fontFamily; + msg = opt_end ? 'font_family_end' : 'font_family_start'; + msgs.push({'msg': msg, 'opt_subs': [this.fontFamily_]}); + } if (msgs.length) { - msgs.forEach(function(msg) { + msgs.forEach(function(obj) { cvox.ChromeVox.tts.speak( - Msgs.getMsg(msg), cvox.QueueMode.QUEUE, + Msgs.getMsg(obj['msg'], obj['opt_subs']), cvox.QueueMode.QUEUE, cvox.AbstractTts.PERSONALITY_ANNOTATION); }); }
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index 0aee7614..84c9118 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -3025,12 +3025,44 @@ <message desc="Spoken when a user navigates to the end of strike through text." name="IDS_CHROMEVOX_LINE_THROUGH_END"> Strike through end </message> + <message desc="Spoken to describe bolded text." name="IDS_CHROMEVOX_BOLD"> + Bold + </message> + <message desc="Spoken to describe italicized text." name="IDS_CHROMEVOX_ITALIC"> + Italic + </message> + <message desc="Spoken to describe underlined text." name="IDS_CHROMEVOX_UNDERLINE"> + Underline + </message> + <message desc="Spoken to describe line-through text." name="IDS_CHROMEVOX_LINETHROUGH"> + Line through + </message> <message desc="Spoken when a user navigates to the beginning of a link's text." name="IDS_CHROMEVOX_LINK_START"> Link start </message> <message desc="Spoken when a user navigates to the end of a link's text." name="IDS_CHROMEVOX_LINK_END"> Link end </message> + + <message desc="Spoken when a user navigates to the beginning of a font family's text, e.g. 'Arial start'" name="IDS_CHROMEVOX_FONT_FAMILY_START"> + <ph name="font_family">$1</ph> start + </message> + <message desc="Spoken when a user navigates to the end of a font family's text, e.g. 'Arial end'" name="IDS_CHROMEVOX_FONT_FAMILY_END"> + <ph name="font_family">$1</ph> end + </message> + <message desc="Spoken when a user navigates to the beginning of a font size's text, e.g. 'Size 12 start'" name="IDS_CHROMEVOX_FONT_SIZE_START"> + Size <ph name="font_size">$1</ph> start + </message> + <message desc="Spoken when a user navigates to the end of a font size's text, e.g. 'Size 12 end'" name="IDS_CHROMEVOX_FONT_SIZE_END"> + Size <ph name="font_size">$1</ph> end + </message> + <message desc="Spoken when a user navigates to the beginning of a font color's text, e.g. 'Red start'" name="IDS_CHROMEVOX_FONT_COLOR_START"> + <ph name="font_color">$1</ph> start + </message> + <message desc="Spoken when a user navigates to the end of a font color's text, e.g. 'Red end'" name="IDS_CHROMEVOX_FONT_COLOR_END"> + <ph name="font_color">$1</ph> end + </message> + <message desc="Shown to a user when they press a braille keyboard command that requires on screen keyboard to be enabled." name="IDS_CHROMEVOX_ENABLE_VIRTUAL_KEYBOARD"> Please enable the on screen keyboard under status tray, accessibility to use extended braille commands. </message> @@ -3213,6 +3245,439 @@ name="IDS_CHROMEVOX_OPTIONS_LANG_SWITCHING_CHECKBOX_LABEL"> Automatically detect and switch ChromeVox language. </message> + + <message desc="Spoken to describe all rich text attributes of a node." name="IDS_CHROMEVOX_RICH_TEXT_ATTRIBUTES"> + Text formatting. + <ph name="font_size_string">$1</ph> + <ph name="color_string">$2</ph> + <ph name="bold_string">$3</ph> + <ph name="italic_string">$4</ph> + <ph name="underline_string">$5</ph> + <ph name="line_through_string">$6</ph> + <ph name="font_family_string">$7</ph> + </message> + + <!-- Colors --> + <message desc="Spoken to describe color and opacity of text" name="IDS_CHROMEVOX_COLOR_DESCRIPTION"> + <ph name="color">$1</ph>, <ph name="opacity_percentage">$2</ph>% opacity. + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLACK"> + Black + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GREEN"> + Dark Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREEN"> + Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PURPLE"> + Purple + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GOLDEN_ROD"> + Dark Golden Rod + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LEMON_CHIFFON"> + Lemon Chiffon + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SIENNA"> + Sienna + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORANGE"> + Orange + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SADDLE_BROWN"> + Saddle Brown + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CYAN"> + Cyan + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREEN_YELLOW"> + Green Yellow + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CHOCOLATE"> + Chocolate + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MAROON"> + Maroon + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GOLDEN_ROD"> + Golden Rod + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FOREST_GREEN"> + Forest Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLIVE_DRAB"> + Olive Drab + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_IVORY"> + Ivory + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BEIGE"> + Beige + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BROWN"> + Brown + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_YELLOW_GREEN"> + Yellow Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORANGE_RED"> + Orange Red + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_OLIVE_GREEN"> + Dark Olive Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIME_GREEN"> + Lime Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIME"> + Lime + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_GOLDEN_ROD"> + Pale Golden Rod + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_HOT_PINK"> + Hot Pink + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CRIMSON"> + Crimson + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_POWDER_BLUE"> + Powder Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLIVE"> + Olive + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_YELLOW"> + Light Yellow + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LINEN"> + Linen + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_BLUE"> + Dark Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GHOST_WHITE"> + Ghost White + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TOMATO"> + Tomato + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_KHAKI"> + Khaki + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SLATE_GREY"> + Dark Slate Grey + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORAL"> + Coral + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MINT_CREAM"> + Mint Cream + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TEAL"> + Teal + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_MAGENTA"> + Dark Magenta + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SALMON"> + Light Salmon + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SEA_GREEN"> + Sea Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_RED"> + Red + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ROSY_BROWN"> + Rosy Brown + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_INDIAN_RED"> + Indian Red + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GREY"> + Light Grey + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SANDY_BROWN"> + Sandy Brown + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GREEN"> + Light Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_BLUE"> + Light Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_ORANGE"> + Dark Orange + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DIM_GREY"> + Dim Grey + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLANCHED_ALMOND"> + Blanched Almond + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_KHAKI"> + Dark Khaki + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MAGENTA"> + Magenta + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MIDNIGHT_BLUE"> + Midnight Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SEA_GREEN"> + Medium Sea Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SALMON"> + Salmon + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DEEP_PINK"> + Deep Pink + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SALMON"> + Dark Salmon + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PERU"> + Peru + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SPRING_GREEN"> + Spring Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_NAVY"> + Navy + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_CORAL"> + Light Coral + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_INDIGO"> + Indigo + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHITE"> + White + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_VIOLET_RED"> + Medium Violet Red + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BURLY_WOOD"> + Burly Wood + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAVENDER"> + Lavender + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SLATE_BLUE"> + Dark Slate Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TAN"> + Tan + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SEA_GREEN"> + Dark Sea Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SLATE_GREY"> + Slate Grey + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_VIOLET_RED"> + Pale Violet Red + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORNSILK"> + Cornsilk + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_TURQUOISE"> + Pale Turquoise + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SLATE_GREY"> + Light Slate Grey + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_GREEN"> + Pale Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_REBECCA_PURPLE"> + Rebecca Purple + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SPRING_GREEN"> + Medium Spring Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PINK"> + Pink + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CADET_BLUE"> + Cadet Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREY"> + Grey + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_VIOLET"> + Violet + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GREY"> + Dark Grey + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SEA_GREEN"> + Light Sea Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_CYAN"> + Dark Cyan + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_NAVAJO_WHITE"> + Navajo White + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ALICE_BLUE"> + Alice Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FLORAL_WHITE"> + Floral White + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MISTY_ROSE"> + Misty Rose + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHEAT"> + Wheat + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_STEEL_BLUE"> + Steel Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MOCCASIN"> + Moccasin + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PEACH_PUFF"> + Peach Puff + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GOLD"> + Gold + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAVENDER_BLUSH"> + Lavender Blush + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SILVER"> + Silver + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_PINK"> + Light Pink + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_AZURE"> + Azure + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BISQUE"> + Bisque + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_ORCHID"> + Dark Orchid + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLD_LACE"> + Old Lace + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_TURQUOISE"> + Medium Turquoise + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SLATE_BLUE"> + Slate Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_BLUE"> + Medium Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TURQUOISE"> + Turquoise + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_TURQUOISE"> + Dark Turquoise + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GOLDEN_ROD_YELLOW"> + Light Golden Rod Yellow + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_VIOLET"> + Dark Violet + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_AQUAMARINE"> + Aquamarine + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PAPAYA_WHIP"> + Papaya Whip + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORCHID"> + Orchid + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ANTIQUE_WHITE"> + Antique White + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_THISTLE"> + Thistle + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_PURPLE"> + Medium Purple + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GAINSBORO"> + Gainsboro + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PLUM"> + Plum + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_STEEL_BLUE"> + Light Steel Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_RED"> + Dark Red + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SEA_SHELL"> + Sea Shell + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ROYAL_BLUE"> + Royal Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLUE_VIOLET"> + Blue Violet + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAWN_GREEN"> + Lawn Green + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_CYAN"> + Light Cyan + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FIRE_BRICK"> + Fire Brick + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SKY_BLUE"> + Sky Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORNFLOWER_BLUE"> + Cornflower Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SLATE_BLUE"> + Medium Slate Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLUE"> + Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_HONEYDEW"> + HoneyDew + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_ORCHID"> + Medium Orchid + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHITE_SMOKE"> + White Smoke + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_YELLOW"> + Yellow + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SKY_BLUE"> + Light Sky Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DEEP_SKY_BLUE"> + Deep Sky Blue + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SNOW"> + Snow + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_AQUA_MARINE"> + Medium Aqua Marine + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CHARTREUSE"> + Chartreuse + </message> + <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DODGER_BLUE"> + Dodger Blue + </message> </messages> </release> </grit>
diff --git a/chrome/browser/resources/offline_pages/OWNERS b/chrome/browser/resources/offline_pages/OWNERS new file mode 100644 index 0000000..f5dcbcc --- /dev/null +++ b/chrome/browser/resources/offline_pages/OWNERS
@@ -0,0 +1,4 @@ +file://components/offline_pages/OWNERS + +# TEAM: offline-dev@chromium.org +# COMPONENT: UI>Browser>Offline
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html index b0c6432..834d691 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -231,8 +231,8 @@ </div> <div slot="dialog-buttons"> <paper-button class="cancel-button secondary-button" - on-click="onCancelConfiguringTap_"> - $i18n{cancel} + on-click="onCloseConfiguringTap_"> + $i18n{close} </paper-button> </div> </add-printer-dialog>
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js index 9a8766ca..9b97ab7 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -260,9 +260,8 @@ }, /** @private */ - onCancelConfiguringTap_: function() { + onCloseConfiguringTap_: function() { this.close(); - this.fire('configuring-dialog-closed'); }, close: function() { @@ -315,7 +314,6 @@ }, listeners: { - 'configuring-dialog-closed': 'configuringDialogClosed_', 'open-manually-add-printer-dialog': 'openManuallyAddPrinterDialog_', 'open-configuring-printer-dialog': 'openConfiguringPrinterDialog_', 'open-discovery-printers-dialog': 'openDiscoveryPrintersDialog_', @@ -444,26 +442,6 @@ }, /** @private */ - configuringDialogClosed_: function() { - // If the configuring dialog is closed, we want to return whence we came. - // - // TODO(justincarlson) - This shouldn't need to be a conditional; - // clean up the way we switch dialogs so we don't have to supply - // redundant information and can just return to the previous - // dialog. - if (this.previousDialog_ == AddPrinterDialogs.DISCOVERY) { - this.switchDialog_( - this.currentDialog_, this.previousDialog_, 'showDiscoveryDialog_'); - } else if (this.previousDialog_ == AddPrinterDialogs.MANUALLY) { - this.switchDialog_( - this.currentDialog_, this.previousDialog_, 'showManuallyAddDialog_'); - } else if (this.previousDialog_ == AddPrinterDialogs.MANUFACTURER) { - this.switchDialog_( - this.currentDialog_, this.previousDialog_, 'showManufacturerDialog_'); - } - }, - - /** @private */ onNoDetectedPrinter_: function() { // If there is no detected printer, automatically open manually-add-printer // dialog only when the user opens the discovery-dialog through the
diff --git a/chrome/browser/resources/usb_internals/usb_internals.js b/chrome/browser/resources/usb_internals/usb_internals.js index 0315f13..09fe786 100644 --- a/chrome/browser/resources/usb_internals/usb_internals.js +++ b/chrome/browser/resources/usb_internals/usb_internals.js
@@ -14,7 +14,7 @@ const pageHandler = mojom.UsbInternalsPageHandler.getProxy(); this.usbManagerTest = new device.mojom.UsbDeviceManagerTestProxy; - pageHandler.bindTestInterface(this.usbManagerTest.createRequest()); + pageHandler.bindTestInterface(this.usbManagerTest.$.createRequest()); cr.ui.decorate('tabbox', cr.ui.TabBox); $('add-test-device-form').addEventListener('submit', (event) => {
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc index 709176c..d153e66 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host.cc +++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -38,6 +38,7 @@ #include "content/public/common/frame_navigate_params.h" #include "content/public/common/resource_load_info.mojom.h" #include "content/public/common/url_constants.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_response_headers.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "url/gurl.h" @@ -87,7 +88,7 @@ url_ = navigation_handle->GetURL(); if (navigation_handle->GetResponseHeaders()) navigation_handle->GetResponseHeaders()->GetMimeType(&mime_type_); - socket_address_ = navigation_handle->GetSocketAddress(); + remote_endpoint_ = navigation_handle->GetSocketAddress(); } void Start() { @@ -105,10 +106,11 @@ DontClassifyForPhishing(NO_CLASSIFY_UNSUPPORTED_MIME_TYPE); } - if (csd_service_->IsPrivateIPAddress(socket_address_.host())) { + if (csd_service_->IsPrivateIPAddress( + remote_endpoint_.ToStringWithoutPort())) { DVLOG(1) << "Skipping phishing classification for URL: " << url_ << " because of hosting on private IP: " - << socket_address_.host(); + << remote_endpoint_.ToStringWithoutPort(); DontClassifyForPhishing(NO_CLASSIFY_PRIVATE_IP); DontClassifyForMalware(NO_CLASSIFY_PRIVATE_IP); } @@ -117,7 +119,7 @@ if (!url_.SchemeIsHTTPOrHTTPS()) { DVLOG(1) << "Skipping phishing classification for URL: " << url_ << " because it is not HTTP or HTTPS: " - << socket_address_.host(); + << remote_endpoint_.ToStringWithoutPort(); DontClassifyForPhishing(NO_CLASSIFY_SCHEME_NOT_SUPPORTED); } @@ -323,7 +325,7 @@ GURL url_; std::string mime_type_; - net::HostPortPair socket_address_; + net::IPEndPoint remote_endpoint_; WebContents* web_contents_; ClientSideDetectionService* csd_service_; // We keep a ref pointer here just to make sure the safe browsing @@ -394,10 +396,11 @@ content::ResourceType resource_type = navigation_handle->IsInMainFrame() ? content::RESOURCE_TYPE_MAIN_FRAME : content::RESOURCE_TYPE_SUB_FRAME; - UpdateIPUrlMap(navigation_handle->GetSocketAddress().host() /* ip */, - navigation_handle->GetURL().spec() /* url */, - navigation_handle->IsPost() ? "POST" : "GET", - navigation_handle->GetReferrer().url.spec(), resource_type); + UpdateIPUrlMap( + navigation_handle->GetSocketAddress().ToStringWithoutPort() /* ip */, + navigation_handle->GetURL().spec() /* url */, + navigation_handle->IsPost() ? "POST" : "GET", + navigation_handle->GetReferrer().url.spec(), resource_type); } if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted()) @@ -464,11 +467,11 @@ if (!content::IsResourceTypeFrame(resource_load_info.resource_type) && browse_info_.get() && should_extract_malware_features_ && resource_load_info.url.is_valid() && - resource_load_info.network_info->ip_port_pair.has_value()) { - UpdateIPUrlMap(resource_load_info.network_info->ip_port_pair->host(), - resource_load_info.url.spec(), resource_load_info.method, - resource_load_info.referrer.spec(), - resource_load_info.resource_type); + resource_load_info.network_info->remote_endpoint.has_value()) { + UpdateIPUrlMap( + resource_load_info.network_info->remote_endpoint->ToStringWithoutPort(), + resource_load_info.url.spec(), resource_load_info.method, + resource_load_info.referrer.spec(), resource_load_info.resource_type); } }
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc b/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc index 5b0eb7b..5570560 100644 --- a/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc +++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
@@ -445,6 +445,8 @@ signature_info_ = results.signature_info; image_headers_.reset(new ClientDownloadRequest_ImageHeaders()); *image_headers_ = results.image_headers; + file_count_ = results.file_count; + directory_count_ = results.directory_count; #if defined(OS_MACOSX) if (!results.disk_image_signature.empty()) @@ -700,6 +702,8 @@ request->set_allocated_image_headers(image_headers_.release()); if (!archived_binaries_.empty()) request->mutable_archived_binary()->Swap(&archived_binaries_); + request->set_archive_file_count(file_count_); + request->set_archive_directory_count(directory_count_); if (!request->SerializeToString(&client_download_request_data_)) { FinishRequest(DownloadCheckResult::UNKNOWN, REASON_INVALID_REQUEST_PROTO); return;
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request.h b/chrome/browser/safe_browsing/download_protection/check_client_download_request.h index af72d113..5571249 100644 --- a/chrome/browser/safe_browsing/download_protection/check_client_download_request.h +++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request.h
@@ -134,6 +134,8 @@ bool is_extended_reporting_; bool is_incognito_; bool is_under_advanced_protection_; + int file_count_; + int directory_count_; base::WeakPtrFactory<CheckClientDownloadRequest> weakptr_factory_;
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer.cc b/chrome/browser/safe_browsing/download_protection/file_analyzer.cc index be01921a..8201624 100644 --- a/chrome/browser/safe_browsing/download_protection/file_analyzer.cc +++ b/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
@@ -69,7 +69,7 @@ } // namespace -FileAnalyzer::Results::Results() {} +FileAnalyzer::Results::Results() : file_count(0), directory_count(0) {} FileAnalyzer::Results::~Results() {} FileAnalyzer::Results::Results(const FileAnalyzer::Results& other) = default; @@ -208,6 +208,9 @@ results_.type = ClientDownloadRequest::ZIPPED_EXECUTABLE; } + results_.file_count = archive_results.file_count; + results_.directory_count = archive_results.directory_count; + std::move(callback_).Run(std::move(results_)); }
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer.h b/chrome/browser/safe_browsing/download_protection/file_analyzer.h index a1f5abf..99684ff 100644 --- a/chrome/browser/safe_browsing/download_protection/file_analyzer.h +++ b/chrome/browser/safe_browsing/download_protection/file_analyzer.h
@@ -72,6 +72,12 @@ ClientDownloadRequest::DetachedCodeSignature> detached_code_signatures; #endif + + // For archive files, the number of contained files. + int file_count; + + // For archive files, the number of contained directories. + int directory_count; }; explicit FileAnalyzer(
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc b/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc index 511f495..b00616c9 100644 --- a/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc +++ b/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc
@@ -768,4 +768,65 @@ EXPECT_TRUE(result_.archived_binaries.Get(0).digests().sha256().empty()); } +TEST_F(FileAnalyzerTest, ZipFilesGetFileCount) { + scoped_refptr<MockBinaryFeatureExtractor> extractor = + new testing::StrictMock<MockBinaryFeatureExtractor>(); + FileAnalyzer analyzer(extractor); + base::RunLoop run_loop; + + base::FilePath target_path(FILE_PATH_LITERAL("target.zip")); + base::FilePath tmp_path = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("tmp.crdownload")); + + base::ScopedTempDir zip_source_dir; + ASSERT_TRUE(zip_source_dir.CreateUniqueTempDir()); + std::string file_contents = "dummy file"; + ASSERT_EQ(static_cast<int>(file_contents.size()), + base::WriteFile( + zip_source_dir.GetPath().Append(FILE_PATH_LITERAL("file.exe")), + file_contents.data(), file_contents.size())); + ASSERT_TRUE(zip::Zip(zip_source_dir.GetPath(), tmp_path, + /* include_hidden_files= */ + false)); + + analyzer.Start( + target_path, tmp_path, + base::BindOnce(&FileAnalyzerTest::DoneCallback, base::Unretained(this), + run_loop.QuitClosure())); + run_loop.Run(); + + ASSERT_TRUE(has_result_); + EXPECT_EQ(1, result_.file_count); + EXPECT_EQ(0, result_.directory_count); +} + +TEST_F(FileAnalyzerTest, ZipFilesGetDirectoryCount) { + scoped_refptr<MockBinaryFeatureExtractor> extractor = + new testing::StrictMock<MockBinaryFeatureExtractor>(); + FileAnalyzer analyzer(extractor); + base::RunLoop run_loop; + + base::FilePath target_path(FILE_PATH_LITERAL("target.zip")); + base::FilePath tmp_path = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("tmp.crdownload")); + + base::ScopedTempDir zip_source_dir; + ASSERT_TRUE(zip_source_dir.CreateUniqueTempDir()); + ASSERT_TRUE(base::CreateDirectory( + zip_source_dir.GetPath().Append(FILE_PATH_LITERAL("direcotry")))); + ASSERT_TRUE(zip::Zip(zip_source_dir.GetPath(), tmp_path, + /* include_hidden_files= */ + false)); + + analyzer.Start( + target_path, tmp_path, + base::BindOnce(&FileAnalyzerTest::DoneCallback, base::Unretained(this), + run_loop.QuitClosure())); + run_loop.Run(); + + ASSERT_TRUE(has_result_); + EXPECT_EQ(0, result_.file_count); + EXPECT_EQ(1, result_.directory_count); +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc index aa76c7a6e..20f17e9 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc
@@ -20,6 +20,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/resource_type.h" +#include "net/base/ip_endpoint.h" using content::WebContents; @@ -227,10 +228,10 @@ void SafeBrowsingNavigationObserver::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if ((navigation_handle->HasCommitted() || navigation_handle->IsDownload()) && - !navigation_handle->GetSocketAddress().IsEmpty()) { + !navigation_handle->GetSocketAddress().address().empty()) { manager_->RecordHostToIpMapping( navigation_handle->GetURL().host(), - navigation_handle->GetSocketAddress().host()); + navigation_handle->GetSocketAddress().ToStringWithoutPort()); } if (navigation_handle_map_.find(navigation_handle) ==
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc index dbbaada..84f3fc4 100644 --- a/chrome/browser/safe_browsing/threat_details_unittest.cc +++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
@@ -32,6 +32,7 @@ #include "content/public/test/navigation_simulator.h" #include "content/public/test/test_renderer_host.h" #include "content/public/test/web_contents_tester.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/http/http_util.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" @@ -376,7 +377,7 @@ network::ResourceResponseHead head; head.headers = new net::HttpResponseHeaders( net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size())); - head.socket_address = net::HostPortPair("1.2.3.4", 80); + head.remote_endpoint = net::IPEndPoint(net::IPAddress(1, 2, 3, 4), 80); head.mime_type = "text/html"; network::URLLoaderCompletionStatus status; status.decoded_body_length = content.size();
diff --git a/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc b/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc index abe2259..12ad59b0 100644 --- a/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc +++ b/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc
@@ -9,10 +9,12 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/chrome_device_id_helper.h" #include "chrome/browser/sync/device_info_sync_service_factory.h" +#include "chrome/browser/sync/model_type_store_service_factory.h" #include "chrome/common/channel_info.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/send_tab_to_self/send_tab_to_self_sync_service.h" #include "components/sync/device_info/device_info_sync_service.h" +#include "components/sync/model/model_type_store_service.h" #include "ui/base/device_form_factor.h" // static @@ -33,6 +35,7 @@ "SendTabToSelfSyncService", BrowserContextDependencyManager::GetInstance()) { DependsOn(DeviceInfoSyncServiceFactory::GetInstance()); + DependsOn(ModelTypeStoreServiceFactory::GetInstance()); } SendTabToSelfSyncServiceFactory::~SendTabToSelfSyncServiceFactory() {} @@ -45,8 +48,10 @@ DeviceInfoSyncServiceFactory::GetForProfile(profile) ->GetLocalDeviceInfoProvider(); - // TODO(jeffreycohen): use KeyedService to provide a DeviceInfo ptr. + syncer::OnceModelTypeStoreFactory store_factory = + ModelTypeStoreServiceFactory::GetForProfile(profile)->GetStoreFactory(); return new send_tab_to_self::SendTabToSelfSyncService( - chrome::GetChannel(), local_device_info_provider); + chrome::GetChannel(), local_device_info_provider, + std::move(store_factory)); }
diff --git a/chrome/browser/translate/translate_fake_page.cc b/chrome/browser/translate/translate_fake_page.cc index e009e6a..de2c7a6 100644 --- a/chrome/browser/translate/translate_fake_page.cc +++ b/chrome/browser/translate/translate_fake_page.cc
@@ -54,8 +54,6 @@ // translate::mojom::Page implementation. void FakePageImpl::Translate(const std::string& translate_script, - network::mojom::URLLoaderFactoryPtr - unused_loader_factory_for_translate_script, const std::string& source_lang, const std::string& target_lang, TranslateCallback callback) {
diff --git a/chrome/browser/translate/translate_fake_page.h b/chrome/browser/translate/translate_fake_page.h index c456071..bd368d22 100644 --- a/chrome/browser/translate/translate_fake_page.h +++ b/chrome/browser/translate/translate_fake_page.h
@@ -9,12 +9,10 @@ #include <memory> #include <set> -#include <string> #include <tuple> #include <utility> #include <vector> -#include "base/optional.h" #include "build/build_config.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" @@ -49,12 +47,10 @@ translate::mojom::PagePtr BindToNewPagePtr(); // translate::mojom::Page implementation. - void Translate( - const std::string& translate_script, - network::mojom::URLLoaderFactoryPtr loader_factory_for_translate_script, - const std::string& source_lang, - const std::string& target_lang, - TranslateCallback callback) override; + void Translate(const std::string& translate_script, + const std::string& source_lang, + const std::string& target_lang, + TranslateCallback callback) override; void RevertTranslation() override;
diff --git a/chrome/browser/translate/translate_manager_browsertest.cc b/chrome/browser/translate/translate_manager_browsertest.cc index 0926637..d44a784 100644 --- a/chrome/browser/translate/translate_manager_browsertest.cc +++ b/chrome/browser/translate/translate_manager_browsertest.cc
@@ -7,12 +7,9 @@ #include <memory> #include "base/bind.h" -#include "base/feature_list.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/metrics/histogram_tester.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/metrics/subprocess_metrics_provider.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" @@ -34,8 +31,6 @@ #include "content/public/test/browser_test_utils.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" -#include "services/network/initiator_lock_compatibility.h" -#include "services/network/public/cpp/features.h" #include "url/gurl.h" namespace { @@ -988,107 +983,3 @@ EXPECT_EQ("fr", restored_translate_client->GetLanguageState().current_language()); } - -// Test that the translation is successful in presence of AppCache. -// See also: -// - https://crbug.com/910287#c24: AppCache / Translate renderer kills. -// - https://crbug.com/925457: Translate is incompatible with -// |request_initiator_site_lock|. -IN_PROC_BROWSER_TEST_F(TranslateManagerBrowserTest, AppCacheInteraction) { - // The real translate script used in production will try to fetch some stuff - // from the translate servers - the test tries to simulate a close-enough - // scenario below (close-enough to repro https://crbug.com/910287#c24). - // - // Unlike the real script, the request below doesn't use - // GetTranslateSecurityOrigin and instead fetches a resource from localhost, - // to simplify the test (e.g. avoid having to set up a https test server with - // the right certs). Also, unlike the real script, the test below uses a - // random png resource (although as with the real script the resource is not - // protected by CORB). - const char kTranslateScriptTemplate[] = R"( - var google = {}; - google.translate = (function() { - return { - TranslateService: function() { - return { - isAvailable : function() { return true; }, - restore : function() { return; }, - getDetectedLanguage : function() { return "fr"; }, - translatePage : function(originalLang, targetLang, - onTranslateProgress) { - fetch($1, {mode: 'no-cors'}) - .then(_ => onTranslateProgress(100, true, false)); - } - }; - } - }; - })(); - cr.googleTranslate.onTranslateElementLoad(); - )"; - GURL fetch_url = - embedded_test_server()->GetURL("/downloads/image-octet-stream.png"); - std::string translate_script = - content::JsReplace(kTranslateScriptTemplate, fetch_url); - SetTranslateScript(translate_script); - - ChromeTranslateClient* chrome_translate_client = GetChromeTranslateClient(); - - // There is a possible race condition, when the language is not yet detected, - // so we check for that and wait if necessary. - if (chrome_translate_client->GetLanguageState().original_language().empty()) - WaitUntilLanguageDetected(); - EXPECT_EQ("und", - chrome_translate_client->GetLanguageState().original_language()); - - // Open a new tab with a page in French and wait until AppCache controls - // subresource loads. - GURL main_url = embedded_test_server()->GetURL( - "/appcache/french_page_with_appcache.html"); - ResetObserver(); - AddTabAtIndex(0, main_url, ui::PAGE_TRANSITION_TYPED); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - base::string16 expected_title = base::UTF8ToUTF16("AppCache mis à jour"); - content::TitleWatcher title_watcher(web_contents, expected_title); - chrome_translate_client = GetChromeTranslateClient(); - WaitUntilLanguageDetected(); - EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); - ui_test_utils::NavigateToURL(browser(), main_url); - WaitUntilLanguageDetected(); - - // Translate the page through TranslateManager. - // In the past, this might have led to renderer kills, because of - // request_initiator in requests triggered by the Translate feature was - // different than the request_initiator_site_lock associated with the - // URLLoaderFactory. See also https://crbug.com/910287#c24. - base::HistogramTester histograms; - translate::TranslateManager* manager = - chrome_translate_client->GetTranslateManager(); - manager->TranslatePage( - chrome_translate_client->GetLanguageState().original_language(), "en", - true); - - // Wait for NOTIFICATION_PAGE_TRANSLATED notification. - WaitUntilPageTranslated(); - - EXPECT_FALSE(chrome_translate_client->GetLanguageState().translation_error()); - EXPECT_EQ(translate::TranslateErrors::NONE, GetPageTranslatedResult()); - - // Verify that |request_initiator| seen by the network service was compatible - // with |request_initiator_site_lock| that was declared by the browser for the - // URLLoaderFactory. See also https://crbug.com/925457. - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - SubprocessMetricsProvider::MergeHistogramDeltasForTesting(); - using LockCompatibility = network::InitiatorLockCompatibility; - EXPECT_EQ( - 0, - histograms.GetBucketCount( - "NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility", - static_cast<int>(LockCompatibility::kIncorrectLock))); - EXPECT_LE( - 1, - histograms.GetBucketCount( - "NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility", - static_cast<int>(LockCompatibility::kCompatibleLock))); - } -}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 0c6eace3..1506939 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3371,6 +3371,8 @@ "ash/assistant/assistant_context_util.h", "ash/assistant/assistant_image_downloader.cc", "ash/assistant/assistant_image_downloader.h", + "ash/assistant/assistant_pref_util.cc", + "ash/assistant/assistant_pref_util.h", "ash/assistant/assistant_setup.cc", "ash/assistant/assistant_setup.h", "ash/assistant/device_actions.cc",
diff --git a/chrome/browser/ui/app_list/crostini/OWNERS b/chrome/browser/ui/app_list/crostini/OWNERS index 83af899..9d9bf0c4 100644 --- a/chrome/browser/ui/app_list/crostini/OWNERS +++ b/chrome/browser/ui/app_list/crostini/OWNERS
@@ -1,3 +1 @@ -benwells@chromium.org -nverne@chromium.org -timloh@chromium.org +file://chrome/browser/chromeos/crostini/OWNERS
diff --git a/chrome/browser/ui/ash/assistant/assistant_client.cc b/chrome/browser/ui/ash/assistant/assistant_client.cc index d523a271..a6508e2 100644 --- a/chrome/browser/ui/ash/assistant/assistant_client.cc +++ b/chrome/browser/ui/ash/assistant/assistant_client.cc
@@ -7,8 +7,8 @@ #include <utility> #include "ash/public/interfaces/voice_interaction_controller.mojom.h" -#include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h" +#include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/assistant/assistant_context_util.h" #include "chrome/browser/ui/ash/assistant/assistant_image_downloader.h" @@ -39,7 +39,7 @@ } void AssistantClient::MaybeInit(Profile* profile) { - if (arc::IsAssistantAllowedForProfile(profile) != + if (assistant::IsAssistantAllowedForProfile(profile) != ash::mojom::AssistantAllowedState::ALLOWED) { return; }
diff --git a/chrome/browser/ui/ash/assistant/assistant_pref_util.cc b/chrome/browser/ui/ash/assistant/assistant_pref_util.cc new file mode 100644 index 0000000..127a63a6c --- /dev/null +++ b/chrome/browser/ui/ash/assistant/assistant_pref_util.cc
@@ -0,0 +1,36 @@ +// Copyright 2019 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/ui/ash/assistant/assistant_pref_util.h" + +#include <string> + +#include "components/arc/arc_prefs.h" +#include "components/prefs/pref_registry_simple.h" + +namespace assistant { +namespace prefs { + +const char kAssistantConsentStatus[] = + "settings.voice_interaction.activity_control.consent_status"; + +void RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterIntegerPref( + kAssistantConsentStatus, + static_cast<int>(ash::mojom::ConsentStatus::kUnknown)); +} + +ash::mojom::ConsentStatus GetConsentStatus(PrefService* pref_service) { + return static_cast<ash::mojom::ConsentStatus>( + pref_service->GetInteger(kAssistantConsentStatus)); +} + +void SetConsentStatus(PrefService* pref_service, + ash::mojom::ConsentStatus consent_status) { + pref_service->SetInteger(kAssistantConsentStatus, + static_cast<int>(consent_status)); +} + +} // namespace prefs +} // namespace assistant
diff --git a/chrome/browser/ui/ash/assistant/assistant_pref_util.h b/chrome/browser/ui/ash/assistant/assistant_pref_util.h new file mode 100644 index 0000000..77ef30d --- /dev/null +++ b/chrome/browser/ui/ash/assistant/assistant_pref_util.h
@@ -0,0 +1,31 @@ +// Copyright 2019 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_UI_ASH_ASSISTANT_ASSISTANT_PREF_UTIL_H_ +#define CHROME_BROWSER_UI_ASH_ASSISTANT_ASSISTANT_PREF_UTIL_H_ + +#include "ash/public/interfaces/voice_interaction_controller.mojom.h" +#include "components/prefs/pref_service.h" + +class PrefRegistrySimple; + +namespace assistant { +namespace prefs { + +extern const char kAssistantConsentStatus[]; + +// Registers Assistant specific profile preferences. +void RegisterProfilePrefs(PrefRegistrySimple* registry); + +// Gets the user's consent status from the given preference service. +ash::mojom::ConsentStatus GetConsentStatus(PrefService* pref_service); + +// Sets the user's consent status in the given preference service. +void SetConsentStatus(PrefService* pref_service, + ash::mojom::ConsentStatus consent_status); + +} // namespace prefs +} // namespace assistant + +#endif // CHROME_BROWSER_UI_ASH_ASSISTANT_ASSISTANT_PREF_UTIL_H_
diff --git a/chrome/browser/ui/ash/assistant/assistant_setup.cc b/chrome/browser/ui/ash/assistant/assistant_setup.cc index 68f5ed5..cee0021 100644 --- a/chrome/browser/ui/ash/assistant/assistant_setup.cc +++ b/chrome/browser/ui/ash/assistant/assistant_setup.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/ash/assistant/assistant_pref_util.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h" #include "chrome/grit/generated_resources.h" @@ -188,29 +189,25 @@ case ConsentFlowUi::ASK_FOR_CONSENT: if (consent_ui.has_activity_control_ui() && consent_ui.activity_control_ui().setting_zippy().size()) { - prefs->SetBoolean(arc::prefs::kVoiceInteractionActivityControlAccepted, - false); + assistant::prefs::SetConsentStatus( + prefs, ash::mojom::ConsentStatus::kNotFound); } else { - prefs->SetBoolean(arc::prefs::kVoiceInteractionActivityControlAccepted, - true); + assistant::prefs::SetConsentStatus( + prefs, ash::mojom::ConsentStatus::kActivityControlAccepted); } break; case ConsentFlowUi::ERROR_ACCOUNT: - // Show the opted out mode UI for unsupported Account as they are in opted - // out mode. - // TODO(llin): we should show a error account message in Opted out UI or - // in the onboarding flow. - prefs->SetBoolean(arc::prefs::kVoiceInteractionActivityControlAccepted, - false); + assistant::prefs::SetConsentStatus( + prefs, ash::mojom::ConsentStatus::kUnauthorized); break; case ConsentFlowUi::ALREADY_CONSENTED: - prefs->SetBoolean(arc::prefs::kVoiceInteractionActivityControlAccepted, - true); + assistant::prefs::SetConsentStatus( + prefs, ash::mojom::ConsentStatus::kActivityControlAccepted); break; case ConsentFlowUi::UNSPECIFIED: case ConsentFlowUi::ERROR: - prefs->SetBoolean(arc::prefs::kVoiceInteractionActivityControlAccepted, - false); + assistant::prefs::SetConsentStatus(prefs, + ash::mojom::ConsentStatus::kUnknown); LOG(ERROR) << "Invalid activity control consent status."; } } @@ -219,7 +216,7 @@ auto* pref_service = ProfileManager::GetActiveUserProfile()->GetPrefs(); DCHECK(pref_service); if (!pref_service->GetUserPrefValue( - arc::prefs::kVoiceInteractionActivityControlAccepted)) { + assistant::prefs::kAssistantConsentStatus)) { base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&AssistantSetup::StartAssistantOptInFlow, weak_factory_.GetWeakPtr(),
diff --git a/chrome/browser/ui/ash/assistant/assistant_setup.h b/chrome/browser/ui/ash/assistant/assistant_setup.h index 1a16670b..bc665d5 100644 --- a/chrome/browser/ui/ash/assistant/assistant_setup.h +++ b/chrome/browser/ui/ash/assistant/assistant_setup.h
@@ -28,7 +28,7 @@ ash::mojom::FlowType type, StartAssistantOptInFlowCallback callback) override; - // If prefs::kVoiceInteractionActivityControlAccepted is nullptr, means the + // If prefs::kVoiceInteractionConsentStatus is nullptr, means the // pref is not set by user. Therefore we need to start OOBE. void MaybeStartAssistantOptInFlow();
diff --git a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc index 03129b2..76a98bf 100644 --- a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc +++ b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc
@@ -34,23 +34,7 @@ base::WrapUnique(new AlternateNavInfoBarDelegate( Profile::FromBrowserContext(web_contents->GetBrowserContext()), text, std::make_unique<AutocompleteMatch>(match), match.destination_url, - search_url, base::OnceClosure())))); -} - -// static -void AlternateNavInfoBarDelegate::CreateForLookalikeUrlNavigation( - content::WebContents* web_contents, - const base::string16& text, - const GURL& destination_url, - const GURL& original_url, - base::OnceClosure link_clicked_callback) { - InfoBarService* infobar_service = - InfoBarService::FromWebContents(web_contents); - infobar_service->AddInfoBar(AlternateNavInfoBarDelegate::CreateInfoBar( - base::WrapUnique(new AlternateNavInfoBarDelegate( - Profile::FromBrowserContext(web_contents->GetBrowserContext()), text, - nullptr, destination_url, original_url, - std::move(link_clicked_callback))))); + search_url)))); } AlternateNavInfoBarDelegate::AlternateNavInfoBarDelegate( @@ -58,15 +42,13 @@ const base::string16& text, std::unique_ptr<AutocompleteMatch> match, const GURL& destination_url, - const GURL& original_url, - base::OnceClosure link_clicked_callback) + const GURL& original_url) : infobars::InfoBarDelegate(), profile_(profile), text_(text), match_(std::move(match)), destination_url_(destination_url), - original_url_(original_url), - link_clicked_callback_(std::move(link_clicked_callback)) { + original_url_(original_url) { if (match_) DCHECK_EQ(destination_url_, match_->destination_url); @@ -98,28 +80,19 @@ HistoryServiceFactory::GetForProfile(profile_, ServiceAccessType::IMPLICIT_ACCESS); - if (match_) { - // If there is an autocomplete match, this is an omnibox navigation. Tell - // the shortcuts backend to remove the shortcut it added for the - // original search and instead add one reflecting this navigation. - scoped_refptr<ShortcutsBackend> shortcuts_backend( - ShortcutsBackendFactory::GetForProfile(profile_)); - if (shortcuts_backend.get()) { // May be NULL in incognito. - shortcuts_backend->DeleteShortcutsWithURL(original_url_); - shortcuts_backend->AddOrUpdateShortcut(text_, *match_); - } - - // Tell the history system to remove any saved search term for the search. - if (history_service) - history_service->DeleteKeywordSearchTermForURL(original_url_); - } else { - // This is a lookalike URL navigation suggestion. Remove the current entry. - if (history_service) - history_service->DeleteURL(original_url_); + // Tell the shortcuts backend to remove the shortcut it added for the + // original search and instead add one reflecting this navigation. + scoped_refptr<ShortcutsBackend> shortcuts_backend( + ShortcutsBackendFactory::GetForProfile(profile_)); + if (shortcuts_backend.get()) { // May be NULL in incognito. + shortcuts_backend->DeleteShortcutsWithURL(original_url_); + shortcuts_backend->AddOrUpdateShortcut(text_, *match_); } - if (!link_clicked_callback_.is_null()) - std::move(link_clicked_callback_).Run(); + // Tell the history system to remove any saved search term for the search. + if (history_service) + history_service->DeleteKeywordSearchTermForURL(original_url_); + // Pretend the user typed this URL, so that navigating to it will be the // default action when it's typed again in the future. InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL(
diff --git a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h index 0dbd51d..10733c41 100644 --- a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h +++ b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h
@@ -35,14 +35,6 @@ const AutocompleteMatch& match, const GURL& search_url); - // Creates the delegate for navigations involving lookalike URLs - // (e.g. googlé.com). - static void CreateForLookalikeUrlNavigation( - content::WebContents* web_contents, - const base::string16& text, - const GURL& suggested_url, - const GURL& original_url, - base::OnceClosure link_clicked_callback); base::string16 GetMessageTextWithOffset(size_t* link_offset) const; base::string16 GetLinkText() const; GURL GetLinkURL() const; @@ -53,8 +45,7 @@ const base::string16& text, std::unique_ptr<AutocompleteMatch> match, const GURL& destination_url, - const GURL& original_url, - base::OnceClosure link_clicked_callback); + const GURL& original_url); // Returns an alternate nav infobar that owns |delegate|. static std::unique_ptr<infobars::InfoBar> CreateInfoBar( @@ -77,13 +68,9 @@ // Original URL of the navigation. When the user clicks the suggested // navigation link, this will be removed from history. - // For search navigations this is the search URL. For lookalike URL - // navigations, this is the URL that visually matches a top domain or a domain - // with a site engagement score. + // For search navigations this is the search URL. const GURL original_url_; - base::OnceClosure link_clicked_callback_; - DISALLOW_COPY_AND_ASSIGN(AlternateNavInfoBarDelegate); };
diff --git a/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc b/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc index f799d88..6afcdd8 100644 --- a/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc +++ b/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc
@@ -296,7 +296,8 @@ void OnCloseContents(content::WebContents* source, bool* out_close_dialog) override {} - bool HandleContextMenu(const content::ContextMenuParams& params) override { + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override { return true; }
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 95e9d4d0..d1c71358 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/history/top_sites_factory.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/installable/installable_manager.h" -#include "chrome/browser/lookalikes/lookalike_url_navigation_observer.h" #include "chrome/browser/media/media_engagement_service.h" #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_observer.h" #include "chrome/browser/metrics/oom/out_of_memory_reporter.h" @@ -292,7 +291,6 @@ FramebustBlockTabHelper::CreateForWebContents(web_contents); HungPluginTabHelper::CreateForWebContents(web_contents); JavaScriptDialogTabHelper::CreateForWebContents(web_contents); - LookalikeUrlNavigationObserver::CreateForWebContents(web_contents); ManagePasswordsUIController::CreateForWebContents(web_contents); pdf::PDFWebContentsHelper::CreateForWebContentsWithClient( web_contents, std::make_unique<ChromePDFWebContentsHelperClient>());
diff --git a/chrome/browser/ui/user_manager.cc b/chrome/browser/ui/user_manager.cc index b039fc8..cecb7be 100644 --- a/chrome/browser/ui/user_manager.cc +++ b/chrome/browser/ui/user_manager.cc
@@ -21,6 +21,7 @@ : guest_web_contents_(nullptr) {} bool UserManagerProfileDialog::BaseDialogDelegate::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { // Ignores context menu. return true;
diff --git a/chrome/browser/ui/user_manager.h b/chrome/browser/ui/user_manager.h index 7c37bfd5..cf0e188 100644 --- a/chrome/browser/ui/user_manager.h +++ b/chrome/browser/ui/user_manager.h
@@ -98,7 +98,8 @@ BaseDialogDelegate(); // content::WebContentsDelegate: - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; // content::WebContentsDelegate: void LoadingStateChanged(content::WebContents* source,
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc index b12ee4b..86b7ef64 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -270,9 +270,8 @@ // TearDown. class BookmarkBarViewEventTestBase : public ViewEventTestBase { public: - BookmarkBarViewEventTestBase() - : ViewEventTestBase(), - model_(NULL) {} + BookmarkBarViewEventTestBase() = default; + ~BookmarkBarViewEventTestBase() override = default; void SetUp() override { content_client_.reset(new ChromeContentClient); @@ -377,7 +376,7 @@ // See comment above class description for what this does. virtual bool CreateBigMenu() { return false; } - BookmarkModel* model_; + BookmarkModel* model_ = nullptr; std::unique_ptr<BookmarkBarView> bb_view_; TestingPageNavigator navigator_; @@ -717,12 +716,11 @@ void Step2() { // Menu should be showing. views::MenuItemView* menu = bb_view_->GetMenu(); - ASSERT_TRUE(menu != NULL); - ASSERT_TRUE(menu->GetSubmenu()->IsShowing()); - - views::MenuItemView* child_menu = - menu->GetSubmenu()->GetMenuItemAt(0); - ASSERT_TRUE(child_menu != NULL); + ASSERT_NE(nullptr, menu); + views::SubmenuView* submenu = menu->GetSubmenu(); + ASSERT_TRUE(submenu->IsShowing()); + views::MenuItemView* child_menu = submenu->GetMenuItemAt(0); + ASSERT_NE(nullptr, child_menu); // Move mouse to center of menu and press button. ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT, @@ -827,12 +825,11 @@ void Step2() { // Menu should be showing. views::MenuItemView* menu = bb_view_->GetMenu(); - ASSERT_TRUE(menu != NULL); - ASSERT_TRUE(menu->GetSubmenu()->IsShowing()); - - views::MenuItemView* child_menu = - menu->GetSubmenu()->GetMenuItemAt(0); - ASSERT_TRUE(child_menu != NULL); + ASSERT_NE(nullptr, menu); + views::SubmenuView* submenu = menu->GetSubmenu(); + ASSERT_TRUE(submenu->IsShowing()); + views::MenuItemView* child_menu = submenu->GetMenuItemAt(0); + ASSERT_NE(nullptr, child_menu); // Move mouse to center of menu and press button. ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT, @@ -842,9 +839,8 @@ void Step3() { // Drag over other button. - views::LabelButton* other_button = bb_view_->other_bookmarks_button(); - gfx::Point loc(other_button->width() / 2, other_button->height() / 2); - views::View::ConvertPointToScreen(other_button, &loc); + gfx::Point loc = ui_test_utils::GetCenterInScreenCoordinates( + bb_view_->other_bookmarks_button()); #if defined(USE_AURA) // TODO: fix this. Aura requires an additional mouse event to trigger drag @@ -865,9 +861,8 @@ void Step3A() { // Drag over other button. - views::LabelButton* other_button = bb_view_->other_bookmarks_button(); - gfx::Point loc(other_button->width() / 2, other_button->height() / 2); - views::View::ConvertPointToScreen(other_button, &loc); + gfx::Point loc = ui_test_utils::GetCenterInScreenCoordinates( + bb_view_->other_bookmarks_button()); ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone( loc.x(), loc.y(), @@ -876,14 +871,15 @@ void Step4() { views::MenuItemView* drop_menu = bb_view_->GetDropMenu(); - ASSERT_TRUE(drop_menu != NULL); - ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing()); + ASSERT_NE(nullptr, drop_menu); + views::SubmenuView* drop_submenu = drop_menu->GetSubmenu(); + ASSERT_TRUE(drop_submenu->IsShowing()); + // The button should be highlighted now. views::LabelButton* other_button = bb_view_->other_bookmarks_button(); - ASSERT_EQ(views::Button::STATE_PRESSED, other_button->state()); + EXPECT_EQ(views::Button::STATE_PRESSED, other_button->state()); - views::MenuItemView* target_menu = - drop_menu->GetSubmenu()->GetMenuItemAt(0); + views::MenuItemView* target_menu = drop_submenu->GetMenuItemAt(0); gfx::Point loc(1, 1); views::View::ConvertPointToScreen(target_menu, &loc); ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone( @@ -897,10 +893,10 @@ } void Step6() { - ASSERT_TRUE(model_->other_node()->GetChild(0)->url() == url_dragging_); + EXPECT_EQ(url_dragging_, model_->other_node()->GetChild(0)->url()); // The button should be in normal state now. views::LabelButton* other_button = bb_view_->other_bookmarks_button(); - ASSERT_EQ(views::Button::STATE_NORMAL, other_button->state()); + EXPECT_EQ(views::Button::STATE_NORMAL, other_button->state()); Done(); } @@ -934,12 +930,11 @@ void Step2() { // Menu should be showing. views::MenuItemView* menu = bb_view_->GetMenu(); - ASSERT_TRUE(menu != NULL); - ASSERT_TRUE(menu->GetSubmenu()->IsShowing()); - - views::MenuItemView* child_menu = - menu->GetSubmenu()->GetMenuItemAt(0); - ASSERT_TRUE(child_menu != NULL); + ASSERT_NE(nullptr, menu); + views::SubmenuView* submenu = menu->GetSubmenu(); + ASSERT_TRUE(submenu->IsShowing()); + views::MenuItemView* child_menu = submenu->GetMenuItemAt(0); + ASSERT_NE(nullptr, child_menu); // Move mouse to center of menu and press button. ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT, @@ -949,9 +944,8 @@ void Step3() { // Drag over other button. - views::LabelButton* other_button = bb_view_->other_bookmarks_button(); - gfx::Point loc(other_button->width() / 2, other_button->height() / 2); - views::View::ConvertPointToScreen(other_button, &loc); + gfx::Point loc = ui_test_utils::GetCenterInScreenCoordinates( + bb_view_->other_bookmarks_button()); // Start a drag. #if defined(USE_AURA) @@ -971,9 +965,8 @@ void Step3A() { // Drag over other button. - views::LabelButton* other_button = bb_view_->other_bookmarks_button(); - gfx::Point loc(other_button->width() / 2, other_button->height() / 2); - views::View::ConvertPointToScreen(other_button, &loc); + gfx::Point loc = ui_test_utils::GetCenterInScreenCoordinates( + bb_view_->other_bookmarks_button()); ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone( loc.x() + 10, loc.y(), @@ -982,13 +975,12 @@ void Step4() { views::MenuItemView* drop_menu = bb_view_->GetDropMenu(); - ASSERT_TRUE(drop_menu != NULL); + ASSERT_NE(nullptr, drop_menu); ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing()); // Now drag back over first menu. - views::LabelButton* button = GetBookmarkButton(0); - gfx::Point loc(button->width() / 2, button->height() / 2); - views::View::ConvertPointToScreen(button, &loc); + gfx::Point loc = + ui_test_utils::GetCenterInScreenCoordinates(GetBookmarkButton(0)); ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone( loc.x(), loc.y(), base::BindOnce(&BookmarkBarViewTest8::Step5, base::Unretained(this)))); @@ -997,11 +989,11 @@ void Step5() { // Drop on folder F11. views::MenuItemView* drop_menu = bb_view_->GetDropMenu(); - ASSERT_TRUE(drop_menu != NULL); - ASSERT_TRUE(drop_menu->GetSubmenu()->IsShowing()); + ASSERT_NE(nullptr, drop_menu); + views::SubmenuView* drop_submenu = drop_menu->GetSubmenu(); + ASSERT_TRUE(drop_submenu->IsShowing()); - views::MenuItemView* target_menu = - drop_menu->GetSubmenu()->GetMenuItemAt(1); + views::MenuItemView* target_menu = drop_submenu->GetMenuItemAt(1); ui_test_utils::MoveMouseToCenterAndPress( target_menu, ui_controls::LEFT, ui_controls::UP, CreateEventTask(this, &BookmarkBarViewTest8::Step6)); @@ -1011,7 +1003,7 @@ // Make sure drop was processed. GURL final_url = model_->bookmark_bar_node()->GetChild(0)->GetChild(0)-> GetChild(1)->url(); - ASSERT_TRUE(final_url == url_dragging_); + EXPECT_EQ(url_dragging_, final_url); Done(); } @@ -2025,13 +2017,13 @@ private: void Step2() { // Menu should be showing. - views::MenuItemView* menu = bb_view_->GetMenu(); - ASSERT_TRUE(menu); - ASSERT_TRUE(menu->GetSubmenu()->IsShowing()); + views::MenuItemView* drop_menu = bb_view_->GetDropMenu(); + ASSERT_NE(nullptr, drop_menu); + views::SubmenuView* drop_submenu = drop_menu->GetSubmenu(); + ASSERT_TRUE(drop_submenu->IsShowing()); - views::MenuItemView* child_menu = - menu->GetSubmenu()->GetMenuItemAt(0); - ASSERT_TRUE(child_menu != NULL); + views::MenuItemView* child_menu = drop_submenu->GetMenuItemAt(0); + ASSERT_NE(nullptr, child_menu); // Move mouse to center of menu and press button. ui_test_utils::MoveMouseToCenterAndPress(
diff --git a/chrome/browser/ui/views/crostini/OWNERS b/chrome/browser/ui/views/crostini/OWNERS index 83af899..9d9bf0c4 100644 --- a/chrome/browser/ui/views/crostini/OWNERS +++ b/chrome/browser/ui/views/crostini/OWNERS
@@ -1,3 +1 @@ -benwells@chromium.org -nverne@chromium.org -timloh@chromium.org +file://chrome/browser/chromeos/crostini/OWNERS
diff --git a/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc b/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc index b1d571ac..32a2c37 100644 --- a/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc +++ b/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc
@@ -59,8 +59,10 @@ browser_process_platform_part_test_api_->InitializeCrosComponentManager( std::move(cros_component_manager)); } - void ServiceManagerConnectionStarted( - content::ServiceManagerConnection* connection) override { + // Ideally we'd call SetConnectionType in ServiceManagerConnectionStarted, + // but currently we have to wait for PreProfileInit to complete, since that + // creates the ash::Shell that AshService needs in order to start. + void PostProfileInit() override { connection_change_simulator_.SetConnectionType( network::mojom::ConnectionType::CONNECTION_WIFI); }
diff --git a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc index a6c79f7..ce82d09 100644 --- a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc +++ b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc
@@ -34,7 +34,8 @@ void ReopenTabPromoController::ShowPromo() { // This shouldn't be called more than once. Check that state is fresh. - DCHECK_EQ(StepAtDismissal::kBubbleShown, promo_step_); + DCHECK(!is_showing_); + is_showing_ = true; // Here, we start the promo display. We highlight the app menu button and open // the promo bubble. @@ -52,8 +53,7 @@ void ReopenTabPromoController::OnTabReopened(int command_id) { iph_service_->TabReopened(); - if (command_id == AppMenuModel::kMinRecentTabsCommandId) { - DCHECK_EQ(StepAtDismissal::kMenuOpened, promo_step_); + if (is_showing_ && command_id == AppMenuModel::kMinRecentTabsCommandId) { promo_step_ = StepAtDismissal::kTabReopened; } }
diff --git a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h index f445e94..a70be45 100644 --- a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h +++ b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h
@@ -67,6 +67,9 @@ // flow ends. StepAtDismissal promo_step_ = StepAtDismissal::kBubbleShown; + // Whether we are showing the promo. + bool is_showing_ = false; + DISALLOW_COPY_AND_ASSIGN(ReopenTabPromoController); };
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc index bc0464f..687cf337 100644 --- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc +++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc
@@ -89,7 +89,7 @@ void DispatchKeyEventPostIME( std::unique_ptr<ui::Event> event, DispatchKeyEventPostIMECallback callback) override { - std::move(callback).Run(false); + std::move(callback).Run(false, false); } void EnsureCaretNotInRect(const gfx::Rect& rect) override {} void SetEditableSelectionRange(const gfx::Range& range) override {}
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc index 40186ad..a5653fc 100644 --- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc +++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
@@ -14,8 +14,10 @@ : remote_client_(std::move(client)), details_(std::move(details)) {} RemoteTextInputClient::~RemoteTextInputClient() { - while (!pending_callbacks_.empty()) - RunNextPendingCallback(false); + while (!pending_callbacks_.empty()) { + RunNextPendingCallback(/* handled */ false, + /* stopped_propagation */ false); + } } void RemoteTextInputClient::SetTextInputState( @@ -32,8 +34,10 @@ details_->data = std::move(data); } -void RemoteTextInputClient::OnDispatchKeyEventPostIMECompleted(bool completed) { - RunNextPendingCallback(completed); +void RemoteTextInputClient::OnDispatchKeyEventPostIMECompleted( + bool handled, + bool stopped_propagation) { + RunNextPendingCallback(handled, stopped_propagation); } void RemoteTextInputClient::SetCompositionText( @@ -139,7 +143,8 @@ bool RemoteTextInputClient::GetTextFromRange(const gfx::Range& range, base::string16* text) const { if (!details_->data->text.has_value() || - range.GetMin() >= details_->data->text->length()) { + !details_->data->text_range.has_value() || + !details_->data->text_range->Contains(range)) { return false; } @@ -195,8 +200,8 @@ ui::EventDispatchDetails RemoteTextInputClient::DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) { - pending_callbacks_.push(std::move(ack_callback)); + DispatchKeyEventPostIMECallback callback) { + pending_callbacks_.push(std::move(callback)); remote_client_->DispatchKeyEventPostIME( ui::Event::Clone(*event), base::BindOnce(&RemoteTextInputClient::OnDispatchKeyEventPostIMECompleted, @@ -204,11 +209,12 @@ return ui::EventDispatchDetails(); } -void RemoteTextInputClient::RunNextPendingCallback(bool completed) { +void RemoteTextInputClient::RunNextPendingCallback(bool handled, + bool stopped_propagation) { DCHECK(!pending_callbacks_.empty()); - base::OnceCallback<void(bool)> callback = + DispatchKeyEventPostIMECallback callback = std::move(pending_callbacks_.front()); pending_callbacks_.pop(); if (callback) - std::move(callback).Run(completed); + std::move(callback).Run(handled, stopped_propagation); }
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h index 24292eb..169ea9f 100644 --- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h +++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
@@ -27,7 +27,8 @@ private: // See |pending_callbacks_| for details. - void OnDispatchKeyEventPostIMECompleted(bool completed); + void OnDispatchKeyEventPostIMECompleted(bool handled, + bool stopped_propagation); // ui::TextInputClient: void SetCompositionText(const ui::CompositionText& composition) override; @@ -65,11 +66,11 @@ // ui::internal::InputMethodDelegate: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) override; + DispatchKeyEventPostIMECallback callback) override; // Removes the callback at the front of |pending_callbacks_| and runs it with - // |completed| as the argument. - void RunNextPendingCallback(bool completed); + // |handled| and |stopped_propagation| as arguments. + void RunNextPendingCallback(bool handled, bool stopped_propagation); ws::mojom::TextInputClientPtr remote_client_; ws::mojom::SessionDetailsPtr details_; @@ -80,7 +81,7 @@ // This is done to ensure if we are destroyed all the callbacks are run. // This is necessary as the callbacks may have originated from a remote // client. - base::queue<base::OnceCallback<void(bool)>> pending_callbacks_; + base::queue<DispatchKeyEventPostIMECallback> pending_callbacks_; base::WeakPtrFactory<RemoteTextInputClient> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc index 13f3887..6e0d3c5 100644 --- a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc +++ b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
@@ -53,12 +53,13 @@ // A simple view to serve as a drop target. class TestTargetView : public views::View { public: - TestTargetView(); - ~TestTargetView() override; + TestTargetView() = default; + ~TestTargetView() override = default; - // Initializes this view to have the same bounds as |parent| and two draggable - // child views. - void Init(views::View* parent); + // Initializes this view to have the same bounds as its parent, and to have + // two draggable child views. + void Init(); + bool dragging() const { return dragging_; } bool dropped() const { return dropped_; } @@ -74,20 +75,17 @@ void OnDragExited() override; // Whether or not we are currently dragging. - bool dragging_; + bool dragging_ = false; // Whether or not a drop has been performed on the view. - bool dropped_; + bool dropped_ = false; DISALLOW_COPY_AND_ASSIGN(TestTargetView); }; -TestTargetView::TestTargetView() : dragging_(false), dropped_(false) { -} - -void TestTargetView::Init(views::View* parent) { - // First, match the parent's size. - SetSize(parent->size()); +void TestTargetView::Init() { + // First, fill the parent completely. + SetBoundsRect(parent()->GetLocalBounds()); // Then add two draggable views, each 10x2. views::View* first = new TestDragView(); @@ -99,9 +97,6 @@ second->SetBounds(15, 2, 10, 2); } -TestTargetView::~TestTargetView() { -} - bool TestTargetView::GetDropFormats( int* formats, std::set<ui::ClipboardFormatType>* format_types) { @@ -141,18 +136,18 @@ class MenuViewDragAndDropTest : public MenuTestBase { public: - MenuViewDragAndDropTest(); - ~MenuViewDragAndDropTest() override; + MenuViewDragAndDropTest() = default; + ~MenuViewDragAndDropTest() override = default; protected: + // MenuTestBase: + void BuildMenu(views::MenuItemView* menu) override; + TestTargetView* target_view() { return target_view_; } bool asked_to_close() const { return asked_to_close_; } bool performed_in_menu_drop() const { return performed_in_menu_drop_; } private: - // MenuTestBase: - void BuildMenu(views::MenuItemView* menu) override; - // views::MenuDelegate: bool GetDropFormats(views::MenuItemView* menu, int* formats, @@ -173,34 +168,23 @@ bool ShouldCloseOnDragComplete() override; // The special view in the menu, which supports its own drag and drop. - TestTargetView* target_view_; + TestTargetView* target_view_ = nullptr; // Whether or not we have been asked to close on drag complete. - bool asked_to_close_; + bool asked_to_close_ = false; // Whether or not a drop was performed in-menu (i.e., not including drops // in separate child views). - bool performed_in_menu_drop_; + bool performed_in_menu_drop_ = false; DISALLOW_COPY_AND_ASSIGN(MenuViewDragAndDropTest); }; -MenuViewDragAndDropTest::MenuViewDragAndDropTest() - : target_view_(NULL), - asked_to_close_(false), - performed_in_menu_drop_(false) { -} - -MenuViewDragAndDropTest::~MenuViewDragAndDropTest() { -} - void MenuViewDragAndDropTest::BuildMenu(views::MenuItemView* menu) { // Build a menu item that has a nested view that supports its own drag and // drop... - views::MenuItemView* menu_item_view = - menu->AppendMenuItem(1, - base::ASCIIToUTF16("item 1"), - views::MenuItemView::NORMAL); + views::MenuItemView* menu_item_view = menu->AppendMenuItem( + 1, base::ASCIIToUTF16("item 1"), views::MenuItemView::NORMAL); target_view_ = new TestTargetView(); menu_item_view->AddChildView(target_view_); // ... as well as two other, normal items. @@ -261,13 +245,14 @@ class MenuViewDragAndDropTestTestInMenuDrag : public MenuViewDragAndDropTest { public: - MenuViewDragAndDropTestTestInMenuDrag() {} - ~MenuViewDragAndDropTestTestInMenuDrag() override {} + MenuViewDragAndDropTestTestInMenuDrag() = default; + ~MenuViewDragAndDropTestTestInMenuDrag() override = default; - private: + protected: // MenuViewDragAndDropTest: void DoTestWithMenuOpen() override; + private: void Step2(); void Step3(); void Step4(); @@ -282,17 +267,15 @@ // We do this here (instead of in BuildMenu()) so that the menu is already // built and the bounds are correct. - target_view()->Init(submenu->GetMenuItemAt(0)); + target_view()->Init(); // We're going to drag the second menu element. views::MenuItemView* drag_view = submenu->GetMenuItemAt(1); - ASSERT_TRUE(drag_view != NULL); + ASSERT_NE(nullptr, drag_view); // Move mouse to center of menu and press button. ui_test_utils::MoveMouseToCenterAndPress( - drag_view, - ui_controls::LEFT, - ui_controls::DOWN, + drag_view, ui_controls::LEFT, ui_controls::DOWN, CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step2)); } @@ -303,8 +286,7 @@ // Start a drag. ui_controls::SendMouseMoveNotifyWhenDone( - loc.x() + 10, - loc.y(), + loc.x() + 10, loc.y(), CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step3)); ScheduleMouseMoveInBackground(loc.x(), loc.y()); @@ -318,13 +300,11 @@ ui_controls::SendMouseMove(loc.x(), loc.y()); ui_controls::SendMouseEventsNotifyWhenDone( - ui_controls::LEFT, - ui_controls::UP, + ui_controls::LEFT, ui_controls::UP, CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step4)); } void MenuViewDragAndDropTestTestInMenuDrag::Step4() { - // Verify our state. // We should have performed an in-menu drop, and the nested view should not // have had a drag and drop. Since the drag happened in menu code, the // delegate should not have been asked whether or not to close, and the menu @@ -347,13 +327,14 @@ class MenuViewDragAndDropTestNestedDrag : public MenuViewDragAndDropTest { public: - MenuViewDragAndDropTestNestedDrag() {} - ~MenuViewDragAndDropTestNestedDrag() override {} + MenuViewDragAndDropTestNestedDrag() = default; + ~MenuViewDragAndDropTestNestedDrag() override = default; - private: + protected: // MenuViewDragAndDropTest: void DoTestWithMenuOpen() override; + private: void Step2(); void Step3(); void Step4(); @@ -370,23 +351,21 @@ views::View* first_view = submenu->GetMenuItemAt(0); ASSERT_EQ(1, first_view->child_count()); views::View* child_view = first_view->child_at(0); - ASSERT_EQ(child_view, target_view()); + EXPECT_EQ(child_view, target_view()); // We do this here (instead of in BuildMenu()) so that the menu is already // built and the bounds are correct. - target_view()->Init(submenu->GetMenuItemAt(0)); + target_view()->Init(); // The target view should now have two children. ASSERT_EQ(2, target_view()->child_count()); views::View* drag_view = target_view()->child_at(0); - ASSERT_TRUE(drag_view != NULL); + ASSERT_NE(nullptr, drag_view); // Move mouse to center of menu and press button. ui_test_utils::MoveMouseToCenterAndPress( - drag_view, - ui_controls::LEFT, - ui_controls::DOWN, + drag_view, ui_controls::LEFT, ui_controls::DOWN, CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step2)); } @@ -397,8 +376,7 @@ // Start a drag. ui_controls::SendMouseMoveNotifyWhenDone( - loc.x() + 3, - loc.y(), + loc.x() + 3, loc.y(), CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step3)); ScheduleMouseMoveInBackground(loc.x(), loc.y()); @@ -415,13 +393,11 @@ ui_controls::SendMouseMove(loc.x(), loc.y()); ui_controls::SendMouseEventsNotifyWhenDone( - ui_controls::LEFT, - ui_controls::UP, + ui_controls::LEFT, ui_controls::UP, CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step4)); } void MenuViewDragAndDropTestNestedDrag::Step4() { - // Check our state. // The target view should have finished its drag, and should have dropped the // view. The main menu should not have done any drag, and the delegate should // have been asked if it wanted to close. Since the delegate did not want to @@ -430,10 +406,11 @@ EXPECT_TRUE(target_view()->dropped()); EXPECT_FALSE(performed_in_menu_drop()); EXPECT_TRUE(asked_to_close()); - EXPECT_TRUE(menu()->GetSubmenu()->IsShowing()); + views::SubmenuView* submenu = menu()->GetSubmenu(); + EXPECT_TRUE(submenu->IsShowing()); // Clean up. - menu()->GetSubmenu()->Close(); + submenu->Close(); Done(); }
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index bbdb96f2..caa8249d 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -611,6 +611,7 @@ } bool ProfileChooserView::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { // Suppresses the context menu because some features, such as inspecting // elements, are not appropriate in a bubble.
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.h b/chrome/browser/ui/views/profiles/profile_chooser_view.h index c94f8b8..5b2f65f 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.h +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.h
@@ -95,7 +95,8 @@ base::string16 GetAccessibleWindowTitle() const override; // content::WebContentsDelegate: - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc index 37d031c..3a8357c2 100644 --- a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc +++ b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc
@@ -173,6 +173,7 @@ } bool SigninViewControllerDelegateViews::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { // Discard the context menu return true;
diff --git a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h index 474d251..c27280d8 100644 --- a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h +++ b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h
@@ -53,7 +53,8 @@ content::WebContents* GetWebContents() override; // content::WebContentsDelegate: - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; bool HandleKeyboardEvent( content::WebContents* source, const content::NativeWebKeyboardEvent& event) override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc index 172f53e..53360c73 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc
@@ -51,8 +51,16 @@ void AppMenuShown() override; protected: - AppMenuButton* app_menu_button() { return app_menu_button_; } - BrowserActionsContainer* browser_actions() { return browser_actions_; } + AppMenuButton* GetAppMenuButton() { + return BrowserView::GetBrowserViewForBrowser(browser()) + ->toolbar_button_provider() + ->GetAppMenuButton(); + } + BrowserActionsContainer* GetBrowserActions() { + return BrowserView::GetBrowserViewForBrowser(browser()) + ->toolbar_button_provider() + ->GetBrowserActionsContainer(); + } // Performs a drag-and-drop operation by moving the mouse to |start|, clicking // the left button, moving the mouse to |end|, and releasing the left button. @@ -60,12 +68,8 @@ private: // InProcessBrowserTest: - void SetUpCommandLine(base::CommandLine* command_line) override; void SetUpOnMainThread() override; - void TearDownOnMainThread() override; - AppMenuButton* app_menu_button_ = nullptr; - BrowserActionsContainer* browser_actions_ = nullptr; bool menu_shown_ = false; base::OnceClosure quit_closure_; }; @@ -85,17 +89,17 @@ // Begin listening for the app menu to open. ScopedObserver<AppMenuButton, AppMenuButtonObserver> observer(this); - observer.Add(app_menu_button()); + observer.Add(GetAppMenuButton()); // Send the mouse to |start|, and click. The event queue must be flushed // after processing the click, or the next mouse move sent may get processed // before the click is fully handled, causing the test to fail. - ASSERT_TRUE(ui_controls::SendMouseMove(start.x(), start.y())); - ASSERT_TRUE( + EXPECT_TRUE(ui_controls::SendMouseMove(start.x(), start.y())); + EXPECT_TRUE( ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::DOWN)); // Enqueue an event to move the mouse, which will start a drag. - ASSERT_TRUE(ui_controls::SendMouseMove(end.x() + 10, end.y())); + EXPECT_TRUE(ui_controls::SendMouseMove(end.x() + 10, end.y())); // Enqueue an event to move the mouse to |end|. This must be done on a // background thread, since starting a drag triggers a nested message loop @@ -113,32 +117,19 @@ base::RunLoop run_loop; quit_closure_ = run_loop.QuitWhenIdleClosure(); run_loop.Run(); + + // Verify postconditions. EXPECT_TRUE(menu_shown_); - // The app menu should have closed once the drag-and-drop completed. - EXPECT_FALSE(app_menu_button()->IsMenuShowing()); -} - -void ToolbarViewInteractiveUITest::SetUpCommandLine( - base::CommandLine* command_line) { - extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); - ToolbarActionsBar::disable_animations_for_testing_ = true; - BrowserAppMenuButton::g_open_app_immediately_for_testing = true; + EXPECT_FALSE(GetAppMenuButton()->IsMenuShowing()); } void ToolbarViewInteractiveUITest::SetUpOnMainThread() { extensions::ExtensionBrowserTest::SetUpOnMainThread(); + + BrowserAppMenuButton::g_open_app_immediately_for_testing = true; ExtensionToolbarMenuView::set_close_menu_delay_for_testing(base::TimeDelta()); - - auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); - auto* toolbar_button_provider = browser_view->toolbar_button_provider(); - app_menu_button_ = toolbar_button_provider->GetAppMenuButton(); - browser_actions_ = toolbar_button_provider->GetBrowserActionsContainer(); -} - -void ToolbarViewInteractiveUITest::TearDownOnMainThread() { - ToolbarActionsBar::disable_animations_for_testing_ = false; - BrowserAppMenuButton::g_open_app_immediately_for_testing = false; + ToolbarActionsBar::disable_animations_for_testing_ = true; } #if defined(OS_LINUX) && defined(USE_AURA) @@ -161,17 +152,20 @@ ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test") .AppendASCII("browser_action") .AppendASCII("basics"))); - base::RunLoop().RunUntilIdle(); // Ensure the extension is fully loaded. + // Ensure the extension is fully loaded, and that the next steps will happen + // with a clean slate. + base::RunLoop().RunUntilIdle(); - ASSERT_EQ(1u, browser_actions()->VisibleBrowserActions()); - - ToolbarActionView* view = browser_actions()->GetToolbarActionViewAt(0); - ASSERT_TRUE(view); + BrowserActionsContainer* const browser_actions = GetBrowserActions(); + ASSERT_EQ(1u, browser_actions->VisibleBrowserActions()); + ToolbarActionView* toolbar_action = + browser_actions->GetToolbarActionViewAt(0); + ASSERT_TRUE(toolbar_action); gfx::Point browser_action_view_loc = - ui_test_utils::GetCenterInScreenCoordinates(view); + ui_test_utils::GetCenterInScreenCoordinates(toolbar_action); gfx::Point app_button_loc = - ui_test_utils::GetCenterInScreenCoordinates(app_menu_button()); + ui_test_utils::GetCenterInScreenCoordinates(GetAppMenuButton()); // Perform a drag and drop from the browser action view to the app button, // which should open the app menu.
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc index 382b4a25..c06cf2b 100644 --- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/ash_util.h" +#include "chrome/browser/ui/ash/assistant/assistant_pref_util.h" #include "chrome/browser/ui/views/chrome_web_dialog_view.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" #include "chrome/common/url_constants.h" @@ -149,7 +150,8 @@ PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); const bool completed = prefs->GetBoolean(arc::prefs::kVoiceInteractionEnabled) && - prefs->GetBoolean(arc::prefs::kVoiceInteractionActivityControlAccepted); + (::assistant::prefs::GetConsentStatus(prefs) == + ash::mojom::ConsentStatus::kActivityControlAccepted); std::move(callback_).Run(completed); SystemWebDialogDelegate::OnDialogClosed(json_retval); }
diff --git a/chrome/browser/ui/webui/chromeos/first_run/first_run_handler.cc b/chrome/browser/ui/webui/chromeos/first_run/first_run_handler.cc index 523bbed..d05e0369 100644 --- a/chrome/browser/ui/webui/chromeos/first_run/first_run_handler.cc +++ b/chrome/browser/ui/webui/chromeos/first_run/first_run_handler.cc
@@ -9,7 +9,7 @@ #include "ash/public/interfaces/voice_interaction_controller.mojom.h" #include "base/bind.h" #include "base/values.h" -#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/profiles/profile_manager.h" #include "chromeos/constants/chromeos_switches.h" #include "content/public/browser/web_ui.h" @@ -18,7 +18,7 @@ bool IsAssistantAllowed() { return ash::mojom::AssistantAllowedState::ALLOWED == - arc::IsAssistantAllowedForProfile( + assistant::IsAssistantAllowedForProfile( ProfileManager::GetActiveUserProfile()); }
diff --git a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc index 58821e2..fa78c67 100644 --- a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/chromeos/login/screens/assistant_optin_flow_screen.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/ash/assistant/assistant_pref_util.h" #include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h" #include "chrome/grit/generated_resources.h" #include "chromeos/services/assistant/public/features.h" @@ -216,8 +217,8 @@ weak_factory_.GetWeakPtr())); } else { RecordAssistantOptInStatus(ACTIVITY_CONTROL_SKIPPED); - profile->GetPrefs()->SetBoolean( - arc::prefs::kVoiceInteractionActivityControlAccepted, false); + ::assistant::prefs::SetConsentStatus(profile->GetPrefs(), + ash::mojom::ConsentStatus::kUnknown); HandleFlowFinished(); } } @@ -314,12 +315,17 @@ // No need to consent. Move to the next screen. activity_control_needed_ = false; PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - prefs->SetBoolean( - arc::prefs::kVoiceInteractionActivityControlAccepted, - (settings_ui.consent_flow_ui().consent_status() == - assistant::ConsentFlowUi_ConsentStatus_ALREADY_CONSENTED || - settings_ui.consent_flow_ui().consent_status() == - assistant::ConsentFlowUi_ConsentStatus_ASK_FOR_CONSENT)); + + bool consented = + settings_ui.consent_flow_ui().consent_status() == + assistant::ConsentFlowUi_ConsentStatus_ALREADY_CONSENTED || + settings_ui.consent_flow_ui().consent_status() == + assistant::ConsentFlowUi_ConsentStatus_ASK_FOR_CONSENT; + + ::assistant::prefs::SetConsentStatus( + prefs, consented ? ash::mojom::ConsentStatus::kActivityControlAccepted + : ash::mojom::ConsentStatus::kUnknown); + // Skip activity control and users will be in opted out mode. ShowNextScreen(); } else { @@ -380,8 +386,8 @@ } else if (activity_control_needed_) { activity_control_needed_ = false; PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - prefs->SetBoolean(arc::prefs::kVoiceInteractionActivityControlAccepted, - true); + ::assistant::prefs::SetConsentStatus( + prefs, ash::mojom::ConsentStatus::kActivityControlAccepted); } }
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc index cc33a62..6c591c5 100644 --- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc +++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -261,8 +261,8 @@ return new LookalikeUrlInterstitialPage( web_contents, safe_url, - std::make_unique<LookalikeUrlControllerClient>(web_contents, nullptr, - request_url, safe_url)); + std::make_unique<LookalikeUrlControllerClient>(web_contents, request_url, + safe_url)); } safe_browsing::SafeBrowsingBlockingPage* CreateSafeBrowsingBlockingPage(
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc index a9542d86..d504f1e 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
@@ -118,9 +118,11 @@ InterventionsInternalsPageHandler::InterventionsInternalsPageHandler( mojom::InterventionsInternalsPageHandlerRequest request, - previews::PreviewsUIService* previews_ui_service) + previews::PreviewsUIService* previews_ui_service, + network::NetworkQualityTracker* network_quality_tracker) : binding_(this, std::move(request)), previews_ui_service_(previews_ui_service), + network_quality_tracker_(network_quality_tracker), current_estimated_ect_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { logger_ = previews_ui_service_->previews_logger(); DCHECK(logger_); @@ -129,7 +131,8 @@ InterventionsInternalsPageHandler::~InterventionsInternalsPageHandler() { DCHECK(logger_); logger_->RemoveObserver(this); - g_browser_process->network_quality_tracker() + (network_quality_tracker_ ? network_quality_tracker_ + : g_browser_process->network_quality_tracker()) ->RemoveEffectiveConnectionTypeObserver(this); } @@ -138,7 +141,8 @@ page_ = std::move(page); DCHECK(page_); logger_->AddAndNotifyObserver(this); - g_browser_process->network_quality_tracker() + (network_quality_tracker_ ? network_quality_tracker_ + : g_browser_process->network_quality_tracker()) ->AddEffectiveConnectionTypeObserver(this); }
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h index 49a50b6..87a45b7 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h
@@ -24,7 +24,8 @@ public: InterventionsInternalsPageHandler( mojom::InterventionsInternalsPageHandlerRequest request, - previews::PreviewsUIService* previews_ui_service); + previews::PreviewsUIService* previews_ui_service, + network::NetworkQualityTracker* network_quality_tracker); ~InterventionsInternalsPageHandler() override; // mojom::InterventionsInternalsPageHandler: @@ -58,6 +59,10 @@ // guaranteed to outlive |this|. previews::PreviewsUIService* previews_ui_service_; + // Passed in during construction. If null, the main browser process tracker + // will be used instead. + network::NetworkQualityTracker* network_quality_tracker_; + // The current estimated effective connection type. net::EffectiveConnectionType current_estimated_ect_;
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc index b88f0037..972c029 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
@@ -284,7 +284,8 @@ mojom::InterventionsInternalsPageHandlerRequest handler_request = mojo::MakeRequest(&page_handler_ptr); page_handler_ = std::make_unique<InterventionsInternalsPageHandler>( - std::move(handler_request), previews_ui_service_.get()); + std::move(handler_request), previews_ui_service_.get(), + &test_network_quality_tracker_); mojom::InterventionsInternalsPagePtr page_ptr; mojom::InterventionsInternalsPageRequest page_request =
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc index c3b1370..106ee247 100644 --- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc +++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc
@@ -67,6 +67,6 @@ void InterventionsInternalsUI::BindInterventionsInternalsPageHandler( mojom::InterventionsInternalsPageHandlerRequest request) { DCHECK(previews_ui_service_); - page_handler_.reset(new InterventionsInternalsPageHandler( - std::move(request), previews_ui_service_)); + page_handler_ = std::make_unique<InterventionsInternalsPageHandler>( + std::move(request), previews_ui_service_, nullptr); }
diff --git a/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc b/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc index c0999a2..5e008a09 100644 --- a/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc +++ b/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc
@@ -219,7 +219,8 @@ void OnDialogClosed(const std::string& json_retval) override; void OnCloseContents(WebContents* source, bool* out_close_dialog) override; bool ShouldShowDialogTitle() const override; - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; // Overridden from ResponseDelegate: void SetDialogInteractionResult(MakeChromeDefaultResult result) override; @@ -347,6 +348,7 @@ } bool SetAsDefaultBrowserDialogImpl::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { return true; }
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 b3926a9..be6b6620 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
@@ -60,6 +60,7 @@ #include "ash/public/interfaces/voice_interaction_controller.mojom.h" #include "base/system/sys_info.h" #include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" @@ -2183,7 +2184,7 @@ void AddSearchStrings(content::WebUIDataSource* html_source, Profile* profile) { #if defined(OS_CHROMEOS) const bool is_assistant_allowed = - arc::IsAssistantAllowedForProfile(profile) == + assistant::IsAssistantAllowedForProfile(profile) == ash::mojom::AssistantAllowedState::ALLOWED; #endif
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index 359a4107..209387fa 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -649,20 +649,19 @@ ] } -if (is_win) { - # This is split out here instead of being part of //chrome/test:browser_tests - # because the tests have hardware requirements and this is cleaner than trying - # to conditionally skip tests based on hardware (browser tests don't have - # the equivalent to Android's @Restriction annotation that allows you to - # easily skip tests at runtime). +# This is split out here instead of being part of //chrome/test:browser_tests +# because the tests have hardware requirements and this is cleaner than trying +# to conditionally skip tests based on hardware (browser tests don't have +# the equivalent to Android's @Restriction annotation that allows you to +# easily skip tests at runtime). +if (!is_android) { test("xr_browser_tests") { + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + + # Common infrastructure. sources = [ - "test/browser_test_browser_renderer_browser_interface.cc", - "test/browser_test_browser_renderer_browser_interface.h", "test/mock_openvr_device_hook_base.cc", "test/mock_openvr_device_hook_base.h", - "test/ui_utils.cc", - "test/ui_utils.h", "test/webvr_browser_test.cc", "test/webvr_browser_test.h", "test/webxr_browser_test.cc", @@ -671,32 +670,26 @@ "test/webxr_vr_browser_test.h", "test/xr_browser_test.cc", "test/xr_browser_test.h", - "webxr_vr_frame_pose_browser_test.cc", - "webxr_vr_input_browser_test.cc", - "webxr_vr_permission_request_browser_test.cc", - "webxr_vr_pixel_browser_test.cc", - "webxr_vr_tab_browser_test.cc", - "webxr_vr_transition_browser_test.cc", ] - defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + # Common/partially common tests. + sources += [ "webxr_vr_transition_browser_test.cc" ] + # Common dependencies. deps = [ ":vr_common", "//base", + "//chrome:packed_resources", "//chrome/test:browser_tests_runner", "//chrome/test:test_support", "//chrome/test:test_support_ui", "//device/vr:vr", "//device/vr/public/mojom:mojom", "//device/vr/public/mojom:test_mojom", - "//third_party/openvr:openvr", ] + data_deps = [] - data_deps = [ - "//device/vr:openvr_mock", - ] - + # Common data data = [ "//chrome/test/data/xr/e2e_test_files/", "//third_party/blink/web_tests/resources/testharness.js", @@ -705,5 +698,29 @@ "$root_out_dir/chrome_200_percent.pak", "$root_out_dir/resources.pak", ] + + # Windows-only tests and dependencies. + if (is_win) { + # Infrastructure. + sources += [ + "test/browser_test_browser_renderer_browser_interface.cc", + "test/browser_test_browser_renderer_browser_interface.h", + "test/ui_utils.cc", + "test/ui_utils.h", + ] + + # Tests. + sources += [ + "webxr_vr_frame_pose_browser_test.cc", + "webxr_vr_input_browser_test.cc", + "webxr_vr_permission_request_browser_test.cc", + "webxr_vr_pixel_browser_test.cc", + "webxr_vr_tab_browser_test.cc", + ] + + deps += [ "//third_party/openvr:openvr" ] + + data_deps += [ "//device/vr:openvr_mock" ] + } } }
diff --git a/chrome/browser/vr/metrics/session_metrics_helper.cc b/chrome/browser/vr/metrics/session_metrics_helper.cc index 09871f1a..8446460 100644 --- a/chrome/browser/vr/metrics/session_metrics_helper.cc +++ b/chrome/browser/vr/metrics/session_metrics_helper.cc
@@ -51,10 +51,6 @@ MODE_BROWSER_WITH_VIDEO, MODE_WEBVR_WITH_VIDEO, SESSION_VR_WITH_VIDEO, - MODE_FULLSCREEN_DLA, - MODE_BROWSER_DLA, - MODE_WEBVR_DLA, - SESSION_VR_DLA, }; const char* HistogramNameFromSessionType(SessionEventName name) { @@ -67,10 +63,6 @@ static constexpr char kWebVrVideo[] = "VRSessionVideoTime.WebVR"; static constexpr char kBrowserVideo[] = "VRSessionVideoTime.Browser"; static constexpr char kFullscreenVideo[] = "VRSessionVideoTime.Fullscreen"; - static constexpr char kVrSessionDla[] = "VRSessionTimeFromDLA"; - static constexpr char kWebVrDla[] = "VRSessionTimeFromDLA.WebVR"; - static constexpr char kBrowserDla[] = "VRSessionTimeFromDLA.Browser"; - static constexpr char kFullscreenDla[] = "VRSessionTimeFromDLA.Fullscreen"; switch (name) { case MODE_FULLSCREEN: @@ -89,14 +81,6 @@ return kWebVrVideo; case SESSION_VR_WITH_VIDEO: return kVrSessionVideo; - case MODE_FULLSCREEN_DLA: - return kFullscreenDla; - case MODE_BROWSER_DLA: - return kBrowserDla; - case MODE_WEBVR_DLA: - return kWebVrDla; - case SESSION_VR_DLA: - return kVrSessionDla; default: NOTREACHED(); return nullptr; @@ -221,16 +205,13 @@ } SessionMetricsHelper* SessionMetricsHelper::CreateForWebContents( content::WebContents* contents, - Mode initial_mode, - bool started_with_autopresentation) { + Mode initial_mode) { // This is not leaked as the SessionMetricsHelperData will clean it up. - return new SessionMetricsHelper(contents, initial_mode, - started_with_autopresentation); + return new SessionMetricsHelper(contents, initial_mode); } SessionMetricsHelper::SessionMetricsHelper(content::WebContents* contents, - Mode initial_mode, - bool started_with_autopresentation) { + Mode initial_mode) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(contents); @@ -243,15 +224,9 @@ is_webvr_ = initial_mode == Mode::kWebXrVrPresentation; is_vr_enabled_ = initial_mode != Mode::kNoVr; - started_with_autopresentation_ = started_with_autopresentation; - if (started_with_autopresentation) { - session_timer_ = std::make_unique<SessionTimerImpl<SESSION_VR_DLA>>( - kMaximumVideoSessionGap, kMinimumVideoSessionDuration); - } else { - session_timer_ = std::make_unique<SessionTimerImpl<SESSION_VR>>( - kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); - } + session_timer_ = std::make_unique<SessionTimerImpl<SESSION_VR>>( + kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); session_video_timer_ = std::make_unique<SessionTimerImpl<SESSION_VR_WITH_VIDEO>>( kMaximumVideoSessionGap, kMinimumVideoSessionDuration); @@ -462,26 +437,16 @@ } void SessionMetricsHelper::OnEnterRegularBrowsing() { - if (started_with_autopresentation_) { - mode_timer_ = std::make_unique<SessionTimerImpl<MODE_BROWSER_DLA>>( - kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); - } else { - mode_timer_ = std::make_unique<SessionTimerImpl<MODE_BROWSER>>( - kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); - } + mode_timer_ = std::make_unique<SessionTimerImpl<MODE_BROWSER>>( + kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); mode_video_timer_ = std::make_unique<SessionTimerImpl<MODE_BROWSER_WITH_VIDEO>>( kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); } void SessionMetricsHelper::OnEnterPresentation() { - if (started_with_autopresentation_) { - mode_timer_ = std::make_unique<SessionTimerImpl<MODE_WEBVR_DLA>>( - kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); - } else { - mode_timer_ = std::make_unique<SessionTimerImpl<MODE_WEBVR>>( - kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); - } + mode_timer_ = std::make_unique<SessionTimerImpl<MODE_WEBVR>>( + kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); mode_video_timer_ = std::make_unique<SessionTimerImpl<MODE_WEBVR_WITH_VIDEO>>( kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); @@ -515,13 +480,8 @@ } void SessionMetricsHelper::OnEnterFullscreenBrowsing() { - if (started_with_autopresentation_) { - mode_timer_ = std::make_unique<SessionTimerImpl<MODE_FULLSCREEN_DLA>>( - kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); - } else { - mode_timer_ = std::make_unique<SessionTimerImpl<MODE_FULLSCREEN>>( - kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); - } + mode_timer_ = std::make_unique<SessionTimerImpl<MODE_FULLSCREEN>>( + kMaximumHeadsetSessionGap, kMinimumHeadsetSessionDuration); mode_video_timer_ = std::make_unique<SessionTimerImpl<MODE_FULLSCREEN_WITH_VIDEO>>(
diff --git a/chrome/browser/vr/metrics/session_metrics_helper.h b/chrome/browser/vr/metrics/session_metrics_helper.h index eb8f0d4d..16f2fc8a 100644 --- a/chrome/browser/vr/metrics/session_metrics_helper.h +++ b/chrome/browser/vr/metrics/session_metrics_helper.h
@@ -155,8 +155,7 @@ static SessionMetricsHelper* FromWebContents(content::WebContents* contents); static SessionMetricsHelper* CreateForWebContents( content::WebContents* contents, - Mode initial_mode, - bool started_with_autopresentation); + Mode initial_mode); ~SessionMetricsHelper() override; @@ -170,9 +169,7 @@ void ReportRequestPresent(); private: - SessionMetricsHelper(content::WebContents* contents, - Mode initial_mode, - bool started_with_autopresentation); + SessionMetricsHelper(content::WebContents* contents, Mode initial_mode); // WebContentObserver void MediaStartedPlaying(const MediaPlayerInfo& media_info, @@ -215,7 +212,6 @@ bool is_fullscreen_ = false; bool is_webvr_ = false; bool is_vr_enabled_ = false; - bool started_with_autopresentation_ = false; GURL last_requested_url_; NavigationMethod last_url_request_method_;
diff --git a/chrome/browser/vr/service/xr_device_impl.cc b/chrome/browser/vr/service/xr_device_impl.cc index 88c03ec..5a0b162 100644 --- a/chrome/browser/vr/service/xr_device_impl.cc +++ b/chrome/browser/vr/service/xr_device_impl.cc
@@ -175,8 +175,8 @@ if (!metrics_helper) { // This will only happen if we are not already in VR, set start params // accordingly. - metrics_helper = SessionMetricsHelper::CreateForWebContents( - web_contents, Mode::kNoVr, false); + metrics_helper = + SessionMetricsHelper::CreateForWebContents(web_contents, Mode::kNoVr); } metrics_helper->ReportRequestPresent(); }
diff --git a/chrome/browser/vr/test/webvr_browser_test.h b/chrome/browser/vr/test/webvr_browser_test.h index 674006f..1ee7466 100644 --- a/chrome/browser/vr/test/webvr_browser_test.h +++ b/chrome/browser/vr/test/webvr_browser_test.h
@@ -32,6 +32,16 @@ using WebXrBrowserTestBase::EndSessionOrFail; }; +// Test class with OpenVR support disabled. +class WebVrBrowserTestOpenVrDisabled : public WebVrBrowserTestBase { + public: + WebVrBrowserTestOpenVrDisabled() { + append_switches_.push_back(switches::kEnableWebVR); + } +}; + +// OpenVR feature only defined on Windows. +#ifdef OS_WIN // Test class with standard features enabled: WebVR and OpenVR support. class WebVrBrowserTestStandard : public WebVrBrowserTestBase { public: @@ -48,14 +58,7 @@ enable_features_.push_back(features::kOpenVR); } }; - -// Test class with OpenVR support disabled. -class WebVrBrowserTestOpenVrDisabled : public WebVrBrowserTestBase { - public: - WebVrBrowserTestOpenVrDisabled() { - append_switches_.push_back(switches::kEnableWebVR); - } -}; +#endif // OS_WIN } // namespace vr
diff --git a/chrome/browser/vr/test/webxr_vr_browser_test.h b/chrome/browser/vr/test/webxr_vr_browser_test.h index e8f47129..fdc042a 100644 --- a/chrome/browser/vr/test/webxr_vr_browser_test.h +++ b/chrome/browser/vr/test/webxr_vr_browser_test.h
@@ -31,6 +31,16 @@ using WebXrBrowserTestBase::EndSessionOrFail; }; +// Test class with OpenVR disabled. +class WebXrVrBrowserTestOpenVrDisabled : public WebXrVrBrowserTestBase { + public: + WebXrVrBrowserTestOpenVrDisabled() { + enable_features_.push_back(features::kWebXr); + } +}; + +// OpenVR feature only defined on Windows. +#ifdef OS_WIN // Test class with standard features enabled: WebXR and OpenVR. class WebXrVrBrowserTestStandard : public WebXrVrBrowserTestBase { public: @@ -47,14 +57,7 @@ enable_features_.push_back(features::kOpenVR); } }; - -// Test class with OpenVR disabled. -class WebXrVrBrowserTestOpenVrDisabled : public WebXrVrBrowserTestBase { - public: - WebXrVrBrowserTestOpenVrDisabled() { - enable_features_.push_back(features::kWebXr); - } -}; +#endif // OS_WIN } // namespace vr
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc index 52062d4..077282a 100644 --- a/chrome/browser/vr/testapp/vr_test_context.cc +++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -525,7 +525,6 @@ webvr_frames_received_ = false; UiInitialState state; state.in_web_vr = true; - state.web_vr_autopresentation_expected = true; ui_instance_->ReinitializeForTest(state); } else { ui_instance_->ReinitializeForTest(UiInitialState());
diff --git a/chrome/browser/vr/ui_initial_state.h b/chrome/browser/vr/ui_initial_state.h index 377acf1..af7dc56 100644 --- a/chrome/browser/vr/ui_initial_state.h +++ b/chrome/browser/vr/ui_initial_state.h
@@ -15,7 +15,6 @@ UiInitialState(); UiInitialState(const UiInitialState& other); bool in_web_vr = false; - bool web_vr_autopresentation_expected = false; bool browsing_disabled = false; bool has_or_can_request_record_audio_permission = true; bool assets_supported = false;
diff --git a/chrome/browser/vr/ui_pixeltest.cc b/chrome/browser/vr/ui_pixeltest.cc index 958741a..b377c73 100644 --- a/chrome/browser/vr/ui_pixeltest.cc +++ b/chrome/browser/vr/ui_pixeltest.cc
@@ -22,7 +22,6 @@ // Set up scene. UiInitialState ui_initial_state; ui_initial_state.in_web_vr = false; - ui_initial_state.web_vr_autopresentation_expected = false; MakeUi(ui_initial_state, LocationBarState(GURL("https://example.com"), security_state::SECURE, &omnibox::kHttpsValidIcon, true, false));
diff --git a/chrome/browser/vr/webxr_vr_transition_browser_test.cc b/chrome/browser/vr/webxr_vr_transition_browser_test.cc index 7fde682..173e061 100644 --- a/chrome/browser/vr/webxr_vr_transition_browser_test.cc +++ b/chrome/browser/vr/webxr_vr_transition_browser_test.cc
@@ -15,6 +15,58 @@ namespace vr { +// Tests that WebVR/WebXR is not exposed if the flag is not on and the page does +// not have an origin trial token. +void TestApiDisabledWithoutFlagSetImpl(WebXrVrBrowserTestBase* t, + std::string filename) { + t->LoadUrlAndAwaitInitialization(t->GetFileUrlForHtmlTestFile(filename)); + t->WaitOnJavaScriptStep(); + t->EndTest(); +} + +// Tests that WebVR does not return any devices if OpenVR support is disabled. +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestOpenVrDisabled, + TestWebVrNoDevicesWithoutOpenVr) { + LoadUrlAndAwaitInitialization( + GetFileUrlForHtmlTestFile("generic_webvr_page")); + EXPECT_FALSE(XrDeviceFound()) + << "Found a VRDisplay even with OpenVR disabled"; + AssertNoJavaScriptErrors(); +} + +// Tests that WebXR does not return any devices if OpenVR support is disabled. +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestOpenVrDisabled, + TestWebXrNoDevicesWithoutOpenVr) { + LoadUrlAndAwaitInitialization( + GetFileUrlForHtmlTestFile("test_webxr_does_not_return_device")); + WaitOnJavaScriptStep(); + EndTest(); +} + +// Windows-specific tests. +#ifdef OS_WIN + +IN_PROC_BROWSER_TEST_F(WebVrBrowserTestWebVrDisabled, + TestWebVrDisabledWithoutFlagSet) { + TestApiDisabledWithoutFlagSetImpl(this, + "test_webvr_disabled_without_flag_set"); +} +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestWebXrDisabled, + TestWebXrDisabledWithoutFlagSet) { + TestApiDisabledWithoutFlagSetImpl(this, + "test_webxr_disabled_without_flag_set"); +} + +// Tests that window.requestAnimationFrame continues to fire when we have a +// non-immersive WebXR session. +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, + TestWindowRafFiresDuringNonImmersiveSession) { + LoadUrlAndAwaitInitialization(GetFileUrlForHtmlTestFile( + "test_window_raf_fires_during_non_immersive_session")); + WaitOnJavaScriptStep(); + EndTest(); +} + // Tests that a successful requestPresent or requestSession call enters // an immersive session. void TestPresentationEntryImpl(WebXrVrBrowserTestBase* t, @@ -55,58 +107,6 @@ this, "webxr_test_window_raf_fires_while_presenting"); } -// 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(WebXrVrBrowserTestBase* t, - std::string filename) { - t->LoadUrlAndAwaitInitialization(t->GetFileUrlForHtmlTestFile(filename)); - t->WaitOnJavaScriptStep(); - t->EndTest(); -} - -IN_PROC_BROWSER_TEST_F(WebVrBrowserTestWebVrDisabled, - TestWebVrDisabledWithoutFlagSet) { - TestApiDisabledWithoutFlagSetImpl(this, - "test_webvr_disabled_without_flag_set"); -} -IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestWebXrDisabled, - TestWebXrDisabledWithoutFlagSet) { - TestApiDisabledWithoutFlagSetImpl(this, - "test_webxr_disabled_without_flag_set"); -} - -// 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(WebVrBrowserTestOpenVrDisabled, - TestWebVrNoDevicesWithoutOpenVr) { - LoadUrlAndAwaitInitialization( - GetFileUrlForHtmlTestFile("generic_webvr_page")); - EXPECT_FALSE(XrDeviceFound()) - << "Found a VRDisplay even with OpenVR disabled"; - 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(WebXrVrBrowserTestOpenVrDisabled, - TestWebXrNoDevicesWithoutOpenVr) { - LoadUrlAndAwaitInitialization( - GetFileUrlForHtmlTestFile("test_webxr_does_not_return_device")); - WaitOnJavaScriptStep(); - EndTest(); -} - -// Tests that window.requestAnimationFrame continues to fire when we have a -// non-immersive WebXR session. -IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestStandard, - TestWindowRafFiresDuringNonImmersiveSession) { - LoadUrlAndAwaitInitialization(GetFileUrlForHtmlTestFile( - "test_window_raf_fires_during_non_immersive_session")); - 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(WebXrVrBrowserTestStandard, @@ -121,4 +121,6 @@ EndTest(); } +#endif // OS_WIN + } // namespace vr
diff --git a/chrome/common/cloud_print/cloud_print_helpers.cc b/chrome/common/cloud_print/cloud_print_helpers.cc index 54187afa7..c36ae44 100644 --- a/chrome/common/cloud_print/cloud_print_helpers.cc +++ b/chrome/common/cloud_print/cloud_print_helpers.cc
@@ -8,6 +8,7 @@ #include <limits> #include <memory> +#include <utility> #include "base/json/json_reader.h" #include "base/logging.h" @@ -184,23 +185,15 @@ return cloud_print_server_url.ReplaceComponents(replacements); } -std::unique_ptr<base::DictionaryValue> ParseResponseJSON( - const std::string& response_data, - bool* succeeded) { - std::unique_ptr<base::Value> message_value( - base::JSONReader::ReadDeprecated(response_data)); - if (!message_value.get()) - return std::unique_ptr<base::DictionaryValue>(); +base::Value ParseResponseJSON(const std::string& response_data, + bool* succeeded) { + base::Optional<base::Value> message_value = + base::JSONReader::Read(response_data); + if (!message_value || !message_value->is_dict()) + return base::Value(); - if (!message_value->is_dict()) - return std::unique_ptr<base::DictionaryValue>(); - - std::unique_ptr<base::DictionaryValue> response_dict( - static_cast<base::DictionaryValue*>(message_value.release())); - if (succeeded && - !response_dict->GetBoolean(kSuccessValue, succeeded)) - *succeeded = false; - return response_dict; + *succeeded = message_value->FindBoolKey(kSuccessValue).value_or(false); + return std::move(*message_value); } std::string GetMultipartMimeType(const std::string& mime_boundary) {
diff --git a/chrome/common/cloud_print/cloud_print_helpers.h b/chrome/common/cloud_print/cloud_print_helpers.h index b62f00f..904f934 100644 --- a/chrome/common/cloud_print/cloud_print_helpers.h +++ b/chrome/common/cloud_print/cloud_print_helpers.h
@@ -10,11 +10,10 @@ #include <string> #include <vector> - class GURL; namespace base { -class DictionaryValue; +class Value; } // Helper consts and methods for both cloud print and chrome browser. @@ -60,12 +59,11 @@ const std::string& proxy_id); // Parses the response data for any cloud print server request. The method -// returns null if there was an error in parsing the JSON. The succeeded -// value returns the value of the "success" value in the response JSON. -// Returns the response as a dictionary value. -std::unique_ptr<base::DictionaryValue> ParseResponseJSON( - const std::string& response_data, - bool* succeeded); +// returns none Value if there was an error in parsing the JSON. The |succeeded| +// parameters returns the value of the "success" value in the response JSON. +// Returns the response as a dictionary value on success. +base::Value ParseResponseJSON(const std::string& response_data, + bool* succeeded); // Returns the MIME type of multipart with |mime_boundary|. std::string GetMultipartMimeType(const std::string& mime_boundary);
diff --git a/chrome/common/safe_browsing/archive_analyzer_results.h b/chrome/common/safe_browsing/archive_analyzer_results.h index 374bfac..86d1900 100644 --- a/chrome/common/safe_browsing/archive_analyzer_results.h +++ b/chrome/common/safe_browsing/archive_analyzer_results.h
@@ -33,6 +33,8 @@ ClientDownloadRequest_DetachedCodeSignature> detached_code_signatures; #endif // OS_MACOSX + int file_count; + int directory_count; ArchiveAnalyzerResults(); ArchiveAnalyzerResults(const ArchiveAnalyzerResults& other); ~ArchiveAnalyzerResults();
diff --git a/chrome/common/safe_browsing/zip_analyzer.cc b/chrome/common/safe_browsing/zip_analyzer.cc index 75f9ce7..773f8bb 100644 --- a/chrome/common/safe_browsing/zip_analyzer.cc +++ b/chrome/common/safe_browsing/zip_analyzer.cc
@@ -71,6 +71,8 @@ bool contains_zip = false; bool advanced = true; int zip_entry_count = 0; + results->file_count = 0; + results->directory_count = 0; for (; reader.HasMore(); advanced = reader.AdvanceToNextEntry()) { if (!advanced) { DVLOG(1) << "Could not advance to next entry, aborting zip scan."; @@ -95,6 +97,11 @@ FILE_PATH_LITERAL(".zip")) contains_zip = true; zip_entry_count++; + + if (reader.current_entry_info()->is_directory()) + results->directory_count++; + else + results->file_count++; } results->success = true;
diff --git a/chrome/credential_provider/gaiacp/os_user_manager.cc b/chrome/credential_provider/gaiacp/os_user_manager.cc index 3d5f376..5d3de3b 100644 --- a/chrome/credential_provider/gaiacp/os_user_manager.cc +++ b/chrome/credential_provider/gaiacp/os_user_manager.cc
@@ -422,9 +422,9 @@ local_domain_buffer, &domain_length, &use)) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr != HRESULT_FROM_WIN32(ERROR_NONE_MAPPED)) { - if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { - if ((username_size > 0 && name_length >= username_size)) - hr = S_OK; + if (username_size == 0 && + hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { + hr = S_OK; } } }
diff --git a/chrome/installer/mini_installer/mini_installer_exe_main.cc b/chrome/installer/mini_installer/mini_installer_exe_main.cc index 59dd5bc..2967b5b 100644 --- a/chrome/installer/mini_installer/mini_installer_exe_main.cc +++ b/chrome/installer/mini_installer/mini_installer_exe_main.cc
@@ -4,6 +4,7 @@ #include <stdint.h> +#include "build/build_config.h" #include "chrome/installer/mini_installer/mini_installer.h" // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx @@ -27,6 +28,9 @@ } #endif +// We don't link with the CRT so we have to implement CRT functions that the +// compiler generates calls to. + // VC Express editions don't come with the memset CRT obj file and linking to // the obj files between versions becomes a bit problematic. Therefore, // simply implement memset. @@ -56,4 +60,22 @@ *scan++ = static_cast<uint8_t>(c); return dest; } + +#if defined(_DEBUG) && defined(ARCH_CPU_ARM64) +// The compiler generates calls to memcpy for ARM64 debug builds so we need to +// supply a memcpy implementation in that configuration. +// See comments above for why we do this incantation. +#ifdef __clang__ +__attribute__((used)) +#else +#pragma function(memcpy) +#endif +void* memcpy(void* destination, const void* source, size_t count) { + auto* dst = reinterpret_cast<uint8_t*>(destination); + auto* src = reinterpret_cast<const uint8_t*>(source); + while (count--) + *dst++ = *src++; + return destination; +} +#endif } // extern "C"
diff --git a/chrome/renderer/translate/translate_helper_browsertest.cc b/chrome/renderer/translate/translate_helper_browsertest.cc index d8888c7..93e6f1b 100644 --- a/chrome/renderer/translate/translate_helper_browsertest.cc +++ b/chrome/renderer/translate/translate_helper_browsertest.cc
@@ -89,8 +89,7 @@ trans_result_error_type_ = translate::TranslateErrors::NONE; // Will get new result values via OnPageTranslated. - Translate(translate_script, network::mojom::URLLoaderFactoryPtr(), - source_lang, target_lang, + Translate(translate_script, source_lang, target_lang, base::Bind(&TestTranslateHelper::OnPageTranslated, base::Unretained(this))); }
diff --git a/chrome/service/cloud_print/cloud_print_auth.cc b/chrome/service/cloud_print/cloud_print_auth.cc index 8acf7d6..e956456 100644 --- a/chrome/service/cloud_print/cloud_print_auth.cc +++ b/chrome/service/cloud_print/cloud_print_auth.cc
@@ -4,6 +4,8 @@ #include "chrome/service/cloud_print/cloud_print_auth.h" +#include <vector> + #include "base/bind.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" @@ -164,8 +166,10 @@ CloudPrintURLFetcher::ResponseAction CloudPrintAuth::HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { + DCHECK(json_data.is_dict()); + if (!succeeded) { VLOG(1) << "CP_AUTH: Creating robot account failed"; UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", @@ -175,8 +179,8 @@ return CloudPrintURLFetcher::STOP_PROCESSING; } - std::string auth_code; - if (!json_data->GetString(kOAuthCodeValue, &auth_code)) { + const std::string* auth_code = json_data.FindStringKey(kOAuthCodeValue); + if (!auth_code) { VLOG(1) << "CP_AUTH: Creating robot account returned invalid json response"; UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_ROBO_JSON_ERROR, @@ -189,14 +193,14 @@ AUTH_EVENT_ROBO_SUCCEEDED, AUTH_EVENT_MAX); - json_data->GetString(kXMPPJidValue, &robot_email_); + const std::string* robot_email = json_data.FindStringKey(kXMPPJidValue); + if (robot_email) + robot_email_ = *robot_email; // Now that we have an auth code we need to get the refresh and access tokens. - oauth_client_.reset( - new gaia::GaiaOAuthClient(client_->GetURLLoaderFactory())); - oauth_client_->GetTokensFromAuthCode(oauth_client_info_, - auth_code, - kCloudPrintAPIMaxRetryCount, - this); + oauth_client_ = + std::make_unique<gaia::GaiaOAuthClient>(client_->GetURLLoaderFactory()); + oauth_client_->GetTokensFromAuthCode(oauth_client_info_, *auth_code, + kCloudPrintAPIMaxRetryCount, this); return CloudPrintURLFetcher::STOP_PROCESSING; }
diff --git a/chrome/service/cloud_print/cloud_print_auth.h b/chrome/service/cloud_print/cloud_print_auth.h index a295398..143b2cb 100644 --- a/chrome/service/cloud_print/cloud_print_auth.h +++ b/chrome/service/cloud_print/cloud_print_auth.h
@@ -79,7 +79,7 @@ CloudPrintURLFetcher::ResponseAction HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) override; CloudPrintURLFetcher::ResponseAction OnRequestAuthError() override; std::string GetAuthHeader() override;
diff --git a/chrome/service/cloud_print/cloud_print_connector.cc b/chrome/service/cloud_print/cloud_print_connector.cc index 2e5ca0d..34a3f53cc5 100644 --- a/chrome/service/cloud_print/cloud_print_connector.cc +++ b/chrome/service/cloud_print/cloud_print_connector.cc
@@ -6,6 +6,10 @@ #include <stddef.h> +#include <algorithm> +#include <limits> +#include <vector> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/location.h" @@ -187,7 +191,7 @@ CloudPrintURLFetcher::ResponseAction CloudPrintConnector::HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { if (!IsRunning()) // Orphan response. Connector has been stopped already. return CloudPrintURLFetcher::STOP_PROCESSING; @@ -208,11 +212,10 @@ CloudPrintConnector::~CloudPrintConnector() {} CloudPrintURLFetcher::ResponseAction -CloudPrintConnector::HandlePrinterListResponse( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded) { +CloudPrintConnector::HandlePrinterListResponse(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded) { DCHECK(succeeded); if (!succeeded) return CloudPrintURLFetcher::RETRY_REQUEST; @@ -240,25 +243,29 @@ } // Go through the list of the cloud printers and init print job handlers. - const base::ListValue* printer_list = nullptr; // There may be no "printers" value in the JSON - if (json_data->GetList(kPrinterListValue, &printer_list) && printer_list) { - for (size_t i = 0; i < printer_list->GetSize(); ++i) { - const base::DictionaryValue* printer_data = nullptr; - if (!printer_list->GetDictionary(i, &printer_data)) + const base::Value* printer_list = + json_data.FindKeyOfType(kPrinterListValue, base::Value::Type::LIST); + if (printer_list) { + for (const auto& printer : printer_list->GetList()) { + if (!printer.is_dict()) continue; std::string printer_name; - printer_data->GetString(kNameValue, &printer_name); std::string printer_id; - printer_data->GetString(kIdValue, &printer_id); + const std::string* str = printer.FindStringKey(kNameValue); + if (str) + printer_name = *str; + str = printer.FindStringKey(kIdValue); + if (str) + printer_id = *str; if (!settings_.ShouldConnect(printer_name)) { VLOG(1) << "CP_CONNECTOR: Deleting " << printer_name << " id: " << printer_id << " as blacklisted"; AddPendingDeleteTask(printer_id); } else if (RemovePrinterFromList(printer_name, &local_printers)) { - InitJobHandlerForPrinter(printer_data); + InitJobHandlerForPrinter(printer); } else { // Cloud printer is not found on the local system. if (full_list || settings_.delete_on_enum_fail()) { @@ -291,7 +298,7 @@ CloudPrintConnector::HandlePrinterListResponseSettingsUpdate( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { DCHECK(succeeded); if (!succeeded) @@ -302,11 +309,10 @@ } CloudPrintURLFetcher::ResponseAction -CloudPrintConnector::HandlePrinterDeleteResponse( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded) { +CloudPrintConnector::HandlePrinterDeleteResponse(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded) { VLOG(1) << "CP_CONNECTOR: Handler printer delete response" << ", succeeded: " << succeeded << ", url: " << url; @@ -318,17 +324,18 @@ CloudPrintConnector::HandleRegisterPrinterResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { VLOG(1) << "CP_CONNECTOR: Handler printer register response" << ", succeeded: " << succeeded << ", url: " << url; if (succeeded) { - const base::ListValue* printer_list = nullptr; + const base::Value* printer_list = + json_data.FindKeyOfType(kPrinterListValue, base::Value::Type::LIST); // There should be a "printers" value in the JSON - if (json_data->GetList(kPrinterListValue, &printer_list)) { - const base::DictionaryValue* printer_data = nullptr; - if (printer_list->GetDictionary(0, &printer_data)) + if (printer_list && !printer_list->GetList().empty()) { + const base::Value& printer_data = printer_list->GetList()[0]; + if (printer_data.is_dict()) InitJobHandlerForPrinter(printer_data); } } @@ -336,7 +343,6 @@ return CloudPrintURLFetcher::STOP_PROCESSING; } - void CloudPrintConnector::StartGetRequest(const GURL& url, int max_retries, ResponseHandler handler) { @@ -391,10 +397,13 @@ } void CloudPrintConnector::InitJobHandlerForPrinter( - const base::DictionaryValue* printer_data) { - DCHECK(printer_data); + const base::Value& printer_data) { + DCHECK(printer_data.is_dict()); + PrinterJobHandler::PrinterInfoFromCloud printer_info_cloud; - printer_data->GetString(kIdValue, &printer_info_cloud.printer_id); + const std::string* str = printer_data.FindStringKey(kIdValue); + if (str) + printer_info_cloud.printer_id = *str; DCHECK(!printer_info_cloud.printer_id.empty()); VLOG(1) << "CP_CONNECTOR: Init job handler" << ", printer id: " << printer_info_cloud.printer_id; @@ -402,34 +411,38 @@ return; // Nothing to do if we already have a job handler for this printer. printing::PrinterBasicInfo printer_info; - printer_data->GetString(kNameValue, &printer_info.printer_name); + str = printer_data.FindStringKey(kNameValue); + if (str) + printer_info.printer_name = *str; DCHECK(!printer_info.printer_name.empty()); - printer_data->GetString(kPrinterDescValue, - &printer_info.printer_description); + str = printer_data.FindStringKey(kPrinterDescValue); + if (str) + printer_info.printer_description = *str; // Printer status is a string value which actually contains an integer. - std::string printer_status; - if (printer_data->GetString(kPrinterStatusValue, &printer_status)) { - base::StringToInt(printer_status, &printer_info.printer_status); - } - printer_data->GetString(kPrinterCapsHashValue, - &printer_info_cloud.caps_hash); - const base::ListValue* tags_list = nullptr; - if (printer_data->GetList(kTagsValue, &tags_list) && tags_list) { - for (size_t i = 0; i < tags_list->GetSize(); ++i) { - std::string tag; - if (tags_list->GetString(i, &tag) && - base::StartsWith(tag, kCloudPrintServiceTagsHashTagName, + str = printer_data.FindStringKey(kPrinterStatusValue); + if (str) + base::StringToInt(*str, &printer_info.printer_status); + str = printer_data.FindStringKey(kPrinterCapsHashValue); + if (str) + printer_info_cloud.caps_hash = *str; + + const base::Value* tags_list = + printer_data.FindKeyOfType(kTagsValue, base::Value::Type::LIST); + if (tags_list) { + for (const auto& tag : tags_list->GetList()) { + if (tag.is_string() && + base::StartsWith(tag.GetString(), kCloudPrintServiceTagsHashTagName, base::CompareCase::INSENSITIVE_ASCII)) { std::vector<std::string> tag_parts = base::SplitString( - tag, "=", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); + tag.GetString(), "=", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); if (tag_parts.size() == 2) printer_info_cloud.tags_hash = tag_parts[1]; } } } - int xmpp_timeout = 0; - printer_data->GetInteger(kLocalSettingsPendingXmppValue, &xmpp_timeout); + int xmpp_timeout = + printer_data.FindIntKey(kLocalSettingsPendingXmppValue).value_or(0); printer_info_cloud.current_xmpp_timeout = settings_.xmpp_ping_timeout_sec(); printer_info_cloud.pending_xmpp_timeout = xmpp_timeout; @@ -444,17 +457,19 @@ } void CloudPrintConnector::UpdateSettingsFromPrintersList( - const base::DictionaryValue* json_data) { - const base::ListValue* printer_list = nullptr; + const base::Value& json_data) { int min_xmpp_timeout = std::numeric_limits<int>::max(); // There may be no "printers" value in the JSON - if (json_data->GetList(kPrinterListValue, &printer_list) && printer_list) { - for (size_t i = 0; i < printer_list->GetSize(); ++i) { - const base::DictionaryValue* printer_data = nullptr; - if (printer_list->GetDictionary(i, &printer_data)) { + const base::Value* printer_list = + json_data.FindKeyOfType(kPrinterListValue, base::Value::Type::LIST); + if (printer_list) { + for (const auto& printer : printer_list->GetList()) { + if (printer.is_dict()) { int xmpp_timeout = 0; - if (printer_data->GetInteger(kLocalSettingsPendingXmppValue, - &xmpp_timeout)) { + base::Optional<int> timeout = + printer.FindIntKey(kLocalSettingsPendingXmppValue); + if (timeout) { + xmpp_timeout = *timeout; min_xmpp_timeout = std::min(xmpp_timeout, min_xmpp_timeout); } }
diff --git a/chrome/service/cloud_print/cloud_print_connector.h b/chrome/service/cloud_print/cloud_print_connector.h index 7f123a8..8648495 100644 --- a/chrome/service/cloud_print/cloud_print_connector.h +++ b/chrome/service/cloud_print/cloud_print_connector.h
@@ -64,11 +64,10 @@ // Prototype for a response handler. typedef CloudPrintURLFetcher::ResponseAction ( - CloudPrintConnector::*ResponseHandler)( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded); + CloudPrintConnector::*ResponseHandler)(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded); enum PendingTaskType { PENDING_PRINTERS_NONE, @@ -105,7 +104,7 @@ CloudPrintURLFetcher::ResponseAction HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) override; CloudPrintURLFetcher::ResponseAction OnRequestAuthError() override; std::string GetAuthHeader() override; @@ -114,25 +113,25 @@ CloudPrintURLFetcher::ResponseAction HandlePrinterListResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded); CloudPrintURLFetcher::ResponseAction HandlePrinterListResponseSettingsUpdate( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded); CloudPrintURLFetcher::ResponseAction HandlePrinterDeleteResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded); CloudPrintURLFetcher::ResponseAction HandleRegisterPrinterResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded); // End response handlers @@ -154,9 +153,9 @@ bool RemovePrinterFromList(const std::string& printer_name, printing::PrinterList* printer_list); - void InitJobHandlerForPrinter(const base::DictionaryValue* printer_data); + void InitJobHandlerForPrinter(const base::Value& printer_data); - void UpdateSettingsFromPrintersList(const base::DictionaryValue* json_data); + void UpdateSettingsFromPrintersList(const base::Value& json_data); void AddPendingAvailableTask(); void AddPendingDeleteTask(const std::string& id);
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher.cc b/chrome/service/cloud_print/cloud_print_url_fetcher.cc index 4a984b0c..075b8ba 100644 --- a/chrome/service/cloud_print/cloud_print_url_fetcher.cc +++ b/chrome/service/cloud_print/cloud_print_url_fetcher.cc
@@ -121,11 +121,10 @@ } CloudPrintURLFetcher::ResponseAction -CloudPrintURLFetcher::Delegate::HandleJSONData( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded) { +CloudPrintURLFetcher::Delegate::HandleJSONData(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded) { return CONTINUE_PROCESSING; } @@ -198,14 +197,11 @@ // response, we will retry (to handle the case where we got redirected // to a non-cloudprint-server URL eg. for authentication). bool succeeded = false; - std::unique_ptr<base::DictionaryValue> response_dict = - ParseResponseJSON(data, &succeeded); + base::Value response_dict = ParseResponseJSON(data, &succeeded); - if (response_dict) { - action = delegate_->HandleJSONData(source, - source->GetURL(), - response_dict.get(), - succeeded); + if (response_dict.is_dict()) { + action = delegate_->HandleJSONData(source, source->GetURL(), + response_dict, succeeded); } else { action = RETRY_REQUEST; }
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher.h b/chrome/service/cloud_print/cloud_print_url_fetcher.h index 50cc6c7..fb1acb4cc 100644 --- a/chrome/service/cloud_print/cloud_print_url_fetcher.h +++ b/chrome/service/cloud_print/cloud_print_url_fetcher.h
@@ -16,7 +16,7 @@ class GURL; namespace base { -class DictionaryValue; +class Value; } namespace net { @@ -89,11 +89,10 @@ // This will be invoked only if HandleRawResponse and HandleRawData return // CONTINUE_PROCESSING AND if the response contains a valid JSON dictionary. // |succeeded| is the value of the "success" field in the response JSON. - virtual ResponseAction HandleJSONData( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded); + virtual ResponseAction HandleJSONData(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded); // Invoked when the retry limit for this request has been reached (if there // was a retry limit - a limit of -1 implies no limit).
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc b/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc index 5ec24513..c368165 100644 --- a/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc +++ b/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
@@ -164,7 +164,7 @@ CloudPrintURLFetcher::ResponseAction HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) override; void SetHandleRawResponse(bool handle_raw_response) { @@ -280,11 +280,10 @@ } CloudPrintURLFetcher::ResponseAction -CloudPrintURLFetcherBasicTest::HandleJSONData( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded) { +CloudPrintURLFetcherBasicTest::HandleJSONData(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded) { // We should never get here if we returned true in one of the above methods. EXPECT_FALSE(handle_raw_response_); EXPECT_FALSE(handle_raw_data_);
diff --git a/chrome/service/cloud_print/cloud_print_wipeout.cc b/chrome/service/cloud_print/cloud_print_wipeout.cc index 134ae98..40db126 100644 --- a/chrome/service/cloud_print/cloud_print_wipeout.cc +++ b/chrome/service/cloud_print/cloud_print_wipeout.cc
@@ -49,7 +49,7 @@ CloudPrintURLFetcher::ResponseAction CloudPrintWipeout::HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { // We don't care if delete was successful or not here. UnregisterNextPrinter();
diff --git a/chrome/service/cloud_print/cloud_print_wipeout.h b/chrome/service/cloud_print/cloud_print_wipeout.h index 4a3a3d2..1e17f75 100644 --- a/chrome/service/cloud_print/cloud_print_wipeout.h +++ b/chrome/service/cloud_print/cloud_print_wipeout.h
@@ -38,7 +38,7 @@ CloudPrintURLFetcher::ResponseAction HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) override; void OnRequestGiveUp() override; CloudPrintURLFetcher::ResponseAction OnRequestAuthError() override;
diff --git a/chrome/service/cloud_print/job_status_updater.cc b/chrome/service/cloud_print/job_status_updater.cc index 76b8d9b..063faf4 100644 --- a/chrome/service/cloud_print/job_status_updater.cc +++ b/chrome/service/cloud_print/job_status_updater.cc
@@ -99,7 +99,7 @@ CloudPrintURLFetcher::ResponseAction JobStatusUpdater::HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { if (IsTerminalJobState(last_job_details_.status)) { base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/service/cloud_print/job_status_updater.h b/chrome/service/cloud_print/job_status_updater.h index ab5e81a2..7308731 100644 --- a/chrome/service/cloud_print/job_status_updater.h +++ b/chrome/service/cloud_print/job_status_updater.h
@@ -50,7 +50,7 @@ CloudPrintURLFetcher::ResponseAction HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) override; CloudPrintURLFetcher::ResponseAction OnRequestAuthError() override; std::string GetAuthHeader() override;
diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index a497a3a..093cef0 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc
@@ -4,6 +4,7 @@ #include "chrome/service/cloud_print/printer_job_handler.h" +#include <utility> #include <vector> #include "base/bind.h" @@ -173,7 +174,7 @@ CloudPrintURLFetcher::ResponseAction PrinterJobHandler::HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { DCHECK(next_json_data_handler_); return (this->*next_json_data_handler_)(source, url, json_data, succeeded); @@ -287,11 +288,10 @@ // Begin Response handlers CloudPrintURLFetcher::ResponseAction -PrinterJobHandler::HandlePrinterUpdateResponse( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded) { +PrinterJobHandler::HandlePrinterUpdateResponse(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded) { VLOG(1) << "CP_CONNECTOR: Handling printer update response" << ", printer id: " << printer_info_cloud_.printer_id; // We are done here. Go to the Stop state @@ -303,16 +303,15 @@ } CloudPrintURLFetcher::ResponseAction -PrinterJobHandler::HandleJobMetadataResponse( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded) { +PrinterJobHandler::HandleJobMetadataResponse(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded) { VLOG(1) << "CP_CONNECTOR: Handling job metadata response" << ", printer id: " << printer_info_cloud_.printer_id; if (succeeded) { std::vector<JobDetails> jobs = - job_queue_handler_.GetJobsFromQueue(*json_data); + job_queue_handler_.GetJobsFromQueue(json_data); if (!jobs.empty()) { if (jobs[0].time_remaining_.is_zero()) { job_details_ = jobs[0]; @@ -414,7 +413,7 @@ PrinterJobHandler::HandleInProgressStatusUpdateResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { VLOG(1) << "CP_CONNECTOR: Handling success status update response" << ", printer id: " << printer_info_cloud_.printer_id; @@ -427,7 +426,7 @@ PrinterJobHandler::HandleFailureStatusUpdateResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) { VLOG(1) << "CP_CONNECTOR: Handling failure status update response" << ", printer id: " << printer_info_cloud_.printer_id;
diff --git a/chrome/service/cloud_print/printer_job_handler.h b/chrome/service/cloud_print/printer_job_handler.h index ebf9d4a..efa30bd 100644 --- a/chrome/service/cloud_print/printer_job_handler.h +++ b/chrome/service/cloud_print/printer_job_handler.h
@@ -127,7 +127,7 @@ CloudPrintURLFetcher::ResponseAction HandleJSONData( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded) override; void OnRequestGiveUp() override; CloudPrintURLFetcher::ResponseAction OnRequestAuthError() override; @@ -160,11 +160,10 @@ // Prototype for a JSON data handler. typedef CloudPrintURLFetcher::ResponseAction ( - PrinterJobHandler::*JSONDataHandler)( - const net::URLFetcher* source, - const GURL& url, - const base::DictionaryValue* json_data, - bool succeeded); + PrinterJobHandler::*JSONDataHandler)(const net::URLFetcher* source, + const GURL& url, + const base::Value& json_data, + bool succeeded); // Prototype for a data handler. typedef CloudPrintURLFetcher::ResponseAction ( PrinterJobHandler::*DataHandler)(const net::URLFetcher* source, @@ -177,13 +176,13 @@ CloudPrintURLFetcher::ResponseAction HandlePrinterUpdateResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded); CloudPrintURLFetcher::ResponseAction HandleJobMetadataResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded); CloudPrintURLFetcher::ResponseAction HandlePrintTicketResponse( @@ -199,13 +198,13 @@ CloudPrintURLFetcher::ResponseAction HandleInProgressStatusUpdateResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded); CloudPrintURLFetcher::ResponseAction HandleFailureStatusUpdateResponse( const net::URLFetcher* source, const GURL& url, - const base::DictionaryValue* json_data, + const base::Value& json_data, bool succeeded); // End request handlers for each state in the state machine
diff --git a/chrome/service/cloud_print/printer_job_queue_handler.cc b/chrome/service/cloud_print/printer_job_queue_handler.cc index f8577716..36cf82e 100644 --- a/chrome/service/cloud_print/printer_job_queue_handler.cc +++ b/chrome/service/cloud_print/printer_job_queue_handler.cc
@@ -25,22 +25,33 @@ return base::Time::Now(); } -JobDetails ConstructJobDetailsFromJson(const base::DictionaryValue& job_data) { - JobDetails job_details; +JobDetails ConstructJobDetailsFromJson(const base::Value& job_data) { + DCHECK(job_data.is_dict()); - job_data.GetString(kIdValue, &job_details.job_id_); - job_data.GetString(kTitleValue, &job_details.job_title_); - job_data.GetString(kOwnerValue, &job_details.job_owner_); - job_data.GetString(kTicketUrlValue, &job_details.print_ticket_url_); - job_data.GetString(kFileUrlValue, &job_details.print_data_url_); + JobDetails job_details; + const std::string* str = job_data.FindStringKey(kIdValue); + if (str) + job_details.job_id_ = *str; + str = job_data.FindStringKey(kTitleValue); + if (str) + job_details.job_title_ = *str; + str = job_data.FindStringKey(kOwnerValue); + if (str) + job_details.job_owner_ = *str; + str = job_data.FindStringKey(kTicketUrlValue); + if (str) + job_details.print_ticket_url_ = *str; + str = job_data.FindStringKey(kFileUrlValue); + if (str) + job_details.print_data_url_ = *str; // Get tags for print job. - const base::ListValue* tags = nullptr; - if (job_data.GetList(kTagsValue, &tags)) { - for (size_t i = 0; i < tags->GetSize(); i++) { - std::string value; - if (tags->GetString(i, &value)) - job_details.tags_.push_back(value); + const base::Value* tags = + job_data.FindKeyOfType(kTagsValue, base::Value::Type::LIST); + if (tags) { + for (const auto& tag : tags->GetList()) { + if (tag.is_string()) + job_details.tags_.push_back(tag.GetString()); } } return job_details; @@ -109,20 +120,22 @@ } std::vector<JobDetails> PrinterJobQueueHandler::GetJobsFromQueue( - const base::DictionaryValue& json_data) { + const base::Value& json_data) { + DCHECK(json_data.is_dict()); + std::vector<JobDetails> jobs; - const base::ListValue* job_list = nullptr; - if (!json_data.GetList(kJobListValue, &job_list)) + const base::Value* job_list = + json_data.FindKeyOfType(kJobListValue, base::Value::Type::LIST); + if (!job_list) return jobs; std::vector<JobDetails> jobs_with_timeouts; - for (const auto& job_value : *job_list) { - const base::DictionaryValue* job_data = nullptr; - if (!job_value.GetAsDictionary(&job_data)) + for (const auto& job_value : job_list->GetList()) { + if (!job_value.is_dict()) continue; - JobDetails job_details_current = ConstructJobDetailsFromJson(*job_data); + JobDetails job_details_current = ConstructJobDetailsFromJson(job_value); job_details_current.time_remaining_ = ComputeBackoffTime(job_details_current.job_id_); if (job_details_current.time_remaining_.is_zero()) {
diff --git a/chrome/service/cloud_print/printer_job_queue_handler.h b/chrome/service/cloud_print/printer_job_queue_handler.h index 4bf813679..6a2e9425 100644 --- a/chrome/service/cloud_print/printer_job_queue_handler.h +++ b/chrome/service/cloud_print/printer_job_queue_handler.h
@@ -18,7 +18,7 @@ #include "chrome/common/cloud_print/cloud_print_constants.h" namespace base { -class DictionaryValue; +class Value; } namespace cloud_print { @@ -64,9 +64,8 @@ // Returns a vector with details of all jobs in the queue, sorted by time // until they are ready to print, lowest to highest. Jobs that are ready to - // print will have a time_remaining_ of 0. - std::vector<JobDetails> GetJobsFromQueue( - const base::DictionaryValue& json_data); + // print will have a |time_remaining_| of 0. + std::vector<JobDetails> GetJobsFromQueue(const base::Value& json_data); // Marks a job fetch as failed. Returns "true" if the job will be retried. bool JobFetchFailed(const std::string& job_id);
diff --git a/chrome/service/cloud_print/printer_job_queue_handler_unittest.cc b/chrome/service/cloud_print/printer_job_queue_handler_unittest.cc index 920d2d89..ded9038 100644 --- a/chrome/service/cloud_print/printer_job_queue_handler_unittest.cc +++ b/chrome/service/cloud_print/printer_job_queue_handler_unittest.cc
@@ -8,8 +8,8 @@ #include <set> -#include "base/json/json_reader.h" #include "base/memory/ptr_util.h" +#include "base/test/values_test_util.h" #include "base/values.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -68,16 +68,12 @@ class PrinterJobQueueHandlerTest : public ::testing::Test { protected: - void SetUp() override { - base::JSONReader json_reader; - data_ = base::DictionaryValue::From( - json_reader.ReadDeprecated(kJobListResponse)); - } + void SetUp() override { data_ = base::test::ParseJson(kJobListResponse); } - const base::DictionaryValue& GetDictionary() const { return *data_; } + const base::Value& GetDictionary() const { return data_; } private: - std::unique_ptr<base::DictionaryValue> data_; + base::Value data_; }; TEST_F(PrinterJobQueueHandlerTest, BasicJobReadTest) {
diff --git a/chrome/services/file_util/public/mojom/safe_archive_analyzer_param_traits.h b/chrome/services/file_util/public/mojom/safe_archive_analyzer_param_traits.h index a0b7080..a297d76 100644 --- a/chrome/services/file_util/public/mojom/safe_archive_analyzer_param_traits.h +++ b/chrome/services/file_util/public/mojom/safe_archive_analyzer_param_traits.h
@@ -3,6 +3,8 @@ // found in the LICENSE file. // Multiply-included param traits file, so no include guard. +// Disabling the presubmit warning with: +// no-include-guard-because-multiply-included #if !defined(FULL_SAFE_BROWSING) #error FULL_SAFE_BROWSING should be defined. @@ -103,4 +105,6 @@ IPC_STRUCT_TRAITS_MEMBER(signature_blob) IPC_STRUCT_TRAITS_MEMBER(detached_code_signatures) #endif // OS_MACOSX + IPC_STRUCT_TRAITS_MEMBER(file_count) + IPC_STRUCT_TRAITS_MEMBER(directory_count) IPC_STRUCT_TRAITS_END()
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 5d144be..addef4b 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -690,7 +690,7 @@ "../browser/loader/cors_origin_access_list_browsertest.cc", "../browser/loadtimes_extension_bindings_browsertest.cc", "../browser/locale_tests_browsertest.cc", - "../browser/lookalikes/lookalike_url_navigation_observer_browsertest.cc", + "../browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc", "../browser/media/autoplay_metrics_browsertest.cc", "../browser/media/cast_mirroring_service_host_browsertest.cc", "../browser/media/defer_background_media_browsertest.cc", @@ -3242,7 +3242,7 @@ "../browser/importer/firefox_profile_lock_unittest.cc", "../browser/importer/profile_writer_unittest.cc", "../browser/lifetime/application_lifetime_unittest.cc", - "../browser/lookalikes/lookalike_url_navigation_observer_unittest.cc", + "../browser/lookalikes/lookalike_url_navigation_throttle_unittest.cc", # Media remoting is not supported on Android for now. "../browser/media/cast_remoting_connector_unittest.cc",
diff --git a/chrome/test/base/interactive_test_utils_common_views.cc b/chrome/test/base/interactive_test_utils_common_views.cc index 1e399b2..9c3f6fd 100644 --- a/chrome/test/base/interactive_test_utils_common_views.cc +++ b/chrome/test/base/interactive_test_utils_common_views.cc
@@ -31,12 +31,17 @@ animator->StopAnimating(); } - gfx::Point view_center(view->width() / 2, view->height() / 2); - views::View::ConvertPointToScreen(view, &view_center); + gfx::Point view_center = GetCenterInScreenCoordinates(view); ui_controls::SendMouseMoveNotifyWhenDone( view_center.x(), view_center.y(), base::BindOnce(&internal::ClickTask, button, button_state, closure, accelerator_state)); } +gfx::Point GetCenterInScreenCoordinates(const views::View* view) { + gfx::Point center = view->GetLocalBounds().CenterPoint(); + views::View::ConvertPointToScreen(view, ¢er); + return center; +} + } // namespace ui_test_utils
diff --git a/chrome/test/base/interactive_test_utils_views.cc b/chrome/test/base/interactive_test_utils_views.cc index 3f04aa0..f62d538 100644 --- a/chrome/test/base/interactive_test_utils_views.cc +++ b/chrome/test/base/interactive_test_utils_views.cc
@@ -44,10 +44,4 @@ view->RequestFocus(); } -gfx::Point GetCenterInScreenCoordinates(const views::View* view) { - gfx::Point center(view->width() / 2, view->height() / 2); - views::View::ConvertPointToScreen(view, ¢er); - return center; -} - } // namespace ui_test_utils
diff --git a/chrome/test/data/android/manage_render_test_goldens.py b/chrome/test/data/android/manage_render_test_goldens.py index bf6c057cf..51764f1f 100755 --- a/chrome/test/data/android/manage_render_test_goldens.py +++ b/chrome/test/data/android/manage_render_test_goldens.py
@@ -45,12 +45,18 @@ def download(directory): - subprocess.check_call([ - 'download_from_google_storage', - '--bucket', STORAGE_BUCKET, - '-d', directory, - '-t', str(THREAD_COUNT), - ]) + # Downloading the files can be very spammy, so only show the output if + # something actually goes wrong. + try: + subprocess.check_output([ + 'download_from_google_storage', + '--bucket', STORAGE_BUCKET, + '-d', directory, + '-t', str(THREAD_COUNT), + ], stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + print ('Downloading RenderTest goldens in directory %s failed with error ' + '%d: %s') % (directory, e.returncode, e.output) def upload(directory):
diff --git a/chrome/test/data/appcache/french_page_with_appcache.html b/chrome/test/data/appcache/french_page_with_appcache.html deleted file mode 100644 index 16df202b..0000000 --- a/chrome/test/data/appcache/french_page_with_appcache.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<html manifest="simple_page.manifest"> -<head> - <head><title>Cette page est en Français</title></head> - <script type="text/javascript"> - function onCachedEvent() { - window.document.title = "AppCache mis à jour"; - } - - function onLoad() { - window.applicationCache.addEventListener('cached', onCachedEvent, false); - } - </script> -</head> -<body onload="onLoad()"> -Cette page a été rédigée en français. Saviez-vous que le Français est la langue officielle des jeux olympiques? Ça vous en bouche un coin, pas vrai? -</body> -</html>
diff --git a/chrome/test/data/appcache/simple_page.manifest b/chrome/test/data/appcache/simple_page.manifest deleted file mode 100644 index a6f40c55..0000000 --- a/chrome/test/data/appcache/simple_page.manifest +++ /dev/null
@@ -1,4 +0,0 @@ -CACHE MANIFEST - -NETWORK: -*
diff --git a/chrome/test/data/extensions/api_test/worker/background.js b/chrome/test/data/extensions/api_test/worker/background.js index 7706614..b52c81b0 100644 --- a/chrome/test/data/extensions/api_test/worker/background.js +++ b/chrome/test/data/extensions/api_test/worker/background.js
@@ -88,11 +88,10 @@ undefined, () => { return new Worker(redirectedWorkerUrl) }, workerUrl), - // TODO(crbug.com/861564): expectedUrl should be the response URL. sameOriginRedirectTest.bind( undefined, () => { return new Worker(redirectedWorkerUrl, {type: 'module'}) }, - redirectedWorkerUrl), + workerUrl), sameOriginRedirectTest.bind( undefined, () => { return new SharedWorker(redirectedSharedWorkerUrl) },
diff --git a/chrome/test/data/webui/settings/cups_printer_page_tests.js b/chrome/test/data/webui/settings/cups_printer_page_tests.js index 6e52b0a..5a0b14e 100644 --- a/chrome/test/data/webui/settings/cups_printer_page_tests.js +++ b/chrome/test/data/webui/settings/cups_printer_page_tests.js
@@ -410,4 +410,42 @@ assertDeepEquals(usbInfo, printer.printerUsbInfo); }); }); + + /** + * Test that the close button exists on the configure dialog. + */ + test('ConfigureDialogCancelDisabled', function() { + // Starts in discovery dialog, select add manually button. + const discoveryDialog = dialog.$$('add-printer-discovery-dialog'); + assertTrue(!!discoveryDialog); + discoveryDialog.$$('.secondary-button').click(); + Polymer.dom.flush(); + + // Now we should be in the manually add dialog. + const addDialog = dialog.$$('add-printer-manually-dialog'); + assertTrue(!!addDialog); + fillAddManuallyDialog(addDialog); + + // Advance to the configure dialog. + addDialog.$$('.action-button').click(); + Polymer.dom.flush(); + + // Configure is shown. + const configureDialog = dialog.$$('add-printer-configuring-dialog'); + assertTrue(!!configureDialog); + + const closeButton = configureDialog.$$('.cancel-button'); + assertTrue(!!closeButton); + assertFalse(closeButton.disabled); + + const waitForClose = test_util.eventToPromise('close', configureDialog); + + closeButton.click(); + Polymer.dom.flush(); + + return waitForClose.then(() => { + dialog = page.$$('settings-cups-add-printer-dialog'); + assertFalse(dialog.showConfiguringDialog_); + }); + }); });
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_webxr_poses.html b/chrome/test/data/xr/e2e_test_files/html/test_webxr_poses.html index 866a3e50..32ac995 100644 --- a/chrome/test/data/xr/e2e_test_files/html/test_webxr_poses.html +++ b/chrome/test/data/xr/e2e_test_files/html/test_webxr_poses.html
@@ -17,6 +17,7 @@ <script> var frame_id = 0; var frame_data_array = {}; + var pose_array = {}; // We exit presentation before checking stuff that needs the frame of // reference, so we need to cache its value. var cached_frame_of_ref = null; @@ -42,13 +43,12 @@ function checkFrameView(frame_id, eye, expected) { let frame_data = frame_data_array[frame_id]; - let pose = frame_data.getViewerPose(cached_frame_of_ref); + let pose = pose_array[frame_id]; return MatrixCompare(pose.views[eye].viewMatrix, expected); } function checkFramePose(frame_id, expected) { - let frame_data = frame_data_array[frame_id]; - let pose = frame_data.getViewerPose(cached_frame_of_ref); + let pose = pose_array[frame_id]; if (!pose) { console.log("unexpected - null pose"); return false; @@ -63,6 +63,7 @@ frame_id++; frame_data_array[frame_id] = frame; cached_frame_of_ref = sessionInfos[sessionTypes.IMMERSIVE].currentRefSpace; + pose_array[frame_id] = frame.getViewerPose(cached_frame_of_ref); var encoded_frame_id = {}; encoded_frame_id.r = frame_id % 256;
diff --git a/chromecast/browser/cast_media_blocker_unittest.cc b/chromecast/browser/cast_media_blocker_unittest.cc index 7ebcf27..760d206 100644 --- a/chromecast/browser/cast_media_blocker_unittest.cc +++ b/chromecast/browser/cast_media_blocker_unittest.cc
@@ -45,6 +45,11 @@ MOCK_METHOD0(NextTrack, void()); MOCK_METHOD0(SkipAd, void()); MOCK_METHOD1(SetAudioFocusGroupId, void(const base::UnguessableToken&)); + MOCK_METHOD4(GetMediaImageBitmap, + void(const media_session::MediaImage&, + int minimum_size_px, + int desired_size_px, + GetMediaImageBitmapCallback callback)); private: DISALLOW_COPY_AND_ASSIGN(MockMediaSession);
diff --git a/chromecast/browser/extension_request_protocol_handler.cc b/chromecast/browser/extension_request_protocol_handler.cc index 0c0cb09..b673ed88 100644 --- a/chromecast/browser/extension_request_protocol_handler.cc +++ b/chromecast/browser/extension_request_protocol_handler.cc
@@ -11,6 +11,7 @@ #include "extensions/browser/extension_system.h" #include "extensions/browser/info_map.h" #include "extensions/common/extension.h" +#include "net/base/ip_endpoint.h" #include "net/base/upload_data_stream.h" #include "net/url_request/redirect_info.h" #include "net/url_request/url_request_context.h" @@ -23,7 +24,7 @@ class UploadDataStreamRedirect : public net::UploadDataStream { public: - UploadDataStreamRedirect(net::UploadDataStream* parent); + explicit UploadDataStreamRedirect(net::UploadDataStream* parent); ~UploadDataStreamRedirect() override; private: @@ -105,7 +106,7 @@ net::ResponseHeadersCallback callback) override; bool GetMimeType(std::string* mime_type) const override; int GetResponseCode() const override; - net::HostPortPair GetSocketAddress() const override; + net::IPEndPoint GetResponseRemoteEndpoint() const override; void StopCaching() override; bool GetFullRequestHeaders(net::HttpRequestHeaders* headers) const override; int64_t GetTotalReceivedBytes() const override; @@ -114,7 +115,7 @@ bool GetCharset(std::string* charset) override; void GetResponseInfo(net::HttpResponseInfo* info) override; void GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override; - bool GetRemoteEndpoint(net::IPEndPoint* endpoint) const override; + bool GetTransactionRemoteEndpoint(net::IPEndPoint* endpoint) const override; void PopulateNetErrorDetails(net::NetErrorDetails* details) const override; bool IsRedirectResponse(GURL* location, int* http_status_code, @@ -218,8 +219,8 @@ return sub_request_->GetResponseCode(); } -net::HostPortPair CastExtensionURLRequestJob::GetSocketAddress() const { - return sub_request_->GetSocketAddress(); +net::IPEndPoint CastExtensionURLRequestJob::GetResponseRemoteEndpoint() const { + return sub_request_->GetResponseRemoteEndpoint(); } void CastExtensionURLRequestJob::StopCaching() { @@ -257,9 +258,9 @@ sub_request_->GetLoadTimingInfo(load_timing_info); } -bool CastExtensionURLRequestJob::GetRemoteEndpoint( +bool CastExtensionURLRequestJob::GetTransactionRemoteEndpoint( net::IPEndPoint* endpoint) const { - return sub_request_->GetRemoteEndpoint(endpoint); + return sub_request_->GetTransactionRemoteEndpoint(endpoint); } void CastExtensionURLRequestJob::PopulateNetErrorDetails(
diff --git a/chromecast/common/mojom/typemaps.gni b/chromecast/common/mojom/typemaps.gni deleted file mode 100644 index 75d50bf..0000000 --- a/chromecast/common/mojom/typemaps.gni +++ /dev/null
@@ -1,5 +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. - -typemaps = [ "//chromecast/common/mojom/multiroom.typemap" ]
diff --git a/chromecast/media/cma/BUILD.gn b/chromecast/media/cma/BUILD.gn index 427c96c..bf49cf6 100644 --- a/chromecast/media/cma/BUILD.gn +++ b/chromecast/media/cma/BUILD.gn
@@ -77,7 +77,16 @@ if (enable_video_with_mixed_audio) { defines = [ "ENABLE_VIDEO_WITH_MIXED_AUDIO" ] - libs = ["videodecoderformixer"] + + # libvideodecoderformixer is linked here for the + # VideoDecoderForMixer::InitializeGraphicsForTesting symbol. Currently only + # alsa platforms do anything useful in this initialization, so otherwise + # just link in a dummy. + if (use_alsa) { + libs = [ "videodecoderformixer" ] + } else { + sources += [ "backend/dummy_initialize_graphics_for_testing.cc" ] + } } data = [
diff --git a/chromecast/media/cma/backend/dummy_initialize_graphics_for_testing.cc b/chromecast/media/cma/backend/dummy_initialize_graphics_for_testing.cc new file mode 100644 index 0000000..df6928f --- /dev/null +++ b/chromecast/media/cma/backend/dummy_initialize_graphics_for_testing.cc
@@ -0,0 +1,15 @@ +// Copyright 2019 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 "chromecast/media/cma/backend/video_decoder_for_mixer.h" + +namespace chromecast { +namespace media { + +CHROMECAST_EXPORT void VideoDecoderForMixer::InitializeGraphicsForTesting() { + // No initialization required. +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/typemaps.gni b/chromecast/typemaps.gni new file mode 100644 index 0000000..e3efd00 --- /dev/null +++ b/chromecast/typemaps.gni
@@ -0,0 +1,12 @@ +# Copyright 2019 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("//build/config/chromecast_build.gni") + +typemaps = [ "//chromecast/common/mojom/multiroom.typemap" ] + +if (chromecast_branding != "public") { + _typemap_internal = read_file("//chromecast/internal/typemaps.gni", "scope") + typemaps += _typemap_internal.typemaps +}
diff --git a/chromeos/services/assistant/media_session/assistant_media_session.h b/chromeos/services/assistant/media_session/assistant_media_session.h index eb38975..7b0e3eb 100644 --- a/chromeos/services/assistant/media_session/assistant_media_session.h +++ b/chromeos/services/assistant/media_session/assistant_media_session.h
@@ -43,6 +43,10 @@ void SkipAd() override {} void Seek(base::TimeDelta seek_time) override {} void Stop(SuspendType suspend_type) override {} + void GetMediaImageBitmap(const media_session::MediaImage& image, + int minimum_size_px, + int desired_size_px, + GetMediaImageBitmapCallback callback) override {} // Requests/abandons audio focus to the AudioFocusManager. void RequestAudioFocus(media_session::mojom::AudioFocusType audio_focus_type);
diff --git a/components/arc/arc_prefs.cc b/components/arc/arc_prefs.cc index e72aa38..de576c5 100644 --- a/components/arc/arc_prefs.cc +++ b/components/arc/arc_prefs.cc
@@ -109,10 +109,6 @@ // engagement time was last recorded. Accumulated results are sent to UMA if day // ID has changed. const char kEngagementTimeDayId[] = "arc.metrics.engagement_time.day_id"; -// A preference that indicates the user has accepted voice interaction activity -// control settings. -const char kVoiceInteractionActivityControlAccepted[] = - "settings.voice_interaction.activity_control.accepted"; // A preference that indicates the user has allowed voice interaction services // to access the "context" (text and graphic content that is currently on // screen). @@ -160,8 +156,6 @@ static_cast<int>(ArcSupervisionTransition::NO_TRANSITION)); // Sorted in lexicographical order. - registry->RegisterBooleanPref(kVoiceInteractionActivityControlAccepted, - false); registry->RegisterBooleanPref(kAlwaysOnVpnLockdown, false); registry->RegisterStringPref(kAlwaysOnVpnPackage, std::string()); registry->RegisterBooleanPref(kArcDataRemoveRequested, false);
diff --git a/components/arc/arc_prefs.h b/components/arc/arc_prefs.h index 5da55db..cf17451 100644 --- a/components/arc/arc_prefs.h +++ b/components/arc/arc_prefs.h
@@ -45,7 +45,6 @@ ARC_EXPORT extern const char kEngagementTimeTotal[]; // TODO(b/110211045): Move Assistant related prefs to ash. -ARC_EXPORT extern const char kVoiceInteractionActivityControlAccepted[]; ARC_EXPORT extern const char kVoiceInteractionContextEnabled[]; ARC_EXPORT extern const char kVoiceInteractionEnabled[]; ARC_EXPORT extern const char kVoiceInteractionHotwordAlwaysOn[];
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index 0a749d1..e9871cd2 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -435,9 +435,10 @@ // |FieldTypeGroup|. bool FormHasAddressField(const FormData& form) WARN_UNUSED_RESULT; - // Returns a list of values from the stored profiles that match |type| and the - // value of |field| and returns the labels of the matching profiles. |labels| - // is filled with the Profile label. + // Returns Suggestions corresponding to both the |autofill_field| type and + // stored profiles whose values match the contents of |field|. |form| stores + // data about the form with which the user is interacting, e.g. the number and + // types of form fields. std::vector<Suggestion> GetProfileSuggestions( const FormStructure& form, const FormFieldData& field,
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index a7e6cde..5fdf760 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -254,6 +254,11 @@ "AutofillShowAutocompleteConsoleWarnings", base::FEATURE_DISABLED_BY_DEFAULT}; +// Controls whether suggestions' labels use the full disclosure format to +// display disambiguation information. +const base::Feature kAutofillShowFullDisclosureLabel{ + "AutofillShowFullDisclosureLabel", base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls attaching the autofill type predictions to their respective // element in the DOM. const base::Feature kAutofillShowTypePredictions{
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 485e42c..ec9c4784 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -68,6 +68,7 @@ extern const base::Feature kAutofillSettingsCardTypeSplit; extern const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms; extern const base::Feature kAutofillShowAutocompleteConsoleWarnings; +extern const base::Feature kAutofillShowFullDisclosureLabel; extern const base::Feature kAutofillShowTypePredictions; extern const base::Feature kAutofillSkipComparingInferredLabels; extern const base::Feature kAutofillSuppressDisusedAddresses;
diff --git a/components/crash/content/app/crashpad.cc b/components/crash/content/app/crashpad.cc index 72c9703..5eba3742 100644 --- a/components/crash/content/app/crashpad.cc +++ b/components/crash/content/app/crashpad.cc
@@ -24,6 +24,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/system/sys_info.h" #include "base/time/time.h" #include "build/build_config.h" #include "components/crash/content/app/crash_reporter_client.h" @@ -170,6 +171,9 @@ pid_key.Set(base::NumberToString(::GetCurrentProcessId())); #endif + static crashpad::StringAnnotation<24> osarch_key("osarch"); + osarch_key.Set(base::SysInfo::OperatingSystemArchitecture()); + logging::SetLogMessageHandler(LogMessageHandler); // If clients called CRASHPAD_SIMULATE_CRASH() instead of
diff --git a/components/domain_reliability/monitor.cc b/components/domain_reliability/monitor.cc index 0e09a8f..6f094f1 100644 --- a/components/domain_reliability/monitor.cc +++ b/components/domain_reliability/monitor.cc
@@ -17,7 +17,6 @@ #include "components/domain_reliability/google_configs.h" #include "components/domain_reliability/header.h" #include "components/domain_reliability/quic_error_mapping.h" -#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" @@ -243,7 +242,7 @@ request.GetLoadTimingInfo(&load_timing_info); request.GetConnectionAttempts(&connection_attempts); request.PopulateNetErrorDetails(&details); - if (!request.GetRemoteEndpoint(&remote_endpoint)) + if (!request.GetTransactionRemoteEndpoint(&remote_endpoint)) remote_endpoint = net::IPEndPoint(); }
diff --git a/components/domain_reliability/monitor_unittest.cc b/components/domain_reliability/monitor_unittest.cc index 1619bee..cf32e1d7 100644 --- a/components/domain_reliability/monitor_unittest.cc +++ b/components/domain_reliability/monitor_unittest.cc
@@ -19,7 +19,6 @@ #include "components/domain_reliability/config.h" #include "components/domain_reliability/google_configs.h" #include "components/domain_reliability/test_util.h" -#include "net/base/host_port_pair.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" #include "net/http/http_util.h" @@ -72,8 +71,8 @@ static RequestInfo MakeRequestInfo() { RequestInfo request; request.status = net::URLRequestStatus(); - request.response_info.socket_address = - net::HostPortPair::FromString("12.34.56.78:80"); + request.response_info.remote_endpoint = + net::IPEndPoint(net::IPAddress(12, 34, 56, 78), 80); request.response_info.headers = MakeHttpResponseHeaders( "HTTP/1.1 200 OK\n\n"); request.response_info.was_cached = false; @@ -202,8 +201,8 @@ RequestInfo request = MakeRequestInfo(); request.url = GURL("http://example/"); request.status = net::URLRequestStatus::FromError(net::ERR_CONNECTION_RESET); - request.response_info.socket_address = - net::HostPortPair::FromString("127.0.0.1:3128"); + request.response_info.remote_endpoint = + net::IPEndPoint(net::IPAddress(127, 0, 0, 1), 3128); request.response_info.was_fetched_via_proxy = true; OnRequestLegComplete(request);
diff --git a/components/download/internal/common/download_response_handler.cc b/components/download/internal/common/download_response_handler.cc index acccd91..7ab6994 100644 --- a/components/download/internal/common/download_response_handler.cc +++ b/components/download/internal/common/download_response_handler.cc
@@ -129,7 +129,7 @@ create_info->total_bytes = head.content_length > 0 ? head.content_length : 0; create_info->result = result; if (result == DOWNLOAD_INTERRUPT_REASON_NONE) - create_info->remote_address = head.socket_address.host(); + create_info->remote_address = head.remote_endpoint.ToStringWithoutPort(); create_info->method = method_; create_info->connection_info = head.connection_info; create_info->url_chain = url_chain_;
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc index 372d5cd..15b50bd 100644 --- a/components/exo/client_controlled_shell_surface_unittest.cc +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -18,7 +18,9 @@ #include "ash/wm/drag_window_resizer.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/splitview/split_view_controller.h" +#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "ash/wm/tablet_mode/tablet_mode_window_drag_controller.h" #include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h" #include "ash/wm/window_positioning_utils.h" #include "ash/wm/window_resizer.h" @@ -1086,8 +1088,50 @@ ASSERT_FALSE(window_state->is_dragged()); } +namespace { + +class ClientControlledShellSurfaceDragTest : public test::ExoTestBase { + public: + ClientControlledShellSurfaceDragTest() = default; + ~ClientControlledShellSurfaceDragTest() override = default; + + // Sends a gesture scroll sequence to TabletModeAppWindowDragController. + void SendGestureEvents(aura::Window* window, + const gfx::Point& location, + bool fling = false, + float velocity = 0.f) { + ash::wm::WindowState* window_state = ash::wm::GetWindowState(window); + window_state->CreateDragDetails(gfx::Point(0, 0), HTCLIENT, + ::wm::WINDOW_MOVE_SOURCE_TOUCH); + std::unique_ptr<ash::TabletModeWindowDragController> controller_ = + std::make_unique<ash::TabletModeWindowDragController>( + window_state, + std::make_unique<ash::TabletModeBrowserWindowDragDelegate>()); + controller_->drag_delegate_for_testing() + ->set_drag_start_deadline_for_testing(base::Time::Now()); + controller_->Drag(location, 0); + if (fling) { + ui::GestureEventDetails details = + ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, 0, velocity); + ui::GestureEvent event = + ui::GestureEvent(location.x(), location.y(), ui::EF_NONE, + base::TimeTicks::Now(), details); + ui::Event::DispatcherApi(&event).set_target(window); + controller_->FlingOrSwipe(&event); + } else { + controller_->CompleteDrag(); + } + ash::wm::GetWindowState(window)->DeleteDragDetails(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ClientControlledShellSurfaceDragTest); +}; + +} // namespace + // Test the functionalities of dragging a window from top in tablet mode. -TEST_F(ClientControlledShellSurfaceTest, DragWindowFromTopInTabletMode) { +TEST_F(ClientControlledShellSurfaceDragTest, DragWindowFromTopInTabletMode) { UpdateDisplay("800x600"); ash::Shell* shell = ash::Shell::Get(); shell->tablet_mode_controller()->EnableTabletModeWindowManager(true); @@ -1106,26 +1150,18 @@ ASSERT_TRUE(ash::wm::GetWindowState(window)->IsMaximized()); surface->SetFrame(SurfaceFrameType::AUTOHIDE); surface->Commit(); - ui::test::EventGenerator* event_generator = GetEventGenerator(); // Drag the window by a small amount of distance will maximize the window // again. - const gfx::Point start(0, 0); - gfx::Point end(0, 10); - event_generator->GestureScrollSequence( - start, end, base::TimeDelta::FromMilliseconds(100), 2); + SendGestureEvents(window, gfx::Point(0, 10)); EXPECT_TRUE(ash::wm::GetWindowState(window)->IsMaximized()); + EXPECT_FALSE(shell->overview_controller()->IsSelecting()); // FLING the window not inisde preview area with large enough y veloicty // (larger than kFlingToOverviewThreshold) will drop the window into overview. - EXPECT_FALSE(shell->overview_controller()->IsSelecting()); - end = gfx::Point(400, 210); - const base::TimeDelta duration = - event_generator->CalculateScrollDurationForFlingVelocity( - start, end, - ash::TabletModeWindowDragDelegate::kFlingToOverviewThreshold + 10.f, - 200); - event_generator->GestureScrollSequence(start, end, duration, 200); + SendGestureEvents( + window, gfx::Point(400, 10), /*fling=*/true, + ash::TabletModeWindowDragDelegate::kFlingToOverviewThreshold + 10.f); ASSERT_TRUE(shell->overview_controller()->IsSelecting()); EXPECT_TRUE( shell->overview_controller()->overview_session()->IsWindowInOverview( @@ -1133,12 +1169,8 @@ // Drag the window long enough (pass one fourth of the screen vertical // height) to snap the window to splitscreen. - end = gfx::Point(0, 210); shell->overview_controller()->ToggleOverview(); - EXPECT_FALSE(shell->overview_controller()->IsSelecting()); - EXPECT_TRUE(ash::wm::GetWindowState(window)->IsMaximized()); - event_generator->GestureScrollSequence( - start, end, base::TimeDelta::FromMilliseconds(100), 20); + SendGestureEvents(window, gfx::Point(0, 210)); EXPECT_EQ(ash::wm::GetWindowState(window)->GetStateType(), ash::mojom::WindowStateType::LEFT_SNAPPED); }
diff --git a/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h b/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h index efee31e..a7ff935 100644 --- a/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h +++ b/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h
@@ -23,7 +23,7 @@ // absent language. class SerializedLanguageTree { public: - virtual ~SerializedLanguageTree(){}; + virtual ~SerializedLanguageTree() {} virtual std::string GetLanguageAt(const size_t pos) const = 0; virtual size_t GetNumLanguages() const = 0; @@ -42,7 +42,7 @@ BitsetSerializedLanguageTree(std::vector<std::string> languages, std::bitset<numbits> bits) : languages_(languages), bits_(bits) {} - ~BitsetSerializedLanguageTree() override{}; + ~BitsetSerializedLanguageTree() override {} // SerializedTree implementation std::string GetLanguageAt(const size_t pos) const override {
diff --git a/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstaller.java b/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstaller.java index 85d1b679..879472a 100644 --- a/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstaller.java +++ b/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstaller.java
@@ -49,6 +49,17 @@ updateCrashKeys(); } + /** + * Needs to be called in attachBaseContext of the activities that want to have access to + * splits prior to application restart. + * + * For details, see: + * https://developer.android.com/reference/com/google/android/play/core/splitcompat/SplitCompat.html#install(android.content.Context) + */ + public static void initActivity(Context context) { + SplitCompat.install(context); + } + /** Writes fully installed and emulated modules to crash keys. */ public static void updateCrashKeys() { Context context = ContextUtils.getApplicationContext();
diff --git a/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java b/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java index 65ee45b..5dd14d3 100644 --- a/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java +++ b/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java
@@ -4,11 +4,16 @@ package org.chromium.components.module_installer; +import android.content.Context; + import org.chromium.base.VisibleForTesting; /** Dummy fallback of ModuleInstaller for APK builds. */ public class ModuleInstaller { public static void init() {} + + public static void initActivity(Context context) {} + public static void updateCrashKeys(){}; public static void install(
diff --git a/components/module_installer/android/java/src-test/org/chromium/components/module_installer/ModuleInstaller.java b/components/module_installer/android/java/src-test/org/chromium/components/module_installer/ModuleInstaller.java index 9df2a24..720b8e8 100644 --- a/components/module_installer/android/java/src-test/org/chromium/components/module_installer/ModuleInstaller.java +++ b/components/module_installer/android/java/src-test/org/chromium/components/module_installer/ModuleInstaller.java
@@ -4,6 +4,8 @@ package org.chromium.components.module_installer; +import android.content.Context; + import org.chromium.base.VisibleForTesting; import java.util.HashSet; @@ -14,6 +16,9 @@ private static Set<String> sModulesRequestedDeffered = new HashSet<>(); public static void init() {} + + public static void initActivity(Context context) {} + public static void updateCrashKeys(){}; public static void install(
diff --git a/components/network_session_configurator/browser/network_session_configurator.cc b/components/network_session_configurator/browser/network_session_configurator.cc index c1968ee6..711ea17 100644 --- a/components/network_session_configurator/browser/network_session_configurator.cc +++ b/components/network_session_configurator/browser/network_session_configurator.cc
@@ -325,13 +325,6 @@ "true"); } -bool ShouldQuicRaceStaleDNSOnConnection( - const VariationParameters& quic_trial_params) { - return base::LowerCaseEqualsASCII( - GetVariationParam(quic_trial_params, "race_stale_dns_on_connection"), - "true"); -} - int GetQuicMaxTimeOnNonDefaultNetworkSeconds( const VariationParameters& quic_trial_params) { int value; @@ -489,8 +482,6 @@ ShouldQuicRetryOnAlternateNetworkBeforeHandshake(quic_trial_params); params->quic_go_away_on_path_degrading = ShouldQuicGoawayOnPathDegrading(quic_trial_params); - params->quic_race_stale_dns_on_connection = - ShouldQuicRaceStaleDNSOnConnection(quic_trial_params); int idle_session_migration_period_seconds = GetQuicIdleSessionMigrationPeriodSeconds(quic_trial_params); if (idle_session_migration_period_seconds > 0) {
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc index fdd273b..9d2ec009 100644 --- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -121,7 +121,6 @@ EXPECT_FALSE(params_.quic_estimate_initial_rtt); EXPECT_FALSE(params_.quic_migrate_sessions_on_network_change_v2); EXPECT_FALSE(params_.quic_migrate_sessions_early_v2); - EXPECT_FALSE(params_.quic_race_stale_dns_on_connection); EXPECT_FALSE(params_.quic_retry_on_alternate_network_before_handshake); EXPECT_FALSE(params_.quic_go_away_on_path_degrading); EXPECT_FALSE(params_.quic_allow_server_migration); @@ -376,18 +375,6 @@ } TEST_F(NetworkSessionConfiguratorTest, - QuicRaceStaleDNSOnCOnnectionFromFieldTrialParams) { - std::map<std::string, std::string> field_trial_params; - field_trial_params["race_stale_dns_on_connection"] = "true"; - variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); - base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); - - ParseFieldTrials(); - - EXPECT_TRUE(params_.quic_race_stale_dns_on_connection); -} - -TEST_F(NetworkSessionConfiguratorTest, QuicGoawayOnPathDegradingFromFieldTrialParams) { std::map<std::string, std::string> field_trial_params; field_trial_params["go_away_on_path_degrading"] = "true";
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_request.cc b/components/offline_pages/core/prefetch/generate_page_bundle_request.cc index ea2270f2..9a612a8 100644 --- a/components/offline_pages/core/prefetch/generate_page_bundle_request.cc +++ b/components/offline_pages/core/prefetch/generate_page_bundle_request.cc
@@ -22,6 +22,7 @@ int max_bundle_size_bytes, const std::vector<std::string>& page_urls, version_info::Channel channel, + bool send_testing_header, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, PrefetchRequestFinishedCallback callback) : callback_(std::move(callback)), requested_urls_(page_urls) { @@ -41,7 +42,8 @@ request.SerializeToString(&upload_data); fetcher_ = PrefetchRequestFetcher::CreateForPost( - GeneratePageBundleRequestURL(channel), upload_data, url_loader_factory, + GeneratePageBundleRequestURL(channel), upload_data, send_testing_header, + url_loader_factory, base::BindOnce(&GeneratePageBundleRequest::OnCompleted, // Fetcher is owned by this instance. base::Unretained(this)));
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_request.h b/components/offline_pages/core/prefetch/generate_page_bundle_request.h index 3c4af0c..61df8ed 100644 --- a/components/offline_pages/core/prefetch/generate_page_bundle_request.h +++ b/components/offline_pages/core/prefetch/generate_page_bundle_request.h
@@ -29,6 +29,7 @@ int max_bundle_size_bytes, const std::vector<std::string>& page_urls, version_info::Channel channel, + bool send_testing_header, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, PrefetchRequestFinishedCallback callback); ~GeneratePageBundleRequest();
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc b/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc index c99ca90..9436ed7 100644 --- a/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc +++ b/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc
@@ -39,19 +39,21 @@ class GeneratePageBundleRequestTest : public PrefetchRequestTestBase { public: std::unique_ptr<GeneratePageBundleRequest> CreateRequest( + bool testing_header, PrefetchRequestFinishedCallback callback) { std::vector<std::string> page_urls = {kTestURL, kTestURL2}; return std::unique_ptr<GeneratePageBundleRequest>( new GeneratePageBundleRequest( kTestUserAgent, kTestGCMID, kTestMaxBundleSize, page_urls, - kTestChannel, shared_url_loader_factory(), std::move(callback))); + kTestChannel, testing_header, shared_url_loader_factory(), + std::move(callback))); } }; TEST_F(GeneratePageBundleRequestTest, RequestData) { base::MockCallback<PrefetchRequestFinishedCallback> callback; std::unique_ptr<GeneratePageBundleRequest> request( - CreateRequest(callback.Get())); + CreateRequest(false, callback.Get())); EXPECT_EQ(2UL, request->requested_urls().size()); EXPECT_THAT(request->requested_urls(), Contains(kTestURL)); @@ -94,7 +96,7 @@ base::MockCallback<PrefetchRequestFinishedCallback> callback; std::unique_ptr<GeneratePageBundleRequest> request( - CreateRequest(callback.Get())); + CreateRequest(false, callback.Get())); network::TestURLLoaderFactory::PendingRequest* pending_request = GetPendingRequest(); DCHECK(pending_request); @@ -104,10 +106,34 @@ GetExperiementHeaderValue(pending_request)); } +TEST_F(GeneratePageBundleRequestTest, NoTestingHeaderInRequestData) { + base::MockCallback<PrefetchRequestFinishedCallback> callback; + // Make a request without the header. + std::unique_ptr<GeneratePageBundleRequest> request( + CreateRequest(false, callback.Get())); + + std::string testing_header; + bool has_header = GetPendingRequest()->request.headers.GetHeader( + "X-Offline-Prefetch-Testing", &testing_header); + EXPECT_FALSE(has_header); +} + +TEST_F(GeneratePageBundleRequestTest, TestingHeaderInRequestData) { + base::MockCallback<PrefetchRequestFinishedCallback> callback; + // Make a request with the header. + std::unique_ptr<GeneratePageBundleRequest> request( + CreateRequest(true, callback.Get())); + std::string testing_header; + bool has_header = GetPendingRequest()->request.headers.GetHeader( + "X-Offline-Prefetch-Testing", &testing_header); + EXPECT_TRUE(has_header); + EXPECT_EQ("true", testing_header); +} + TEST_F(GeneratePageBundleRequestTest, EmptyResponse) { base::MockCallback<PrefetchRequestFinishedCallback> callback; std::unique_ptr<GeneratePageBundleRequest> request( - CreateRequest(callback.Get())); + CreateRequest(false, callback.Get())); PrefetchRequestStatus status; std::string operation_name; @@ -126,7 +152,7 @@ TEST_F(GeneratePageBundleRequestTest, InvalidResponse) { base::MockCallback<PrefetchRequestFinishedCallback> callback; std::unique_ptr<GeneratePageBundleRequest> request( - CreateRequest(callback.Get())); + CreateRequest(false, callback.Get())); PrefetchRequestStatus status; std::string operation_name;
diff --git a/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc b/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc index f63ce7aa..f510a99f 100644 --- a/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc
@@ -70,10 +70,12 @@ ? kMaxBundleSizeForLimitlessBytes : kMaxBundleSizeBytes; uint64_t request_id = GetNextRequestId(); + bool send_testing_header = + prefetch_prefs::ShouldSendPrefetchTestingHeader(prefs_); generate_page_bundle_requests_[request_id] = std::make_unique<GeneratePageBundleRequest>( user_agent_, gcm_registration_id, max_bundle_size, url_strings, - channel_, url_loader_factory_, + channel_, send_testing_header, url_loader_factory_, base::BindOnce( &PrefetchNetworkRequestFactoryImpl::GeneratePageBundleRequestDone, weak_factory_.GetWeakPtr(), std::move(callback), request_id));
diff --git a/components/offline_pages/core/prefetch/prefetch_prefs.cc b/components/offline_pages/core/prefetch/prefetch_prefs.cc index 3a4ee084..88524f3 100644 --- a/components/offline_pages/core/prefetch/prefetch_prefs.cc +++ b/components/offline_pages/core/prefetch/prefetch_prefs.cc
@@ -16,6 +16,8 @@ const char kEnabled[] = "offline_prefetch.enabled"; const char kLimitlessPrefetchingEnabledTimePref[] = "offline_prefetch.limitless_prefetching_enabled_time"; +const char kSendPrefetchTestingHeaderPref[] = + "offline_prefetch.send_testing_header"; } // namespace const char kBackoff[] = "offline_prefetch.backoff"; @@ -25,6 +27,7 @@ registry->RegisterBooleanPref(kEnabled, true); registry->RegisterTimePref(kLimitlessPrefetchingEnabledTimePref, base::Time()); + registry->RegisterBooleanPref(kSendPrefetchTestingHeaderPref, false); } void SetPrefetchingEnabledInSettings(PrefService* prefs, bool enabled) { @@ -58,5 +61,15 @@ return (now >= enabled_time) && (now < (enabled_time + max_duration)); } +void SetSendPrefetchTestingHeader(PrefService* prefs, bool enabled) { + DCHECK(prefs); + prefs->SetBoolean(kSendPrefetchTestingHeaderPref, enabled); +} + +bool ShouldSendPrefetchTestingHeader(PrefService* prefs) { + DCHECK(prefs); + return prefs->GetBoolean(kSendPrefetchTestingHeaderPref); +} + } // namespace prefetch_prefs } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_prefs.h b/components/offline_pages/core/prefetch/prefetch_prefs.h index 7e590cc2..4cbb794d 100644 --- a/components/offline_pages/core/prefetch/prefetch_prefs.h +++ b/components/offline_pages/core/prefetch/prefetch_prefs.h
@@ -28,6 +28,13 @@ bool IsLimitlessPrefetchingEnabled(PrefService* prefs); +// Sets whether a header "X-Offline-Prefetch_Testing: true" should be sent with +// GeneratePageBundle requests. This header exempts the request from country +// filtering so that prefetching can be tested in filtered countries. +void SetSendPrefetchTestingHeader(PrefService* prefs, bool enabled); + +bool ShouldSendPrefetchTestingHeader(PrefService* prefs); + } // namespace prefetch_prefs } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_prefs_unittest.cc b/components/offline_pages/core/prefetch/prefetch_prefs_unittest.cc index 2ba8077..990f591 100644 --- a/components/offline_pages/core/prefetch/prefetch_prefs_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_prefs_unittest.cc
@@ -70,4 +70,14 @@ EXPECT_FALSE(prefetch_prefs::IsLimitlessPrefetchingEnabled(prefs())); } +TEST_F(PrefetchPrefsTest, SendTestingHeaderPref) { + EXPECT_FALSE(prefetch_prefs::ShouldSendPrefetchTestingHeader(prefs())); + + prefetch_prefs::SetSendPrefetchTestingHeader(prefs(), true); + EXPECT_TRUE(prefetch_prefs::ShouldSendPrefetchTestingHeader(prefs())); + + prefetch_prefs::SetSendPrefetchTestingHeader(prefs(), false); + EXPECT_FALSE(prefetch_prefs::ShouldSendPrefetchTestingHeader(prefs())); +} + } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc b/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc index 2a5833cc..ce80feb 100644 --- a/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc +++ b/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc
@@ -34,22 +34,25 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, FinishedCallback callback) { return base::WrapUnique(new PrefetchRequestFetcher( - url, std::string(), url_loader_factory, std::move(callback))); + url, std::string(), false, url_loader_factory, std::move(callback))); } // static std::unique_ptr<PrefetchRequestFetcher> PrefetchRequestFetcher::CreateForPost( const GURL& url, const std::string& message, + bool send_testing_header, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, FinishedCallback callback) { - return base::WrapUnique(new PrefetchRequestFetcher( - url, message, url_loader_factory, std::move(callback))); + return base::WrapUnique( + new PrefetchRequestFetcher(url, message, send_testing_header, + url_loader_factory, std::move(callback))); } PrefetchRequestFetcher::PrefetchRequestFetcher( const GURL& url, const std::string& message, + bool send_testing_header, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, FinishedCallback callback) : url_loader_factory_(url_loader_factory), callback_(std::move(callback)) { @@ -85,6 +88,9 @@ if (!experiment_header.empty()) resource_request->headers.AddHeaderFromString(experiment_header); + if (send_testing_header) + resource_request->headers.AddHeaderFromString(kPrefetchTestingHeader); + if (message.empty()) resource_request->headers.SetHeader(net::HttpRequestHeaders::kContentType, kRequestContentType);
diff --git a/components/offline_pages/core/prefetch/prefetch_request_fetcher.h b/components/offline_pages/core/prefetch/prefetch_request_fetcher.h index d025a86..83171e2 100644 --- a/components/offline_pages/core/prefetch/prefetch_request_fetcher.h +++ b/components/offline_pages/core/prefetch/prefetch_request_fetcher.h
@@ -34,6 +34,7 @@ static std::unique_ptr<PrefetchRequestFetcher> CreateForPost( const GURL& url, const std::string& message, + bool send_testing_header, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, FinishedCallback callback); @@ -47,6 +48,7 @@ PrefetchRequestFetcher( const GURL& url, const std::string& message, + bool send_testing_header, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, FinishedCallback callback);
diff --git a/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc b/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc index aa0a2777..5978e41 100644 --- a/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc
@@ -72,9 +72,11 @@ base::OnceCallback<void(void)> respond_callback, std::string* data_received) { base::MockCallback<PrefetchRequestFetcher::FinishedCallback> callback; + bool send_prefetch_testing_header = false; std::unique_ptr<PrefetchRequestFetcher> fetcher = PrefetchRequestFetcher::CreateForPost( - kTestURL, kTestMessage, shared_url_loader_factory(), callback.Get()); + kTestURL, kTestMessage, send_prefetch_testing_header, + shared_url_loader_factory(), callback.Get()); PrefetchRequestStatus status; std::string data;
diff --git a/components/offline_pages/core/prefetch/prefetch_request_operation_response_unittest.cc b/components/offline_pages/core/prefetch/prefetch_request_operation_response_unittest.cc index b203671..48dacb3 100644 --- a/components/offline_pages/core/prefetch/prefetch_request_operation_response_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_request_operation_response_unittest.cc
@@ -56,7 +56,8 @@ std::vector<std::string> pages = {kTestURL, kTestURL2}; fetcher_.reset(new GeneratePageBundleRequest( kTestUserAgent, kTestGCMID, kTestMaxBundleSize, pages, kTestChannel, - url_loader_factory, std::move(callback))); + /*send_prefetch_testing_header=*/false, url_loader_factory, + std::move(callback))); } private:
diff --git a/components/offline_pages/core/prefetch/prefetch_server_urls.cc b/components/offline_pages/core/prefetch/prefetch_server_urls.cc index 818ab80..411fe32 100644 --- a/components/offline_pages/core/prefetch/prefetch_server_urls.cc +++ b/components/offline_pages/core/prefetch/prefetch_server_urls.cc
@@ -14,6 +14,7 @@ const char kPrefetchServer[] = "https://offlinepages-pa.googleapis.com/"; const char kPrefetchExperimentHeaderName[] = "X-Offline-Prefetch-Experiment"; const char kPrefetchOperationHeaderName[] = "X-Offline-Prefetch-Operation"; +const char kPrefetchTestingHeader[] = "X-Offline-Prefetch-Testing: true"; namespace {
diff --git a/components/offline_pages/core/prefetch/prefetch_server_urls.h b/components/offline_pages/core/prefetch/prefetch_server_urls.h index c42eab8a..efd6827 100644 --- a/components/offline_pages/core/prefetch/prefetch_server_urls.h +++ b/components/offline_pages/core/prefetch/prefetch_server_urls.h
@@ -14,6 +14,7 @@ extern const char kPrefetchServer[]; extern const char kPrefetchExperimentHeaderName[]; extern const char kPrefetchOperationHeaderName[]; +extern const char kPrefetchTestingHeader[]; // Returns the URL to send a request to generate page bundle. GURL GeneratePageBundleRequestURL(version_info::Channel channel);
diff --git a/components/policy/core/common/cloud/device_management_service.cc b/components/policy/core/common/cloud/device_management_service.cc index 074db44..a22d894 100644 --- a/components/policy/core/common/cloud/device_management_service.cc +++ b/components/policy/core/common/cloud/device_management_service.cc
@@ -64,7 +64,7 @@ case net::ERR_PROXY_CONNECTION_FAILED: case net::ERR_TUNNEL_CONNECTION_FAILED: case net::ERR_PROXY_AUTH_UNSUPPORTED: - case net::ERR_HTTPS_PROXY_TUNNEL_RESPONSE: + case net::ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT: case net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED: case net::ERR_PROXY_CERTIFICATE_INVALID: case net::ERR_SOCKS_CONNECTION_FAILED:
diff --git a/components/safe_browsing/browser/threat_details_cache.cc b/components/safe_browsing/browser/threat_details_cache.cc index c8fca75..8ad043b 100644 --- a/components/safe_browsing/browser/threat_details_cache.cc +++ b/components/safe_browsing/browser/threat_details_cache.cc
@@ -17,7 +17,7 @@ #include "components/safe_browsing/browser/threat_details_cache.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" @@ -203,7 +203,7 @@ !current_load_->ResponseInfo()->proxy_server.is_direct(); if (!was_fetched_via_proxy) { pb_response->set_remote_ip( - current_load_->ResponseInfo()->socket_address.ToString()); + current_load_->ResponseInfo()->remote_endpoint.ToString()); } }
diff --git a/components/safe_browsing/features.cc b/components/safe_browsing/features.cc index 41a24b1..f00d697 100644 --- a/components/safe_browsing/features.cc +++ b/components/safe_browsing/features.cc
@@ -23,8 +23,9 @@ base::FEATURE_DISABLED_BY_DEFAULT}; // Controls the billing interstitial UI. +// TODO(http://crbug.com/933807): remove this base::Feature after a full launch. const base::Feature kBillingInterstitial{"BillingInterstitial", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // If enabled in pre-network-service world, SafeBrowsing URL checks are done by // applying SafeBrowsing's URLLoaderThrottle subclasses to ThrottlingURLLoader.
diff --git a/components/send_tab_to_self/BUILD.gn b/components/send_tab_to_self/BUILD.gn index 7c92a1b8..900b9b2 100644 --- a/components/send_tab_to_self/BUILD.gn +++ b/components/send_tab_to_self/BUILD.gn
@@ -17,10 +17,14 @@ deps = [ "//base", "//components/keyed_service/core", + "//components/send_tab_to_self/proto:send_tab_to_self_proto", "//components/sync", "//components/version_info", "//url", ] + public_deps = [ + "//components/send_tab_to_self/proto:send_tab_to_self_proto", + ] } source_set("unit_tests") { @@ -33,6 +37,7 @@ ":send_tab_to_self", "//base", "//base/test:test_support", + "//components/send_tab_to_self/proto:send_tab_to_self_proto", "//components/sync", "//components/sync:test_support_driver", "//components/sync:test_support_model",
diff --git a/components/send_tab_to_self/proto/BUILD.gn b/components/send_tab_to_self/proto/BUILD.gn new file mode 100644 index 0000000..57e0838f --- /dev/null +++ b/components/send_tab_to_self/proto/BUILD.gn
@@ -0,0 +1,29 @@ +# Copyright 2019 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("//third_party/protobuf/proto_library.gni") + +copy("send_tab_to_self_header_include") { + sources = [ + "send_tab_to_self_header_include.h", + ] + outputs = [ + "$root_gen_dir" + + "/components/send_tab_to_self/proto/send_tab_to_self_specifics.pb.h", + ] + deps = [ + "//components/sync/protocol:protocol", + ] +} + +proto_library("send_tab_to_self_proto") { + import_dirs = [ "//components/sync/protocol" ] + sources = [ + "send_tab_to_self.proto", + ] + deps = [ + ":send_tab_to_self_header_include", + "//components/sync/protocol:protocol", + ] +}
diff --git a/components/send_tab_to_self/proto/DEPS b/components/send_tab_to_self/proto/DEPS new file mode 100644 index 0000000..60ba8970 --- /dev/null +++ b/components/send_tab_to_self/proto/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+components/sync/protocol", +]
diff --git a/components/send_tab_to_self/proto/send_tab_to_self.proto b/components/send_tab_to_self/proto/send_tab_to_self.proto new file mode 100644 index 0000000..3294d38e --- /dev/null +++ b/components/send_tab_to_self/proto/send_tab_to_self.proto
@@ -0,0 +1,20 @@ +// Copyright 2019 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. +// +// Sync protocol datatype extension for the send tab to self entries. + +syntax = "proto2"; + +import "send_tab_to_self_specifics.proto"; + +option optimize_for = LITE_RUNTIME; + +package send_tab_to_self; + +// Local Send tab to self entry. This proto contains the fields stored locally +// for a send tab to self entry. +message SendTabToSelfLocal { + // The Send tab to self specifics proto. + optional sync_pb.SendTabToSelfSpecifics specifics = 1; +}
diff --git a/components/send_tab_to_self/proto/send_tab_to_self_header_include.h b/components/send_tab_to_self/proto/send_tab_to_self_header_include.h new file mode 100644 index 0000000..b2bc370 --- /dev/null +++ b/components/send_tab_to_self/proto/send_tab_to_self_header_include.h
@@ -0,0 +1,12 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SEND_TAB_TO_SELF_PROTO_SEND_TAB_TO_SELF_HEADER_INCLUDE_H_ +#define COMPONENTS_SEND_TAB_TO_SELF_PROTO_SEND_TAB_TO_SELF_HEADER_INCLUDE_H_ + +// This is a bridge to include the generated proto header for the +// send tab to self proto. +#include "components/sync/protocol/send_tab_to_self_specifics.pb.h" + +#endif // COMPONENTS_SEND_TAB_TO_SELF_PROTO_SEND_TAB_TO_SELF_HEADER_INCLUDE_H_
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge.cc b/components/send_tab_to_self/send_tab_to_self_bridge.cc index 7f2875be..e05aaf1 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge.cc +++ b/components/send_tab_to_self/send_tab_to_self_bridge.cc
@@ -10,6 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/optional.h" #include "base/time/clock.h" +#include "components/send_tab_to_self/proto/send_tab_to_self.pb.h" #include "components/sync/device_info/device_info.h" #include "components/sync/device_info/local_device_info_provider.h" #include "components/sync/model/entity_change.h" @@ -17,32 +18,48 @@ #include "components/sync/model/metadata_change_list.h" #include "components/sync/model/model_type_change_processor.h" #include "components/sync/model/mutable_data_batch.h" -#include "components/sync/model_impl/in_memory_metadata_change_list.h" #include "components/sync/protocol/model_type_state.pb.h" namespace send_tab_to_self { +namespace { + +using syncer::ModelTypeStore; + +// Converts a time field from sync protobufs to a time object. +base::Time ProtoTimeToTime(int64_t proto_t) { + return base::Time::FromDeltaSinceWindowsEpoch( + base::TimeDelta::FromMicroseconds(proto_t)); +} + +// Allocate a EntityData and copies |specifics| into it. +std::unique_ptr<syncer::EntityData> CopyToEntityData( + const sync_pb::SendTabToSelfSpecifics& specifics) { + auto entity_data = std::make_unique<syncer::EntityData>(); + *entity_data->specifics.mutable_send_tab_to_self() = specifics; + entity_data->non_unique_name = specifics.url(); + entity_data->creation_time = ProtoTimeToTime(specifics.shared_time_usec()); + return entity_data; +} + +} // namespace + SendTabToSelfBridge::SendTabToSelfBridge( std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor, syncer::LocalDeviceInfoProvider* local_device_info_provider, - base::Clock* clock) + base::Clock* clock, + syncer::OnceModelTypeStoreFactory create_store_callback) : ModelTypeSyncBridge(std::move(change_processor)), + clock_(clock), local_device_info_provider_(local_device_info_provider), - clock_(clock) { + weak_ptr_factory_(this) { DCHECK(local_device_info_provider); DCHECK(clock_); - if (local_device_info_provider->GetLocalDeviceInfo()) { - OnDeviceProviderInitialized(); - } else { - device_subscription_ = - local_device_info_provider->RegisterOnInitializedCallback( - base::BindRepeating( - &SendTabToSelfBridge::OnDeviceProviderInitialized, - base::Unretained(this))); - } - - // TODO(jeffreycohen): Create a local store and read meta data from it. + std::move(create_store_callback) + .Run(syncer::SEND_TAB_TO_SELF, + base::BindOnce(&SendTabToSelfBridge::OnStoreCreated, + weak_ptr_factory_.GetWeakPtr())); } SendTabToSelfBridge::~SendTabToSelfBridge() { @@ -50,12 +67,13 @@ std::unique_ptr<syncer::MetadataChangeList> SendTabToSelfBridge::CreateMetadataChangeList() { - return std::make_unique<syncer::InMemoryMetadataChangeList>(); + return ModelTypeStore::WriteBatch::CreateMetadataChangeList(); } base::Optional<syncer::ModelError> SendTabToSelfBridge::MergeSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { + DCHECK(entries_.empty()); return ApplySyncChanges(std::move(metadata_change_list), std::move(entity_data)); } @@ -65,57 +83,71 @@ syncer::EntityChangeList entity_changes) { std::vector<const SendTabToSelfEntry*> added; std::vector<std::string> removed; + std::unique_ptr<ModelTypeStore::WriteBatch> batch = + store_->CreateWriteBatch(); + for (syncer::EntityChange& change : entity_changes) { + const std::string& guid = change.storage_key(); if (change.type() == syncer::EntityChange::ACTION_DELETE) { - entries_.erase(change.storage_key()); - removed.push_back(change.storage_key()); + if (entries_.find(guid) != entries_.end()) { + entries_.erase(change.storage_key()); + batch->DeleteData(guid); + removed.push_back(change.storage_key()); + } } else { // syncer::EntityChange::ACTION_UPDATE is not supported by this bridge DCHECK(change.type() == syncer::EntityChange::ACTION_ADD); const sync_pb::SendTabToSelfSpecifics& specifics = change.data().specifics.send_tab_to_self(); - // TODO(jeffreycohen): FromProto expects a valid entry. External data - // needs to be sanitized before it's passed through. + std::unique_ptr<SendTabToSelfEntry> entry = SendTabToSelfEntry::FromProto(specifics, clock_->Now()); // This entry is new. Add it to the model. added.push_back(entry.get()); + SendTabToSelfLocal entry_pb = entry->AsLocalProto(); entries_[entry->GetGUID()] = std::move(entry); + + // Write to the store. + batch->WriteData(guid, entry_pb.SerializeAsString()); } } + + batch->TakeMetadataChangesFrom(std::move(metadata_change_list)); + Commit(std::move(batch)); + if (!removed.empty()) { NotifyRemoteSendTabToSelfEntryDeleted(removed); } if (!added.empty()) { NotifyRemoteSendTabToSelfEntryAdded(added); } + return base::nullopt; } void SendTabToSelfBridge::GetData(StorageKeyList storage_keys, DataCallback callback) { - syncer::InMemoryMetadataChangeList metadata_change_list; + auto batch = std::make_unique<syncer::MutableDataBatch>(); for (const std::string& guid : storage_keys) { const SendTabToSelfEntry* entry = GetEntryByGUID(guid); if (!entry) { continue; } - std::unique_ptr<sync_pb::SendTabToSelfSpecifics> specifics = - entry->AsProto(); - auto entity_data = std::make_unique<syncer::EntityData>(); - *entity_data->specifics.mutable_send_tab_to_self() = *specifics; - entity_data->non_unique_name = specifics->url(); - change_processor()->Put(specifics->guid(), std::move(entity_data), - &metadata_change_list); + batch->Put(guid, CopyToEntityData(entry->AsLocalProto().specifics())); } + std::move(callback).Run(std::move(batch)); } void SendTabToSelfBridge::GetAllDataForDebugging(DataCallback callback) { - // TODO(jeffreycohen): Add once we have a batch model. - NOTIMPLEMENTED(); + auto batch = std::make_unique<syncer::MutableDataBatch>(); + for (const auto& it : entries_) { + batch->Put(it.first, + CopyToEntityData(it.second->AsLocalProto().specifics())); + } + std::move(callback).Run(std::move(batch)); } std::string SendTabToSelfBridge::GetClientTag( @@ -142,12 +174,19 @@ DCHECK_EQ(0ul, entries_.size()); return; } - syncer::InMemoryMetadataChangeList metadata_change_list; - for (const auto& key : GetAllGuids()) { - change_processor()->Delete(key, &metadata_change_list); + std::unique_ptr<ModelTypeStore::WriteBatch> batch = + store_->CreateWriteBatch(); + + std::vector<std::string> all_guids = GetAllGuids(); + + for (const auto& guid : all_guids) { + change_processor()->Delete(guid, batch->GetMetadataChangeList()); + batch->DeleteData(guid); } entries_.clear(); + + NotifyRemoteSendTabToSelfEntryDeleted(all_guids); } const SendTabToSelfEntry* SendTabToSelfBridge::GetEntryByGUID( @@ -177,17 +216,22 @@ guid, url, trimmed_title, clock_->Now(), navigation_time, local_device_name_); - syncer::InMemoryMetadataChangeList metadata_change_list; - + std::unique_ptr<ModelTypeStore::WriteBatch> batch = + store_->CreateWriteBatch(); // This entry is new. Add it to the store and model. - auto entity_data = std::make_unique<syncer::EntityData>(); - *entity_data->specifics.mutable_send_tab_to_self() = *entry->AsProto(); - entity_data->non_unique_name = entry->GetURL().spec(); - entity_data->creation_time = entry->GetSharedTime(); + auto entity_data = CopyToEntityData(entry->AsLocalProto().specifics()); - change_processor()->Put(guid, std::move(entity_data), &metadata_change_list); + change_processor()->Put(guid, std::move(entity_data), + batch->GetMetadataChangeList()); - return entries_.emplace(guid, std::move(entry)).first->second.get(); + const SendTabToSelfEntry* result = + entries_.emplace(guid, std::move(entry)).first->second.get(); + SendTabToSelfLocal specifics = result->AsLocalProto(); + + batch->WriteData(guid, specifics.SerializeAsString()); + + Commit(std::move(batch)); + return result; } void SendTabToSelfBridge::DeleteEntry(const std::string& guid) { @@ -197,11 +241,14 @@ } DCHECK(change_processor()->IsTrackingMetadata()); - syncer::InMemoryMetadataChangeList metadata_change_list; - change_processor()->Delete(guid, &metadata_change_list); + + std::unique_ptr<ModelTypeStore::WriteBatch> batch = + store_->CreateWriteBatch(); + change_processor()->Delete(guid, batch->GetMetadataChangeList()); entries_.erase(guid); - + batch->DeleteData(guid); + Commit(std::move(batch)); } void SendTabToSelfBridge::DismissEntry(const std::string& guid) { @@ -214,6 +261,13 @@ // TODO(jeffreycohen) Implement once there is local storage. } +// static +std::unique_ptr<syncer::ModelTypeStore> +SendTabToSelfBridge::DestroyAndStealStoreForTest( + std::unique_ptr<SendTabToSelfBridge> bridge) { + return std::move(bridge->store_); +} + void SendTabToSelfBridge::NotifyRemoteSendTabToSelfEntryAdded( const std::vector<const SendTabToSelfEntry*>& new_entries) { for (SendTabToSelfModelObserver& observer : observers_) { @@ -228,14 +282,89 @@ } } +void SendTabToSelfBridge::NotifySendTabToSelfModelLoaded() { + for (SendTabToSelfModelObserver& observer : observers_) { + observer.SendTabToSelfModelLoaded(); + } +} + +void SendTabToSelfBridge::OnStoreCreated( + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore> store) { + if (error) { + change_processor()->ReportError(*error); + return; + } + + store_ = std::move(store); + store_->ReadAllData(base::BindOnce(&SendTabToSelfBridge::OnReadAllData, + weak_ptr_factory_.GetWeakPtr())); +} + +void SendTabToSelfBridge::OnReadAllData( + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore::RecordList> record_list) { + if (error) { + change_processor()->ReportError(*error); + return; + } + + for (const syncer::ModelTypeStore::Record& r : *record_list) { + auto specifics = std::make_unique<SendTabToSelfLocal>(); + if (specifics->ParseFromString(r.value)) { + entries_[specifics->specifics().guid()] = + SendTabToSelfEntry::FromLocalProto(*specifics, clock_->Now()); + } else { + change_processor()->ReportError( + {FROM_HERE, "Failed to deserialize specifics."}); + return; + } + } + + if (local_device_info_provider_->GetLocalDeviceInfo()) { + OnDeviceProviderInitialized(); + } else { + device_subscription_ = + local_device_info_provider_->RegisterOnInitializedCallback( + base::BindRepeating( + &SendTabToSelfBridge::OnDeviceProviderInitialized, + base::Unretained(this))); + } +} + void SendTabToSelfBridge::OnDeviceProviderInitialized() { device_subscription_.reset(); local_device_name_ = local_device_info_provider_->GetLocalDeviceInfo()->client_name(); - auto batch = std::make_unique<syncer::MetadataBatch>(); + // now that all of the providers are ready we can read the metadata. + store_->ReadAllMetadata(base::BindOnce( + &SendTabToSelfBridge::OnReadAllMetadata, weak_ptr_factory_.GetWeakPtr())); +} - this->change_processor()->ModelReadyToSync(std::move(batch)); +void SendTabToSelfBridge::OnReadAllMetadata( + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch) { + if (error) { + change_processor()->ReportError(*error); + return; + } + change_processor()->ModelReadyToSync(std::move(metadata_batch)); + NotifySendTabToSelfModelLoaded(); +} + +void SendTabToSelfBridge::OnCommit( + const base::Optional<syncer::ModelError>& error) { + if (error) { + change_processor()->ReportError(*error); + } +} + +void SendTabToSelfBridge::Commit( + std::unique_ptr<ModelTypeStore::WriteBatch> batch) { + store_->CommitWriteBatch(std::move(batch), + base::BindOnce(&SendTabToSelfBridge::OnCommit, + weak_ptr_factory_.GetWeakPtr())); } } // namespace send_tab_to_self
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge.h b/components/send_tab_to_self/send_tab_to_self_bridge.h index 89da9b1..feb5a4e6 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge.h +++ b/components/send_tab_to_self/send_tab_to_self_bridge.h
@@ -12,14 +12,15 @@ #include <vector> #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "components/send_tab_to_self/send_tab_to_self_entry.h" #include "components/send_tab_to_self/send_tab_to_self_model.h" #include "components/sync/base/model_type.h" #include "components/sync/device_info/local_device_info_provider.h" +#include "components/sync/model/model_type_store.h" #include "components/sync/model/model_type_sync_bridge.h" namespace syncer { -class LocalDeviceInfoProvider; class ModelTypeChangeProcessor; } // namespace syncer @@ -39,7 +40,8 @@ SendTabToSelfBridge( std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor, syncer::LocalDeviceInfoProvider* local_device_info_provider, - base::Clock* clock); + base::Clock* clock, + syncer::OnceModelTypeStoreFactory create_store_callback); ~SendTabToSelfBridge() override; // syncer::ModelTypeSyncBridge overrides. @@ -68,6 +70,10 @@ void DeleteEntry(const std::string& guid) override; void DismissEntry(const std::string& guid) override; + // For testing only. + static std::unique_ptr<syncer::ModelTypeStore> DestroyAndStealStoreForTest( + std::unique_ptr<SendTabToSelfBridge> bridge); + private: using SendTabToSelfEntries = std::map<std::string, std::unique_ptr<SendTabToSelfEntry>>; @@ -82,23 +88,47 @@ void NotifyRemoteSendTabToSelfEntryDeleted( const std::vector<std::string>& guids); + // Notify all observers that the model is loaded; + void NotifySendTabToSelfModelLoaded(); + + // Methods used as callbacks given to DataTypeStore. + void OnStoreCreated(const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore> store); + void OnReadAllData( + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore::RecordList> record_list); + // Used as callback given to LocalDeviceInfoProvider. void OnDeviceProviderInitialized(); + void OnReadAllMetadata(const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch); + void OnCommit(const base::Optional<syncer::ModelError>& error); + + // Persists the changes in the given aggregators + void Commit(std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch); + // |entries_| is keyed by GUIDs. SendTabToSelfEntries entries_; + // |clock_| isn't owned. + const base::Clock* const clock_; + + // |local_device_info_provider_| isn't owned. syncer::LocalDeviceInfoProvider* const local_device_info_provider_; std::string local_device_name_; - const base::Clock* const clock_; + // In charge of actually persisting changes to disk, or loading previous data. + std::unique_ptr<syncer::ModelTypeStore> store_; // Used to listen for provider initialization. If the provider is already // initialized during our constructor then the subscription is never used. std::unique_ptr<syncer::LocalDeviceInfoProvider::Subscription> device_subscription_; + base::WeakPtrFactory<SendTabToSelfBridge> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(SendTabToSelfBridge); };
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc b/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc index ac447ad..be7650e1 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc +++ b/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
@@ -10,12 +10,18 @@ #include "base/bind.h" #include "base/run_loop.h" +#include "base/strings/stringprintf.h" #include "base/test/scoped_task_environment.h" #include "base/test/simple_test_clock.h" +#include "components/send_tab_to_self/proto/send_tab_to_self.pb.h" #include "components/sync/device_info/local_device_info_provider_mock.h" +#include "components/sync/model/entity_change.h" #include "components/sync/model/metadata_batch.h" #include "components/sync/model/mock_model_type_change_processor.h" +#include "components/sync/model/model_type_store_test_util.h" #include "components/sync/model_impl/in_memory_metadata_change_list.h" +#include "components/sync/protocol/model_type_state.pb.h" +#include "components/sync/test/test_matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -24,16 +30,69 @@ namespace { using testing::_; +using testing::IsEmpty; +using testing::Return; +using testing::SizeIs; + +const char kGuidFormat[] = "guid %d"; +const char kURLFormat[] = "https://www.url%d.com/"; +const char kTitleFormat[] = "title %d"; +const char kDeviceFormat[] = "device %d"; + +sync_pb::SendTabToSelfSpecifics CreateSpecifics( + int suffix, + base::Time shared_time = base::Time::Now(), + base::Time navigation_time = base::Time::Now()) { + sync_pb::SendTabToSelfSpecifics specifics; + specifics.set_guid(base::StringPrintf(kGuidFormat, suffix)); + specifics.set_url(base::StringPrintf(kURLFormat, suffix)); + specifics.set_device_name(base::StringPrintf(kDeviceFormat, suffix)); + specifics.set_title(base::StringPrintf(kTitleFormat, suffix)); + specifics.set_shared_time_usec( + shared_time.ToDeltaSinceWindowsEpoch().InMicroseconds()); + specifics.set_navigation_time_usec( + navigation_time.ToDeltaSinceWindowsEpoch().InMicroseconds()); + return specifics; +} + +sync_pb::ModelTypeState StateWithEncryption( + const std::string& encryption_key_name) { + sync_pb::ModelTypeState state; + state.set_encryption_key_name(encryption_key_name); + return state; +} +class MockSendTabToSelfModelObserver : public SendTabToSelfModelObserver { + public: + MOCK_METHOD0(SendTabToSelfModelLoaded, void()); + MOCK_METHOD1(EntriesAddedRemotely, + void(const std::vector<const SendTabToSelfEntry*>&)); + + MOCK_METHOD1(EntriesRemovedRemotely, void(const std::vector<std::string>&)); +}; class SendTabToSelfBridgeTest : public testing::Test { protected: SendTabToSelfBridgeTest() - : bridge_(mock_processor_.CreateForwardingProcessor(), - &provider_, - &clock_) { + : store_(syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()) { provider_.Initialize("cache_guid", "machine"); - ON_CALL(mock_processor_, IsTrackingMetadata()) - .WillByDefault(testing::Return(true)); + ON_CALL(mock_processor_, IsTrackingMetadata()).WillByDefault(Return(true)); + } + + // Initialized the bridge based on the current local device and store. Can + // only be called once per run, as it passes |store_|. + void InitializeBridge() { + bridge_ = std::make_unique<SendTabToSelfBridge>( + mock_processor_.CreateForwardingProcessor(), &provider_, &clock_, + syncer::ModelTypeStoreTestUtil::MoveStoreToFactory(std::move(store_))); + bridge_->AddObserver(&mock_observer_); + base::RunLoop().RunUntilIdle(); + } + + void ShutdownBridge() { + bridge_->RemoveObserver(&mock_observer_); + store_ = + SendTabToSelfBridge::DestroyAndStealStoreForTest(std::move(bridge_)); + base::RunLoop().RunUntilIdle(); } base::Time AdvanceAndGetTime() { @@ -42,12 +101,12 @@ } syncer::EntityDataPtr MakeEntityData(const SendTabToSelfEntry& entry) { - std::unique_ptr<sync_pb::SendTabToSelfSpecifics> specifics = - entry.AsProto(); + SendTabToSelfLocal specifics = entry.AsLocalProto(); auto entity_data = std::make_unique<syncer::EntityData>(); - *(entity_data->specifics.mutable_send_tab_to_self()) = *specifics; + *(entity_data->specifics.mutable_send_tab_to_self()) = + specifics.specifics(); entity_data->non_unique_name = entry.GetURL().spec(); // The client_tag_hash field is unused by the send_tab_to_self_bridge, but // is required for a valid entity_data. @@ -55,15 +114,42 @@ return entity_data->PassToPtr(); } + // Helper method to reduce duplicated code between tests. Wraps the given + // specifics objects in an EntityData and EntityChange of type ACTION_ADD, and + // returns an EntityChangeList containing them all. Order is maintained. + syncer::EntityChangeList EntityAddList( + const std::vector<sync_pb::SendTabToSelfSpecifics>& specifics_list) { + syncer::EntityChangeList changes; + for (const auto& specifics : specifics_list) { + auto entity_data = std::make_unique<syncer::EntityData>(); + + *(entity_data->specifics.mutable_send_tab_to_self()) = specifics; + entity_data->non_unique_name = specifics.url(); + // The client_tag_hash field is unused by the send_tab_to_self_bridge, but + // is required for a valid entity_data. + entity_data->client_tag_hash = "someclienttaghash"; + + changes.push_back(syncer::EntityChange::CreateAdd( + specifics.guid(), entity_data->PassToPtr())); + } + return changes; + } + // For Model Tests. void AddSampleEntries() { // Adds timer to avoid having two entries with the same shared timestamp. - bridge_.AddEntry(GURL("http://a.com"), "a", AdvanceAndGetTime()); - bridge_.AddEntry(GURL("http://b.com"), "b", AdvanceAndGetTime()); - bridge_.AddEntry(GURL("http://c.com"), "c", AdvanceAndGetTime()); - bridge_.AddEntry(GURL("http://d.com"), "d", AdvanceAndGetTime()); + bridge_->AddEntry(GURL("http://a.com"), "a", AdvanceAndGetTime()); + bridge_->AddEntry(GURL("http://b.com"), "b", AdvanceAndGetTime()); + bridge_->AddEntry(GURL("http://c.com"), "c", AdvanceAndGetTime()); + bridge_->AddEntry(GURL("http://d.com"), "d", AdvanceAndGetTime()); } + syncer::MockModelTypeChangeProcessor* processor() { return &mock_processor_; } + + SendTabToSelfBridge* bridge() { return bridge_.get(); } + MockSendTabToSelfModelObserver* mock_observer() { return &mock_observer_; } + + private: base::SimpleTestClock clock_; // In memory model type store needs to be able to post tasks. @@ -71,21 +157,28 @@ syncer::LocalDeviceInfoProviderMock provider_; - syncer::MockModelTypeChangeProcessor mock_processor_; + std::unique_ptr<syncer::ModelTypeStore> store_; - SendTabToSelfBridge bridge_; + testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_; - private: + std::unique_ptr<SendTabToSelfBridge> bridge_; + + testing::NiceMock<MockSendTabToSelfModelObserver> mock_observer_; + DISALLOW_COPY_AND_ASSIGN(SendTabToSelfBridgeTest); }; TEST_F(SendTabToSelfBridgeTest, CheckEmpties) { - EXPECT_EQ(0ul, bridge_.GetAllGuids().size()); + InitializeBridge(); + + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(_)).Times(0); + EXPECT_EQ(0ul, bridge()->GetAllGuids().size()); AddSampleEntries(); - EXPECT_EQ(4ul, bridge_.GetAllGuids().size()); + EXPECT_EQ(4ul, bridge()->GetAllGuids().size()); } TEST_F(SendTabToSelfBridgeTest, SyncAddOneEntry) { + InitializeBridge(); syncer::EntityChangeList remote_input; SendTabToSelfEntry entry("guid1", GURL("http://www.example.com/"), "title", @@ -95,14 +188,33 @@ syncer::EntityChange::CreateAdd("guid1", MakeEntityData(entry))); auto metadata_change_list = std::make_unique<syncer::InMemoryMetadataChangeList>(); - bridge_.MergeSyncData(std::move(metadata_change_list), remote_input); - EXPECT_EQ(1ul, bridge_.GetAllGuids().size()); + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(SizeIs(1))); + bridge()->MergeSyncData(std::move(metadata_change_list), remote_input); + EXPECT_EQ(1ul, bridge()->GetAllGuids().size()); +} + +TEST_F(SendTabToSelfBridgeTest, ApplySyncChangesAddTwoSpecifics) { + InitializeBridge(); + + const sync_pb::SendTabToSelfSpecifics specifics1 = CreateSpecifics(1); + const sync_pb::SendTabToSelfSpecifics specifics2 = CreateSpecifics(2); + + sync_pb::ModelTypeState state = StateWithEncryption("ekn"); + std::unique_ptr<syncer::MetadataChangeList> metadata_changes = + bridge()->CreateMetadataChangeList(); + metadata_changes->UpdateModelTypeState(state); + + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(SizeIs(2))); + + auto error = bridge()->ApplySyncChanges( + std::move(metadata_changes), EntityAddList({specifics1, specifics2})); + EXPECT_FALSE(error); } TEST_F(SendTabToSelfBridgeTest, ApplySyncChangesOneAdd) { + InitializeBridge(); SendTabToSelfEntry entry("guid1", GURL("http://www.example.com/"), "title", AdvanceAndGetTime(), AdvanceAndGetTime(), "device"); - std::unique_ptr<sync_pb::SendTabToSelfSpecifics> specifics = entry.AsProto(); syncer::EntityChangeList add_changes; @@ -110,28 +222,111 @@ syncer::EntityChange::CreateAdd("guid1", MakeEntityData(entry))); auto metadata_change_list = std::make_unique<syncer::InMemoryMetadataChangeList>(); - bridge_.ApplySyncChanges(std::move(metadata_change_list), add_changes); - EXPECT_EQ(1ul, bridge_.GetAllGuids().size()); + + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(SizeIs(1))); + bridge()->ApplySyncChanges(std::move(metadata_change_list), add_changes); + EXPECT_EQ(1ul, bridge()->GetAllGuids().size()); } // Tests that the send tab to self entry is correctly removed. TEST_F(SendTabToSelfBridgeTest, ApplySyncChangesOneDeletion) { + InitializeBridge(); SendTabToSelfEntry entry("guid1", GURL("http://www.example.com/"), "title", AdvanceAndGetTime(), AdvanceAndGetTime(), "device"); - std::unique_ptr<sync_pb::SendTabToSelfSpecifics> specifics = entry.AsProto(); syncer::EntityChangeList add_changes; add_changes.push_back( syncer::EntityChange::CreateAdd("guid1", MakeEntityData(entry))); - auto metadata_change_list = - std::make_unique<syncer::InMemoryMetadataChangeList>(); - bridge_.ApplySyncChanges(std::move(metadata_change_list), add_changes); - EXPECT_EQ(1ul, bridge_.GetAllGuids().size()); + + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(SizeIs(1))); + bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(), add_changes); + EXPECT_EQ(1ul, bridge()->GetAllGuids().size()); syncer::EntityChangeList delete_changes; delete_changes.push_back(syncer::EntityChange::CreateDelete("guid1")); - bridge_.ApplySyncChanges(std::move(metadata_change_list), delete_changes); - EXPECT_EQ(0ul, bridge_.GetAllGuids().size()); + + EXPECT_CALL(*mock_observer(), EntriesRemovedRemotely(SizeIs(1))); + bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(), + delete_changes); + EXPECT_EQ(0ul, bridge()->GetAllGuids().size()); +} + +TEST_F(SendTabToSelfBridgeTest, ApplySyncChangesEmpty) { + InitializeBridge(); + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(_)).Times(0); + + auto error = bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(), + syncer::EntityChangeList()); + EXPECT_FALSE(error); +} + +TEST_F(SendTabToSelfBridgeTest, AddEntryAndRestartBridge) { + InitializeBridge(); + + const sync_pb::SendTabToSelfSpecifics specifics = CreateSpecifics(1); + sync_pb::ModelTypeState state = StateWithEncryption("ekn"); + std::unique_ptr<syncer::MetadataChangeList> metadata_changes = + bridge()->CreateMetadataChangeList(); + metadata_changes->UpdateModelTypeState(state); + + auto error = bridge()->ApplySyncChanges(std::move(metadata_changes), + EntityAddList({specifics})); + ASSERT_FALSE(error); + + ShutdownBridge(); + + EXPECT_CALL(*processor(), + ModelReadyToSync(MetadataBatchContains( + syncer::HasEncryptionKeyName(state.encryption_key_name()), + /*entities=*/IsEmpty()))); + + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(_)).Times(0); + InitializeBridge(); + + std::vector<std::string> guids = bridge()->GetAllGuids(); + EXPECT_EQ(1ul, guids.size()); + EXPECT_EQ(specifics.url(), + bridge()->GetEntryByGUID(guids[0])->GetURL().spec()); +} + +TEST_F(SendTabToSelfBridgeTest, ApplySyncChangesInMemory) { + InitializeBridge(); + + const sync_pb::SendTabToSelfSpecifics specifics = CreateSpecifics(1); + std::unique_ptr<syncer::MetadataChangeList> metadata_changes = + bridge()->CreateMetadataChangeList(); + + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(SizeIs(1))); + + auto error_on_add = bridge()->ApplySyncChanges( + bridge()->CreateMetadataChangeList(), EntityAddList({specifics})); + + EXPECT_FALSE(error_on_add); + + EXPECT_EQ(1ul, bridge()->GetAllGuids().size()); + + EXPECT_CALL(*mock_observer(), EntriesRemovedRemotely(SizeIs(1))); + + auto error_on_delete = bridge()->ApplySyncChanges( + bridge()->CreateMetadataChangeList(), + {syncer::EntityChange::CreateDelete(specifics.guid())}); + + EXPECT_FALSE(error_on_delete); + EXPECT_EQ(0ul, bridge()->GetAllGuids().size()); +} + +TEST_F(SendTabToSelfBridgeTest, ApplyDeleteNonexistent) { + InitializeBridge(); + EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(_)).Times(0); + + std::unique_ptr<syncer::MetadataChangeList> metadata_changes = + bridge()->CreateMetadataChangeList(); + + EXPECT_CALL(*processor(), Delete(_, _)).Times(0); + auto error = + bridge()->ApplySyncChanges(std::move(metadata_changes), + {syncer::EntityChange::CreateDelete("guid")}); + EXPECT_FALSE(error); } } // namespace
diff --git a/components/send_tab_to_self/send_tab_to_self_entry.cc b/components/send_tab_to_self/send_tab_to_self_entry.cc index 433c782..9e6c964 100644 --- a/components/send_tab_to_self/send_tab_to_self_entry.cc +++ b/components/send_tab_to_self/send_tab_to_self_entry.cc
@@ -7,6 +7,7 @@ #include "base/guid.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "components/send_tab_to_self/proto/send_tab_to_self.pb.h" #include "components/sync/protocol/send_tab_to_self_specifics.pb.h" namespace send_tab_to_self { @@ -69,9 +70,9 @@ return device_name_; } -std::unique_ptr<sync_pb::SendTabToSelfSpecifics> SendTabToSelfEntry::AsProto() - const { - auto pb_entry = std::make_unique<sync_pb::SendTabToSelfSpecifics>(); +SendTabToSelfLocal SendTabToSelfEntry::AsLocalProto() const { + SendTabToSelfLocal local_entry; + auto* pb_entry = local_entry.mutable_specifics(); pb_entry->set_guid(GetGUID()); pb_entry->set_title(GetTitle()); @@ -81,7 +82,7 @@ TimeToProtoTime(GetOriginalNavigationTime())); pb_entry->set_device_name(GetDeviceName()); - return pb_entry; + return local_entry; } std::unique_ptr<SendTabToSelfEntry> SendTabToSelfEntry::FromProto( @@ -108,4 +109,10 @@ pb_entry.device_name()); } +std::unique_ptr<SendTabToSelfEntry> SendTabToSelfEntry::FromLocalProto( + const SendTabToSelfLocal& local_entry, + base::Time now) { + return FromProto(local_entry.specifics(), now); +} + } // namespace send_tab_to_self
diff --git a/components/send_tab_to_self/send_tab_to_self_entry.h b/components/send_tab_to_self/send_tab_to_self_entry.h index ab0b98e..b8c9003 100644 --- a/components/send_tab_to_self/send_tab_to_self_entry.h +++ b/components/send_tab_to_self/send_tab_to_self_entry.h
@@ -17,6 +17,8 @@ namespace send_tab_to_self { +class SendTabToSelfLocal; + // A tab that is being shared. The URL is a unique identifier for an entry, as // such it should not be empty and is the only thing considered when comparing // entries. @@ -49,8 +51,8 @@ const std::string& GetDeviceName() const; // Returns a protobuf encoding the content of this SendTabToSelfEntry for - // sync. - std::unique_ptr<sync_pb::SendTabToSelfSpecifics> AsProto() const; + // local storage. + SendTabToSelfLocal AsLocalProto() const; // Creates a SendTabToSelfEntry from the protobuf format. // If creation time is not set, it will be set to |now|. @@ -58,6 +60,12 @@ const sync_pb::SendTabToSelfSpecifics& pb_entry, base::Time now); + // Creates a SendTabToSelfEntry from the protobuf format. + // If creation time is not set, it will be set to |now|. + static std::unique_ptr<SendTabToSelfEntry> FromLocalProto( + const SendTabToSelfLocal& pb_entry, + base::Time now); + private: std::string guid_; GURL url_;
diff --git a/components/send_tab_to_self/send_tab_to_self_entry_unittest.cc b/components/send_tab_to_self/send_tab_to_self_entry_unittest.cc index c276a9d..a100601 100644 --- a/components/send_tab_to_self/send_tab_to_self_entry_unittest.cc +++ b/components/send_tab_to_self/send_tab_to_self_entry_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/test/simple_test_tick_clock.h" +#include "components/send_tab_to_self/proto/send_tab_to_self.pb.h" #include "components/sync/protocol/send_tab_to_self_specifics.pb.h" #include "testing/gtest/include/gtest/gtest.h" @@ -68,8 +69,8 @@ SendTabToSelfEntry entry("1", GURL("http://example.com"), "bar", base::Time::FromTimeT(10), base::Time::FromTimeT(10), "device"); - std::unique_ptr<sync_pb::SendTabToSelfSpecifics> pb_entry(entry.AsProto()); - EXPECT_TRUE(IsEqualForTesting(entry, *pb_entry)); + SendTabToSelfLocal pb_entry(entry.AsLocalProto()); + EXPECT_TRUE(IsEqualForTesting(entry, pb_entry.specifics())); } // Tests that the send tab to self entry is correctly parsed from
diff --git a/components/send_tab_to_self/send_tab_to_self_sync_service.cc b/components/send_tab_to_self/send_tab_to_self_sync_service.cc index f22b5d0..200ba05 100644 --- a/components/send_tab_to_self/send_tab_to_self_sync_service.cc +++ b/components/send_tab_to_self/send_tab_to_self_sync_service.cc
@@ -10,18 +10,21 @@ #include "components/send_tab_to_self/send_tab_to_self_model.h" #include "components/sync/base/report_unrecoverable_error.h" #include "components/sync/device_info/local_device_info_provider.h" +#include "components/sync/model/model_type_store.h" #include "components/sync/model_impl/client_tag_based_model_type_processor.h" namespace send_tab_to_self { SendTabToSelfSyncService::SendTabToSelfSyncService( version_info::Channel channel, - syncer::LocalDeviceInfoProvider* local_device_info_provider) { + syncer::LocalDeviceInfoProvider* local_device_info_provider, + syncer::OnceModelTypeStoreFactory create_store_callback) { bridge_ = std::make_unique<send_tab_to_self::SendTabToSelfBridge>( std::make_unique<syncer::ClientTagBasedModelTypeProcessor>( syncer::SEND_TAB_TO_SELF, base::BindRepeating(&syncer::ReportUnrecoverableError, channel)), - local_device_info_provider, base::DefaultClock::GetInstance()); + local_device_info_provider, base::DefaultClock::GetInstance(), + std::move(create_store_callback)); } SendTabToSelfSyncService::~SendTabToSelfSyncService() = default;
diff --git a/components/send_tab_to_self/send_tab_to_self_sync_service.h b/components/send_tab_to_self/send_tab_to_self_sync_service.h index 703eaed..18af7e1 100644 --- a/components/send_tab_to_self/send_tab_to_self_sync_service.h +++ b/components/send_tab_to_self/send_tab_to_self_sync_service.h
@@ -10,6 +10,7 @@ #include "base/memory/weak_ptr.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/sync/model/model_type_store_service.h" #include "components/version_info/channel.h" namespace syncer { @@ -26,7 +27,8 @@ public: SendTabToSelfSyncService( version_info::Channel channel, - syncer::LocalDeviceInfoProvider* local_device_info_provider); + syncer::LocalDeviceInfoProvider* local_device_info_provider, + syncer::OnceModelTypeStoreFactory create_store_callback); ~SendTabToSelfSyncService() override; SendTabToSelfModel* GetSendTabToSelfModel();
diff --git a/components/sync/android/BUILD.gn b/components/sync/android/BUILD.gn index e16c41d..37b8fc2 100644 --- a/components/sync/android/BUILD.gn +++ b/components/sync/android/BUILD.gn
@@ -20,7 +20,7 @@ java_files = [ "java/src/org/chromium/components/sync/AndroidSyncSettings.java", "java/src/org/chromium/components/sync/ModelTypeHelper.java", - "java/src/org/chromium/components/sync/PassphraseType.java", + "java/src/org/chromium/components/sync/Passphrase.java", "java/src/org/chromium/components/sync/SyncConstants.java", "java/src/org/chromium/components/sync/SyncContentResolverDelegate.java", "java/src/org/chromium/components/sync/SystemSyncContentResolverDelegate.java",
diff --git a/components/sync/android/java/src/org/chromium/components/sync/Passphrase.java b/components/sync/android/java/src/org/chromium/components/sync/Passphrase.java new file mode 100644 index 0000000..4cf01b11 --- /dev/null +++ b/components/sync/android/java/src/org/chromium/components/sync/Passphrase.java
@@ -0,0 +1,65 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.sync; + +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + +/** + * This class describes the type of passphrase required, if any, to decrypt synced data. + * It maps the native enum PassphraseType. + */ +public class Passphrase { + @IntDef({Type.IMPLICIT, Type.KEYSTORE, Type.FROZEN_IMPLICIT, Type.CUSTOM}) + @Retention(RetentionPolicy.SOURCE) + public @interface Type { + // Update {@link ProfileSyncService#getPassphraseType()} after changing lowest value. + int IMPLICIT = 0; // GAIA-based passphrase (deprecated). + int KEYSTORE = 1; // Keystore passphrase. + int FROZEN_IMPLICIT = 2; // Frozen GAIA passphrase. + int CUSTOM = 3; // User-provided passphrase. + int NUM_ENTRIES = 4; + } + + /** + * Get the types that are displayed for the current type. + */ + public static List<Integer /* @Type */> getVisibleTypes(@Type int type) { + List<Integer /* @Type */> visibleTypes = new ArrayList<>(); + switch (type) { + case Type.IMPLICIT: // Intentional fall through. + case Type.KEYSTORE: + visibleTypes.add(Type.CUSTOM); + visibleTypes.add(type); + break; + case Type.FROZEN_IMPLICIT: // Intentional fall through. + case Type.CUSTOM: + visibleTypes.add(type); + visibleTypes.add(Type.KEYSTORE); + break; + default: + assert false; + } + return visibleTypes; + } + + /** + * Get the types that are allowed to be enabled from the current type. + * @param isEncryptEverythingAllowed Whether encrypting all data is allowed. + */ + public static List<Integer /* @Type */> getAllowedTypes( + @Type int type, boolean isEncryptEverythingAllowed) { + List<Integer /* @Type */> allowedTypes = new ArrayList<>(); + if (type == Type.IMPLICIT || type == Type.KEYSTORE) { + allowedTypes.add(type); + if (isEncryptEverythingAllowed) allowedTypes.add(Type.CUSTOM); + } + return allowedTypes; + } +} \ No newline at end of file
diff --git a/components/sync/android/java/src/org/chromium/components/sync/PassphraseType.java b/components/sync/android/java/src/org/chromium/components/sync/PassphraseType.java deleted file mode 100644 index 0bc2063..0000000 --- a/components/sync/android/java/src/org/chromium/components/sync/PassphraseType.java +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.components.sync; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.HashSet; -import java.util.Set; - -/** - * This enum describes the type of passphrase required, if any, to decrypt synced data. - * - * It implements the Android {@link Parcelable} interface so it is easy to pass around in intents. - * - * It maps the native enum PassphraseType. - */ -public enum PassphraseType implements Parcelable { - IMPLICIT_PASSPHRASE(0), // GAIA-based passphrase (deprecated). - KEYSTORE_PASSPHRASE(1), // Keystore passphrase. - FROZEN_IMPLICIT_PASSPHRASE(2), // Frozen GAIA passphrase. - CUSTOM_PASSPHRASE(3); // User-provided passphrase. - - public static final Parcelable.Creator<PassphraseType> CREATOR = - new Parcelable.Creator<PassphraseType>() { - @Override - public PassphraseType createFromParcel(Parcel parcel) { - return fromInternalValue(parcel.readInt()); - } - - @Override - public PassphraseType[] newArray(int size) { - return new PassphraseType[size]; - } - }; - - public static PassphraseType fromInternalValue(int value) { - for (PassphraseType type : values()) { - if (type.internalValue() == value) { - return type; - } - } - throw new IllegalArgumentException("No value for " + value + " found."); - } - - private final int mNativeValue; - - private PassphraseType(int nativeValue) { - mNativeValue = nativeValue; - } - - public Set<PassphraseType> getVisibleTypes() { - Set<PassphraseType> visibleTypes = new HashSet<>(); - switch (this) { - case IMPLICIT_PASSPHRASE: // Intentional fall through. - case KEYSTORE_PASSPHRASE: - visibleTypes.add(this); - visibleTypes.add(CUSTOM_PASSPHRASE); - break; - case FROZEN_IMPLICIT_PASSPHRASE: - visibleTypes.add(KEYSTORE_PASSPHRASE); - visibleTypes.add(FROZEN_IMPLICIT_PASSPHRASE); - break; - case CUSTOM_PASSPHRASE: - visibleTypes.add(KEYSTORE_PASSPHRASE); - visibleTypes.add(CUSTOM_PASSPHRASE); - break; - } - return visibleTypes; - } - - /** - * Get the types that are allowed to be enabled from the current type. - * - * @param isEncryptEverythingAllowed Whether encrypting all data is allowed. - */ - public Set<PassphraseType> getAllowedTypes(boolean isEncryptEverythingAllowed) { - Set<PassphraseType> allowedTypes = new HashSet<>(); - switch (this) { - case IMPLICIT_PASSPHRASE: // Intentional fall through. - case KEYSTORE_PASSPHRASE: - allowedTypes.add(this); - if (isEncryptEverythingAllowed) { - allowedTypes.add(CUSTOM_PASSPHRASE); - } - break; - case FROZEN_IMPLICIT_PASSPHRASE: // Intentional fall through. - case CUSTOM_PASSPHRASE: // Intentional fall through. - default: - break; - } - return allowedTypes; - } - - public int internalValue() { - // Since the values in this enums are constant and very small, this cast is safe. - return mNativeValue; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mNativeValue); - } -}
diff --git a/components/translate/content/DEPS b/components/translate/content/DEPS index 83c2ce4..c57486b 100644 --- a/components/translate/content/DEPS +++ b/components/translate/content/DEPS
@@ -1,6 +1,4 @@ include_rules = [ "+content/public/common", "+mojo/public", - "+services/network/public", - "+third_party/blink/public", ]
diff --git a/components/translate/content/browser/content_translate_driver.cc b/components/translate/content/browser/content_translate_driver.cc index cee7663b..7c91e182 100644 --- a/components/translate/content/browser/content_translate_driver.cc +++ b/components/translate/content/browser/content_translate_driver.cc
@@ -4,9 +4,6 @@ #include "components/translate/content/browser/content_translate_driver.h" -#include <string> -#include <utility> - #include "base/bind.h" #include "base/location.h" #include "base/logging.h" @@ -16,7 +13,6 @@ #include "components/search_engines/template_url_service.h" #include "components/translate/core/browser/translate_download_manager.h" #include "components/translate/core/browser/translate_manager.h" -#include "components/translate/core/common/translate_util.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_details.h" @@ -24,15 +20,11 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/page_navigator.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/referrer.h" #include "net/http/http_status_code.h" -#include "services/network/public/mojom/network_context.mojom.h" #include "url/gurl.h" -namespace translate { - namespace { // The maximum number of attempts we'll do to see if the page has finshed @@ -41,6 +33,8 @@ } // namespace +namespace translate { + ContentTranslateDriver::ContentTranslateDriver( content::NavigationController* nav_controller, const TemplateURLService* template_url_service, @@ -113,23 +107,6 @@ observer.OnIsPageTranslatedChanged(web_contents); } -network::mojom::URLLoaderFactoryPtr -ContentTranslateDriver::CreateURLLoaderFactory() { - // Find the renderer process that will need to use the URLLoaderFactory. - // Currently translate requests are only sent to the main frame process. - content::RenderProcessHost* process = - web_contents()->GetMainFrame()->GetProcess(); - - // Create a new URLLoaderFactory, locking the initiator origin to the one - // returned by GetTranslateSecurityOrigin. - network::mojom::URLLoaderFactoryPtr factory; - url::Origin origin = url::Origin::Create(GetTranslateSecurityOrigin()); - network::mojom::TrustedURLLoaderHeaderClientPtrInfo null_header_client; - process->CreateURLLoaderFactory(origin, std::move(null_header_client), - mojo::MakeRequest(&factory)); - return factory; -} - void ContentTranslateDriver::TranslatePage(int page_seq_no, const std::string& translate_script, const std::string& source_lang, @@ -139,7 +116,7 @@ return; // This page has navigated away. it->second->Translate( - translate_script, CreateURLLoaderFactory(), source_lang, target_lang, + translate_script, source_lang, target_lang, base::BindOnce(&ContentTranslateDriver::OnPageTranslated, base::Unretained(this))); }
diff --git a/components/translate/content/browser/content_translate_driver.h b/components/translate/content/browser/content_translate_driver.h index f937d82..9b05c7e 100644 --- a/components/translate/content/browser/content_translate_driver.h +++ b/components/translate/content/browser/content_translate_driver.h
@@ -6,7 +6,6 @@ #define COMPONENTS_TRANSLATE_CONTENT_BROWSER_CONTENT_TRANSLATE_DRIVER_H_ #include <map> -#include <string> #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -16,7 +15,6 @@ #include "components/translate/core/common/translate_errors.h" #include "content/public/browser/web_contents_observer.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "services/network/public/mojom/url_loader_factory.mojom.h" namespace content { class NavigationController; @@ -125,13 +123,6 @@ bool IsDefaultSearchEngineOriginator( const url::Origin& originating_origin) const; - // Creates a URLLoaderFactory that may be used by the translate scripts that - // get injected into isolated worlds within the page to be translated. Such - // scripts (or rather, their isolated worlds) are associated with a - // translate-specific origin like https://translate.googleapis.com and use - // this origin as |request_initiator| of http requests. - network::mojom::URLLoaderFactoryPtr CreateURLLoaderFactory(); - // The navigation controller of the tab we are associated with. content::NavigationController* navigation_controller_;
diff --git a/components/translate/content/common/BUILD.gn b/components/translate/content/common/BUILD.gn index ae52137..a5b6a678 100644 --- a/components/translate/content/common/BUILD.gn +++ b/components/translate/content/common/BUILD.gn
@@ -11,7 +11,6 @@ public_deps = [ "//mojo/public/mojom/base", - "//services/network/public/mojom:mojom", "//url/mojom:url_mojom_gurl", ] }
diff --git a/components/translate/content/common/translate.mojom b/components/translate/content/common/translate.mojom index 0893def..7d09c8f 100644 --- a/components/translate/content/common/translate.mojom +++ b/components/translate/content/common/translate.mojom
@@ -6,7 +6,6 @@ import "mojo/public/mojom/base/time.mojom"; import "mojo/public/mojom/base/string16.mojom"; -import "services/network/public/mojom/url_loader_factory.mojom"; import "url/mojom/url.mojom"; enum TranslateError { @@ -40,12 +39,6 @@ // Requests that the page be translated from |source_lang| to // |target_lang|. // - // |loader_factory_for_translate_script| should provide a factory that the - // translation scripts can use for making fetch requests associated with the - // "translate" origin (the default factory's |request_initiator_site_lock| is - // not compatible with |request_initiator| of fetch requests initiated by the - // "translate" origin). - // // If a Translate request is already in progress with a matching // |target_lang|, this request will respond with |cancelled| set // to |true|. @@ -56,10 +49,7 @@ // // If |cancelled| is |true| all other response values should be // ignored. - Translate(string translate_script, - network.mojom.URLLoaderFactory loader_factory_for_translate_script, - string source_lang, - string target_lang) + Translate(string translate_script, string source_lang, string target_lang) => (bool cancelled, string original_lang, string translated_lang, TranslateError error);
diff --git a/components/translate/content/renderer/BUILD.gn b/components/translate/content/renderer/BUILD.gn index 72a8873..d04d8d6 100644 --- a/components/translate/content/renderer/BUILD.gn +++ b/components/translate/content/renderer/BUILD.gn
@@ -15,6 +15,8 @@ "//components/translate/content/common", "//components/translate/core/common", "//components/translate/core/language_detection", + "//content/public/common", + "//content/public/renderer", "//services/service_manager/public/cpp", "//third_party/blink/public:blink", "//url", @@ -22,8 +24,6 @@ ] public_deps = [ - "//content/public/common", - "//content/public/renderer", "//third_party/blink/public:blink_headers", ] }
diff --git a/components/translate/content/renderer/translate_helper.cc b/components/translate/content/renderer/translate_helper.cc index 8b8a8a6..2cc44a6 100644 --- a/components/translate/content/renderer/translate_helper.cc +++ b/components/translate/content/renderer/translate_helper.cc
@@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/compiler_specific.h" -#include "base/feature_list.h" #include "base/json/string_escape.h" #include "base/location.h" #include "base/logging.h" @@ -26,9 +25,7 @@ #include "content/public/common/url_constants.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_thread.h" -#include "services/network/public/cpp/features.h" #include "services/service_manager/public/cpp/interface_provider.h" -#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" #include "third_party/blink/public/platform/web_isolated_world_info.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_language_detection_details.h" @@ -285,20 +282,10 @@ } // mojom::Page implementations. -void TranslateHelper::Translate( - const std::string& translate_script, - network::mojom::URLLoaderFactoryPtr loader_factory_for_translate_script, - const std::string& source_lang, - const std::string& target_lang, - TranslateCallback callback) { - url::Origin translate_origin = - url::Origin::Create(GetTranslateSecurityOrigin()); - - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - render_frame()->MarkInitiatorAsRequiringSeparateURLLoaderFactory( - translate_origin, std::move(loader_factory_for_translate_script)); - } - +void TranslateHelper::Translate(const std::string& translate_script, + const std::string& source_lang, + const std::string& target_lang, + TranslateCallback callback) { WebLocalFrame* main_frame = render_frame()->GetWebFrame(); if (!main_frame) { // Cancelled. @@ -335,7 +322,8 @@ // Set up v8 isolated world with proper content-security-policy and // security-origin. blink::WebIsolatedWorldInfo info; - info.security_origin = WebSecurityOrigin::Create(translate_origin.GetURL()); + info.security_origin = + WebSecurityOrigin::Create(GetTranslateSecurityOrigin()); info.content_security_policy = WebString::FromUTF8(kContentSecurityPolicy); main_frame->SetIsolatedWorldInfo(world_id_, info);
diff --git a/components/translate/content/renderer/translate_helper.h b/components/translate/content/renderer/translate_helper.h index 5dba2be..494985d0 100644 --- a/components/translate/content/renderer/translate_helper.h +++ b/components/translate/content/renderer/translate_helper.h
@@ -17,7 +17,6 @@ #include "components/translate/core/common/translate_errors.h" #include "content/public/renderer/render_frame_observer.h" #include "mojo/public/cpp/bindings/binding.h" -#include "services/network/public/mojom/url_loader_factory.mojom.h" #include "url/gurl.h" namespace blink { @@ -45,12 +44,10 @@ void PrepareForUrl(const GURL& url); // mojom::Page implementation. - void Translate( - const std::string& translate_script, - network::mojom::URLLoaderFactoryPtr loader_factory_for_translate_script, - const std::string& source_lang, - const std::string& target_lang, - TranslateCallback callback) override; + void Translate(const std::string& translate_script, + const std::string& source_lang, + const std::string& target_lang, + TranslateCallback callback) override; void RevertTranslation() override; protected:
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn index 3a24b18..06cb620 100644 --- a/components/update_client/BUILD.gn +++ b/components/update_client/BUILD.gn
@@ -53,6 +53,7 @@ "crx_downloader.cc", "crx_downloader.h", "crx_update_item.h", + "network.cc", "network.h", "persisted_data.cc", "persisted_data.h",
diff --git a/components/update_client/net/network_impl.cc b/components/update_client/net/network_impl.cc index e7f4ece..bd97998 100644 --- a/components/update_client/net/network_impl.cc +++ b/components/update_client/net/network_impl.cc
@@ -47,6 +47,37 @@ } })"); +// Returns the string value of a header of the server response or an empty +// string if the header is not available. Only the first header is returned +// if multiple instances of the same header are present. +std::string GetStringHeader(const network::SimpleURLLoader* simple_url_loader, + const char* header_name) { + DCHECK(simple_url_loader); + + const auto* response_info = simple_url_loader->ResponseInfo(); + if (!response_info || !response_info->headers) + return {}; + + std::string header_value; + return response_info->headers->EnumerateHeader(nullptr, header_name, + &header_value) + ? header_value + : std::string{}; +} + +// Returns the integral value of a header of the server response or -1 if +// if the header is not available or a conversion error has occured. +int64_t GetInt64Header(const network::SimpleURLLoader* simple_url_loader, + const char* header_name) { + DCHECK(simple_url_loader); + + const auto* response_info = simple_url_loader->ResponseInfo(); + if (!response_info || !response_info->headers) + return -1; + + return response_info->headers->GetInt64HeaderValue(header_name); +} + } // namespace namespace update_client { @@ -83,7 +114,17 @@ constexpr size_t kMaxResponseSize = 1024 * 1024; simple_url_loader_->DownloadToString( shared_url_network_factory_.get(), - std::move(post_request_complete_callback), kMaxResponseSize); + base::BindOnce( + [](const network::SimpleURLLoader* simple_url_loader, + PostRequestCompleteCallback post_request_complete_callback, + std::unique_ptr<std::string> response_body) { + std::move(post_request_complete_callback) + .Run(std::move(response_body), simple_url_loader->NetError(), + GetStringHeader(simple_url_loader, kHeaderEtag), + GetInt64Header(simple_url_loader, kHeaderXRetryAfter)); + }, + simple_url_loader_.get(), std::move(post_request_complete_callback)), + kMaxResponseSize); } void NetworkFetcherImpl::DownloadToFile( @@ -109,42 +150,17 @@ std::move(response_started_callback))); simple_url_loader_->DownloadToFile( shared_url_network_factory_.get(), - std::move(download_to_file_complete_callback), file_path); -} - -int64_t NetworkFetcherImpl::GetContentSize() const { - DCHECK(simple_url_loader_); - return simple_url_loader_->GetContentSize(); -} - -int NetworkFetcherImpl::NetError() const { - DCHECK(simple_url_loader_); - return simple_url_loader_->NetError(); -} - -std::string NetworkFetcherImpl::GetStringHeaderValue( - const char* header_name) const { - DCHECK(simple_url_loader_); - - const auto* response_info = simple_url_loader_->ResponseInfo(); - if (!response_info || !response_info->headers) - return {}; - - std::string header_value; - return response_info->headers->EnumerateHeader(nullptr, header_name, - &header_value) - ? header_value - : std::string{}; -} - -int64_t NetworkFetcherImpl::GetInt64HeaderValue(const char* header_name) const { - DCHECK(simple_url_loader_); - - const auto* response_info = simple_url_loader_->ResponseInfo(); - if (!response_info || !response_info->headers) - return -1; - - return response_info->headers->GetInt64HeaderValue(header_name); + base::BindOnce( + [](const network::SimpleURLLoader* simple_url_loader, + DownloadToFileCompleteCallback download_to_file_complete_callback, + base::FilePath file_path) { + std::move(download_to_file_complete_callback) + .Run(file_path, simple_url_loader->NetError(), + simple_url_loader->GetContentSize()); + }, + simple_url_loader_.get(), + std::move(download_to_file_complete_callback)), + file_path); } void NetworkFetcherImpl::OnResponseStartedCallback(
diff --git a/components/update_client/net/network_impl.h b/components/update_client/net/network_impl.h index 493af60b..c7f2b10 100644 --- a/components/update_client/net/network_impl.h +++ b/components/update_client/net/network_impl.h
@@ -40,11 +40,6 @@ ResponseStartedCallback response_started_callback, DownloadToFileCompleteCallback download_to_file_complete_callback) override; - int NetError() const override; - std::string GetStringHeaderValue(const char* header_name) const override; - int64_t GetInt64HeaderValue(const char* header_name) const override; - int64_t GetContentSize() const override; - private: void OnResponseStartedCallback( ResponseStartedCallback response_started_callback,
diff --git a/components/update_client/network.cc b/components/update_client/network.cc new file mode 100644 index 0000000..cb8e151 --- /dev/null +++ b/components/update_client/network.cc
@@ -0,0 +1,12 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/update_client/network.h" + +namespace update_client { + +constexpr char NetworkFetcher::kHeaderEtag[]; +constexpr char NetworkFetcher::kHeaderXRetryAfter[]; + +} // namespace update_client
diff --git a/components/update_client/network.h b/components/update_client/network.h index 7d871aa..c42d222 100644 --- a/components/update_client/network.h +++ b/components/update_client/network.h
@@ -26,12 +26,27 @@ class NetworkFetcher { public: using PostRequestCompleteCallback = - base::OnceCallback<void(std::unique_ptr<std::string> response_body)>; - using DownloadToFileCompleteCallback = - base::OnceCallback<void(base::FilePath path)>; + base::OnceCallback<void(std::unique_ptr<std::string> response_body, + int net_error, + const std::string& header_etag, + int64_t xheader_retry_after_sec)>; + using DownloadToFileCompleteCallback = base::OnceCallback< + void(base::FilePath path, int net_error, int64_t content_size)>; using ResponseStartedCallback = base::OnceCallback< void(const GURL& final_url, int response_code, int64_t content_length)>; + // The ETag header carries the ECSDA signature of the POST response, if + // signing has been used. + static constexpr char kHeaderEtag[] = "ETag"; + + // The server uses the optional X-Retry-After header to indicate that the + // current request should not be attempted again. + // + // The value of the header is the number of seconds to wait before trying to + // do a subsequent update check. Only the values retrieved over HTTPS are + // trusted. + static constexpr char kHeaderXRetryAfter[] = "X-Retry-After"; + virtual ~NetworkFetcher() = default; virtual void PostRequest( @@ -45,17 +60,6 @@ const base::FilePath& file_path, ResponseStartedCallback response_started_callback, DownloadToFileCompleteCallback download_to_file_complete_callback) = 0; - virtual int NetError() const = 0; - - // Returns the string value of a header of the server response or an empty - // string if the header is not available. Only the first header is returned - // if multiple instances of the same header are present. - virtual std::string GetStringHeaderValue(const char* header_name) const = 0; - - // Returns the integral value of a header of the server response or -1 if - // if the header is not available or a conversion error has occured. - virtual int64_t GetInt64HeaderValue(const char* header_name) const = 0; - virtual int64_t GetContentSize() const = 0; protected: NetworkFetcher() = default;
diff --git a/components/update_client/request_sender.cc b/components/update_client/request_sender.cc index 6747d39..ee911c9 100644 --- a/components/update_client/request_sender.cc +++ b/components/update_client/request_sender.cc
@@ -4,13 +4,13 @@ #include "components/update_client/request_sender.h" -#include <algorithm> #include <utility> #include "base/base64.h" #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "components/client_update_protocol/ecdsa.h" @@ -29,25 +29,6 @@ "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsVwVMmIJaWBjktSx9m1JrZWYBvMm" "bsrGGQPhScDtao+DloD871YmEeunAaQvRMZgDh1nCaWkVG6wo75+yDbKDA=="; -// The ETag header carries the ECSDA signature of the protocol response, if -// signing has been used. -constexpr const char* kHeaderEtag = "ETag"; - -// The server uses the optional X-Retry-After header to indicate that the -// current request should not be attempted again. Any response received along -// with the X-Retry-After header should be interpreted as it would have been -// without the X-Retry-After header. -// -// In addition to the presence of the header, the value of the header is -// used as a signal for when to do future update checks, but only when the -// response is over https. Values over http are not trusted and are ignored. -// -// The value of the header is the number of seconds to wait before trying to do -// a subsequent update check. The upper bound for the number of seconds to wait -// before trying to do a subsequent update check is capped at 24 hours. -constexpr const char* kHeaderXRetryAfter = "X-Retry-After"; -constexpr int64_t kMaxRetryAfterSec = 24 * 60 * 60; - } // namespace RequestSender::RequestSender(scoped_refptr<Configurator> config) @@ -165,33 +146,33 @@ void RequestSender::OnNetworkFetcherComplete( const GURL& original_url, - std::unique_ptr<std::string> response_body) { + std::unique_ptr<std::string> response_body, + int net_error, + const std::string& header_etag, + int64_t xheader_retry_after_sec) { DCHECK(thread_checker_.CalledOnValidThread()); VLOG(1) << "request completed from url: " << original_url.spec(); - int fetch_error = -1; + int error = -1; if (response_body && response_code_ == 200) { - fetch_error = 0; + DCHECK_EQ(0, net_error); + error = 0; } else if (response_code_ != -1) { - fetch_error = response_code_; + error = response_code_; } else { - fetch_error = network_fetcher_->NetError(); + error = net_error; } - int64_t retry_after_sec(-1); - if (original_url.SchemeIsCryptographic() && fetch_error > 0) { - retry_after_sec = network_fetcher_->GetInt64HeaderValue(kHeaderXRetryAfter); - retry_after_sec = std::min(retry_after_sec, kMaxRetryAfterSec); - } + int retry_after_sec = -1; + if (original_url.SchemeIsCryptographic() && error > 0) + retry_after_sec = base::saturated_cast<int>(xheader_retry_after_sec); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&RequestSender::SendInternalComplete, - base::Unretained(this), fetch_error, - response_body ? *response_body : std::string(), - network_fetcher_->GetStringHeaderValue(kHeaderEtag), - static_cast<int>(retry_after_sec))); + FROM_HERE, base::BindOnce(&RequestSender::SendInternalComplete, + base::Unretained(this), error, + response_body ? *response_body : std::string(), + header_etag, retry_after_sec)); } void RequestSender::HandleSendError(int error, int retry_after_sec) {
diff --git a/components/update_client/request_sender.h b/components/update_client/request_sender.h index cc851d3e..7b9e21b 100644 --- a/components/update_client/request_sender.h +++ b/components/update_client/request_sender.h
@@ -70,7 +70,10 @@ int64_t content_length); void OnNetworkFetcherComplete(const GURL& original_url, - std::unique_ptr<std::string> response_body); + std::unique_ptr<std::string> response_body, + int net_error, + const std::string& header_etag, + int64_t xheader_retry_after_sec); // Implements the error handling and url fallback mechanism. void SendInternal();
diff --git a/components/update_client/update_engine.cc b/components/update_client/update_engine.cc index 3340adc..a6d6920 100644 --- a/components/update_client/update_engine.cc +++ b/components/update_client/update_engine.cc
@@ -4,6 +4,7 @@ #include "components/update_client/update_engine.h" +#include <algorithm> #include <memory> #include <utility> @@ -199,12 +200,12 @@ update_context->retry_after_sec = retry_after_sec; - const int throttle_sec(update_context->retry_after_sec); - DCHECK_LE(throttle_sec, 24 * 60 * 60); - // Only positive values for throttle_sec are effective. 0 means that no - // throttling occurs and has the effect of resetting the member. + // throttling occurs and it resets |throttle_updates_until_|. // Negative values are not trusted and are ignored. + constexpr int kMaxRetryAfterSec = 24 * 60 * 60; // 24 hours. + const int throttle_sec = + std::min(update_context->retry_after_sec, kMaxRetryAfterSec); if (throttle_sec >= 0) { throttle_updates_until_ = throttle_sec ? base::TimeTicks::Now() +
diff --git a/components/update_client/url_fetcher_downloader.cc b/components/update_client/url_fetcher_downloader.cc index 898c112..b802e5f 100644 --- a/components/update_client/url_fetcher_downloader.cc +++ b/components/update_client/url_fetcher_downloader.cc
@@ -90,7 +90,9 @@ download_start_time_ = base::TimeTicks::Now(); } -void UrlFetcherDownloader::OnNetworkFetcherComplete(base::FilePath file_path) { +void UrlFetcherDownloader::OnNetworkFetcherComplete(base::FilePath file_path, + int net_error, + int64_t content_size) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); const base::TimeTicks download_end_time(base::TimeTicks::Now()); @@ -102,41 +104,39 @@ // Consider a 5xx response from the server as an indication to terminate // the request and avoid overloading the server in this case. // is not accepting requests for the moment. - int fetch_error = -1; + int error = -1; if (!file_path.empty() && response_code_ == 200) { - fetch_error = 0; + DCHECK_EQ(0, net_error); + error = 0; } else if (response_code_ != -1) { - fetch_error = response_code_; + error = response_code_; } else { - fetch_error = network_fetcher_->NetError(); + error = net_error; } - const bool is_handled = fetch_error == 0 || IsHttpServerError(fetch_error); + const bool is_handled = error == 0 || IsHttpServerError(error); Result result; - result.error = fetch_error; - if (!fetch_error) { + result.error = error; + if (!error) { result.response = file_path; } DownloadMetrics download_metrics; download_metrics.url = url(); download_metrics.downloader = DownloadMetrics::kUrlFetcher; - download_metrics.error = fetch_error; + download_metrics.error = error; // Tests expected -1, in case of failures and no content is available. - download_metrics.downloaded_bytes = - fetch_error && !network_fetcher_->GetContentSize() - ? -1 - : network_fetcher_->GetContentSize(); + download_metrics.downloaded_bytes = error ? -1 : content_size; download_metrics.total_bytes = total_bytes_; download_metrics.download_time_ms = download_time.InMilliseconds(); - VLOG(1) << "Downloaded " << network_fetcher_->GetContentSize() << " bytes in " + VLOG(1) << "Downloaded " << content_size << " bytes in " << download_time.InMilliseconds() << "ms from " << final_url_.spec() << " to " << result.response.value(); // Delete the download directory in the error cases. - if (fetch_error && !download_dir_.empty()) + if (error && !download_dir_.empty()) base::PostTaskWithTraits( FROM_HERE, kTaskTraits, base::BindOnce(IgnoreResult(&base::DeleteFile), download_dir_, true));
diff --git a/components/update_client/url_fetcher_downloader.h b/components/update_client/url_fetcher_downloader.h index f35cbb3..da4dc170 100644 --- a/components/update_client/url_fetcher_downloader.h +++ b/components/update_client/url_fetcher_downloader.h
@@ -35,7 +35,9 @@ void CreateDownloadDir(); void StartURLFetch(const GURL& url); - void OnNetworkFetcherComplete(base::FilePath file_path); + void OnNetworkFetcherComplete(base::FilePath file_path, + int net_error, + int64_t content_size); void OnResponseStarted(const GURL& final_url, int response_code, int64_t content_length);
diff --git a/components/url_pattern_index/fuzzy_pattern_matching.h b/components/url_pattern_index/fuzzy_pattern_matching.h index 52dc75b..3feb7701 100644 --- a/components/url_pattern_index/fuzzy_pattern_matching.h +++ b/components/url_pattern_index/fuzzy_pattern_matching.h
@@ -6,8 +6,10 @@ // separator character, which is any ASCII symbol except letters, digits, and // the following: '_', '-', '.', '%'. Note that the separator placeholder // character '^' is itself a separator, as well as '\0'. -// TODO(pkalinnikov): In addition, a separator placeholder at the end of the -// pattern can be matched by the end of |text|. +// +// In addition, a separator placeholder at the end of the pattern can be matched +// by the end of |text|. This should be handled by the clients using the +// following utility functions. // // We define a fuzzy occurrence as an occurrence of a |subpattern| in |text| // such that all its non-placeholder characters are equal to the corresponding
diff --git a/components/url_pattern_index/url_pattern.cc b/components/url_pattern_index/url_pattern.cc index a9762fa..81b80bfb 100644 --- a/components/url_pattern_index/url_pattern.cc +++ b/components/url_pattern_index/url_pattern.cc
@@ -144,6 +144,80 @@ return base::StringPiece::npos; } +// Helper for DoesTextMatchLastSubpattern. Treats kSeparatorPlaceholder as not +// matching the end of the text. +bool DoesTextMatchLastSubpatternInternal(proto::AnchorType anchor_left, + proto::AnchorType anchor_right, + base::StringPiece text, + url::Component url_host, + base::StringPiece subpattern) { + // Enumerate all possible combinations of |anchor_left| and |anchor_right|. + if (anchor_left == proto::ANCHOR_TYPE_NONE && + anchor_right == proto::ANCHOR_TYPE_NONE) { + return FindSubpattern(text, subpattern) != base::StringPiece::npos; + } + + if (anchor_left == proto::ANCHOR_TYPE_NONE && + anchor_right == proto::ANCHOR_TYPE_BOUNDARY) { + return EndsWithFuzzy(text, subpattern); + } + + if (anchor_left == proto::ANCHOR_TYPE_BOUNDARY && + anchor_right == proto::ANCHOR_TYPE_NONE) { + return StartsWithFuzzy(text, subpattern); + } + + if (anchor_left == proto::ANCHOR_TYPE_BOUNDARY && + anchor_right == proto::ANCHOR_TYPE_BOUNDARY) { + return text.size() == subpattern.size() && + StartsWithFuzzy(text, subpattern); + } + + if (anchor_left == proto::ANCHOR_TYPE_SUBDOMAIN && + anchor_right == proto::ANCHOR_TYPE_NONE) { + return url_host.is_nonempty() && + FindSubdomainAnchoredSubpattern(text, url_host, subpattern) != + base::StringPiece::npos; + } + + if (anchor_left == proto::ANCHOR_TYPE_SUBDOMAIN && + anchor_right == proto::ANCHOR_TYPE_BOUNDARY) { + return url_host.is_nonempty() && text.size() >= subpattern.size() && + IsSubdomainAnchored(text, url_host, + text.size() - subpattern.size()) && + EndsWithFuzzy(text, subpattern); + } + + NOTREACHED(); + return false; +} + +// Matches the last |subpattern| against |text|. Special treatment is required +// for the last subpattern since |kSeparatorPlaceholder| can also match the end +// of the text. +bool DoesTextMatchLastSubpattern(proto::AnchorType anchor_left, + proto::AnchorType anchor_right, + base::StringPiece text, + url::Component url_host, + base::StringPiece subpattern) { + DCHECK(!subpattern.empty()); + + if (DoesTextMatchLastSubpatternInternal(anchor_left, anchor_right, text, + url_host, subpattern)) { + return true; + } + + // If the last |subpattern| ends with kSeparatorPlaceholder, then it can also + // match the end of text. + if (subpattern.back() == kSeparatorPlaceholder) { + subpattern.remove_suffix(1); + return DoesTextMatchLastSubpatternInternal( + anchor_left, proto::ANCHOR_TYPE_BOUNDARY, text, url_host, subpattern); + } + + return false; +} + // Returns whether the given |url_pattern| matches the given |url_spec|. // Compares the pattern the the url in a case-sensitive manner. bool IsCaseSensitiveMatch(base::StringPiece url_pattern, @@ -157,6 +231,7 @@ auto subpattern_it = subpatterns.begin(); auto subpattern_end = subpatterns.end(); + // No subpatterns. if (subpattern_it == subpattern_end) { return anchor_left == proto::ANCHOR_TYPE_NONE || anchor_right == proto::ANCHOR_TYPE_NONE; @@ -165,22 +240,10 @@ base::StringPiece subpattern = *subpattern_it; ++subpattern_it; - // If there is only one |subpattern|, and it has a right anchor, then simply - // check that it is a suffix of the |url_spec|, and the left anchor is - // fulfilled. - if (subpattern_it == subpattern_end && - anchor_right == proto::ANCHOR_TYPE_BOUNDARY) { - if (!EndsWithFuzzy(url_spec, subpattern)) - return false; - if (anchor_left == proto::ANCHOR_TYPE_BOUNDARY) - return url_spec.size() == subpattern.size(); - if (anchor_left == proto::ANCHOR_TYPE_SUBDOMAIN) { - DCHECK_LE(subpattern.size(), url_spec.size()); - return url_host.is_nonempty() && - IsSubdomainAnchored(url_spec, url_host, - url_spec.size() - subpattern.size()); - } - return true; + // There is only one |subpattern|. + if (subpattern_it == subpattern_end) { + return DoesTextMatchLastSubpattern(anchor_left, anchor_right, url_spec, + url_host, subpattern); } // Otherwise, the first |subpattern| does not have to be a suffix. But it @@ -189,10 +252,6 @@ if (anchor_left == proto::ANCHOR_TYPE_BOUNDARY) { if (!StartsWithFuzzy(url_spec, subpattern)) return false; - if (subpattern_it == subpattern_end) { - DCHECK_EQ(anchor_right, proto::ANCHOR_TYPE_NONE); - return true; - } text.remove_prefix(subpattern.size()); } else if (anchor_left == proto::ANCHOR_TYPE_SUBDOMAIN) { if (!url_host.is_nonempty()) @@ -201,10 +260,6 @@ FindSubdomainAnchoredSubpattern(url_spec, url_host, subpattern); if (match_begin == base::StringPiece::npos) return false; - if (subpattern_it == subpattern_end) { - DCHECK_EQ(anchor_right, proto::ANCHOR_TYPE_NONE); - return true; - } text.remove_prefix(match_begin + subpattern.size()); } else { DCHECK_EQ(anchor_left, proto::ANCHOR_TYPE_NONE); @@ -212,26 +267,24 @@ subpattern_it = subpatterns.begin(); } - // Consecutively find all the remaining subpatterns in the |text|. If the - // pattern has a right anchor, don't search for the last subpattern, but - // instead check that it is a suffix of the |text|. - while (subpattern_it != subpattern_end) { - subpattern = *subpattern_it; - DCHECK(!subpattern.empty()); + DCHECK(subpattern_it != subpattern_end); + subpattern = *subpattern_it; - if (++subpattern_it == subpattern_end && - anchor_right == proto::ANCHOR_TYPE_BOUNDARY) { - break; - } + // Consecutively find all the remaining subpatterns in the |text|. Handle the + // last subpattern outside the loop. + while (++subpattern_it != subpattern_end) { + DCHECK(!subpattern.empty()); const size_t match_position = FindSubpattern(text, subpattern); if (match_position == base::StringPiece::npos) return false; text.remove_prefix(match_position + subpattern.size()); + + subpattern = *subpattern_it; } - return anchor_right != proto::ANCHOR_TYPE_BOUNDARY || - EndsWithFuzzy(text, subpattern); + return DoesTextMatchLastSubpattern(proto::ANCHOR_TYPE_NONE, anchor_right, + text, url::Component(), subpattern); } } // namespace
diff --git a/components/url_pattern_index/url_pattern_unittest.cc b/components/url_pattern_index/url_pattern_unittest.cc index d067d12..950c907 100644 --- a/components/url_pattern_index/url_pattern_unittest.cc +++ b/components/url_pattern_index/url_pattern_unittest.cc
@@ -90,7 +90,9 @@ {{"^^a^^"}, "http://ex.com/?a=/", true}, {{"^^a^^"}, "http://ex.com/?a=/&b=0", true}, - {{"^^a^^"}, "http://ex.com/?a=", false}, + {{"^^a^^"}, "http://ex.com/?a=x", false}, + // The last ^ matches the end of the url. + {{"^^a^^"}, "http://ex.com/?a=", true}, {{"ex.com^path^*k=v^"}, "http://ex.com/path/?k1=v1&ak=v&kk=vv", true}, {{"ex.com^path^*k=v^"}, "http://ex.com/p/path/?k1=v1&ak=v&kk=vv", false}, @@ -152,6 +154,38 @@ {{"abc*def^", proto::URL_PATTERN_TYPE_WILDCARDED, kDonotMatchCase}, "http://a.com/abcxAdef/vo", true}, + {{"abc^", kAnchorNone, kAnchorNone}, "https://xyz.com/abc/123", true}, + {{"abc^", kAnchorNone, kAnchorNone}, "https://xyz.com/abc", true}, + {{"abc^", kAnchorNone, kAnchorNone}, "https://abc.com", false}, + {{"abc^", kAnchorNone, kBoundary}, "https://xyz.com/abc/", true}, + {{"abc^", kAnchorNone, kBoundary}, "https://xyz.com/abc", true}, + {{"abc^", kAnchorNone, kBoundary}, "https://xyz.com/abc/123", false}, + {{"http://abc.com/x^", kBoundary, kAnchorNone}, "http://abc.com/x", true}, + {{"http://abc.com/x^", kBoundary, kAnchorNone}, + "http://abc.com/x/", + true}, + {{"http://abc.com/x^", kBoundary, kAnchorNone}, + "http://abc.com/x/123", + true}, + {{"http://abc.com/x^", kBoundary, kBoundary}, "http://abc.com/x", true}, + {{"http://abc.com/x^", kBoundary, kBoundary}, "http://abc.com/x/", true}, + {{"http://abc.com/x^", kBoundary, kBoundary}, + "http://abc.com/x/123", + false}, + {{"abc.com^", kSubdomain, kAnchorNone}, "http://xyz.abc.com/123", true}, + {{"abc.com^", kSubdomain, kAnchorNone}, "http://xyz.abc.com", true}, + {{"abc.com^", kSubdomain, kAnchorNone}, + "http://abc.com.xyz.com?q=abc.com", + false}, + {{"abc.com^", kSubdomain, kBoundary}, "http://xyz.abc.com/123", false}, + {{"abc.com^", kSubdomain, kBoundary}, "http://xyz.abc.com", true}, + {{"abc.com^", kSubdomain, kBoundary}, + "http://abc.com.xyz.com?q=abc.com/", + false}, + {{"abc*^", kAnchorNone, kAnchorNone}, "https://abc.com", true}, + {{"abc*^", kAnchorNone, kAnchorNone}, "https://abc.com?q=123", true}, + {{"abc*^", kAnchorNone, kBoundary}, "https://abc.com", true}, + {{"abc*^", kAnchorNone, kBoundary}, "https://abc.com?q=123", true}, }; for (const auto& test_case : kTestCases) {
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 778f9c2..57ef4d7 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -198,7 +198,6 @@ "//ui/base", "//ui/base:buildflags", "//ui/base/clipboard", - "//ui/base/idle", "//ui/base/ime", "//ui/display", "//ui/display/types",
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index b56e5a95..7d9e0ac 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -924,6 +924,11 @@ } IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + AccessibilityAriaSetCountsWithTreeLevels) { + RunAriaTest(FILE_PATH_LITERAL("aria-set-counts-with-tree-levels.html")); +} + +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaSortOnHtmlTable) { RunAriaTest(FILE_PATH_LITERAL("aria-sort-html-table.html")); }
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc index 80d4f29..df359f8c 100644 --- a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc +++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
@@ -242,7 +242,7 @@ if (!JavaBridgeThread::CurrentlyOn()) { JavaBridgeThread::GetTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &GinJavaBridgeDispatcherHost::SetAllowObjectContentsInspection, this, allow)); return;
diff --git a/content/browser/appcache/appcache_update_url_loader_request.cc b/content/browser/appcache/appcache_update_url_loader_request.cc index d43a7cb..8bf8c6a 100644 --- a/content/browser/appcache/appcache_update_url_loader_request.cc +++ b/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "content/browser/appcache/appcache_request_handler.h" #include "content/browser/appcache/appcache_update_url_fetcher.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_response_info.h" #include "net/url_request/url_request_context.h" @@ -145,7 +146,7 @@ http_response_info_->alpn_negotiated_protocol = response_head.alpn_negotiated_protocol; http_response_info_->connection_info = response_head.connection_info; - http_response_info_->socket_address = response_head.socket_address; + http_response_info_->remote_endpoint = response_head.remote_endpoint; fetcher_->OnResponseStarted(net::OK); }
diff --git a/content/browser/appcache/appcache_url_loader_job.cc b/content/browser/appcache/appcache_url_loader_job.cc index c6603a6..c9b6bd9 100644 --- a/content/browser/appcache/appcache_url_loader_job.cc +++ b/content/browser/appcache/appcache_url_loader_job.cc
@@ -12,6 +12,7 @@ #include "content/browser/appcache/appcache_url_loader_request.h" #include "content/browser/url_loader_factory_getter.h" #include "content/public/common/resource_type.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_status_code.h" #include "services/network/public/cpp/net_adapters.h" #include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h" @@ -293,7 +294,7 @@ is_range_request() ? range_response_info_->headers->GetContentLength() : info_->response_data_size(); response_head.connection_info = http_info.connection_info; - response_head.socket_address = http_info.socket_address; + response_head.remote_endpoint = http_info.remote_endpoint; response_head.was_fetched_via_spdy = http_info.was_fetched_via_spdy; response_head.was_alpn_negotiated = http_info.was_alpn_negotiated; response_head.alpn_negotiated_protocol = http_info.alpn_negotiated_protocol;
diff --git a/content/browser/appcache/appcache_url_request_job.cc b/content/browser/appcache/appcache_url_request_job.cc index 158ef9e..fff66184 100644 --- a/content/browser/appcache/appcache_url_request_job.cc +++ b/content/browser/appcache/appcache_url_request_job.cc
@@ -288,10 +288,10 @@ return net::ERR_IO_PENDING; } -net::HostPortPair AppCacheURLRequestJob::GetSocketAddress() const { +net::IPEndPoint AppCacheURLRequestJob::GetResponseRemoteEndpoint() const { if (!http_info()) - return net::HostPortPair(); - return http_info()->socket_address; + return net::IPEndPoint(); + return http_info()->remote_endpoint; } void AppCacheURLRequestJob::SetExtraRequestHeaders(
diff --git a/content/browser/appcache/appcache_url_request_job.h b/content/browser/appcache/appcache_url_request_job.h index 67c3242..b6ed1e91 100644 --- a/content/browser/appcache/appcache_url_request_job.h +++ b/content/browser/appcache/appcache_url_request_job.h
@@ -14,6 +14,7 @@ #include "content/browser/appcache/appcache_job.h" #include "content/browser/appcache/appcache_storage.h" #include "content/common/content_export.h" +#include "net/base/ip_endpoint.h" #include "net/url_request/url_request_job.h" namespace net { @@ -100,7 +101,7 @@ bool GetCharset(std::string* charset) override; void GetResponseInfo(net::HttpResponseInfo* info) override; int ReadRawData(net::IOBuffer* buf, int buf_size) override; - net::HostPortPair GetSocketAddress() const override; + net::IPEndPoint GetResponseRemoteEndpoint() const override; // Sets extra request headers for Job types that support request headers. // This is how we get informed of range-requests.
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index 69d2ffae..8abb1b1 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -51,6 +51,8 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" +#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/upload_bytes_element_reader.h" #include "net/cert/ct_policy_status.h" @@ -1552,8 +1554,9 @@ response->SetHeadersText(raw_info->response_headers_text); } response->SetProtocol(GetProtocol(url, info)); - response->SetRemoteIPAddress(info.socket_address.HostForURL()); - response->SetRemotePort(info.socket_address.port()); + response->SetRemoteIPAddress( + net::HostPortPair::FromIPEndPoint(info.remote_endpoint).HostForURL()); + response->SetRemotePort(info.remote_endpoint.port()); if (info.ssl_info.has_value()) response->SetSecurityDetails(BuildSecurityDetails(*info.ssl_info));
diff --git a/content/browser/dom_storage/session_storage_context_mojo.cc b/content/browser/dom_storage/session_storage_context_mojo.cc index 2696fe9..4e1fdfa 100644 --- a/content/browser/dom_storage/session_storage_context_mojo.cc +++ b/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -152,8 +152,7 @@ } PurgeUnusedAreasIfNeeded(); - found->second->Bind(std::move(request), process_id); - std::move(bind_done).Run(); + found->second->Bind(std::move(request), process_id, std::move(bind_done)); size_t total_cache_size, unused_area_count; GetStatistics(&total_cache_size, &unused_area_count);
diff --git a/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc b/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc index f163725c..5873c2a 100644 --- a/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc +++ b/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc
@@ -96,17 +96,19 @@ void SessionStorageNamespaceImplMojo::Bind( blink::mojom::SessionStorageNamespaceRequest request, - int process_id) { + int process_id, + base::OnceClosure bind_done) { if (waiting_on_clone_population_) { bind_waiting_on_clone_population_ = true; - run_after_clone_population_.push_back( - base::BindOnce(&SessionStorageNamespaceImplMojo::Bind, - base::Unretained(this), std::move(request), process_id)); + run_after_clone_population_.push_back(base::BindOnce( + &SessionStorageNamespaceImplMojo::Bind, base::Unretained(this), + std::move(request), process_id, std::move(bind_done))); return; } DCHECK(IsPopulated()); bindings_.AddBinding(this, std::move(request), process_id); bind_waiting_on_clone_population_ = false; + std::move(bind_done).Run(); } void SessionStorageNamespaceImplMojo::PurgeUnboundAreas() {
diff --git a/content/browser/dom_storage/session_storage_namespace_impl_mojo.h b/content/browser/dom_storage/session_storage_namespace_impl_mojo.h index d0e2b12..1b285a8 100644 --- a/content/browser/dom_storage/session_storage_namespace_impl_mojo.h +++ b/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
@@ -122,7 +122,8 @@ // eventually be called before the SessionStorageNamespaceRequest can be // bound. void Bind(blink::mojom::SessionStorageNamespaceRequest request, - int process_id); + int process_id, + base::OnceClosure bind_done); bool IsBound() const { return !bindings_.empty() || bind_waiting_on_clone_population_;
diff --git a/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc b/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc index a29283d4..ab25a58 100644 --- a/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc +++ b/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
@@ -192,7 +192,8 @@ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)); blink::mojom::SessionStorageNamespacePtr ss_namespace; - namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1); + namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1, + base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_1; ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1)); @@ -223,7 +224,8 @@ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)); blink::mojom::SessionStorageNamespacePtr ss_namespace; - namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1); + namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1, + base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_1; ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1)); @@ -263,7 +265,7 @@ blink::mojom::SessionStorageNamespacePtr ss_namespace1; namespace_impl1->Bind(mojo::MakeRequest(&ss_namespace1), - kTestProcessIdOrigin1); + kTestProcessIdOrigin1, base::DoNothing()); ss_namespace1->Clone(test_namespace_id2_); ss_namespace1.FlushForTesting(); @@ -271,7 +273,7 @@ blink::mojom::SessionStorageNamespacePtr ss_namespace2; namespace_impl2->Bind(mojo::MakeRequest(&ss_namespace2), - kTestProcessIdOrigin1); + kTestProcessIdOrigin1, base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_2; ss_namespace2->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_2)); @@ -318,7 +320,7 @@ blink::mojom::SessionStorageNamespacePtr ss_namespace1; namespace_impl1->Bind(mojo::MakeRequest(&ss_namespace1), - kTestProcessIdOrigin1); + kTestProcessIdOrigin1, base::DoNothing()); // Set that we are waiting for clone, so binding is possible. namespace_impl2->SetWaitingForClonePopulation(); @@ -329,7 +331,7 @@ // Get a new area. blink::mojom::SessionStorageNamespacePtr ss_namespace2; namespace_impl2->Bind(mojo::MakeRequest(&ss_namespace2), - kTestProcessIdAllOrigins); + kTestProcessIdAllOrigins, base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1; blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o2; ss_namespace2->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_n2_o1)); @@ -379,7 +381,8 @@ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)); blink::mojom::SessionStorageNamespacePtr ss_namespace; - namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1); + namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1, + base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_1; ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1)); @@ -449,7 +452,8 @@ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)); blink::mojom::SessionStorageNamespacePtr ss_namespace; - namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1); + namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1, + base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_1; ss_namespace->OpenArea(test_origin3_, mojo::MakeRequest(&leveldb_1)); ss_namespace.FlushForTesting(); @@ -474,7 +478,8 @@ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)); blink::mojom::SessionStorageNamespacePtr ss_namespace; - namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1); + namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1, + base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_1; ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1)); @@ -506,7 +511,7 @@ blink::mojom::SessionStorageNamespacePtr ss_namespace_o1; namespace_impl->Bind(mojo::MakeRequest(&ss_namespace_o1), - kTestProcessIdOrigin1); + kTestProcessIdOrigin1, base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_1; ss_namespace_o1->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1)); ss_namespace_o1.FlushForTesting(); @@ -518,7 +523,7 @@ blink::mojom::SessionStorageNamespacePtr ss_namespace_o2; namespace_impl->Bind(mojo::MakeRequest(&ss_namespace_o2), - kTestProcessIdOrigin3); + kTestProcessIdOrigin3, base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_2; ss_namespace_o2->OpenArea(test_origin3_, mojo::MakeRequest(&leveldb_2)); ss_namespace_o2.FlushForTesting(); @@ -547,7 +552,8 @@ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)); blink::mojom::SessionStorageNamespacePtr ss_namespace; - namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1); + namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1, + base::DoNothing()); blink::mojom::StorageAreaAssociatedPtr leveldb_1; ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc index 2a707e8b7a..0458f8d 100644 --- a/content/browser/download/download_request_core.cc +++ b/content/browser/download/download_request_core.cc
@@ -36,6 +36,7 @@ #include "content/public/browser/resource_context.h" #include "content/public/browser/web_contents.h" #include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" @@ -224,8 +225,10 @@ new download::DownloadCreateInfo(base::Time::Now(), std::move(save_info_))); - if (result == download::DOWNLOAD_INTERRUPT_REASON_NONE) - create_info->remote_address = request()->GetSocketAddress().host(); + if (result == download::DOWNLOAD_INTERRUPT_REASON_NONE) { + create_info->remote_address = + request()->GetResponseRemoteEndpoint().ToStringWithoutPort(); + } create_info->method = request()->method(); create_info->connection_info = request()->response_info().connection_info; create_info->url_chain = request()->url_chain();
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index 2770942..88da921 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -435,12 +435,12 @@ return previous_url_; } -net::HostPortPair NavigationHandleImpl::GetSocketAddress() { +net::IPEndPoint NavigationHandleImpl::GetSocketAddress() { // This is CANCELING because although the data comes in after // WILL_PROCESS_RESPONSE, it's possible for the navigation to be cancelled // after and the caller might want this value. DCHECK(state_ >= CANCELING); - return socket_address_; + return remote_endpoint_; } void NavigationHandleImpl::Resume(NavigationThrottle* resuming_throttle) { @@ -676,7 +676,7 @@ RenderFrameHostImpl* render_frame_host, scoped_refptr<net::HttpResponseHeaders> response_headers, net::HttpResponseInfo::ConnectionInfo connection_info, - const net::HostPortPair& socket_address, + const net::IPEndPoint& remote_endpoint, const net::SSLInfo& ssl_info, const GlobalRequestID& request_id, bool is_download, @@ -698,7 +698,7 @@ was_cached_ = was_cached; state_ = PROCESSING_WILL_PROCESS_RESPONSE; ssl_info_ = ssl_info; - socket_address_ = socket_address; + remote_endpoint_ = remote_endpoint; complete_callback_ = std::move(callback); // Notify each throttle of the response.
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h index ccf10021..297e1df 100644 --- a/content/browser/frame_host/navigation_handle_impl.h +++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -31,6 +31,7 @@ #include "content/public/browser/navigation_throttle.h" #include "content/public/browser/navigation_type.h" #include "content/public/browser/restore_type.h" +#include "net/base/ip_endpoint.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" #include "third_party/blink/public/platform/web_mixed_content_context_type.h" #include "url/gurl.h" @@ -114,7 +115,7 @@ bool DidReplaceEntry() override; bool ShouldUpdateHistory() override; const GURL& GetPreviousURL() override; - net::HostPortPair GetSocketAddress() override; + net::IPEndPoint GetSocketAddress() override; const net::HttpRequestHeaders& GetRequestHeaders() override; void RemoveRequestHeader(const std::string& header_name) override; void SetRequestHeader(const std::string& header_name, @@ -270,7 +271,7 @@ RenderFrameHostImpl* render_frame_host, scoped_refptr<net::HttpResponseHeaders> response_headers, net::HttpResponseInfo::ConnectionInfo connection_info, - const net::HostPortPair& socket_address, + const net::IPEndPoint& remote_endpoint, const net::SSLInfo& ssl_info, const GlobalRequestID& request_id, bool is_download, @@ -531,7 +532,7 @@ GURL previous_url_; GURL base_url_; - net::HostPortPair socket_address_; + net::IPEndPoint remote_endpoint_; NavigationType navigation_type_; // Used to inform a RenderProcessHost that we expect this navigation to commit
diff --git a/content/browser/frame_host/navigation_handle_impl_unittest.cc b/content/browser/frame_host/navigation_handle_impl_unittest.cc index 9333980..ab6e174 100644 --- a/content/browser/frame_host/navigation_handle_impl_unittest.cc +++ b/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -148,7 +148,7 @@ // in both cases. test_handle_->WillProcessResponse( main_test_rfh(), scoped_refptr<net::HttpResponseHeaders>(), - net::HttpResponseInfo::CONNECTION_INFO_QUIC_35, net::HostPortPair(), + net::HttpResponseInfo::CONNECTION_INFO_QUIC_35, net::IPEndPoint(), net::SSLInfo(), GlobalRequestID(), false, false, false, false, base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult, base::Unretained(this)));
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 20a2e540..08c67f5 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -63,6 +63,7 @@ #include "content/public/common/url_constants.h" #include "content/public/common/url_utils.h" #include "content/public/common/web_preferences.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" @@ -1236,7 +1237,7 @@ // Check if the navigation should be allowed to proceed. navigation_handle_->WillProcessResponse( render_frame_host, response->head.headers.get(), - response->head.connection_info, response->head.socket_address, ssl_info_, + response->head.connection_info, response->head.remote_endpoint, ssl_info_, request_id, is_download_, is_stream, response->head.is_signed_exchange_inner_response, response->head.was_fetched_via_cache,
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 546efb0..1376c91 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -180,6 +180,7 @@ #include "third_party/blink/public/common/feature_policy/feature_policy.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/frame/frame_policy.h" +#include "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom.h" #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h" #include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" @@ -5069,13 +5070,7 @@ if (!GetContentClient()->browser()->CanCommitURL(GetProcess(), url)) return false; - // TODO(nasko): This check should be updated to apply to all URLs, not just - // standard ones. - auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); - if (url.IsStandard() && - !policy->CanAccessDataForOrigin(GetProcess()->GetID(), url)) { - return false; - } + // TODO(nasko): Consider checking the |url| against CanAccessDataForOrigin. return true; } @@ -5755,7 +5750,19 @@ // This is a test-only interface, not exposed in production. void RenderFrameHostImpl::GetFrameHostTestInterface( - blink::mojom::FrameHostTestInterfaceRequest request) {} + blink::mojom::FrameHostTestInterfaceRequest request) { + class FrameHostTestInterfaceImpl + : public blink::mojom::FrameHostTestInterface { + public: + void Ping(const GURL& url, const std::string& event) override {} + void GetName(GetNameCallback callback) override { + std::move(callback).Run("RenderFrameHostImpl"); + } + }; + + mojo::MakeStrongBinding(std::make_unique<FrameHostTestInterfaceImpl>(), + std::move(request)); +} std::unique_ptr<NavigationRequest> RenderFrameHostImpl::TakeNavigationRequestForSameDocumentCommit(
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc index cb41cda..fbb1b7c 100644 --- a/content/browser/loader/resource_loader.cc +++ b/content/browser/loader/resource_loader.cc
@@ -32,6 +32,7 @@ #include "content/public/common/navigation_policy.h" #include "content/public/common/resource_type.h" #include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/cert/symantec_certs.h" #include "net/http/http_response_headers.h" @@ -85,7 +86,7 @@ response->head.alpn_negotiated_protocol = response_info.alpn_negotiated_protocol; response->head.connection_info = response_info.connection_info; - response->head.socket_address = response_info.socket_address; + response->head.remote_endpoint = response_info.remote_endpoint; response->head.proxy_server = request->proxy_server(); response->head.network_accessed = response_info.network_accessed; response->head.async_revalidation_requested =
diff --git a/content/browser/media/session/media_session_browsertest.cc b/content/browser/media/session/media_session_browsertest.cc index a9b7b95..f91ea1c 100644 --- a/content/browser/media/session/media_session_browsertest.cc +++ b/content/browser/media/session/media_session_browsertest.cc
@@ -5,6 +5,7 @@ #include "content/public/browser/media_session.h" #include "base/command_line.h" +#include "base/optional.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" @@ -16,19 +17,67 @@ #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" #include "media/base/media_switches.h" +#include "net/test/embedded_test_server/http_request.h" #include "services/media_session/public/cpp/features.h" #include "services/media_session/public/cpp/test/audio_focus_test_util.h" +#include "services/media_session/public/cpp/test/mock_media_session.h" namespace content { namespace { +const char kMediaSessionImageTestURL[] = "/media/session/image_test_page.html"; +const char kMediaSessionImageTestPageVideoElement[] = "video"; + +const char kMediaSessionTestImagePath[] = "/media/session/test_image.jpg"; + +class MediaImageGetterHelper { + public: + MediaImageGetterHelper(content::MediaSession* media_session, + const media_session::MediaImage& image, + int min_size, + int desired_size) { + media_session->GetMediaImageBitmap( + image, min_size, desired_size, + base::BindOnce(&MediaImageGetterHelper::OnComplete, + base::Unretained(this))); + } + + void Wait() { + if (bitmap_.has_value()) + return; + + run_loop_.Run(); + } + + const SkBitmap& bitmap() { return *bitmap_; } + + private: + void OnComplete(const SkBitmap& bitmap) { + bitmap_ = bitmap; + run_loop_.Quit(); + } + + base::RunLoop run_loop_; + base::Optional<SkBitmap> bitmap_; + + DISALLOW_COPY_AND_ASSIGN(MediaImageGetterHelper); +}; + // Integration tests for content::MediaSession that do not take into // consideration the implementation details contrary to // MediaSessionImplBrowserTest. class MediaSessionBrowserTest : public ContentBrowserTest { public: - MediaSessionBrowserTest() = default; + MediaSessionBrowserTest() { + embedded_test_server()->RegisterRequestMonitor(base::BindRepeating( + &MediaSessionBrowserTest::OnServerRequest, base::Unretained(this))); + } + + void SetUp() override { + ContentBrowserTest::SetUp(); + visited_urls_.clear(); + } void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitchASCII( @@ -79,6 +128,40 @@ return result; } + bool WasURLVisited(const GURL& url) { + return base::ContainsKey(visited_urls_, url); + } + + MediaSession* SetupMediaImageTest() { + NavigateToURL(shell(), + embedded_test_server()->GetURL(kMediaSessionImageTestURL)); + StartPlaybackAndWait(shell(), kMediaSessionImageTestPageVideoElement); + + MediaSession* media_session = MediaSession::Get(shell()->web_contents()); + + std::vector<media_session::MediaImage> expected_images; + expected_images.push_back(CreateTestImageWithSize(1)); + expected_images.push_back(CreateTestImageWithSize(10)); + + media_session::test::MockMediaSessionMojoObserver observer(*media_session); + observer.WaitForExpectedImagesOfType( + media_session::mojom::MediaSessionImageType::kArtwork, expected_images); + + return media_session; + } + + media_session::MediaImage CreateTestImageWithSize(int size) const { + media_session::MediaImage image; + image.src = GetTestImageURL(); + image.type = base::ASCIIToUTF16("image/jpeg"); + image.sizes.push_back(gfx::Size(size, size)); + return image; + } + + GURL GetTestImageURL() const { + return embedded_test_server()->GetURL(kMediaSessionTestImagePath); + } + private: class MediaStartStopObserver : public WebContentsObserver { public: @@ -114,6 +197,12 @@ DISALLOW_COPY_AND_ASSIGN(MediaStartStopObserver); }; + void OnServerRequest(const net::test_server::HttpRequest& request) { + visited_urls_.insert(request.GetURL()); + } + + std::set<GURL> visited_urls_; + base::test::ScopedFeatureList disabled_feature_list_; base::test::ScopedFeatureList scoped_feature_list_; @@ -239,4 +328,80 @@ } #endif // defined(OS_ANDROID) +IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, GetMediaImageBitmap) { + ASSERT_TRUE(embedded_test_server()->Start()); + + MediaSession* media_session = SetupMediaImageTest(); + ASSERT_NE(nullptr, media_session); + + media_session::MediaImage image; + image.src = embedded_test_server()->GetURL("/media/session/test_image.jpg"); + image.type = base::ASCIIToUTF16("image/jpeg"); + image.sizes.push_back(gfx::Size(1, 1)); + + MediaImageGetterHelper helper(media_session, CreateTestImageWithSize(1), 0, + 10); + helper.Wait(); + + // The test image is a 1x1 test image. + EXPECT_EQ(1, helper.bitmap().width()); + EXPECT_EQ(1, helper.bitmap().height()); + EXPECT_EQ(kRGBA_8888_SkColorType, helper.bitmap().colorType()); + + EXPECT_TRUE(WasURLVisited(GetTestImageURL())); +} + +IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, + GetMediaImageBitmap_ImageTooSmall) { + ASSERT_TRUE(embedded_test_server()->Start()); + + MediaSession* media_session = SetupMediaImageTest(); + ASSERT_NE(nullptr, media_session); + + MediaImageGetterHelper helper(media_session, CreateTestImageWithSize(10), 10, + 10); + helper.Wait(); + + // The |image| is too small but we do not know that until after we have + // downloaded it. We should still receive a null image though. + EXPECT_TRUE(helper.bitmap().isNull()); + EXPECT_TRUE(WasURLVisited(GetTestImageURL())); +} + +IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, + GetMediaImageBitmap_ImageTooSmall_BeforeDownload) { + ASSERT_TRUE(embedded_test_server()->Start()); + + MediaSession* media_session = SetupMediaImageTest(); + ASSERT_NE(nullptr, media_session); + + MediaImageGetterHelper helper(media_session, CreateTestImageWithSize(1), 10, + 10); + helper.Wait(); + + // Since |image| is too small but we know this in advance we should not + // download it and instead we should receive a null image. + EXPECT_TRUE(helper.bitmap().isNull()); + EXPECT_FALSE(WasURLVisited(GetTestImageURL())); +} + +IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, + GetMediaImageBitmap_InvalidImage) { + ASSERT_TRUE(embedded_test_server()->Start()); + + MediaSession* media_session = SetupMediaImageTest(); + ASSERT_NE(nullptr, media_session); + + media_session::MediaImage image = CreateTestImageWithSize(1); + image.src = embedded_test_server()->GetURL("/blank.jpg"); + + MediaImageGetterHelper helper(media_session, image, 0, 10); + helper.Wait(); + + // Since |image| is not an image that is associated with the test page we + // should not download it and instead we should receive a null image. + EXPECT_TRUE(helper.bitmap().isNull()); + EXPECT_FALSE(WasURLVisited(image.src)); +} + } // namespace content
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc index 1342957..123dab9 100644 --- a/content/browser/media/session/media_session_impl.cc +++ b/content/browser/media/session/media_session_impl.cc
@@ -24,6 +24,7 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "media/base/media_content_type.h" +#include "services/media_session/public/cpp/media_image_manager.h" #include "services/media_session/public/mojom/audio_focus.mojom.h" #include "third_party/blink/public/platform/modules/mediasession/media_session.mojom.h" @@ -102,6 +103,10 @@ vector.push_back(str); } +bool IsSizeAtLeast(const gfx::Size& size, int min_size) { + return size.width() >= min_size || size.height() >= min_size; +} + } // anonymous namespace MediaSessionImpl::PlayerIdentifier::PlayerIdentifier( @@ -544,6 +549,43 @@ AbandonSystemAudioFocusIfNeeded(); } +void MediaSessionImpl::OnImageDownloadComplete( + GetMediaImageBitmapCallback callback, + int minimum_size_px, + int desired_size_px, + int id, + int http_status_code, + const GURL& image_url, + const std::vector<SkBitmap>& bitmaps, + const std::vector<gfx::Size>& sizes) { + DCHECK(bitmaps.size() == sizes.size()); + SkBitmap image; + double best_image_score = 0.0; + + // Rank |sizes| and |bitmaps| using MediaImageManager. + for (size_t i = 0; i < bitmaps.size(); i++) { + double image_score = media_session::MediaImageManager::GetImageSizeScore( + minimum_size_px, desired_size_px, sizes.at(i)); + + if (image_score > best_image_score) + image = bitmaps.at(i); + } + + // If the image is the wrong color type then we should convert it. + SkBitmap bitmap; + if (!image.isNull()) { + if (image.colorType() == kRGBA_8888_SkColorType) { + bitmap = image; + } else { + SkImageInfo info = image.info().makeColorType(kRGBA_8888_SkColorType); + if (bitmap.tryAllocPixels(info)) + image.readPixels(info, bitmap.getPixels(), bitmap.rowBytes(), 0, 0); + } + } + + std::move(callback).Run(bitmap); +} + void MediaSessionImpl::OnSystemAudioFocusRequested(bool result) { uma_helper_.RecordRequestAudioFocusResult(result); if (result) @@ -790,6 +832,34 @@ DidReceiveAction(media_session::mojom::MediaSessionAction::kSkipAd); } +void MediaSessionImpl::GetMediaImageBitmap( + const media_session::MediaImage& image, + int minimum_size_px, + int desired_size_px, + GetMediaImageBitmapCallback callback) { + // We should make sure |image| is in |images_|. + bool found = false; + for (auto& image_type : images_) + found = found || base::ContainsValue(image_type.second, image); + + // Check that |image.sizes| contains a size that is above the minimum size. + bool check_size = false; + for (auto& size : image.sizes) + check_size = check_size || IsSizeAtLeast(size, minimum_size_px); + + if (!found || !check_size) { + std::move(callback).Run(SkBitmap()); + return; + } + + web_contents()->DownloadImage( + image.src, false, desired_size_px /* max_bitmap_size */, + false /* bypass_cache */, + base::BindOnce(&MediaSessionImpl::OnImageDownloadComplete, + base::Unretained(this), std::move(callback), + minimum_size_px, desired_size_px)); +} + void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() { if (audio_focus_state_ == State::INACTIVE || !normal_players_.empty() || !pepper_players_.empty() || !one_shot_players_.empty()) {
diff --git a/content/browser/media/session/media_session_impl.h b/content/browser/media/session/media_session_impl.h index 66686b6..43cd7e8 100644 --- a/content/browser/media/session/media_session_impl.h +++ b/content/browser/media/session/media_session_impl.h
@@ -236,6 +236,15 @@ // Skip ad. CONTENT_EXPORT void SkipAd() override; + // Downloads the bitmap version of a MediaImage at least |minimum_size_px| + // and closest to |desired_size_px|. If the download failed, was too small or + // the image did not come from the media session then returns a null image. + CONTENT_EXPORT void GetMediaImageBitmap( + const media_session::MediaImage& image, + int minimum_size_px, + int desired_size_px, + GetMediaImageBitmapCallback callback) override; + const base::UnguessableToken& audio_focus_group_id() const { return audio_focus_group_id_; } @@ -284,6 +293,16 @@ void Initialize(); + // Called when we have finished downloading an image. + void OnImageDownloadComplete(GetMediaImageBitmapCallback callback, + int minimum_size_px, + int desired_size_px, + int id, + int http_status_code, + const GURL& image_url, + const std::vector<SkBitmap>& bitmaps, + const std::vector<gfx::Size>& sizes); + // Called when system audio focus has been requested and whether the request // was granted. void OnSystemAudioFocusRequested(bool result);
diff --git a/content/browser/renderer_host/render_view_host_browsertest.cc b/content/browser/renderer_host/render_view_host_browsertest.cc index 50a50af..2367087 100644 --- a/content/browser/renderer_host/render_view_host_browsertest.cc +++ b/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -22,7 +22,7 @@ #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" #include "net/base/filename_util.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/test/embedded_test_server/embedded_test_server.h" namespace content { @@ -47,13 +47,13 @@ NavigationHandleImpl* impl = static_cast<NavigationHandleImpl*>(navigation_handle); - observed_socket_address_ = navigation_handle->GetSocketAddress(); + observed_remote_endpoint_ = navigation_handle->GetSocketAddress(); base_url_ = impl->base_url(); ++navigation_count_; } - const net::HostPortPair& observed_socket_address() const { - return observed_socket_address_; + const net::IPEndPoint& observed_remote_endpoint() const { + return observed_remote_endpoint_; } GURL base_url() const { @@ -63,7 +63,7 @@ int navigation_count() const { return navigation_count_; } private: - net::HostPortPair observed_socket_address_; + net::IPEndPoint observed_remote_endpoint_; GURL base_url_; int navigation_count_; @@ -77,9 +77,9 @@ GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); NavigateToURL(shell(), test_url); - EXPECT_EQ(net::HostPortPair::FromURL( - embedded_test_server()->base_url()).ToString(), - observer.observed_socket_address().ToString()); + EXPECT_EQ( + net::HostPortPair::FromURL(embedded_test_server()->base_url()), + net::HostPortPair::FromIPEndPoint(observer.observed_remote_endpoint())); EXPECT_EQ(1, observer.navigation_count()); }
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 96d1d48..763bfcc8 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -346,8 +346,11 @@ } ~KeyEventResultTracker() { - if (is_async_ && async_callback_) - std::move(async_callback_).Run(false); + if (is_async_ && async_callback_) { + std::move(async_callback_) + .Run(/* handled */ false, + /* stopped_propagation */ false); + } } base::WeakPtr<KeyEventResultTracker> GetWeakPtr() { @@ -371,10 +374,13 @@ // Called when processing is complete. This may never be called, in which case // the destructor is responsible for updating the callback from the event. void OnEventProcessingDone(bool handled) { - if (is_async_ && async_callback_) - std::move(async_callback_).Run(handled); - else if (!is_async_ && handled) + if (is_async_ && async_callback_) { + // This supplies false for |stopped_propagation| so that InsertChar() gets + // called. Content never calls StopPropagation(). + std::move(async_callback_).Run(handled, /* stopped_propagation */ false); + } else if (!is_async_ && handled) { key_event_->SetHandled(); + } } private: @@ -386,7 +392,7 @@ // Callback from the event. This is obtained from |key_event_| if the event is // handled async. - base::OnceCallback<void(bool)> async_callback_; + base::OnceCallback<void(bool, bool)> async_callback_; base::WeakPtrFactory<KeyEventResultTracker> weak_factory_{this};
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 2fbfa3c0..4d93d58 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -5307,13 +5307,16 @@ view_->InitAsChild(nullptr); view_->Show(); bool async_callback_run = false; - bool async_callback_result = false; + bool async_callback_handled_result = false; + bool async_callback_stopped_propagation_result = false; ui::KeyEvent key_event1(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); ui::KeyEvent::KeyDispatcherApi(&key_event1) - .set_async_callback(base::BindLambdaForTesting([&](bool handled) { - async_callback_result = handled; - async_callback_run = true; - })); + .set_async_callback(base::BindLambdaForTesting( + [&](bool handled, bool stopped_propagation) { + async_callback_handled_result = handled; + async_callback_stopped_propagation_result = stopped_propagation; + async_callback_run = true; + })); view_->OnKeyEvent(&key_event1); // Normally event should be handled. EXPECT_TRUE(key_event1.handled()); @@ -5330,20 +5333,25 @@ EXPECT_EQ("RawKeyDown", GetMessageNames(events)); events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED); EXPECT_TRUE(async_callback_run); - EXPECT_TRUE(async_callback_result); + EXPECT_TRUE(async_callback_handled_result); + // |async_callback_stopped_propagation_result| should always be false. + EXPECT_FALSE(async_callback_stopped_propagation_result); } TEST_F(RenderWidgetHostViewAuraTest, KeyEventAsyncUnhandled) { view_->InitAsChild(nullptr); view_->Show(); bool async_callback_run = false; - bool async_callback_result = false; + bool async_callback_handled_result = false; + bool async_callback_stopped_propagation_result = false; ui::KeyEvent key_event1(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); ui::KeyEvent::KeyDispatcherApi(&key_event1) - .set_async_callback(base::BindLambdaForTesting([&](bool handled) { - async_callback_result = handled; - async_callback_run = true; - })); + .set_async_callback(base::BindLambdaForTesting( + [&](bool handled, bool stopped_propagation) { + async_callback_handled_result = handled; + async_callback_stopped_propagation_result = stopped_propagation; + async_callback_run = true; + })); view_->OnKeyEvent(&key_event1); // Normally event should be handled. EXPECT_TRUE(key_event1.handled()); @@ -5360,20 +5368,25 @@ EXPECT_EQ("RawKeyDown", GetMessageNames(events)); events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_TRUE(async_callback_run); - EXPECT_FALSE(async_callback_result); + EXPECT_FALSE(async_callback_handled_result); + // |async_callback_stopped_propagation_result| should always be false. + EXPECT_FALSE(async_callback_stopped_propagation_result); } TEST_F(RenderWidgetHostViewAuraTest, KeyEventAsyncNotifiedWhenRouterChanges) { view_->InitAsChild(nullptr); view_->Show(); bool async_callback_run = false; - bool async_callback_result = false; + bool async_callback_handled_result = false; + bool async_callback_stopped_propagation_result = false; ui::KeyEvent key_event1(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); ui::KeyEvent::KeyDispatcherApi(&key_event1) - .set_async_callback(base::BindLambdaForTesting([&](bool handled) { - async_callback_result = handled; - async_callback_run = true; - })); + .set_async_callback(base::BindLambdaForTesting( + [&](bool handled, bool stopped_propagation) { + async_callback_handled_result = handled; + async_callback_stopped_propagation_result = stopped_propagation; + async_callback_run = true; + })); view_->OnKeyEvent(&key_event1); // Normally event should be handled. EXPECT_TRUE(key_event1.handled()); @@ -5384,7 +5397,9 @@ // RendererExited() should result in running the callback. widget_host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1); EXPECT_TRUE(async_callback_run); - EXPECT_FALSE(async_callback_result); + EXPECT_FALSE(async_callback_handled_result); + // |async_callback_stopped_propagation_result| should always be false. + EXPECT_FALSE(async_callback_stopped_propagation_result); // RendererExited() results in destroying the view. view_ = nullptr;
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index 45f7063..83d0a79 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -1284,59 +1284,4 @@ EXPECT_EQ(bad_message::INVALID_INITIATOR_ORIGIN, kill_waiter.Wait()); } -namespace { - -// An interceptor class that allows replacing the URL of the commit IPC from -// the renderer process to the browser process. -class DidCommitUrlReplacer : public DidCommitProvisionalLoadInterceptor { - public: - DidCommitUrlReplacer(WebContents* web_contents, const GURL& replacement_url) - : DidCommitProvisionalLoadInterceptor(web_contents), - replacement_url_(replacement_url) {} - ~DidCommitUrlReplacer() override = default; - - protected: - bool WillDispatchDidCommitProvisionalLoad( - RenderFrameHost* render_frame_host, - ::FrameHostMsg_DidCommitProvisionalLoad_Params* params, - mojom::DidCommitProvisionalLoadInterfaceParamsPtr& interface_params) - override { - params->url = replacement_url_; - return true; - } - - private: - GURL replacement_url_; - - DISALLOW_COPY_AND_ASSIGN(DidCommitUrlReplacer); -}; - -} // namespace - -// Test which verifies that when an exploited renderer process sends a commit -// message with URL that the process is not allowed to commit. -IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, DidCommitInvalidURL) { - // Explicitly isolating foo.com helps ensure that this test is applicable on - // platforms without site-per-process. - IsolateOrigin("foo.com"); - - // Navigate to foo.com initially. - GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html")); - EXPECT_TRUE(NavigateToURL(shell(), foo_url)); - - // Create the interceoptor object which will replace the URL of the subsequent - // navigation with bar.com based URL. - GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title3.html")); - DidCommitUrlReplacer url_replacer(shell()->web_contents(), bar_url); - - // Navigate to another URL within foo.com, which would usually be committed - // succsesfuly, but when the URL is modified it should result in the - // termination of the renderer process. - RenderProcessHostKillWaiter kill_waiter( - shell()->web_contents()->GetMainFrame()->GetProcess()); - NavigateToURL(shell(), - embedded_test_server()->GetURL("foo.com", "/title2.html")); - EXPECT_EQ(bad_message::RFH_CAN_COMMIT_URL_BLOCKED, kill_waiter.Wait()); -} - } // namespace content
diff --git a/content/browser/service_worker/service_worker_installed_script_loader.cc b/content/browser/service_worker/service_worker_installed_script_loader.cc index d25fe43..2a6df6c4 100644 --- a/content/browser/service_worker/service_worker_installed_script_loader.cc +++ b/content/browser/service_worker/service_worker_installed_script_loader.cc
@@ -14,6 +14,7 @@ #include "content/browser/service_worker/service_worker_write_to_cache_job.h" #include "content/browser/url_loader_factory_getter.h" #include "content/common/service_worker/service_worker_utils.h" +#include "net/base/ip_endpoint.h" #include "net/cert/cert_status_flags.h" #include "services/network/public/cpp/resource_response.h" #include "third_party/blink/public/common/mime_util/mime_util.h" @@ -98,7 +99,7 @@ head.was_alpn_negotiated = info->was_alpn_negotiated; head.connection_info = info->connection_info; head.alpn_negotiated_protocol = info->alpn_negotiated_protocol; - head.socket_address = info->socket_address; + head.remote_endpoint = info->remote_endpoint; head.cert_status = info->ssl_info.cert_status; if (options_ & network::mojom::kURLLoadOptionSendSSLInfoWithResponse)
diff --git a/content/browser/service_worker/service_worker_new_script_loader.cc b/content/browser/service_worker/service_worker_new_script_loader.cc index 5a5475cb..9cc55e1 100644 --- a/content/browser/service_worker/service_worker_new_script_loader.cc +++ b/content/browser/service_worker/service_worker_new_script_loader.cc
@@ -17,6 +17,7 @@ #include "content/browser/service_worker/service_worker_write_to_cache_job.h" #include "content/browser/url_loader_factory_getter.h" #include "content/common/service_worker/service_worker_utils.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/cert/cert_status_flags.h" #include "services/network/public/cpp/resource_response.h" @@ -189,7 +190,7 @@ response_info->alpn_negotiated_protocol = response_head.alpn_negotiated_protocol; response_info->connection_info = response_head.connection_info; - response_info->socket_address = response_head.socket_address; + response_info->remote_endpoint = response_head.remote_endpoint; response_info->response_time = response_head.response_time; // The following sequence is equivalent to
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker.cc b/content/browser/service_worker/service_worker_single_script_update_checker.cc index 5851558d..946d38f 100644 --- a/content/browser/service_worker/service_worker_single_script_update_checker.cc +++ b/content/browser/service_worker/service_worker_single_script_update_checker.cc
@@ -9,6 +9,7 @@ #include "content/browser/service_worker/service_worker_cache_writer.h" #include "content/public/common/resource_type.h" #include "mojo/public/cpp/system/simple_watcher.h" +#include "net/base/ip_endpoint.h" #include "services/network/public/cpp/net_adapters.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "third_party/blink/public/common/mime_util/mime_util.h" @@ -123,7 +124,7 @@ response_info->alpn_negotiated_protocol = response_head.alpn_negotiated_protocol; response_info->connection_info = response_head.connection_info; - response_info->socket_address = response_head.socket_address; + response_info->remote_endpoint = response_head.remote_endpoint; // TODO(momohatt): Check for header errors.
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 297fccb..3387960 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -4983,7 +4983,8 @@ ~ContextMenuObserverDelegate() override {} - bool HandleContextMenu(const content::ContextMenuParams& params) override { + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override { context_menu_created_ = true; menu_params_ = params; message_loop_runner_->Quit();
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc index 63639ea1..65ea05d 100644 --- a/content/browser/tracing/background_tracing_manager_impl.cc +++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -511,6 +511,10 @@ } #endif + is_tracing_ = TracingControllerImpl::GetInstance()->StartTracing( + config, base::BindOnce(&BackgroundTracingManagerImpl::OnStartTracingDone, + base::Unretained(this), preset)); + // Activate the categories immediately. StartTracing eventually does this // itself, but asynchronously via PostTask, and in the meantime events will be // dropped. This ensures that we start recording events for those categories @@ -522,10 +526,6 @@ base::trace_event::TraceLog::GetInstance()->SetEnabled(config, modes); } - is_tracing_ = TracingControllerImpl::GetInstance()->StartTracing( - config, base::BindOnce(&BackgroundTracingManagerImpl::OnStartTracingDone, - base::Unretained(this), preset)); - RecordBackgroundTracingMetric(RECORDING_ENABLED); }
diff --git a/content/browser/tracing/cast_tracing_agent.cc b/content/browser/tracing/cast_tracing_agent.cc index fa4ae658..770f64c 100644 --- a/content/browser/tracing/cast_tracing_agent.cc +++ b/content/browser/tracing/cast_tracing_agent.cc
@@ -279,13 +279,14 @@ // tracing::mojom::Agent. Called by Mojo internals on the UI thread. void CastTracingAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!session_); session_ = std::make_unique<CastSystemTracingSession>(worker_task_runner_); session_->StartTracing( config, base::BindOnce(&CastTracingAgent::StartTracingCallbackProxy, - base::Unretained(this))); + base::Unretained(this), std::move(callback))); } void CastTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) { @@ -305,10 +306,12 @@ } void CastTracingAgent::StartTracingCallbackProxy( + Agent::StartTracingCallback callback, bool success) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!success) session_.reset(); + std::move(callback).Run(success); } void CastTracingAgent::HandleTraceData(chromecast::SystemTracer::Status status,
diff --git a/content/browser/tracing/cast_tracing_agent.h b/content/browser/tracing/cast_tracing_agent.h index 8d59d1c..7b90f2a 100644 --- a/content/browser/tracing/cast_tracing_agent.h +++ b/content/browser/tracing/cast_tracing_agent.h
@@ -33,10 +33,12 @@ // tracing::mojom::Agent. Called by Mojo internals on the UI thread. void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) override; void StopAndFlush(tracing::mojom::RecorderPtr recorder) override; - void StartTracingCallbackProxy(bool success); + void StartTracingCallbackProxy(Agent::StartTracingCallback callback, + bool success); void HandleTraceData(chromecast::SystemTracer::Status status, std::string trace_data);
diff --git a/content/browser/tracing/cros_tracing_agent.cc b/content/browser/tracing/cros_tracing_agent.cc index 427f6d0..a28b7c56 100644 --- a/content/browser/tracing/cros_tracing_agent.cc +++ b/content/browser/tracing/cros_tracing_agent.cc
@@ -227,12 +227,13 @@ // tracing::mojom::Agent. Called by Mojo internals on the UI thread. void CrOSTracingAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) { DCHECK(!session_); session_ = std::make_unique<CrOSSystemTracingSession>(); session_->StartTracing( config, base::BindOnce(&CrOSTracingAgent::StartTracingCallbackProxy, - base::Unretained(this))); + base::Unretained(this), std::move(callback))); } void CrOSTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) { @@ -245,9 +246,11 @@ } void CrOSTracingAgent::StartTracingCallbackProxy( + Agent::StartTracingCallback callback, bool success) { if (!success) session_.reset(); + std::move(callback).Run(success); } void CrOSTracingAgent::RecorderProxy(
diff --git a/content/browser/tracing/cros_tracing_agent.h b/content/browser/tracing/cros_tracing_agent.h index 91ae13c..289db7c 100644 --- a/content/browser/tracing/cros_tracing_agent.h +++ b/content/browser/tracing/cros_tracing_agent.h
@@ -32,10 +32,12 @@ // tracing::mojom::Agent. Called by Mojo internals on the UI thread. void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) override; void StopAndFlush(tracing::mojom::RecorderPtr recorder) override; - void StartTracingCallbackProxy(bool success); + void StartTracingCallbackProxy(Agent::StartTracingCallback callback, + bool success); void RecorderProxy(const scoped_refptr<base::RefCountedString>& events); std::unique_ptr<CrOSSystemTracingSession> session_;
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 558c2c5..a78b1434 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -55,7 +55,7 @@ #endif #if defined(OS_ANDROID) -#include "base/debug/elf_reader_linux.h" +#include "base/debug/elf_reader.h" // Symbol with virtual address of the start of ELF header of the current binary. extern char __ehdr_start; @@ -143,22 +143,16 @@ } TracingControllerImpl::TracingControllerImpl() - : delegate_(GetContentClient()->browser()->GetTracingDelegate()), - weak_ptr_factory_(this) { + : delegate_(GetContentClient()->browser()->GetTracingDelegate()) { DCHECK(!g_tracing_controller); DCHECK_CURRENTLY_ON(BrowserThread::UI); // Deliberately leaked, like this class. base::FileTracing::SetProvider(new FileTracingProviderImpl); AddAgents(); - base::trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver( - weak_ptr_factory_.GetWeakPtr()); g_tracing_controller = this; } -TracingControllerImpl::~TracingControllerImpl() { - base::trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver( - this); -} +TracingControllerImpl::~TracingControllerImpl() = default; void TracingControllerImpl::AddAgents() { tracing::TracedProcessImpl::GetInstance()->SetTaskRunner( @@ -221,10 +215,10 @@ // obtained from process maps since library can be mapped from apk directly. // This is not added as part of memory-infra os dumps since it is special case // only for chrome library. - base::Optional<std::string> soname = + base::Optional<base::StringPiece> soname = base::debug::ReadElfLibraryName(&__ehdr_start); if (soname) - metadata_dict->SetString("chrome-library-name", soname.value()); + metadata_dict->SetString("chrome-library-name", *soname); #endif // defined(OS_ANDROID) metadata_dict->SetInteger("chrome-bitness", 8 * sizeof(uintptr_t)); @@ -364,32 +358,20 @@ trace_config_ = std::make_unique<base::trace_event::TraceConfig>(trace_config); - start_tracing_done_ = std::move(callback); ConnectToServiceIfNeeded(); - coordinator_->StartTracing(trace_config.ToString()); - - if (start_tracing_done_ && - (base::trace_event::TraceLog::GetInstance()->IsEnabled() || - !trace_config.process_filter_config().IsEnabled( - base::Process::Current().Pid()))) { - // If we're already tracing, or if the current process is excluded from the - // process filter, we'll never receive a callback from the TraceLog, so then - // we just run the callback right away. - std::move(start_tracing_done_).Run(); - } - + coordinator_->StartTracing( + trace_config.ToString(), + base::BindOnce( + [](StartTracingDoneCallback callback, bool success) { + if (!callback.is_null()) + std::move(callback).Run(); + }, + std::move(callback))); // TODO(chiniforooshan): The actual success value should be sent by the // callback asynchronously. return true; } -void TracingControllerImpl::OnTraceLogEnabled() { - if (start_tracing_done_) - std::move(start_tracing_done_).Run(); -} - -void TracingControllerImpl::OnTraceLogDisabled() {} - bool TracingControllerImpl::StopTracing( const scoped_refptr<TraceDataEndpoint>& trace_data_endpoint) { return StopTracing(std::move(trace_data_endpoint), "");
diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h index 5a6f9e6..dbb0b86 100644 --- a/content/browser/tracing/tracing_controller_impl.h +++ b/content/browser/tracing/tracing_controller_impl.h
@@ -12,8 +12,6 @@ #include "base/callback_forward.h" #include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/trace_event/trace_log.h" #include "content/common/content_export.h" #include "content/public/browser/tracing_controller.h" #include "mojo/public/cpp/system/data_pipe_drainer.h" @@ -38,10 +36,8 @@ class TracingDelegate; class TracingUI; -class TracingControllerImpl - : public TracingController, - public mojo::DataPipeDrainer::Client, - public base::trace_event::TraceLog::AsyncEnabledStateObserver { +class TracingControllerImpl : public TracingController, + public mojo::DataPipeDrainer::Client { public: // Create an endpoint for dumping the trace data to a callback. CONTENT_EXPORT static scoped_refptr<TraceDataEndpoint> CreateCallbackEndpoint( @@ -87,10 +83,6 @@ void OnDataAvailable(const void* data, size_t num_bytes) override; void OnDataComplete() override; - // base::trace_event::TraceLog::AsyncEnabledStateObserver - void OnTraceLogEnabled() override; - void OnTraceLogDisabled() override; - void OnMetadataAvailable(base::Value metadata); void CompleteFlush(); @@ -99,7 +91,6 @@ std::vector<std::unique_ptr<tracing::BaseAgent>> agents_; std::unique_ptr<TracingDelegate> delegate_; std::unique_ptr<base::trace_event::TraceConfig> trace_config_; - StartTracingDoneCallback start_tracing_done_; std::unique_ptr<mojo::DataPipeDrainer> drainer_; scoped_refptr<TraceDataEndpoint> trace_data_endpoint_; std::unique_ptr<base::DictionaryValue> filtered_metadata_; @@ -107,8 +98,6 @@ bool is_data_complete_ = false; bool is_metadata_available_ = false; - // NOTE: Weak pointers must be invalidated before all other member variables. - base::WeakPtrFactory<TracingControllerImpl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl); };
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 20b3c89..69498d13 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -615,8 +615,7 @@ #endif // !defined(OS_ANDROID) #if defined(OS_ANDROID) - if (base::FeatureList::IsEnabled(features::kDisplayCutoutAPI)) - display_cutout_host_impl_ = std::make_unique<DisplayCutoutHostImpl>(this); + display_cutout_host_impl_ = std::make_unique<DisplayCutoutHostImpl>(this); #endif registry_.AddInterface(base::BindRepeating( @@ -5265,7 +5264,8 @@ ContextMenuParams context_menu_params(params); // Allow WebContentsDelegates to handle the context menu operation first. - if (delegate_ && delegate_->HandleContextMenu(context_menu_params)) + if (delegate_ && + delegate_->HandleContextMenu(render_frame_host, context_menu_params)) return; render_view_host_delegate_view_->ShowContextMenu(render_frame_host,
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index d8a9f7c..be9986ee 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -58,6 +58,7 @@ #include "content/test/content_browser_test_utils_internal.h" #include "content/test/test_content_browser_client.h" #include "net/base/features.h" +#include "net/base/ip_endpoint.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/controllable_http_response.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -711,9 +712,9 @@ if (!first_network_request) EXPECT_GT(resource_load_info->request_id, 0); EXPECT_EQ(mime_type, resource_load_info->mime_type); - ASSERT_TRUE(resource_load_info->network_info->ip_port_pair); - EXPECT_EQ(ip_address, - resource_load_info->network_info->ip_port_pair->host()); + ASSERT_TRUE(resource_load_info->network_info->remote_endpoint); + EXPECT_EQ(ip_address, resource_load_info->network_info->remote_endpoint + ->ToStringWithoutPort()); EXPECT_EQ(was_cached, resource_load_info->was_cached); // Simple sanity check of the load timing info. auto CheckTime = [before_request, after_request](auto actual) {
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index dfc5758b..19eab86 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -3364,4 +3364,28 @@ EXPECT_TRUE(observer.observed_did_first_visually_non_empty_paint()); } +namespace { + +class MockWebContentsDelegate : public WebContentsDelegate { + public: + MOCK_METHOD2(HandleContextMenu, + bool(RenderFrameHost*, const ContextMenuParams&)); +}; + +} // namespace + +TEST_F(WebContentsImplTest, HandleContextMenuDelegate) { + MockWebContentsDelegate delegate; + contents()->SetDelegate(&delegate); + + RenderFrameHost* rfh = main_test_rfh(); + EXPECT_CALL(delegate, HandleContextMenu(rfh, ::testing::_)) + .WillOnce(::testing::Return(true)); + + ContextMenuParams params; + contents()->ShowContextMenu(rfh, params); + + contents()->SetDelegate(nullptr); +} + } // namespace content
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc index ab316c8..cf02399 100644 --- a/content/browser/web_contents/web_contents_view_android.cc +++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -310,6 +310,7 @@ RenderFrameHost* render_frame_host, const ContextMenuParams& params) { auto* rwhv = static_cast<RenderWidgetHostViewAndroid*>( web_contents_->GetRenderWidgetHostView()); + // See if context menu is handled by SelectionController as a selection menu. // If not, use the delegate to show it. if (rwhv && rwhv->ShowSelectionMenu(params))
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm index 7f4308b..08a0d43 100644 --- a/content/browser/web_contents/web_contents_view_mac.mm +++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -255,12 +255,6 @@ void WebContentsViewMac::ShowContextMenu( RenderFrameHost* render_frame_host, const ContextMenuParams& params) { - // Allow delegates to handle the context menu operation first. - if (web_contents_->GetDelegate() && - web_contents_->GetDelegate()->HandleContextMenu(params)) { - return; - } - if (delegate()) delegate()->ShowContextMenu(render_frame_host, params); else
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher.cc b/content/browser/web_package/signed_exchange_cert_fetcher.cc index a4f67e2..d72a0ed8 100644 --- a/content/browser/web_package/signed_exchange_cert_fetcher.cc +++ b/content/browser/web_package/signed_exchange_cert_fetcher.cc
@@ -21,6 +21,7 @@ #include "content/public/common/url_loader_throttle.h" #include "ipc/ipc_message.h" #include "mojo/public/cpp/system/simple_watcher.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/http/http_status_code.h" #include "services/network/loader_util.h" @@ -218,9 +219,8 @@ resource_request_->url, head); } - if (reporter_) { - reporter_->set_cert_server_ip(head.socket_address.host()); - } + if (reporter_) + reporter_->set_cert_server_ip_address(head.remote_endpoint.address()); // |headers| is null when loading data URL. if (head.headers && head.headers->response_code() != net::HTTP_OK) {
diff --git a/content/browser/web_package/signed_exchange_reporter.cc b/content/browser/web_package/signed_exchange_reporter.cc index f49859f..c1ec58c 100644 --- a/content/browser/web_package/signed_exchange_reporter.cc +++ b/content/browser/web_package/signed_exchange_reporter.cc
@@ -11,6 +11,7 @@ #include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "content/public/common/content_features.h" +#include "net/base/ip_endpoint.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/resource_response.h" @@ -38,15 +39,15 @@ base::OnceCallback<int(void)> frame_tree_node_id_getter) : outer_url_(outer_url), referrer_(referrer), - server_ip_(response.socket_address.host()), + server_ip_address_(response.remote_endpoint.address()), status_code_(response.headers ? response.headers->response_code() : 0), frame_tree_node_id_getter_(std::move(frame_tree_node_id_getter)) {} SignedExchangeReporter::~SignedExchangeReporter() = default; -void SignedExchangeReporter::set_cert_server_ip( - const std::string& cert_server_ip) { - cert_server_ip_ = cert_server_ip; +void SignedExchangeReporter::set_cert_server_ip_address( + const net::IPAddress& cert_server_ip_address) { + cert_server_ip_address_ = cert_server_ip_address; } void SignedExchangeReporter::set_inner_url(const GURL& inner_url) {
diff --git a/content/browser/web_package/signed_exchange_reporter.h b/content/browser/web_package/signed_exchange_reporter.h index 4373e4e..84ea328 100644 --- a/content/browser/web_package/signed_exchange_reporter.h +++ b/content/browser/web_package/signed_exchange_reporter.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "content/browser/web_package/signed_exchange_error.h" #include "content/common/content_export.h" +#include "net/base/ip_address.h" #include "url/gurl.h" namespace network { @@ -30,7 +31,7 @@ ~SignedExchangeReporter(); - void set_cert_server_ip(const std::string& cert_server_ip); + void set_cert_server_ip_address(const net::IPAddress& cert_server_ip_address); void set_inner_url(const GURL& inner_url); void set_cert_url(const GURL& cert_url); @@ -45,10 +46,10 @@ const GURL outer_url_; const std::string referrer_; - const std::string server_ip_; + const net::IPAddress server_ip_address_; const int status_code_; base::OnceCallback<int(void)> frame_tree_node_id_getter_; - std::string cert_server_ip_; + net::IPAddress cert_server_ip_address_; GURL inner_url_; GURL cert_url_;
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index d0eae9e..93e9548 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -141,13 +141,11 @@ client->OnScriptLoadFailed(); return; } - auto* storage_partition_impl = static_cast<StoragePartitionImpl*>( - render_process_host->GetStoragePartition()); // Set up the default network loader factory. network::mojom::URLLoaderFactoryPtrInfo default_factory_info; CreateNetworkFactory(mojo::MakeRequest(&default_factory_info), - storage_partition_impl->GetNetworkContext()); + render_process_host); subresource_loader_factories->default_factory_info() = std::move(default_factory_info); @@ -196,16 +194,11 @@ // |default_factory_connection_error_handler_holder_| for reference. // (https://crbug.com/906991) void CreateNetworkFactory(network::mojom::URLLoaderFactoryRequest request, - network::mojom::NetworkContext* network_context) { + RenderProcessHost* process) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - network::mojom::URLLoaderFactoryParamsPtr params = - network::mojom::URLLoaderFactoryParams::New(); - params->process_id = process_id_; - // TODO(lukasza): https://crbug.com/792546: Start using CORB. - params->is_corb_enabled = false; - - network_context->CreateURLLoaderFactory(std::move(request), - std::move(params)); + network::mojom::TrustedURLLoaderHeaderClientPtrInfo no_header_client; + process->CreateURLLoaderFactory(origin_, std::move(no_header_client), + std::move(request)); } void CreateWebUsbService(blink::mojom::WebUsbServiceRequest request) {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index b3174c30..68951f4a 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -424,9 +424,8 @@ WebRuntimeFeatures::EnablePageLifecycle(true); #if defined(OS_ANDROID) - if (base::FeatureList::IsEnabled(features::kDisplayCutoutAPI) && - base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_P) { + if (base::android::BuildInfo::GetInstance()->sdk_int() >= + base::android::SDK_VERSION_P) { // Display Cutout is limited to Android P+. WebRuntimeFeatures::EnableDisplayCutoutAPI(true); }
diff --git a/content/public/browser/media_session.h b/content/public/browser/media_session.h index 725ef06..e8e0207 100644 --- a/content/public/browser/media_session.h +++ b/content/public/browser/media_session.h
@@ -89,6 +89,14 @@ // |type| represents the origin of the request. void Stop(SuspendType suspend_type) override = 0; + // Downloads the bitmap version of a MediaImage at least |minimum_size_px| + // and closest to |desired_size_px|. If the download failed, was too small or + // the image did not come from the media session then returns a null image. + void GetMediaImageBitmap(const media_session::MediaImage& image, + int minimum_size_px, + int desired_size_px, + GetMediaImageBitmapCallback callback) override = 0; + protected: MediaSession() = default; };
diff --git a/content/public/browser/navigation_handle.h b/content/public/browser/navigation_handle.h index d20c820..beb8fe7f 100644 --- a/content/public/browser/navigation_handle.h +++ b/content/public/browser/navigation_handle.h
@@ -14,7 +14,7 @@ #include "content/public/browser/restore_type.h" #include "content/public/common/referrer.h" #include "content/public/common/transferrable_url_loader.mojom.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/http/http_response_info.h" #include "services/network/public/cpp/resource_request_body.h" @@ -232,7 +232,7 @@ virtual const GURL& GetPreviousURL() = 0; // Returns the remote address of the socket which fetched this resource. - virtual net::HostPortPair GetSocketAddress() = 0; + virtual net::IPEndPoint GetSocketAddress() = 0; // Returns the headers used for this request. virtual const net::HttpRequestHeaders& GetRequestHeaders() = 0;
diff --git a/content/public/browser/tracing_controller.h b/content/public/browser/tracing_controller.h index 51151438..c2e3e98d 100644 --- a/content/public/browser/tracing_controller.h +++ b/content/public/browser/tracing_controller.h
@@ -75,9 +75,8 @@ // Tracing begins immediately locally, and asynchronously on child processes // as soon as they receive the StartTracing request. // - // Once tracing is enabled in the current process and trace events can be - // emitted (unless excluded from the config), StartTracingDoneCallback will - // be called back. + // Once all child processes have acked to the StartTracing request, + // StartTracingDoneCallback will be called back. // // |category_filter| is a filter to control what category groups should be // traced. A filter can have an optional '-' prefix to exclude category groups
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc index 0da8714..51bc80f 100644 --- a/content/public/browser/web_contents_delegate.cc +++ b/content/public/browser/web_contents_delegate.cc
@@ -83,7 +83,8 @@ callback.Run(true); } -bool WebContentsDelegate::HandleContextMenu(const ContextMenuParams& params) { +bool WebContentsDelegate::HandleContextMenu(RenderFrameHost* render_frame_host, + const ContextMenuParams& params) { return false; }
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h index 478e98a8..d1c1870 100644 --- a/content/public/browser/web_contents_delegate.h +++ b/content/public/browser/web_contents_delegate.h
@@ -246,7 +246,8 @@ const base::Callback<void(bool)>& callback); // Returns true if the context menu operation was handled by the delegate. - virtual bool HandleContextMenu(const ContextMenuParams& params); + virtual bool HandleContextMenu(RenderFrameHost* render_frame_host, + const ContextMenuParams& params); // Allows delegates to handle keyboard events before sending to the renderer. // See enum for description of return values.
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index 22adef2..cd52885 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn
@@ -364,6 +364,7 @@ ":resource_type_bindings", "//mojo/public/mojom/base:base", "//services/network/public/mojom", + "//services/network/public/mojom:mojom_ip_address", "//services/network/public/mojom:websocket_mojom", "//third_party/blink/public:mojo_bindings", "//ui/accessibility:ax_enums_mojo",
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 9c25da53..72987d3 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -687,11 +687,6 @@ const base::Feature kAndroidAutofillAccessibility{ "AndroidAutofillAccessibility", base::FEATURE_ENABLED_BY_DEFAULT}; -// Enables developers to use the CSS safe-area-* and viewport-fit APIs which -// allow them to support devices with a display cutout. -const base::Feature kDisplayCutoutAPI{"DisplayCutoutAPI", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Enables hiding incorrectly-sized frames while in fullscreen. const base::Feature kHideIncorrectlySizedFullscreenFrames{ "HideIncorrectlySizedFullscreenFrames", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 10e4aaf..8cb5719 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -156,7 +156,6 @@ CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility; CONTENT_EXPORT extern const base::Feature kBackgroundMediaRendererHasModerateBinding; -CONTENT_EXPORT extern const base::Feature kDisplayCutoutAPI; CONTENT_EXPORT extern const base::Feature kHideIncorrectlySizedFullscreenFrames; CONTENT_EXPORT extern const base::Feature kWebNfc; CONTENT_EXPORT extern const base::Feature kWebXrRenderPath;
diff --git a/content/public/common/profiling.cc b/content/public/common/profiling.cc index fe6201c..d083588 100644 --- a/content/public/common/profiling.cc +++ b/content/public/common/profiling.cc
@@ -65,7 +65,7 @@ } } thread->task_runner()->PostDelayedTask( - FROM_HERE, base::Bind(&FlushProfilingData, thread), + FROM_HERE, base::BindOnce(&FlushProfilingData, thread), base::TimeDelta::FromSeconds(flush_seconds)); } @@ -80,8 +80,8 @@ return; thread_ = new base::Thread("Profiling_Flush"); thread_->Start(); - thread_->task_runner()->PostTask(FROM_HERE, - base::Bind(&FlushProfilingData, thread_)); + thread_->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&FlushProfilingData, thread_)); } void Stop() {
diff --git a/content/public/common/resource_load_info.mojom b/content/public/common/resource_load_info.mojom index 3294653..6e17f0c 100644 --- a/content/public/common/resource_load_info.mojom +++ b/content/public/common/resource_load_info.mojom
@@ -7,6 +7,7 @@ import "content/public/common/load_timing_info.mojom"; import "content/public/common/resource_type.mojom"; import "services/network/public/mojom/ip_address.mojom"; +import "services/network/public/mojom/ip_endpoint.mojom"; import "services/network/public/mojom/network_param.mojom"; import "url/mojom/url.mojom"; @@ -20,7 +21,7 @@ bool always_access_network; // The host IP and port of the response. - network.mojom.HostPortPair? ip_port_pair; + network.mojom.IPEndPoint? remote_endpoint; }; // Information for a redirect.
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h index 59f14073..95179687 100644 --- a/content/public/renderer/render_frame.h +++ b/content/public/renderer/render_frame.h
@@ -8,7 +8,6 @@ #include <stddef.h> #include <memory> -#include <string> #include "base/callback_forward.h" #include "base/single_thread_task_runner.h" @@ -21,7 +20,6 @@ #include "ppapi/buildflags/buildflags.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" -#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h" #include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/web/web_navigation_policy.h" @@ -296,16 +294,6 @@ virtual void SetRenderFrameMediaPlaybackOptions( const RenderFrameMediaPlaybackOptions& opts) = 0; - // Requests that fetches initiated by |initiator_origin| should go through the - // provided |url_loader_factory|. This method should be called before - // executing scripts in a isolated world - such scripts are typically - // associated with a security origin different from the main world (and - // therefore fetches from such scripts set |request_initiator| that is - // incompatible with |request_initiator_site_lock|. - virtual void MarkInitiatorAsRequiringSeparateURLLoaderFactory( - const url::Origin& initiator_origin, - network::mojom::URLLoaderFactoryPtr url_loader_factory) = 0; - protected: ~RenderFrame() override {}
diff --git a/content/public/test/mock_navigation_handle.h b/content/public/test/mock_navigation_handle.h index 7a43701..832b086 100644 --- a/content/public/test/mock_navigation_handle.h +++ b/content/public/test/mock_navigation_handle.h
@@ -9,6 +9,7 @@ #include "content/public/browser/global_request_id.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" +#include "net/base/ip_endpoint.h" #include "testing/gmock/include/gmock/gmock.h" #include "url/gurl.h" @@ -66,7 +67,7 @@ MOCK_METHOD0(DidReplaceEntry, bool()); MOCK_METHOD0(ShouldUpdateHistory, bool()); MOCK_METHOD0(GetPreviousURL, const GURL&()); - MOCK_METHOD0(GetSocketAddress, net::HostPortPair()); + MOCK_METHOD0(GetSocketAddress, net::IPEndPoint()); const net::HttpRequestHeaders& GetRequestHeaders() override { return request_headers_; }
diff --git a/content/public/test/navigation_simulator.h b/content/public/test/navigation_simulator.h index 124e687..ee42a3e 100644 --- a/content/public/test/navigation_simulator.h +++ b/content/public/test/navigation_simulator.h
@@ -17,7 +17,7 @@ class GURL; namespace net { -class HostPortPair; +class IPEndPoint; class HttpResponseHeaders; } // namespace net @@ -252,7 +252,7 @@ // The following parameters can change at any point until the page fails or // commits. They should be specified before calling |Fail| or |Commit|. - virtual void SetSocketAddress(const net::HostPortPair& socket_address) = 0; + virtual void SetSocketAddress(const net::IPEndPoint& remote_endpoint) = 0; // Pretend the navigation is against an inner response of a signed exchange. virtual void SetIsSignedExchangeInnerResponse(
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc index 13288f8..811c170 100644 --- a/content/renderer/compositor/layer_tree_view.cc +++ b/content/renderer/compositor/layer_tree_view.cc
@@ -571,7 +571,9 @@ delegate_->WillBeginCompositorFrame(); } -void LayerTreeView::DidBeginMainFrame() {} +void LayerTreeView::DidBeginMainFrame() { + delegate_->DidBeginMainFrame(); +} void LayerTreeView::DidUpdateLayers() { // Dump property trees and layers if run with:
diff --git a/content/renderer/compositor/layer_tree_view_delegate.h b/content/renderer/compositor/layer_tree_view_delegate.h index a5d2d82..c219245 100644 --- a/content/renderer/compositor/layer_tree_view_delegate.h +++ b/content/renderer/compositor/layer_tree_view_delegate.h
@@ -56,6 +56,10 @@ // Notifies that the compositor has issued a BeginMainFrame. virtual void BeginMainFrame(base::TimeTicks frame_time) = 0; + // Notifies that the layer tree host has completed a call to + // RequestMainFrameUpdate in response to a BeginMainFrame. + virtual void DidBeginMainFrame() = 0; + // Requests a LayerTreeFrameSink to submit CompositorFrames to. virtual void RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) = 0;
diff --git a/content/renderer/loader/resource_load_stats.cc b/content/renderer/loader/resource_load_stats.cc index e8122cd9..79bf325 100644 --- a/content/renderer/loader/resource_load_stats.cc +++ b/content/renderer/loader/resource_load_stats.cc
@@ -10,6 +10,7 @@ #include "content/public/common/resource_load_info.mojom.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" +#include "net/base/ip_endpoint.h" #include "net/url_request/redirect_info.h" #include "services/network/public/cpp/resource_response.h" #include "services/network/public/cpp/url_loader_completion_status.h" @@ -131,8 +132,8 @@ redirect_response.network_accessed; net_redirect_info->network_info->always_access_network = AlwaysAccessNetwork(redirect_response.headers); - net_redirect_info->network_info->ip_port_pair = - redirect_response.socket_address; + net_redirect_info->network_info->remote_endpoint = + redirect_response.remote_endpoint; resource_load_info->redirect_info_chain.push_back( std::move(net_redirect_info)); } @@ -159,7 +160,8 @@ response_head.network_accessed; resource_load_info->network_info->always_access_network = AlwaysAccessNetwork(response_head.headers); - resource_load_info->network_info->ip_port_pair = response_head.socket_address; + resource_load_info->network_info->remote_endpoint = + response_head.remote_endpoint; auto task_runner = RenderThreadImpl::DeprecatedGetMainTaskRunner(); if (!task_runner)
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc index ec9e4e8..08b0d6e 100644 --- a/content/renderer/loader/web_url_loader_impl.cc +++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -42,6 +42,8 @@ #include "content/renderer/loader/web_url_request_util.h" #include "net/base/data_url.h" #include "net/base/filename_util.h" +#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/cert/cert_status_flags.h" @@ -1182,9 +1184,9 @@ response->SetWasCached(!info.load_timing.request_start_time.is_null() && info.response_time < info.load_timing.request_start_time); - response->SetRemoteIPAddress( - WebString::FromUTF8(info.socket_address.HostForURL())); - response->SetRemotePort(info.socket_address.port()); + response->SetRemoteIPAddress(WebString::FromUTF8( + net::HostPortPair::FromIPEndPoint(info.remote_endpoint).HostForURL())); + response->SetRemotePort(info.remote_endpoint.port()); response->SetConnectionID(info.load_timing.socket_log_id); response->SetConnectionReused(info.load_timing.socket_reused); response->SetWasFetchedViaSPDY(info.was_fetched_via_spdy);
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc index 74b75758d..28b97e7 100644 --- a/content/renderer/loader/web_url_loader_impl_unittest.cc +++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -28,6 +28,7 @@ #include "content/renderer/loader/sync_load_response.h" #include "mojo/public/cpp/system/data_pipe.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/cert/x509_util.h" #include "net/http/http_response_headers.h" @@ -560,15 +561,17 @@ {"123.123.123.123", "123.123.123.123"}, {"::1", "[::1]"}, {"2001:0db8:85a3:0000:0000:8a2e:0370:7334", - "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"}, - {"2001:db8:85a3:0:0:8a2e:370:7334", "[2001:db8:85a3:0:0:8a2e:370:7334]"}, + "[2001:db8:85a3::8a2e:370:7334]"}, + {"2001:db8:85a3:0:0:8a2e:370:7334", "[2001:db8:85a3::8a2e:370:7334]"}, {"2001:db8:85a3::8a2e:370:7334", "[2001:db8:85a3::8a2e:370:7334]"}, - {"::ffff:192.0.2.128", "[::ffff:192.0.2.128]"}}; + {"::ffff:192.0.2.128", "[::ffff:c000:280]"}}; for (const auto& test : cases) { SCOPED_TRACE(test.ip); network::ResourceResponseInfo info; - info.socket_address = net::HostPortPair(test.ip, 443); + net::IPAddress address; + ASSERT_TRUE(address.AssignFromIPLiteral(test.ip)); + info.remote_endpoint = net::IPEndPoint(address, 443); blink::WebURLResponse response; WebURLLoaderImpl::PopulateURLResponse(url, info, &response, true, -1); EXPECT_EQ(test.expected, response.RemoteIPAddress().Utf8());
diff --git a/content/renderer/media/android/stream_texture_factory.cc b/content/renderer/media/android/stream_texture_factory.cc index 3500555..cfcb963 100644 --- a/content/renderer/media/android/stream_texture_factory.cc +++ b/content/renderer/media/android/stream_texture_factory.cc
@@ -56,8 +56,9 @@ } // Unretained is safe here only because the object is deleted on |loop_| // thread. - task_runner->PostTask(FROM_HERE, base::Bind(&StreamTextureProxy::BindOnThread, - base::Unretained(this))); + task_runner->PostTask(FROM_HERE, + base::BindOnce(&StreamTextureProxy::BindOnThread, + base::Unretained(this))); } void StreamTextureProxy::BindOnThread() {
diff --git a/content/renderer/media/android/stream_texture_wrapper_impl.cc b/content/renderer/media/android/stream_texture_wrapper_impl.cc index 7505e87..3319214 100644 --- a/content/renderer/media/android/stream_texture_wrapper_impl.cc +++ b/content/renderer/media/android/stream_texture_wrapper_impl.cc
@@ -127,8 +127,8 @@ if (!main_task_runner_->BelongsToCurrentThread()) { main_task_runner_->PostTask( - FROM_HERE, base::Bind(&StreamTextureWrapperImpl::UpdateTextureSize, - weak_factory_.GetWeakPtr(), new_size)); + FROM_HERE, base::BindOnce(&StreamTextureWrapperImpl::UpdateTextureSize, + weak_factory_.GetWeakPtr(), new_size)); return; } @@ -156,9 +156,10 @@ natural_size_ = natural_size; main_task_runner_->PostTask( - FROM_HERE, base::Bind(&StreamTextureWrapperImpl::InitializeOnMainThread, - weak_factory_.GetWeakPtr(), received_frame_cb, - media::BindToCurrentLoop(init_cb))); + FROM_HERE, + base::BindOnce(&StreamTextureWrapperImpl::InitializeOnMainThread, + weak_factory_.GetWeakPtr(), received_frame_cb, + media::BindToCurrentLoop(init_cb))); } void StreamTextureWrapperImpl::InitializeOnMainThread( @@ -187,8 +188,8 @@ // base::Unretained is safe here because this function is the only one that // can call delete. main_task_runner_->PostTask( - FROM_HERE, - base::Bind(&StreamTextureWrapperImpl::Destroy, base::Unretained(this))); + FROM_HERE, base::BindOnce(&StreamTextureWrapperImpl::Destroy, + base::Unretained(this))); return; }
diff --git a/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc b/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc index ff923ef..79b968b 100644 --- a/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc +++ b/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc
@@ -43,6 +43,19 @@ return 0; } +rtc::scoped_refptr<webrtc::DtlsTransportInterface> +FakeRTCRtpSender::DtlsTransport() { + NOTIMPLEMENTED(); + return nullptr; +} + +webrtc::DtlsTransportInformation FakeRTCRtpSender::DtlsTransportInformation() { + NOTIMPLEMENTED(); + static webrtc::DtlsTransportInformation dummy( + webrtc::DtlsTransportState::kNew); + return dummy; +} + blink::WebMediaStreamTrack FakeRTCRtpSender::Track() const { return track_id_ ? CreateWebMediaStreamTrack(*track_id_) : blink::WebMediaStreamTrack(); // null @@ -107,6 +120,20 @@ return 0; } +rtc::scoped_refptr<webrtc::DtlsTransportInterface> +FakeRTCRtpReceiver::DtlsTransport() { + NOTIMPLEMENTED(); + return nullptr; +} + +webrtc::DtlsTransportInformation +FakeRTCRtpReceiver::DtlsTransportInformation() { + NOTIMPLEMENTED(); + static webrtc::DtlsTransportInformation dummy( + webrtc::DtlsTransportState::kNew); + return dummy; +} + const blink::WebMediaStreamTrack& FakeRTCRtpReceiver::Track() const { return track_; }
diff --git a/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h b/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h index 45b2eaf..afdc36ad 100644 --- a/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h +++ b/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h
@@ -34,6 +34,8 @@ std::unique_ptr<blink::WebRTCRtpSender> ShallowCopy() const override; uintptr_t Id() const override; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override; + webrtc::DtlsTransportInformation DtlsTransportInformation() override; blink::WebMediaStreamTrack Track() const override; blink::WebVector<blink::WebString> StreamIds() const override; void ReplaceTrack(blink::WebMediaStreamTrack with_track, @@ -62,6 +64,8 @@ std::unique_ptr<blink::WebRTCRtpReceiver> ShallowCopy() const override; uintptr_t Id() const override; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override; + webrtc::DtlsTransportInformation DtlsTransportInformation() override; const blink::WebMediaStreamTrack& Track() const override; blink::WebVector<blink::WebString> StreamIds() const override; blink::WebVector<std::unique_ptr<blink::WebRTCRtpSource>> GetSources()
diff --git a/content/renderer/media/webrtc/mock_peer_connection_impl.cc b/content/renderer/media/webrtc/mock_peer_connection_impl.cc index 198a637..c26a010 100644 --- a/content/renderer/media/webrtc/mock_peer_connection_impl.cc +++ b/content/renderer/media/webrtc/mock_peer_connection_impl.cc
@@ -125,6 +125,11 @@ return track_; } +rtc::scoped_refptr<webrtc::DtlsTransportInterface> +FakeRtpSender::dtls_transport() const { + return transport_; +} + uint32_t FakeRtpSender::ssrc() const { NOTIMPLEMENTED(); return 0; @@ -177,6 +182,11 @@ return track_; } +rtc::scoped_refptr<webrtc::DtlsTransportInterface> +FakeRtpReceiver::dtls_transport() const { + return transport_; +} + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> FakeRtpReceiver::streams() const { return streams_; @@ -221,8 +231,8 @@ FakeRtpTransceiver::FakeRtpTransceiver( cricket::MediaType media_type, - rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + rtc::scoped_refptr<FakeRtpSender> sender, + rtc::scoped_refptr<FakeRtpReceiver> receiver, base::Optional<std::string> mid, bool stopped, webrtc::RtpTransceiverDirection direction, @@ -277,6 +287,23 @@ NOTIMPLEMENTED(); } +void FakeRtpTransceiver::SetTransport( + rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) { + sender_->SetTransport(transport); + receiver_->SetTransport(transport); +} + +FakeDtlsTransport::FakeDtlsTransport() {} + +rtc::scoped_refptr<webrtc::IceTransportInterface> +FakeDtlsTransport::ice_transport() { + return nullptr; +} + +webrtc::DtlsTransportInformation FakeDtlsTransport::Information() { + return webrtc::DtlsTransportInformation(webrtc::DtlsTransportState::kNew); +} + const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer"; const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer";
diff --git a/content/renderer/media/webrtc/mock_peer_connection_impl.h b/content/renderer/media/webrtc/mock_peer_connection_impl.h index 42e9a8f..1d691c26 100644 --- a/content/renderer/media/webrtc/mock_peer_connection_impl.h +++ b/content/renderer/media/webrtc/mock_peer_connection_impl.h
@@ -30,6 +30,8 @@ bool SetTrack(webrtc::MediaStreamTrackInterface* track) override; rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track() const override; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> dtls_transport() + const override; uint32_t ssrc() const override; cricket::MediaType media_type() const override; std::string id() const override; @@ -41,9 +43,14 @@ const webrtc::RtpParameters& parameters) override; rtc::scoped_refptr<webrtc::DtmfSenderInterface> GetDtmfSender() const override; + void SetTransport( + rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) { + transport_ = transport; + } private: rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track_; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport_; std::vector<std::string> stream_ids_; }; @@ -55,6 +62,8 @@ ~FakeRtpReceiver() override; rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track() const override; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> dtls_transport() + const override; std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams() const override; std::vector<std::string> stream_ids() const override; @@ -64,9 +73,14 @@ bool SetParameters(const webrtc::RtpParameters& parameters) override; void SetObserver(webrtc::RtpReceiverObserverInterface* observer) override; std::vector<webrtc::RtpSource> GetSources() const override; + void SetTransport( + rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) { + transport_ = transport; + } private: rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track_; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport_; std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams_; }; @@ -74,8 +88,8 @@ public: FakeRtpTransceiver( cricket::MediaType media_type, - rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + rtc::scoped_refptr<FakeRtpSender> sender, + rtc::scoped_refptr<FakeRtpReceiver> receiver, base::Optional<std::string> mid, bool stopped, webrtc::RtpTransceiverDirection direction, @@ -94,17 +108,29 @@ absl::optional<webrtc::RtpTransceiverDirection> current_direction() const override; void Stop() override; + void SetTransport( + rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport); private: cricket::MediaType media_type_; - rtc::scoped_refptr<webrtc::RtpSenderInterface> sender_; - rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver_; + rtc::scoped_refptr<FakeRtpSender> sender_; + rtc::scoped_refptr<FakeRtpReceiver> receiver_; absl::optional<std::string> mid_; bool stopped_; webrtc::RtpTransceiverDirection direction_; absl::optional<webrtc::RtpTransceiverDirection> current_direction_; }; +class FakeDtlsTransport : public webrtc::DtlsTransportInterface { + public: + FakeDtlsTransport(); + rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport() override; + webrtc::DtlsTransportInformation Information() override; + void RegisterObserver( + webrtc::DtlsTransportObserverInterface* observer) override {} + void UnregisterObserver() override {} +}; + // TODO(hbos): The use of fakes and mocks is the wrong approach for testing of // this. It introduces complexity, is error prone (not testing the right thing // and bugs in the mocks). This class is a maintenance burden and should be
diff --git a/content/renderer/media/webrtc/rtc_rtp_receiver.cc b/content/renderer/media/webrtc/rtc_rtp_receiver.cc index 93bc443..8edb691 100644 --- a/content/renderer/media/webrtc/rtc_rtp_receiver.cc +++ b/content/renderer/media/webrtc/rtc_rtp_receiver.cc
@@ -21,6 +21,8 @@ : main_task_runner_(std::move(main_task_runner)), signaling_task_runner_(std::move(signaling_task_runner)), webrtc_receiver_(std::move(webrtc_receiver)), + webrtc_dtls_transport_(webrtc_receiver_->dtls_transport()), + webrtc_dtls_transport_information_(webrtc::DtlsTransportState::kNew), is_initialized_(false), track_ref_(std::move(track_ref)), stream_ids_(std::move(stream_id)) { @@ -28,12 +30,18 @@ DCHECK(signaling_task_runner_); DCHECK(webrtc_receiver_); DCHECK(track_ref_); + if (webrtc_dtls_transport_) { + webrtc_dtls_transport_information_ = webrtc_dtls_transport_->Information(); + } } RtpReceiverState::RtpReceiverState(RtpReceiverState&& other) : main_task_runner_(other.main_task_runner_), signaling_task_runner_(other.signaling_task_runner_), webrtc_receiver_(std::move(other.webrtc_receiver_)), + webrtc_dtls_transport_(std::move(other.webrtc_dtls_transport_)), + webrtc_dtls_transport_information_( + other.webrtc_dtls_transport_information_), is_initialized_(other.is_initialized_), track_ref_(std::move(other.track_ref_)), stream_ids_(std::move(other.stream_ids_)) { @@ -55,6 +63,8 @@ other.main_task_runner_ = nullptr; other.signaling_task_runner_ = nullptr; webrtc_receiver_ = std::move(other.webrtc_receiver_); + webrtc_dtls_transport_ = std::move(other.webrtc_dtls_transport_); + webrtc_dtls_transport_information_ = other.webrtc_dtls_transport_information_; track_ref_ = std::move(other.track_ref_); stream_ids_ = std::move(other.stream_ids_); return *this; @@ -91,6 +101,18 @@ return webrtc_receiver_; } +rtc::scoped_refptr<webrtc::DtlsTransportInterface> +RtpReceiverState::webrtc_dtls_transport() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_dtls_transport_; +} + +webrtc::DtlsTransportInformation +RtpReceiverState::webrtc_dtls_transport_information() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_dtls_transport_information_; +} + const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& RtpReceiverState::track_ref() const { DCHECK(main_task_runner_->BelongsToCurrentThread()); @@ -241,6 +263,15 @@ return getId(internal_->state().webrtc_receiver().get()); } +rtc::scoped_refptr<webrtc::DtlsTransportInterface> +RTCRtpReceiver::DtlsTransport() { + return internal_->state().webrtc_dtls_transport(); +} + +webrtc::DtlsTransportInformation RTCRtpReceiver::DtlsTransportInformation() { + return internal_->state().webrtc_dtls_transport_information(); +} + const blink::WebMediaStreamTrack& RTCRtpReceiver::Track() const { return internal_->state().track_ref()->web_track(); }
diff --git a/content/renderer/media/webrtc/rtc_rtp_receiver.h b/content/renderer/media/webrtc/rtc_rtp_receiver.h index f93ea71..8a8119db 100644 --- a/content/renderer/media/webrtc/rtc_rtp_receiver.h +++ b/content/renderer/media/webrtc/rtc_rtp_receiver.h
@@ -79,6 +79,10 @@ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const; scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const; scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver() const; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> webrtc_dtls_transport() + const; + webrtc::DtlsTransportInformation webrtc_dtls_transport_information() const; + const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& track_ref() const; const std::vector<std::string>& stream_ids() const; @@ -87,6 +91,8 @@ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> webrtc_dtls_transport_; + webrtc::DtlsTransportInformation webrtc_dtls_transport_information_; bool is_initialized_; std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref_; std::vector<std::string> stream_ids_; @@ -113,6 +119,9 @@ std::unique_ptr<blink::WebRTCRtpReceiver> ShallowCopy() const override; uintptr_t Id() const override; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override; + webrtc::DtlsTransportInformation DtlsTransportInformation() override; + const blink::WebMediaStreamTrack& Track() const override; blink::WebVector<blink::WebString> StreamIds() const override; blink::WebVector<std::unique_ptr<blink::WebRTCRtpSource>> GetSources()
diff --git a/content/renderer/media/webrtc/rtc_rtp_sender.cc b/content/renderer/media/webrtc/rtc_rtp_sender.cc index b0afdf9..0bea4bcf 100644 --- a/content/renderer/media/webrtc/rtc_rtp_sender.cc +++ b/content/renderer/media/webrtc/rtc_rtp_sender.cc
@@ -46,18 +46,26 @@ : main_task_runner_(std::move(main_task_runner)), signaling_task_runner_(std::move(signaling_task_runner)), webrtc_sender_(std::move(webrtc_sender)), + webrtc_dtls_transport_(webrtc_sender_->dtls_transport()), + webrtc_dtls_transport_information_(webrtc::DtlsTransportState::kNew), is_initialized_(false), track_ref_(std::move(track_ref)), stream_ids_(std::move(stream_ids)) { DCHECK(main_task_runner_); DCHECK(signaling_task_runner_); DCHECK(webrtc_sender_); + if (webrtc_dtls_transport_) { + webrtc_dtls_transport_information_ = webrtc_dtls_transport_->Information(); + } } RtpSenderState::RtpSenderState(RtpSenderState&& other) : main_task_runner_(other.main_task_runner_), signaling_task_runner_(other.signaling_task_runner_), webrtc_sender_(std::move(other.webrtc_sender_)), + webrtc_dtls_transport_(std::move(other.webrtc_dtls_transport_)), + webrtc_dtls_transport_information_( + other.webrtc_dtls_transport_information_), is_initialized_(other.is_initialized_), track_ref_(std::move(other.track_ref_)), stream_ids_(std::move(other.stream_ids_)) { @@ -77,6 +85,8 @@ other.main_task_runner_ = nullptr; other.signaling_task_runner_ = nullptr; webrtc_sender_ = std::move(other.webrtc_sender_); + webrtc_dtls_transport_ = std::move(other.webrtc_dtls_transport_); + webrtc_dtls_transport_information_ = other.webrtc_dtls_transport_information_; is_initialized_ = other.is_initialized_; track_ref_ = std::move(other.track_ref_); stream_ids_ = std::move(other.stream_ids_); @@ -113,6 +123,18 @@ return webrtc_sender_; } +rtc::scoped_refptr<webrtc::DtlsTransportInterface> +RtpSenderState::webrtc_dtls_transport() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_dtls_transport_; +} + +webrtc::DtlsTransportInformation +RtpSenderState::webrtc_dtls_transport_information() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_dtls_transport_information_; +} + const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& RtpSenderState::track_ref() const { DCHECK(main_task_runner_->BelongsToCurrentThread()); @@ -384,6 +406,15 @@ return getId(internal_->state().webrtc_sender().get()); } +rtc::scoped_refptr<webrtc::DtlsTransportInterface> +RTCRtpSender::DtlsTransport() { + return internal_->state().webrtc_dtls_transport(); +} + +webrtc::DtlsTransportInformation RTCRtpSender::DtlsTransportInformation() { + return internal_->state().webrtc_dtls_transport_information(); +} + blink::WebMediaStreamTrack RTCRtpSender::Track() const { const auto& track_ref = internal_->state().track_ref(); return track_ref ? track_ref->web_track() : blink::WebMediaStreamTrack();
diff --git a/content/renderer/media/webrtc/rtc_rtp_sender.h b/content/renderer/media/webrtc/rtc_rtp_sender.h index 4a00277..c0e6bdd 100644 --- a/content/renderer/media/webrtc/rtc_rtp_sender.h +++ b/content/renderer/media/webrtc/rtc_rtp_sender.h
@@ -80,6 +80,9 @@ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const; scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const; scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender() const; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> webrtc_dtls_transport() + const; + webrtc::DtlsTransportInformation webrtc_dtls_transport_information() const; const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& track_ref() const; void set_track_ref( @@ -90,6 +93,8 @@ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> webrtc_dtls_transport_; + webrtc::DtlsTransportInformation webrtc_dtls_transport_information_; bool is_initialized_; std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref_; std::vector<std::string> stream_ids_; @@ -122,6 +127,8 @@ // blink::WebRTCRtpSender. std::unique_ptr<blink::WebRTCRtpSender> ShallowCopy() const override; uintptr_t Id() const override; + rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override; + webrtc::DtlsTransportInformation DtlsTransportInformation() override; blink::WebMediaStreamTrack Track() const override; blink::WebVector<blink::WebString> StreamIds() const override; void ReplaceTrack(blink::WebMediaStreamTrack with_track,
diff --git a/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc b/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc index fb0dc36..accdeb95 100644 --- a/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc +++ b/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc
@@ -105,8 +105,8 @@ } rtc::scoped_refptr<FakeRtpTransceiver> CreateWebRtcTransceiver( - rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + rtc::scoped_refptr<FakeRtpSender> sender, + rtc::scoped_refptr<FakeRtpReceiver> receiver, base::Optional<std::string> mid, bool stopped, webrtc::RtpTransceiverDirection direction,
diff --git a/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc b/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc index 90bf88d2..d1aeb621 100644 --- a/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc +++ b/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc
@@ -55,28 +55,35 @@ CreateBlinkLocalTrack(id)); } - rtc::scoped_refptr<webrtc::RtpTransceiverInterface> CreateWebRtcTransceiver( + rtc::scoped_refptr<FakeRtpTransceiver> CreateWebRtcTransceiver( rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> local_track, const std::string& local_stream_id, const std::string& remote_track_id, - const std::string& remote_stream_id) { - return new rtc::RefCountedObject<FakeRtpTransceiver>( - local_track->kind() == webrtc::MediaStreamTrackInterface::kAudioKind - ? cricket::MEDIA_TYPE_AUDIO - : cricket::MEDIA_TYPE_VIDEO, - CreateWebRtcSender(local_track, local_stream_id), - CreateWebRtcReceiver(remote_track_id, remote_stream_id), base::nullopt, - false, webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + const std::string& remote_stream_id, + rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) { + rtc::scoped_refptr<FakeRtpTransceiver> transceiver = + new rtc::RefCountedObject<FakeRtpTransceiver>( + local_track->kind() == webrtc::MediaStreamTrackInterface::kAudioKind + ? cricket::MEDIA_TYPE_AUDIO + : cricket::MEDIA_TYPE_VIDEO, + CreateWebRtcSender(local_track, local_stream_id), + CreateWebRtcReceiver(remote_track_id, remote_stream_id), + base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv, + base::nullopt); + if (transport.get()) { + transceiver->SetTransport(transport); + } + return transceiver; } - rtc::scoped_refptr<webrtc::RtpSenderInterface> CreateWebRtcSender( + rtc::scoped_refptr<FakeRtpSender> CreateWebRtcSender( rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, const std::string& stream_id) { return new rtc::RefCountedObject<FakeRtpSender>( std::move(track), std::vector<std::string>({stream_id})); } - rtc::scoped_refptr<webrtc::RtpReceiverInterface> CreateWebRtcReceiver( + rtc::scoped_refptr<FakeRtpReceiver> CreateWebRtcReceiver( const std::string& track_id, const std::string& stream_id) { rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_track = @@ -144,6 +151,15 @@ EXPECT_EQ(sender_state->track_ref()->webrtc_track(), webrtc_sender->track().get()); EXPECT_EQ(sender_state->stream_ids(), webrtc_sender->stream_ids()); + EXPECT_EQ(sender_state->webrtc_dtls_transport(), + webrtc_sender->dtls_transport()); + if (webrtc_sender->dtls_transport()) { + EXPECT_EQ(webrtc_sender->dtls_transport()->Information().state(), + sender_state->webrtc_dtls_transport_information().state()); + } else { + EXPECT_EQ(webrtc::DtlsTransportState::kNew, + sender_state->webrtc_dtls_transport_information().state()); + } // Inspect receiver states. const auto& receiver_state = transceiver_state.receiver_state(); EXPECT_TRUE(receiver_state); @@ -158,6 +174,15 @@ receiver_stream_ids.push_back(stream->id()); } EXPECT_EQ(receiver_state->stream_ids(), receiver_stream_ids); + EXPECT_EQ(receiver_state->webrtc_dtls_transport(), + webrtc_receiver->dtls_transport()); + if (webrtc_receiver->dtls_transport()) { + EXPECT_EQ(webrtc_receiver->dtls_transport()->Information().state(), + receiver_state->webrtc_dtls_transport_information().state()); + } else { + EXPECT_EQ(webrtc::DtlsTransportState::kNew, + receiver_state->webrtc_dtls_transport_information().state()); + } // Inspect transceiver states. EXPECT_TRUE( OptionalEquals(transceiver_state.mid(), webrtc_transceiver->mid())); @@ -228,9 +253,9 @@ TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverBlockingly) { auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); - auto webrtc_transceiver = - CreateWebRtcTransceiver(local_track_adapter->webrtc_track(), - "local_stream", "remote_track", "remote_stream"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + local_track_adapter->webrtc_track(), "local_stream", "remote_track", + "remote_stream", nullptr); auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent({webrtc_transceiver}); waitable_event->Wait(); @@ -239,9 +264,22 @@ TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverInCallback) { auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); - auto webrtc_transceiver = - CreateWebRtcTransceiver(local_track_adapter->webrtc_track(), - "local_stream", "remote_track", "remote_stream"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + local_track_adapter->webrtc_track(), "local_stream", "remote_track", + "remote_stream", nullptr); + auto run_loop = AsyncInitializeSurfacerWithCallback( + {webrtc_transceiver}, + base::BindOnce( + &TransceiverStateSurfacerTest::ObtainStatesAndExpectInitialized, + base::Unretained(this), webrtc_transceiver)); + run_loop->Run(); +} + +TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverWithTransport) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + local_track_adapter->webrtc_track(), "local_stream", "remote_track", + "remote_stream", new rtc::RefCountedObject<FakeDtlsTransport>()); auto run_loop = AsyncInitializeSurfacerWithCallback( {webrtc_transceiver}, base::BindOnce(
diff --git a/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc b/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc index 44e8fcc..b532406 100644 --- a/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc +++ b/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc
@@ -262,7 +262,7 @@ track_adapter_map_->GetOrCreateLocalTrackAdapter(web_local_track); scoped_refptr<webrtc::MediaStreamTrackInterface> local_track = local_track_adapter->webrtc_track(); - rtc::scoped_refptr<webrtc::RtpSenderInterface> sender( + rtc::scoped_refptr<FakeRtpSender> sender( new rtc::RefCountedObject<FakeRtpSender>( local_track.get(), std::vector<std::string>({"local_stream"}))); // A requirement of WebRtcSet[Local/Remote]DescriptionObserverHandler is @@ -275,7 +275,7 @@ MockWebRtcAudioTrack::Create("remote_track"); scoped_refptr<webrtc::MediaStreamInterface> remote_stream( new rtc::RefCountedObject<MockMediaStream>("remote_stream")); - rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver( + rtc::scoped_refptr<FakeRtpReceiver> receiver( new rtc::RefCountedObject<FakeRtpReceiver>( remote_track.get(), std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>(
diff --git a/content/renderer/media_recorder/h264_encoder.cc b/content/renderer/media_recorder/h264_encoder.cc index e85bc53..924dfdf 100644 --- a/content/renderer/media_recorder/h264_encoder.cc +++ b/content/renderer/media_recorder/h264_encoder.cc
@@ -47,8 +47,8 @@ H264Encoder::~H264Encoder() { main_task_runner_->PostTask( FROM_HERE, - base::Bind(&H264Encoder::ShutdownEncoder, base::Passed(&encoding_thread_), - base::Passed(&openh264_encoder_))); + base::BindOnce(&H264Encoder::ShutdownEncoder, std::move(encoding_thread_), + std::move(openh264_encoder_))); } void H264Encoder::EncodeOnEncodingTaskRunner( @@ -106,9 +106,10 @@ const bool is_key_frame = info.eFrameType == videoFrameTypeIDR; origin_task_runner_->PostTask( - FROM_HERE, base::Bind(OnFrameEncodeCompleted, on_encoded_video_callback_, - video_params, base::Passed(&data), nullptr, - capture_timestamp, is_key_frame)); + FROM_HERE, + base::BindOnce(OnFrameEncodeCompleted, on_encoded_video_callback_, + video_params, std::move(data), nullptr, capture_timestamp, + is_key_frame)); } void H264Encoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 7aad270..f3a505f 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -3795,17 +3795,6 @@ ->UpdateThisAndAllClones(std::move(subresource_loader_factories)); } -void RenderFrameImpl::MarkInitiatorAsRequiringSeparateURLLoaderFactory( - const url::Origin& initiator_origin, - network::mojom::URLLoaderFactoryPtr url_loader_factory) { - DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); - - auto factory_bundle = std::make_unique<blink::URLLoaderFactoryBundleInfo>(); - factory_bundle->initiator_specific_factory_infos()[initiator_origin] = - url_loader_factory.PassInterface(); - UpdateSubresourceLoaderFactories(std::move(factory_bundle)); -} - void RenderFrameImpl::BindDevToolsAgent( blink::mojom::DevToolsAgentHostAssociatedPtrInfo host, blink::mojom::DevToolsAgentAssociatedRequest request) { @@ -5047,8 +5036,8 @@ // javascript onselectionchanged is triggered. // See crbug.com/729488 base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&RenderFrameImpl::ShowDeferredContextMenu, - weak_factory_.GetWeakPtr(), params)); + FROM_HERE, base::BindOnce(&RenderFrameImpl::ShowDeferredContextMenu, + weak_factory_.GetWeakPtr(), params)); #else ShowDeferredContextMenu(params); #endif
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 1c651ea..eb842be2 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -613,9 +613,6 @@ void UpdateSubresourceLoaderFactories( std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loader_factories) override; - void MarkInitiatorAsRequiringSeparateURLLoaderFactory( - const url::Origin& initiator_origin, - network::mojom::URLLoaderFactoryPtr url_loader_factory) override; void BindDevToolsAgent( blink::mojom::DevToolsAgentHostAssociatedPtrInfo host, blink::mojom::DevToolsAgentAssociatedRequest request) override;
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc index 0b5c55c..84b4e01 100644 --- a/content/renderer/render_frame_impl_browsertest.cc +++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -776,7 +776,7 @@ } private: - // mojom::DocumentInterfaceBroker + // blink::mojom::DocumentInterfaceBroker void GetFrameHostTestInterface( blink::mojom::FrameHostTestInterfaceRequest request) override { binder_callback_.Run(std::move(request)); @@ -853,9 +853,11 @@ } protected: + // blink::mojom::FrameHostTestInterface void Ping(const GURL& url, const std::string& event) override { ping_source_ = SourceAnnotation{url, event}; } + void GetName(GetNameCallback callback) override {} private: mojo::Binding<blink::mojom::FrameHostTestInterface> binding_;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 1c27abb..43b44e5 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -1102,6 +1102,12 @@ GetWebWidget()->BeginFrame(frame_time, record_main_frame_metrics); } +void RenderWidget::DidBeginMainFrame() { + if (!GetWebWidget()) + return; + GetWebWidget()->DidBeginFrame(); +} + void RenderWidget::RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) { // For widgets that are never visible, we don't start the compositor, so we
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 1443e70..a551d27 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -333,6 +333,7 @@ void SendScrollEndEventFromImplSide( cc::ElementId scroll_latched_element_id) override; void BeginMainFrame(base::TimeTicks frame_time) override; + void DidBeginMainFrame() override; void RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) override; void DidCommitAndDrawCompositorFrame() override;
diff --git a/content/shell/renderer/DEPS b/content/shell/renderer/DEPS index 244f046..8a6cc4d 100644 --- a/content/shell/renderer/DEPS +++ b/content/shell/renderer/DEPS
@@ -3,6 +3,5 @@ "+components/cdm", "+components/web_cache/renderer", "+components/plugins/renderer", - "+content/shell/test_runner", "+services/service_manager/public/cpp", ]
diff --git a/content/shell/renderer/web_test/DEPS b/content/shell/renderer/web_test/DEPS new file mode 100644 index 0000000..8967d67 --- /dev/null +++ b/content/shell/renderer/web_test/DEPS
@@ -0,0 +1,23 @@ +include_rules = [ + # Web test code is interconnected with test_runner. It would be nice to merge + # these two layers and drop extra abstractions between them. + "+content/shell/test_runner", + + # These files use //content/renderer/ for web test helpers, but those includes + # should not leak out to other parts of //content/shell unrelated to web + # tests. To avoid transitively including them to //content/shell through + # this directory, we avoid including them. + "-content/shell/test_runner/web_frame_test_proxy.h", + "-content/shell/test_runner/web_view_test_proxy.h", + "-content/shell/test_runner/web_widget_test_proxy.h", +] + +specific_include_rules = { + # cc files do not leak includes so they are allowed to reference the test + # helpers that include //content/renderer. + ".*\.cc": [ + "+content/shell/test_runner/web_frame_test_proxy.h", + "+content/shell/test_runner/web_view_test_proxy.h", + "+content/shell/test_runner/web_widget_test_proxy.h", + ], +}
diff --git a/content/shell/renderer/web_test/blink_test_runner.cc b/content/shell/renderer/web_test/blink_test_runner.cc index 838d015..3f2d825 100644 --- a/content/shell/renderer/web_test/blink_test_runner.cc +++ b/content/shell/renderer/web_test/blink_test_runner.cc
@@ -52,7 +52,6 @@ #include "content/shell/test_runner/pixel_dump.h" #include "content/shell/test_runner/web_test_interfaces.h" #include "content/shell/test_runner/web_test_runner.h" -#include "content/shell/test_runner/web_view_test_proxy.h" #include "media/base/audio_capturer_source.h" #include "media/base/audio_parameters.h" #include "media/capture/video_capturer_source.h"
diff --git a/content/shell/renderer/web_test/web_test_content_renderer_client.cc b/content/shell/renderer/web_test/web_test_content_renderer_client.cc index f8255052..3d2b7ee 100644 --- a/content/shell/renderer/web_test/web_test_content_renderer_client.cc +++ b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
@@ -39,7 +39,6 @@ #include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h" #include "third_party/blink/public/platform/web_runtime_features.h" #include "third_party/blink/public/web/blink.h" -#include "third_party/blink/public/web/web_frame_widget.h" #include "third_party/blink/public/web/web_plugin_params.h" #include "third_party/blink/public/web/web_testing_support.h" #include "third_party/blink/public/web/web_view.h"
diff --git a/content/shell/test_runner/DEPS b/content/shell/test_runner/DEPS index 2b3abf1..4495fd6 100644 --- a/content/shell/test_runner/DEPS +++ b/content/shell/test_runner/DEPS
@@ -1,7 +1,6 @@ include_rules = [ "+cc", "+content/public/test", - "+content/renderer", "+device/gamepad/public/cpp", "+device/gamepad/public/mojom", "+gin", @@ -22,3 +21,18 @@ "+ui/gfx", "+v8/include", ] + +# //content/renderer is allowed for web tests helpers, but should not leak out +# to other parts of //content/shell unrelated to web tests. So we limit access +# to things that are not used elsewhere. +specific_include_rules = { + # These classes subclass RenderView and RenderWidget to inject behaviour + # for web tests. + "web_(frame|view|widget)_test_proxy\.h": [ + "+content/renderer", + ], + # cc files will not leak //content/renderer includes. + ".*\.cc": [ + "+content/renderer", + ], +}
diff --git a/content/shell/test_runner/web_ax_object_proxy.cc b/content/shell/test_runner/web_ax_object_proxy.cc index 2860354..a4cfdd8d 100644 --- a/content/shell/test_runner/web_ax_object_proxy.cc +++ b/content/shell/test_runner/web_ax_object_proxy.cc
@@ -668,12 +668,6 @@ &WebAXObjectProxy::SelectionFocusOffset) .SetProperty("selectionFocusAffinity", &WebAXObjectProxy::SelectionFocusAffinity) - .SetProperty("selectionStart", &WebAXObjectProxy::SelectionStart) - .SetProperty("selectionEnd", &WebAXObjectProxy::SelectionEnd) - .SetProperty("selectionStartLineNumber", - &WebAXObjectProxy::SelectionStartLineNumber) - .SetProperty("selectionEndLineNumber", - &WebAXObjectProxy::SelectionEndLineNumber) .SetProperty("isAtomic", &WebAXObjectProxy::IsAtomic) .SetProperty("isAutofillAvailable", &WebAXObjectProxy::IsAutofillAvailable) @@ -1047,26 +1041,6 @@ : "downstream"; } -int WebAXObjectProxy::SelectionStart() { - accessibility_object_.UpdateLayoutAndCheckValidity(); - return accessibility_object_.SelectionStart(); -} - -int WebAXObjectProxy::SelectionEnd() { - accessibility_object_.UpdateLayoutAndCheckValidity(); - return accessibility_object_.SelectionEnd(); -} - -int WebAXObjectProxy::SelectionStartLineNumber() { - accessibility_object_.UpdateLayoutAndCheckValidity(); - return accessibility_object_.SelectionStartLineNumber(); -} - -int WebAXObjectProxy::SelectionEndLineNumber() { - accessibility_object_.UpdateLayoutAndCheckValidity(); - return accessibility_object_.SelectionEndLineNumber(); -} - bool WebAXObjectProxy::IsAtomic() { accessibility_object_.UpdateLayoutAndCheckValidity(); return accessibility_object_.LiveRegionAtomic();
diff --git a/content/test/data/accessibility/aria/aria-set-counts-with-tree-levels-expected-blink.txt b/content/test/data/accessibility/aria/aria-set-counts-with-tree-levels-expected-blink.txt new file mode 100644 index 0000000..d313e6f --- /dev/null +++ b/content/test/data/accessibility/aria/aria-set-counts-with-tree-levels-expected-blink.txt
@@ -0,0 +1,26 @@ +rootWebArea +++tree setSize=2 +++++treeItem name='Item A' hierarchicalLevel=1 setSize=2 posInSet=1 selected=false +++++++staticText name='Item A' +++++++++inlineTextBox name='Item A' +++++treeItem name='Item A1' hierarchicalLevel=2 setSize=2 posInSet=1 selected=false +++++++staticText name='Item A1' +++++++++inlineTextBox name='Item A1' +++++treeItem name='Item A1x' hierarchicalLevel=3 setSize=3 posInSet=1 selected=false +++++++staticText name='Item A1x' +++++++++inlineTextBox name='Item A1x' +++++treeItem name='Item A1y' hierarchicalLevel=3 setSize=3 posInSet=2 selected=false +++++++staticText name='Item A1y' +++++++++inlineTextBox name='Item A1y' +++++treeItem name='Item A1z' hierarchicalLevel=3 setSize=3 posInSet=3 selected=false +++++++staticText name='Item A1z' +++++++++inlineTextBox name='Item A1z' +++++treeItem name='Item A2' hierarchicalLevel=2 setSize=2 posInSet=2 selected=false +++++++staticText name='Item A2' +++++++++inlineTextBox name='Item A2' +++++treeItem name='Item B' hierarchicalLevel=1 setSize=2 posInSet=2 selected=false +++++++staticText name='Item B' +++++++++inlineTextBox name='Item B' +++++treeItem name='Item B1' hierarchicalLevel=2 setSize=1 posInSet=1 selected=false +++++++staticText name='Item B1' +++++++++inlineTextBox name='Item B1'
diff --git a/content/test/data/accessibility/aria/aria-set-counts-with-tree-levels.html b/content/test/data/accessibility/aria/aria-set-counts-with-tree-levels.html new file mode 100644 index 0000000..0a48def --- /dev/null +++ b/content/test/data/accessibility/aria/aria-set-counts-with-tree-levels.html
@@ -0,0 +1,25 @@ +<!-- +@BLINK-ALLOW:setSize* +@BLINK-ALLOW:posInSet* +@BLINK-DENY:setSize=0 +@BLINK-DENY:posInSet=0 +--> +<!-- According to CORE-AAM: + For role="treeitem", walk the tree backward and forward until the explicit or + computed level becomes less than the current item's level. Count items only + if they are at the same level as the current item. +--> +<html> +<body> +<div role="tree"> + <div tabIndex="0" aria-level="1" aria-setsize="2" aria-posinset="1" role="treeitem">Item A</div> + <div tabIndex="0" aria-level="2" aria-setsize="2" aria-posinset="1" role="treeitem">Item A1</div> + <div tabIndex="0" aria-level="3" aria-setsize="3" aria-posinset="1" role="treeitem">Item A1x</div> + <div tabIndex="0" aria-level="3" aria-setsize="3" aria-posinset="2" role="treeitem">Item A1y</div> + <div tabIndex="0" aria-level="3" aria-setsize="3" aria-posinset="3" role="treeitem">Item A1z</div> + <div tabIndex="0" aria-level="2" aria-setsize="2" aria-posinset="2" role="treeitem">Item A2</div> + <div tabIndex="0" aria-level="1" aria-setsize="2" aria-posinset="2" role="treeitem">Item B</div> + <div tabIndex="0" aria-level="2" aria-setsize="1" aria-posinset="1" role="treeitem">Item B1</div> +</div> +</body> +</html>
diff --git a/content/test/data/accessibility/event/add-subtree-expected-win.txt b/content/test/data/accessibility/event/add-subtree-expected-win.txt index 57b78be..de590142 100644 --- a/content/test/data/accessibility/event/add-subtree-expected-win.txt +++ b/content/test/data/accessibility/event/add-subtree-expected-win.txt
@@ -1,3 +1,3 @@ EVENT_OBJECT_REORDER on <ul> role=ROLE_SYSTEM_LIST SetSize=3 EVENT_OBJECT_SHOW on <li> role=ROLE_SYSTEM_LISTITEM PosInSet=3 SetSize=3 -IA2_EVENT_TEXT_INSERTED on <ul> role=ROLE_SYSTEM_LIST SetSize=3 new_text={'<obj>' start=2 end=3} +IA2_EVENT_TEXT_INSERTED on <ul> role=ROLE_SYSTEM_LIST SetSize=2 new_text={'<obj>' start=2 end=3}
diff --git a/content/test/data/accessibility/event/remove-hidden-attribute-expected-win.txt b/content/test/data/accessibility/event/remove-hidden-attribute-expected-win.txt index 73cb5b6a..7c485e7 100644 --- a/content/test/data/accessibility/event/remove-hidden-attribute-expected-win.txt +++ b/content/test/data/accessibility/event/remove-hidden-attribute-expected-win.txt
@@ -1,3 +1,3 @@ EVENT_OBJECT_REORDER on <div> role=ROLE_SYSTEM_LIST SetSize=3 EVENT_OBJECT_SHOW on <div#item3> role=ROLE_SYSTEM_LISTITEM name="Item 3" PosInSet=3 SetSize=3 -IA2_EVENT_TEXT_INSERTED on <div> role=ROLE_SYSTEM_LIST SetSize=3 new_text={'<obj>' start=2 end=3} +IA2_EVENT_TEXT_INSERTED on <div> role=ROLE_SYSTEM_LIST SetSize=2 new_text={'<obj>' start=2 end=3}
diff --git a/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt b/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt index 3dadf9f..1200268a 100644 --- a/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt +++ b/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt
@@ -1,3 +1,3 @@ EVENT_OBJECT_REORDER on <ul> role=ROLE_SYSTEM_LIST SetSize=3 EVENT_OBJECT_SHOW on <li#item3> role=ROLE_SYSTEM_LISTITEM PosInSet=3 SetSize=3 -IA2_EVENT_TEXT_INSERTED on <ul> role=ROLE_SYSTEM_LIST SetSize=3 new_text={'<obj>' start=2 end=3} +IA2_EVENT_TEXT_INSERTED on <ul> role=ROLE_SYSTEM_LIST SetSize=2 new_text={'<obj>' start=2 end=3}
diff --git a/content/test/data/media/session/image_test_page.html b/content/test/data/media/session/image_test_page.html new file mode 100644 index 0000000..207e02e8 --- /dev/null +++ b/content/test/data/media/session/image_test_page.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Media Session Image Test Page</title> +<body> +<script> +navigator.mediaSession.metadata = new MediaMetadata({ + artwork: [ + {src: "test_image.jpg", sizes: "1x1", type: "image/jpeg"}, + {src: "test_image.jpg", sizes: "10x10", type: "image/jpeg"} + ] +}); +</script> +<video id="video" controls> + <source src="video-6seconds.webm"> +</video> +</body>
diff --git a/content/test/data/media/session/test_image.jpg b/content/test/data/media/session/test_image.jpg new file mode 100644 index 0000000..da757f73 --- /dev/null +++ b/content/test/data/media/session/test_image.jpg Binary files differ
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc index f215155..af60d4c 100644 --- a/content/test/navigation_simulator_impl.cc +++ b/content/test/navigation_simulator_impl.cc
@@ -313,7 +313,6 @@ : web_contents->GetMainFrame()->frame_tree_node()), request_(nullptr), navigation_url_(original_url), - socket_address_("2001:db8::1", 80), initial_method_("GET"), browser_initiated_(browser_initiated), transition_(browser_initiated ? ui::PAGE_TRANSITION_TYPED @@ -321,6 +320,10 @@ contents_mime_type_("text/html"), load_url_params_(nullptr), weak_factory_(this) { + net::IPAddress address; + CHECK(address.AssignFromIPLiteral("2001:db8::1")); + remote_endpoint_ = net::IPEndPoint(address, 80); + // For renderer-initiated navigation, the RenderFrame must be initialized. Do // it if it hasn't happened yet. if (!browser_initiated) @@ -359,7 +362,7 @@ CHECK_EQ(frame_tree_node_, request_->frame_tree_node()); state_ = STARTED; navigation_url_ = handle->GetURL(); - // |socket_address_| cannot be inferred from the request. + // |remote_endpoint_| cannot be inferred from the request. // |initial_method_| cannot be set after the request has started. browser_initiated_ = request_->browser_initiated(); // |same_document_| should always be false here. @@ -508,7 +511,7 @@ if (frame_tree_node_->navigation_request()) { static_cast<TestRenderFrameHost*>(frame_tree_node_->current_frame_host()) ->PrepareForCommitDeprecatedForNavigationSimulator( - socket_address_, is_signed_exchange_inner_response_); + remote_endpoint_, is_signed_exchange_inner_response_); } // Synchronous failure can cause the navigation to finish here. @@ -810,10 +813,10 @@ } void NavigationSimulatorImpl::SetSocketAddress( - const net::HostPortPair& socket_address) { + const net::IPEndPoint& remote_endpoint) { CHECK_LE(state_, STARTED) << "The socket address cannot be set after the " "navigation has committed or failed"; - socket_address_ = socket_address; + remote_endpoint_ = remote_endpoint; } void NavigationSimulatorImpl::SetIsSignedExchangeInnerResponse(
diff --git a/content/test/navigation_simulator_impl.h b/content/test/navigation_simulator_impl.h index a436e99..c2b721a3 100644 --- a/content/test/navigation_simulator_impl.h +++ b/content/test/navigation_simulator_impl.h
@@ -18,6 +18,7 @@ #include "content/public/test/navigation_simulator.h" #include "mojo/public/cpp/bindings/associated_interface_request.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h" #include "url/gurl.h" @@ -78,7 +79,7 @@ void SetMethod(const std::string& method) override; void SetIsFormSubmission(bool is_form_submission) override; void SetReferrer(const Referrer& referrer) override; - void SetSocketAddress(const net::HostPortPair& socket_address) override; + void SetSocketAddress(const net::IPEndPoint& remote_endpoint) override; void SetIsSignedExchangeInnerResponse( bool is_signed_exchange_inner_response) override; void SetInterfaceProviderRequest( @@ -213,7 +214,7 @@ // Note: additional parameters to modify the navigation should be properly // initialized (if needed) in InitializeFromStartedRequest. GURL navigation_url_; - net::HostPortPair socket_address_; + net::IPEndPoint remote_endpoint_; bool is_signed_exchange_inner_response_ = false; std::string initial_method_; bool is_form_submission_ = false;
diff --git a/content/test/stub_layer_tree_view_delegate.h b/content/test/stub_layer_tree_view_delegate.h index a75b0eb..eddef3c 100644 --- a/content/test/stub_layer_tree_view_delegate.h +++ b/content/test/stub_layer_tree_view_delegate.h
@@ -26,6 +26,7 @@ void SendScrollEndEventFromImplSide( cc::ElementId scroll_latched_element_id) override {} void BeginMainFrame(base::TimeTicks frame_time) override {} + void DidBeginMainFrame() override {} void RecordStartOfFrameMetrics() override {} void RecordEndOfFrameMetrics(base::TimeTicks) override {} void RequestNewLayerTreeFrameSink(
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index 883f2bf8..b7cf360 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -26,6 +26,7 @@ #include "content/test/test_render_view_host.h" #include "content/test/test_render_widget_host.h" #include "mojo/public/cpp/bindings/interface_request.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" @@ -365,26 +366,26 @@ } void TestRenderFrameHost::PrepareForCommit() { - PrepareForCommitInternal(GURL(), net::HostPortPair(), + PrepareForCommitInternal(GURL(), net::IPEndPoint(), /* is_signed_exchange_inner_response=*/false); } void TestRenderFrameHost::PrepareForCommitDeprecatedForNavigationSimulator( - const net::HostPortPair& socket_address, + const net::IPEndPoint& remote_endpoint, bool is_signed_exchange_inner_response) { - PrepareForCommitInternal(GURL(), socket_address, + PrepareForCommitInternal(GURL(), remote_endpoint, is_signed_exchange_inner_response); } void TestRenderFrameHost::PrepareForCommitWithServerRedirect( const GURL& redirect_url) { - PrepareForCommitInternal(redirect_url, net::HostPortPair(), + PrepareForCommitInternal(redirect_url, net::IPEndPoint(), /* is_signed_exchange_inner_response=*/false); } void TestRenderFrameHost::PrepareForCommitInternal( const GURL& redirect_url, - const net::HostPortPair& socket_address, + const net::IPEndPoint& remote_endpoint, bool is_signed_exchange_inner_response) { NavigationRequest* request = frame_tree_node_->navigation_request(); CHECK(request); @@ -423,7 +424,7 @@ // Simulate the network stack commit. scoped_refptr<network::ResourceResponse> response( new network::ResourceResponse); - response->head.socket_address = socket_address; + response->head.remote_endpoint = remote_endpoint; response->head.is_signed_exchange_inner_response = is_signed_exchange_inner_response; // TODO(carlosk): Ideally, it should be possible someday to
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h index 73a0a2d..335a105 100644 --- a/content/test/test_render_frame_host.h +++ b/content/test/test_render_frame_host.h
@@ -26,7 +26,7 @@ struct FrameHostMsg_DidCommitProvisionalLoad_Params; namespace net { -class HostPortPair; +class IPEndPoint; } namespace content { @@ -146,7 +146,7 @@ // TODO(clamy): Have NavigationSimulator make the relevant calls directly and // remove this function. void PrepareForCommitDeprecatedForNavigationSimulator( - const net::HostPortPair& socket_address, + const net::IPEndPoint& remote_endpoint, bool is_signed_exchange_inner_response); // This method does the same as PrepareForCommit. @@ -247,7 +247,7 @@ const ModificationCallback& callback); void PrepareForCommitInternal(const GURL& redirect_url, - const net::HostPortPair& socket_address, + const net::IPEndPoint& remote_endpoint, bool is_signed_exchange_inner_response); // Computes the page ID for a pending navigation in this RenderFrameHost;
diff --git a/docs/android_build_instructions.md b/docs/android_build_instructions.md index b18614b..702d2c9 100644 --- a/docs/android_build_instructions.md +++ b/docs/android_build_instructions.md
@@ -353,11 +353,6 @@ * What it does: Uses multiple `.so` files instead of just one (faster links) * `is_java_debug = true` *(default=`is_debug`)* * What it does: Disables ProGuard (slow build step) - * `enable_incremental_javac = true` *(default=`false`)* - * What it does: Tries to compile only a subset of `.java` files within an - `android_library` for subsequent builds. - * Can cause infrequent (once a month-ish) failures due to not recompiling a - class that should be recompiled. #### Incremental Install "Incremental install" uses reflection and side-loading to speed up the edit
diff --git a/docs/win_cross.md b/docs/win_cross.md index ffea53d..ef55dc3 100644 --- a/docs/win_cross.md +++ b/docs/win_cross.md
@@ -6,8 +6,6 @@ What does *not* work: -* goma. Sorry. ([internal bug](http://b/64390790)) You can use the - [jumbo build](jumbo.md) for faster build times. * 64-bit renderer processes don't use V8 snapshots, slowing down their startup ([bug](https://crbug.com/803591)) * on Mac hosts, building a 32-bit chrome ([bug](https://crbug.com/794838)) @@ -77,6 +75,13 @@ ninja -C out/gnwin base_unittests.exe +## Goma + +For now, one needs to use the rbe backend, not the (default) borg backend: + + goma_auth.py login + GOMA_STUBBY_PROXY_IP_ADDRESS=rbe-staging1.endpoints.cxx-compiler-service.cloud.goog GOMA_USE_CASE=rbe-staging goma_ctl.py ensure_start + ## Copying and running chrome A convenient way to copy chrome over to a Windows box is to build the
diff --git a/extensions/browser/api/idle/BUILD.gn b/extensions/browser/api/idle/BUILD.gn index a635a4f0..edc5714 100644 --- a/extensions/browser/api/idle/BUILD.gn +++ b/extensions/browser/api/idle/BUILD.gn
@@ -21,7 +21,6 @@ deps = [ "//extensions/common/api", - "//ui/base/idle", ] public_deps = [
diff --git a/extensions/browser/api/web_request/web_request_info.cc b/extensions/browser/api/web_request/web_request_info.cc index b1aa4b5..5c32809 100644 --- a/extensions/browser/api/web_request/web_request_info.cc +++ b/extensions/browser/api/web_request/web_request_info.cc
@@ -19,6 +19,7 @@ #include "extensions/browser/extension_navigation_ui_data.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h" +#include "net/base/ip_endpoint.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" @@ -346,7 +347,7 @@ net::URLRequest* url_request) { response_code = url_request->GetResponseCode(); response_headers = url_request->response_headers(); - response_ip = url_request->GetSocketAddress().host(); + response_ip = url_request->GetResponseRemoteEndpoint().ToStringWithoutPort(); response_from_cache = url_request->was_cached(); } @@ -355,7 +356,7 @@ response_headers = response.headers; if (response_headers) response_code = response_headers->response_code(); - response_ip = response.socket_address.host(); + response_ip = response.remote_endpoint.ToStringWithoutPort(); response_from_cache = response.was_fetched_via_cache; }
diff --git a/extensions/browser/api/web_request/web_request_proxying_websocket.cc b/extensions/browser/api/web_request/web_request_proxying_websocket.cc index 856d4bb..3aa4ad81 100644 --- a/extensions/browser/api/web_request/web_request_proxying_websocket.cc +++ b/extensions/browser/api/web_request/web_request_proxying_websocket.cc
@@ -9,6 +9,7 @@ #include "content/public/browser/browser_thread.h" #include "extensions/browser/extension_navigation_ui_data.h" #include "mojo/public/cpp/bindings/strong_binding.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_util.h" namespace extensions { @@ -165,7 +166,7 @@ response_.headers->AddHeader(header->name + ": " + header->value); } } - response_.socket_address = response->socket_address; + response_.remote_endpoint = response->remote_endpoint; forwarding_client_->OnFinishOpeningHandshake(std::move(response)); @@ -232,7 +233,7 @@ void WebRequestProxyingWebSocket::OnAuthRequired( const scoped_refptr<net::AuthChallengeInfo>& auth_info, const scoped_refptr<net::HttpResponseHeaders>& headers, - const net::HostPortPair& socket_address, + const net::IPEndPoint& remote_endpoint, OnAuthRequiredCallback callback) { if (!auth_info || !callback) { OnError(net::ERR_FAILED); @@ -240,7 +241,7 @@ } response_.headers = headers; - response_.socket_address = socket_address; + response_.remote_endpoint = remote_endpoint; auth_required_callback_ = std::move(callback); auto continuation = base::BindRepeating(
diff --git a/extensions/browser/api/web_request/web_request_proxying_websocket.h b/extensions/browser/api/web_request/web_request_proxying_websocket.h index 88ff6f3..173a89d 100644 --- a/extensions/browser/api/web_request/web_request_proxying_websocket.h +++ b/extensions/browser/api/web_request/web_request_proxying_websocket.h
@@ -24,6 +24,10 @@ #include "url/gurl.h" #include "url/origin.h" +namespace net { +class IPEndPoint; +} // namespace net + namespace extensions { // A WebRequestProxyingWebSocket proxies a WebSocket connection and dispatches @@ -81,7 +85,7 @@ // mojom::AuthenticationHandler method: void OnAuthRequired(const scoped_refptr<net::AuthChallengeInfo>& auth_info, const scoped_refptr<net::HttpResponseHeaders>& headers, - const net::HostPortPair& socket_address, + const net::IPEndPoint& remote_endpoint, OnAuthRequiredCallback callback) override; static void StartProxying(
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.cc b/extensions/browser/guest_view/app_view/app_view_guest.cc index 918df08..b075617 100644 --- a/extensions/browser/guest_view/app_view/app_view_guest.cc +++ b/extensions/browser/guest_view/app_view/app_view_guest.cc
@@ -117,7 +117,9 @@ AppViewGuest::~AppViewGuest() { } -bool AppViewGuest::HandleContextMenu(const content::ContextMenuParams& params) { +bool AppViewGuest::HandleContextMenu( + content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) { if (app_view_guest_delegate_) { return app_view_guest_delegate_->HandleContextMenu(web_contents(), params); }
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.h b/extensions/browser/guest_view/app_view/app_view_guest.h index a44c3b9..0fea3d0 100644 --- a/extensions/browser/guest_view/app_view/app_view_guest.h +++ b/extensions/browser/guest_view/app_view/app_view_guest.h
@@ -60,7 +60,8 @@ int GetTaskPrefix() const final; // content::WebContentsDelegate implementation. - bool HandleContextMenu(const content::ContextMenuParams& params) final; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) final; void RequestMediaAccessPermission( content::WebContents* web_contents, const content::MediaStreamRequest& request,
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.cc b/extensions/browser/guest_view/extension_options/extension_options_guest.cc index d69bbe9..0890def7 100644 --- a/extensions/browser/guest_view/extension_options/extension_options_guest.cc +++ b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
@@ -199,6 +199,7 @@ } bool ExtensionOptionsGuest::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { if (!extension_options_guest_delegate_) return false;
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.h b/extensions/browser/guest_view/extension_options/extension_options_guest.h index 7eb02c1..bdeb2d5 100644 --- a/extensions/browser/guest_view/extension_options/extension_options_guest.h +++ b/extensions/browser/guest_view/extension_options/extension_options_guest.h
@@ -48,7 +48,8 @@ content::WebContents* source, const content::OpenURLParams& params) final; void CloseContents(content::WebContents* source) final; - bool HandleContextMenu(const content::ContextMenuParams& params) final; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) final; bool ShouldCreateWebContents( content::WebContents* web_contents, content::RenderFrameHost* opener,
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc index f5696fd..7677eb8a 100644 --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc +++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
@@ -286,6 +286,7 @@ } bool MimeHandlerViewGuest::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { return delegate_ && delegate_->HandleContextMenu(web_contents(), params); }
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h index a448bc2..a0e702b 100644 --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h +++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
@@ -125,7 +125,8 @@ const content::OpenURLParams& params) final; void NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) final; - bool HandleContextMenu(const content::ContextMenuParams& params) final; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) final; bool PreHandleGestureEvent(content::WebContents* source, const blink::WebGestureEvent& event) final; content::JavaScriptDialogManager* GetJavaScriptDialogManager(
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index 884534b..a554840 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -605,6 +605,7 @@ } bool WebViewGuest::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { return web_view_guest_delegate_ && web_view_guest_delegate_->HandleContextMenu(params);
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h index 691ed1f..f155d67 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.h +++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -212,7 +212,8 @@ int32_t line_no, const base::string16& source_id) final; void CloseContents(content::WebContents* source) final; - bool HandleContextMenu(const content::ContextMenuParams& params) final; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) final; bool HandleKeyboardEvent(content::WebContents* source, const content::NativeWebKeyboardEvent& event) final; void LoadProgressChanged(content::WebContents* source, double progress) final;
diff --git a/extensions/common/api/declarative_net_request.idl b/extensions/common/api/declarative_net_request.idl index de1c1a1..34cf471f 100644 --- a/extensions/common/api/declarative_net_request.idl +++ b/extensions/common/api/declarative_net_request.idl
@@ -58,8 +58,8 @@ // specifies the start of a (sub-)domain of the URL. // // <b>'^'</b> : Separator character: This matches anything except a letter, a - // digit or one of the following: _ - . %. - // + // digit or one of the following: _ - . %. This can also match + // the end of the URL. // // Therefore <code>urlFilter</code> is composed of the following parts: // (optional Left/Domain name anchor) + pattern + (optional Right anchor).
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc index 621c32a..160283d 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura.cc +++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -234,12 +234,12 @@ ui::EventDispatchDetails ShellDesktopControllerAura::DispatchKeyEventPostIME( ui::KeyEvent* key_event, - base::OnceCallback<void(bool)> ack_callback) { + DispatchKeyEventPostIMECallback callback) { if (key_event->target()) { aura::WindowTreeHost* host = static_cast<aura::Window*>(key_event->target()) ->GetRootWindow() ->GetHost(); - return host->DispatchKeyEventPostIME(key_event, std::move(ack_callback)); + return host->DispatchKeyEventPostIME(key_event, std::move(callback)); } // Send the key event to the focused window. @@ -247,11 +247,11 @@ const_cast<aura::Window*>(focus_controller_->GetActiveWindow()); if (active_window) { return active_window->GetRootWindow()->GetHost()->DispatchKeyEventPostIME( - key_event, std::move(ack_callback)); + key_event, std::move(callback)); } return GetPrimaryHost()->DispatchKeyEventPostIME(key_event, - std::move(ack_callback)); + std::move(callback)); } void ShellDesktopControllerAura::OnKeepAliveStateChanged(
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.h b/extensions/shell/browser/shell_desktop_controller_aura.h index bddf4df..3617a47 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura.h +++ b/extensions/shell/browser/shell_desktop_controller_aura.h
@@ -98,7 +98,7 @@ // ui::internal::InputMethodDelegate: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* key_event, - base::OnceCallback<void(bool)> ack_callback) override; + DispatchKeyEventPostIMECallback callback) override; // KeepAliveStateObserver: void OnKeepAliveStateChanged(bool is_keeping_alive) override;
diff --git a/fuchsia/engine/browser/frame_impl_browsertest.cc b/fuchsia/engine/browser/frame_impl_browsertest.cc index a6d70ea..0c8ba13 100644 --- a/fuchsia/engine/browser/frame_impl_browsertest.cc +++ b/fuchsia/engine/browser/frame_impl_browsertest.cc
@@ -161,6 +161,28 @@ EXPECT_FALSE(frame); } +IN_PROC_BROWSER_TEST_F(FrameImplTest, ContextDeletedBeforeFrameWithView) { + chromium::web::FramePtr frame = CreateFrame(); + EXPECT_TRUE(frame); + + zx::eventpair import_token; + fuchsia::ui::gfx::ExportToken export_token; + ASSERT_EQ(zx::eventpair::create(0, &import_token, &export_token.value), + ZX_OK); + + frame->CreateView(std::move(export_token)); + base::RunLoop().RunUntilIdle(); + + base::RunLoop run_loop; + frame.set_error_handler([&run_loop](zx_status_t status) { + EXPECT_EQ(status, ZX_ERR_PEER_CLOSED); + run_loop.Quit(); + }); + context().Unbind(); + run_loop.Run(); + EXPECT_FALSE(frame); +} + IN_PROC_BROWSER_TEST_F(FrameImplTest, GoBackAndForward) { chromium::web::FramePtr frame = CreateFrame(); chromium::web::NavigationControllerPtr controller;
diff --git a/fuchsia/runners/BUILD.gn b/fuchsia/runners/BUILD.gn index e103204..0da5786 100644 --- a/fuchsia/runners/BUILD.gn +++ b/fuchsia/runners/BUILD.gn
@@ -89,14 +89,11 @@ sources = [ "cast/fake_application_config_manager.cc", "cast/fake_application_config_manager.h", - "cast/test_common.cc", - "cast/test_common.h", ] public_deps = [ "//base", "//fuchsia:cast_fidl", - "//net:test_support", - "//third_party/fuchsia-sdk/sdk:sys", + "//url", ] visibility = [ ":*" ] }
diff --git a/fuchsia/runners/cast/cast_runner.cc b/fuchsia/runners/cast/cast_runner.cc index 0acfaab..45810131 100644 --- a/fuchsia/runners/cast/cast_runner.cc +++ b/fuchsia/runners/cast/cast_runner.cc
@@ -82,11 +82,6 @@ chromium::cast::ApplicationConfigPtr app_config) { if (!app_config) { DLOG(WARNING) << "No ApplicationConfig was found."; - - // For test purposes, we need to call RegisterComponent even if there is no - // URL to launch. - // TODO: Replace this hack, e.g. with an test-specific callback. - RegisterComponent(std::unique_ptr<WebComponent>(nullptr)); return; }
diff --git a/fuchsia/runners/cast/cast_runner_integration_test.cc b/fuchsia/runners/cast/cast_runner_integration_test.cc index 1ffcd36e..df0e76c 100644 --- a/fuchsia/runners/cast/cast_runner_integration_test.cc +++ b/fuchsia/runners/cast/cast_runner_integration_test.cc
@@ -6,10 +6,12 @@ #include <lib/zx/channel.h> #include "base/fuchsia/fuchsia_logging.h" +#include "base/fuchsia/scoped_service_binding.h" #include "base/fuchsia/service_directory.h" #include "base/fuchsia/service_directory_client.h" #include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" +#include "base/test/bind_test_util.h" #include "base/test/test_timeouts.h" #include "fuchsia/base/fit_adapter.h" #include "fuchsia/base/result_receiver.h" @@ -17,7 +19,6 @@ #include "fuchsia/fidl/chromium/web/cpp/fidl.h" #include "fuchsia/runners/cast/cast_runner.h" #include "fuchsia/runners/cast/fake_application_config_manager.h" -#include "fuchsia/runners/cast/test_common.h" #include "fuchsia/runners/common/web_component.h" #include "fuchsia/runners/common/web_content_runner.h" #include "net/test/embedded_test_server/default_handlers.h" @@ -31,43 +32,72 @@ FILE_PATH_LITERAL("fuchsia/runners/cast/testdata"); void ComponentErrorHandler(zx_status_t status) { - ZX_LOG(ERROR, status) << "Component launch failed."; + ZX_LOG(ERROR, status) << "Component launch failed"; ADD_FAILURE(); } +class FakeCastChannel : public chromium::cast::CastChannel { + public: + FakeCastChannel() = default; + + // chromium::web::CastChannel implementation. + void OnOpened(fidl::InterfaceHandle<chromium::web::MessagePort> channel, + OnOpenedCallback callback_ignored) override { + // |callback_ignored| is dropped because these tests don't exercise multiple + // channel lifetimes. + connected_channel_ = channel.Bind(); + + if (on_channel_connected_) + std::move(on_channel_connected_).Run(); + } + + chromium::web::MessagePort* connected_channel() const { + // Return nullptr if |connected_channel_| is not currently bound. + return connected_channel_ ? connected_channel_.get() : nullptr; + } + + void set_on_channel_connected(base::OnceClosure on_channel_connected) { + on_channel_connected_ = std::move(on_channel_connected); + } + + protected: + // The connected Cast Channel. + chromium::web::MessagePortPtr connected_channel_; + + // A pending on-connect callback, to be invoked once a Cast Channel is + // received. + base::OnceClosure on_channel_connected_; + + DISALLOW_COPY_AND_ASSIGN(FakeCastChannel); +}; + } // namespace -class CastRunnerIntegrationTest : public testing::Test, - public chromium::cast::CastChannel { +class CastRunnerIntegrationTest : public testing::Test { public: CastRunnerIntegrationTest() : run_timeout_(TestTimeouts::action_timeout()), - cast_channel_binding_(this) { + app_config_binding_(&app_config_manager_) { // Create a new test ServiceDirectory, and ServiceDirectoryClient connected // to it, for tests to use to drive the CastRunner. fidl::InterfaceHandle<fuchsia::io::Directory> directory; - test_services_ = std::make_unique<base::fuchsia::ServiceDirectory>( + public_services_ = std::make_unique<base::fuchsia::ServiceDirectory>( directory.NewRequest()); - test_services_client_ = - std::make_unique<base::fuchsia::ServiceDirectoryClient>( - std::move(directory)); // Create the AppConfigManager. - app_config_binding_ = std::make_unique< - fidl::Binding<chromium::cast::ApplicationConfigManager>>( - &app_config_manager_); - chromium::cast::ApplicationConfigManagerPtr app_config_manager_interface; - app_config_binding_->Bind(app_config_manager_interface.NewRequest()); + chromium::cast::ApplicationConfigManagerPtr app_config_manager_ptr; + app_config_binding_.Bind(app_config_manager_ptr.NewRequest()); // Create the CastRunner, published into |test_services_|. cast_runner_ = std::make_unique<CastRunner>( - test_services_.get(), WebContentRunner::CreateDefaultWebContext(), - std::move(app_config_manager_interface), - cast_runner_run_loop_.QuitClosure()); + public_services_.get(), WebContentRunner::CreateDefaultWebContext(), + std::move(app_config_manager_ptr), cast_runner_run_loop_.QuitClosure()); // Connect to the CastRunner's fuchsia.sys.Runner interface. + base::fuchsia::ServiceDirectoryClient public_directory_client( + std::move(directory)); cast_runner_ptr_ = - test_services_client_->ConnectToService<fuchsia::sys::Runner>(); + public_directory_client.ConnectToService<fuchsia::sys::Runner>(); cast_runner_ptr_.set_error_handler([this](zx_status_t status) { ZX_LOG(ERROR, status) << "CastRunner closed channel."; ADD_FAILURE(); @@ -88,23 +118,48 @@ } void WaitUntilCastChannelOpened() { - if (connected_channel_) + if (cast_channel_.connected_channel()) return; base::RunLoop run_loop; - on_channel_connected_cb_ = run_loop.QuitClosure(); + cast_channel_.set_on_channel_connected(run_loop.QuitClosure()); run_loop.Run(); + + DCHECK(cast_channel_.connected_channel()); } - // chromium::web::CastChannel implementation. - void OnOpened(fidl::InterfaceHandle<chromium::web::MessagePort> channel, - OnOpenedCallback callback_ignored) override { - // |callback_ignored| is dropped because these tests don't exercise multiple - // channel lifetimes. - connected_channel_ = channel.Bind(); + fuchsia::sys::ComponentControllerPtr StartCastComponent( + base::StringPiece component_url) { + DCHECK(!component_services_); - if (on_channel_connected_cb_) - std::move(on_channel_connected_cb_).Run(); + // Create a ServiceDirectory and publish the CastChannel into it. + fidl::InterfaceHandle<fuchsia::io::Directory> directory; + component_services_ = std::make_unique<base::fuchsia::ServiceDirectory>( + directory.NewRequest()); + cast_channel_binding_ = std::make_unique< + base::fuchsia::ScopedServiceBinding<chromium::cast::CastChannel>>( + component_services_.get(), &cast_channel_); + + // Configure the Runner, including a service directory channel to publish + // services to. + fuchsia::sys::StartupInfo startup_info; + startup_info.launch_info.url = component_url.as_string(); + + // Place the ServiceDirectory in the |flat_namespace|. + startup_info.flat_namespace.paths.emplace_back("/svc"); + startup_info.flat_namespace.directories.emplace_back( + directory.TakeChannel()); + + fuchsia::sys::Package package; + package.resolved_url = component_url.as_string(); + + fuchsia::sys::ComponentControllerPtr component_controller; + cast_runner_ptr_->StartComponent(std::move(package), + std::move(startup_info), + component_controller.NewRequest()); + + EXPECT_TRUE(component_controller.is_bound()); + return component_controller; } protected: @@ -114,22 +169,17 @@ // Returns fake Cast application information to the CastRunner. FakeApplicationConfigManager app_config_manager_; - std::unique_ptr<fidl::Binding<chromium::cast::ApplicationConfigManager>> - app_config_binding_; + fidl::Binding<chromium::cast::ApplicationConfigManager> app_config_binding_; - // The connected Cast Channel. - chromium::web::MessagePortPtr connected_channel_; - - // A pending on-connect callback, to be invoked once a Cast Channel is - // received. - base::OnceClosure on_channel_connected_cb_; - - // Receives connected channels from the CastRunner. - fidl::Binding<chromium::cast::CastChannel> cast_channel_binding_; + // Incoming service directory, CastChannel and service bindings. + std::unique_ptr<base::fuchsia::ServiceDirectory> component_services_; + FakeCastChannel cast_channel_; + std::unique_ptr< + base::fuchsia::ScopedServiceBinding<chromium::cast::CastChannel>> + cast_channel_binding_; // ServiceDirectory into which the CastRunner will publish itself. - std::unique_ptr<base::fuchsia::ServiceDirectory> test_services_; - std::unique_ptr<base::fuchsia::ServiceDirectoryClient> test_services_client_; + std::unique_ptr<base::fuchsia::ServiceDirectory> public_services_; std::unique_ptr<CastRunner> cast_runner_; fuchsia::sys::RunnerPtr cast_runner_ptr_; @@ -147,11 +197,9 @@ test_server_.GetURL(kBlankAppPath)); // Launch the test-app component. - fuchsia::sys::ComponentControllerPtr component_controller_ptr; - base::fuchsia::ServiceDirectoryClient services_client(StartCastComponent( - base::StringPrintf("cast:%s", kBlankAppId), &cast_runner_ptr_, - component_controller_ptr.NewRequest(), &cast_channel_binding_)); - component_controller_ptr.set_error_handler(&ComponentErrorHandler); + fuchsia::sys::ComponentControllerPtr component_controller = + StartCastComponent(base::StringPrintf("cast:%s", kBlankAppId)); + component_controller.set_error_handler(&ComponentErrorHandler); // Access the NavigationController from the WebComponent. The test will hang // here if no WebComponent was created. @@ -179,30 +227,32 @@ EXPECT_EQ(nav_entry->get()->url, test_server_.GetURL(kBlankAppPath).spec()); } - // Verify that the component is torn down when |component_controller_ptr| is + // Verify that the component is torn down when |component_controller| is // unbound, by observing the destruction of its child Interfaces. base::RunLoop destruction_run_loop; nav_controller.set_error_handler( [&destruction_run_loop](zx_status_t) { destruction_run_loop.Quit(); }); - component_controller_ptr.Unbind(); + component_controller.Unbind(); destruction_run_loop.Run(); } TEST_F(CastRunnerIntegrationTest, IncorrectCastAppId) { - // Launch the test-app component. - fuchsia::sys::ComponentControllerPtr component_controller_ptr; - base::fuchsia::ServiceDirectoryClient services_client(StartCastComponent( - "cast:99999999", &cast_runner_ptr_, component_controller_ptr.NewRequest(), - &cast_channel_binding_)); - component_controller_ptr.set_error_handler(&ComponentErrorHandler); + // Launch the a component with an invalid Cast app Id. + fuchsia::sys::ComponentControllerPtr component_controller = + StartCastComponent("cast:99999999"); - // Ensure no WebComponent was created. + // Run the loop until the ComponentController is dropped, or a WebComponent is + // created. base::RunLoop run_loop; + component_controller.set_error_handler([&run_loop](zx_status_t status) { + EXPECT_EQ(status, ZX_ERR_PEER_CLOSED); + run_loop.Quit(); + }); cr_fuchsia::ResultReceiver<WebComponent*> web_component( run_loop.QuitClosure()); cast_runner_->GetWebComponentForTest(web_component.GetReceiveCallback()); run_loop.Run(); - EXPECT_EQ(*web_component, nullptr); + EXPECT_FALSE(web_component.has_value()); } TEST_F(CastRunnerIntegrationTest, CastChannel) { @@ -212,11 +262,9 @@ test_server_.GetURL(kCastChannelAppPath)); // Launch the test-app component. - fuchsia::sys::ComponentControllerPtr component_controller_ptr; - base::fuchsia::ServiceDirectoryClient services_client(StartCastComponent( - base::StringPrintf("cast:%s", kCastChannelAppId), &cast_runner_ptr_, - component_controller_ptr.NewRequest(), &cast_channel_binding_)); - component_controller_ptr.set_error_handler(&ComponentErrorHandler); + fuchsia::sys::ComponentControllerPtr component_controller = + StartCastComponent(base::StringPrintf("cast:%s", kCastChannelAppId)); + component_controller.set_error_handler(&ComponentErrorHandler); // Access the NavigationController from the WebComponent. The test will hang // here if no WebComponent was created. @@ -252,7 +300,7 @@ base::RunLoop run_loop; cr_fuchsia::ResultReceiver<chromium::web::WebMessage> message( run_loop.QuitClosure()); - connected_channel_->ReceiveMessage( + cast_channel_.connected_channel()->ReceiveMessage( cr_fuchsia::CallbackToFitFunction(message.GetReceiveCallback())); run_loop.Run(); @@ -260,10 +308,10 @@ expected); } - component_controller_ptr.Unbind(); + // Shutdown the component and wait for the CastChannel to close. + component_controller.Unbind(); base::RunLoop run_loop; - cast_channel_binding_.set_error_handler( - [&run_loop](zx_status_t) { run_loop.Quit(); }); + cast_channel_binding_->SetOnLastClientCallback(run_loop.QuitClosure()); run_loop.Run(); } @@ -274,20 +322,18 @@ test_server_.GetURL(kCastChannelAppPath)); // Launch the test-app component. - fuchsia::sys::ComponentControllerPtr component_controller_ptr; - base::fuchsia::ServiceDirectoryClient services_client(StartCastComponent( - base::StringPrintf("cast:%s", kCastChannelAppId), &cast_runner_ptr_, - component_controller_ptr.NewRequest(), &cast_channel_binding_)); + fuchsia::sys::ComponentControllerPtr component_controller = + StartCastComponent(base::StringPrintf("cast:%s", kCastChannelAppId)); // Expect that disconnecting the Cast Channel consumer service will trigger // the destruction of the Cast Component. - cast_channel_binding_.Unbind(); + cast_channel_binding_.reset(); base::RunLoop run_loop; - component_controller_ptr.set_error_handler( + component_controller.set_error_handler( [&run_loop](zx_status_t) { run_loop.Quit(); }); run_loop.Run(); - EXPECT_FALSE(component_controller_ptr.is_bound()); + EXPECT_FALSE(component_controller.is_bound()); } TEST_F(CastRunnerIntegrationTest, CastChannelComponentControllerDropped) { @@ -297,18 +343,15 @@ test_server_.GetURL(kCastChannelAppPath)); // Launch the test-app component. - fuchsia::sys::ComponentControllerPtr component_controller_ptr; - base::fuchsia::ServiceDirectoryClient services_client(StartCastComponent( - base::StringPrintf("cast:%s", kCastChannelAppId), &cast_runner_ptr_, - component_controller_ptr.NewRequest(), &cast_channel_binding_)); + fuchsia::sys::ComponentControllerPtr component_controller = + StartCastComponent(base::StringPrintf("cast:%s", kCastChannelAppId)); // Expect that disconnecting the ComponentController will kill the Cast // Component, which we verify indirectly by listening for the disconnection // of one of its CastChannel FIDL client. - component_controller_ptr.Unbind(); + component_controller.Unbind(); base::RunLoop run_loop; - cast_channel_binding_.set_error_handler( - [&run_loop](zx_status_t) { run_loop.Quit(); }); + cast_channel_binding_->SetOnLastClientCallback(run_loop.QuitClosure()); run_loop.Run(); }
diff --git a/fuchsia/runners/cast/test_common.cc b/fuchsia/runners/cast/test_common.cc deleted file mode 100644 index db08a55..0000000 --- a/fuchsia/runners/cast/test_common.cc +++ /dev/null
@@ -1,65 +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. - -#include "fuchsia/runners/cast/test_common.h" - -#include <lib/fidl/cpp/binding.h> -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/fuchsia/fuchsia_logging.h" -#include "base/fuchsia/service_directory.h" -#include "base/run_loop.h" - -fidl::InterfaceHandle<fuchsia::io::Directory> StartCastComponent( - const base::StringPiece& cast_url, - fuchsia::sys::RunnerPtr* sys_runner, - fidl::InterfaceRequest<fuchsia::sys::ComponentController> - component_controller_request, - fidl::Binding<chromium::cast::CastChannel>* cast_channel_binding) { - // Construct, bind, and populate a ServiceDirectory for publishing - // the CastChannel service to the CastComponent. - fidl::InterfaceHandle<fuchsia::io::Directory> directory; - base::fuchsia::ServiceDirectory cast_channel_directory( - directory.NewRequest()); - base::RunLoop service_connect_runloop; - cast_channel_directory.AddService(base::BindRepeating( - [](base::RepeatingClosure on_connect_cb, - fidl::Binding<chromium::cast::CastChannel>* cast_channel_binding_, - fidl::InterfaceRequest<chromium::cast::CastChannel> request) { - cast_channel_binding_->Bind(std::move(request)); - on_connect_cb.Run(); - }, - base::Passed(service_connect_runloop.QuitClosure()), - base::Unretained(cast_channel_binding))); - - // Configure the Runner, including a service directory channel to publish - // services to. - fuchsia::sys::StartupInfo startup_info; - startup_info.launch_info.url = cast_url.as_string(); - - fidl::InterfaceHandle<fuchsia::io::Directory> component_services; - startup_info.launch_info.directory_request = - component_services.NewRequest().TakeChannel(); - - // Publish the ServiceDirectory into the FlatNamespace for CastChannel to be - // picked up from. - startup_info.flat_namespace.paths.emplace_back("/svc"); - startup_info.flat_namespace.directories.emplace_back(directory.TakeChannel()); - - fuchsia::sys::Package package; - package.resolved_url = cast_url.as_string(); - - sys_runner->get()->StartComponent(std::move(package), std::move(startup_info), - std::move(component_controller_request)); - - // Process the runloop until the CastChannel FIDL service is connected. - service_connect_runloop.Run(); - - // Prepare the service directory for clean teardown. - cast_channel_directory.RemoveAllServices(); - - return component_services; -}
diff --git a/fuchsia/runners/cast/test_common.h b/fuchsia/runners/cast/test_common.h deleted file mode 100644 index ec1c20fd..0000000 --- a/fuchsia/runners/cast/test_common.h +++ /dev/null
@@ -1,32 +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 FUCHSIA_RUNNERS_CAST_TEST_COMMON_H_ -#define FUCHSIA_RUNNERS_CAST_TEST_COMMON_H_ - -#include <fuchsia/sys/cpp/fidl.h> -#include <lib/fidl/cpp/binding.h> - -#include "base/strings/string_piece.h" -#include "fuchsia/fidl/chromium/cast/cpp/fidl.h" - -namespace fuchsia { -namespace io { -class Directory; -} -} // namespace fuchsia - -// Starts a Cast component from the runner |sys_runner| with the URL |cast_url| -// and returns the outgoing service directory client channel. -// The Cast component will connect to the CastChannel FIDL service bound at -// |cast_channel_binding|. -// Blocks until |cast_channel_binding| is bound. -fidl::InterfaceHandle<fuchsia::io::Directory> StartCastComponent( - const base::StringPiece& cast_url, - fuchsia::sys::RunnerPtr* sys_runner, - fidl::InterfaceRequest<fuchsia::sys::ComponentController> - component_controller_request, - fidl::Binding<chromium::cast::CastChannel>* cast_channel_binding); - -#endif // FUCHSIA_RUNNERS_CAST_TEST_COMMON_H_
diff --git a/fuchsia/runners/common/web_component.cc b/fuchsia/runners/common/web_component.cc index e72000c9..eeb7cbbc 100644 --- a/fuchsia/runners/common/web_component.cc +++ b/fuchsia/runners/common/web_component.cc
@@ -61,15 +61,18 @@ // Create the underlying Frame and get its NavigationController. runner_->context()->CreateFrame(frame_.NewRequest()); - // Publish ViewProvider before returning control to the message-loop, to - // ensure that it is available before the ServiceDirectory starts processing - // requests. - view_provider_binding_ = std::make_unique< - base::fuchsia::ScopedServiceBinding<fuchsia::ui::app::ViewProvider>>( - startup_context()->public_services(), this); - legacy_view_provider_binding_ = std::make_unique< - base::fuchsia::ScopedServiceBinding<fuchsia::ui::viewsv1::ViewProvider>>( - startup_context()->public_services(), this); + if (startup_context()->public_services()) { + // Publish ViewProvider before returning control to the message-loop, to + // ensure that it is available before the ServiceDirectory starts processing + // requests. + view_provider_binding_ = std::make_unique< + base::fuchsia::ScopedServiceBinding<fuchsia::ui::app::ViewProvider>>( + startup_context()->public_services(), this); + legacy_view_provider_binding_ = + std::make_unique<base::fuchsia::ScopedServiceBinding< + fuchsia::ui::viewsv1::ViewProvider>>( + startup_context()->public_services(), this); + } } void WebComponent::Kill() {
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg index 84330d4..fc00b99 100644 --- a/infra/config/luci-milo.cfg +++ b/infra/config/luci-milo.cfg
@@ -223,7 +223,7 @@ console_ids: "chromium/chromium.mac" console_ids: "chromium/chromium.linux" console_ids: "chromium/chromium.chromiumos" - console_ids: "chromium/chromium.chrome" + console_ids: "chrome/chromium.chrome" console_ids: "chromium/chromium.memory" console_ids: "chromium/chromium.gpu" } @@ -622,22 +622,22 @@ short_name: "kvn" } builders { - name: "buildbot/chromium.chrome/Google Chrome Win" + name: "buildbucket/luci.chrome.ci/Google Chrome Win" category: "chromium.chrome" short_name: "win" } builders { - name: "buildbot/chromium.chrome/Google Chrome Linux x64" + name: "buildbucket/luci.chrome.ci/Google Chrome Linux x64" category: "chromium.chrome" short_name: "lnx" } builders { - name: "buildbot/chromium.chrome/Google Chrome Mac" + name: "buildbucket/luci.chrome.ci/Google Chrome Mac" category: "chromium.chrome" short_name: "mac" } builders { - name: "buildbot/chromium.chrome/Google Chrome ChromeOS" + name: "buildbucket/luci.chrome.ci/Google Chrome ChromeOS" category: "chromium.chrome" short_name: "cro" } @@ -1057,19 +1057,19 @@ refs: "refs/heads/master" manifest_name: "REVISION" builders { - name: "buildbot/chromium.chrome/Google Chrome Win" + name: "buildbucket/luci.chrome.ci/Google Chrome Win" short_name: "win" } builders { - name: "buildbot/chromium.chrome/Google Chrome Linux x64" + name: "buildbucket/luci.chrome.ci/Google Chrome Linux x64" short_name: "lnx" } builders { - name: "buildbot/chromium.chrome/Google Chrome Mac" + name: "buildbucket/luci.chrome.ci/Google Chrome Mac" short_name: "mac" } builders { - name: "buildbot/chromium.chrome/Google Chrome ChromeOS" + name: "buildbucket/luci.chrome.ci/Google Chrome ChromeOS" short_name: "cro" } }
diff --git a/ios/chrome/browser/main/BUILD.gn b/ios/chrome/browser/main/BUILD.gn index 9d64d50..297d778 100644 --- a/ios/chrome/browser/main/BUILD.gn +++ b/ios/chrome/browser/main/BUILD.gn
@@ -11,6 +11,7 @@ deps = [ "//base", "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/sessions:serialisation", "//ios/chrome/browser/tabs", "//ios/chrome/browser/web_state_list", ]
diff --git a/ios/chrome/browser/main/browser.h b/ios/chrome/browser/main/browser.h index 100e738..e846213 100644 --- a/ios/chrome/browser/main/browser.h +++ b/ios/chrome/browser/main/browser.h
@@ -24,16 +24,15 @@ // See src/docs/ios/objects.md for more information. class Browser : public base::SupportsUserData { public: - // Creates a new Browser attached to |browser_state|. The |tab_model| must be - // non-nil. - static std::unique_ptr<Browser> Create(ios::ChromeBrowserState* browser_state, - TabModel* tab_model); + // Creates a new Browser attached to |browser_state|. + static std::unique_ptr<Browser> Create( + ios::ChromeBrowserState* browser_state); ~Browser() override {} // Accessor for the owning ChromeBrowserState. virtual ios::ChromeBrowserState* GetBrowserState() const = 0; - // Accessor for the TabModel. DEPRECATED: prefer web_state_list() whenever + // Accessor for the TabModel. DEPRECATED: prefer GetWebStateList() whenever // possible. virtual TabModel* GetTabModel() const = 0;
diff --git a/ios/chrome/browser/main/browser_impl.h b/ios/chrome/browser/main/browser_impl.h index b9c8b3f..1d17091 100644 --- a/ios/chrome/browser/main/browser_impl.h +++ b/ios/chrome/browser/main/browser_impl.h
@@ -7,6 +7,7 @@ #import "ios/chrome/browser/main/browser.h" +#include "base/gtest_prod_util.h" #include "base/macros.h" @class TabModel; @@ -23,27 +24,25 @@ // See src/docs/ios/objects.md for more information. class BrowserImpl : public Browser { public: - // Constructs a BrowserImpl attached to |browser_state|. The |tab_model| must - // be non-nil. - BrowserImpl(ios::ChromeBrowserState* browser_state, TabModel* tab_model); + // Constructs a BrowserImpl attached to |browser_state|. + explicit BrowserImpl(ios::ChromeBrowserState* browser_state); ~BrowserImpl() override; - // Accessor for the owning ChromeBrowserState. + // Browser. ios::ChromeBrowserState* GetBrowserState() const override; - - // Accessor for the TabModel. DEPRECATED: prefer web_state_list() whenever - // possible. TabModel* GetTabModel() const override; - - // Accessor for the WebStateList. WebStateList* GetWebStateList() const override; private: + // Exposed to allow unittests to pass in a mock TabModel. + FRIEND_TEST_ALL_PREFIXES(BrowserImplTest, TestAccessors); + BrowserImpl(ios::ChromeBrowserState* browser_state, TabModel* tab_model); + ios::ChromeBrowserState* browser_state_; __strong TabModel* tab_model_; WebStateList* web_state_list_; - DISALLOW_IMPLICIT_CONSTRUCTORS(BrowserImpl); + DISALLOW_COPY_AND_ASSIGN(BrowserImpl); }; #endif // IOS_CHROME_BROWSER_MAIN_BROWSER_IMPL_H_
diff --git a/ios/chrome/browser/main/browser_impl.mm b/ios/chrome/browser/main/browser_impl.mm index ddba98e..3f0eded3 100644 --- a/ios/chrome/browser/main/browser_impl.mm +++ b/ios/chrome/browser/main/browser_impl.mm
@@ -6,12 +6,23 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/sessions/session_service_ios.h" #import "ios/chrome/browser/tabs/tab_model.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +BrowserImpl::BrowserImpl(ios::ChromeBrowserState* browser_state) + : browser_state_(browser_state) { + DCHECK(browser_state_); + tab_model_ = + [[TabModel alloc] initWithSessionService:[SessionServiceIOS sharedService] + browserState:browser_state_]; + web_state_list_ = tab_model_.webStateList; +} + BrowserImpl::BrowserImpl(ios::ChromeBrowserState* browser_state, TabModel* tab_model) : browser_state_(browser_state), tab_model_(tab_model) { @@ -35,7 +46,7 @@ } // static -std::unique_ptr<Browser> Browser::Create(ios::ChromeBrowserState* browser_state, - TabModel* tab_model) { - return std::make_unique<BrowserImpl>(browser_state, tab_model); +std::unique_ptr<Browser> Browser::Create( + ios::ChromeBrowserState* browser_state) { + return std::make_unique<BrowserImpl>(browser_state); }
diff --git a/ios/chrome/browser/main/browser_impl_unittest.mm b/ios/chrome/browser/main/browser_impl_unittest.mm index fc3fe63..2508e26b 100644 --- a/ios/chrome/browser/main/browser_impl_unittest.mm +++ b/ios/chrome/browser/main/browser_impl_unittest.mm
@@ -29,6 +29,8 @@ void WebStateDetached(web::WebState* web_state) override {} }; +} // namespace + class BrowserImplTest : public PlatformTest { protected: BrowserImplTest() @@ -55,5 +57,3 @@ EXPECT_EQ(tab_model_, browser.GetTabModel()); EXPECT_EQ(&web_state_list_, browser.GetWebStateList()); } - -} // namespace
diff --git a/ios/chrome/browser/ui/authentication/cells/account_control_item.mm b/ios/chrome/browser/ui/authentication/cells/account_control_item.mm index d82029b..b211c8d 100644 --- a/ios/chrome/browser/ui/authentication/cells/account_control_item.mm +++ b/ios/chrome/browser/ui/authentication/cells/account_control_item.mm
@@ -101,7 +101,7 @@ _detailTextLabel = [[UILabel alloc] init]; _detailTextLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; _detailTextLabel.adjustsFontForContentSizeCategory = YES; _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; _detailTextLabel.numberOfLines = 0;
diff --git a/ios/chrome/browser/ui/authentication/cells/table_view_account_item.mm b/ios/chrome/browser/ui/authentication/cells/table_view_account_item.mm index 66c763d..b2de2ad3 100644 --- a/ios/chrome/browser/ui/authentication/cells/table_view_account_item.mm +++ b/ios/chrome/browser/ui/authentication/cells/table_view_account_item.mm
@@ -131,7 +131,7 @@ _detailTextLabel = [[UILabel alloc] init]; _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; _detailTextLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; _detailTextLabel.adjustsFontForContentSizeCategory = YES; _detailTextLabel.textColor = UIColorFromRGB(kSettingsCellsDetailTextColor); [contentView addSubview:_detailTextLabel]; @@ -169,10 +169,10 @@ constraintEqualToAnchor:contentView.centerYAnchor], [_imageView.topAnchor constraintGreaterThanOrEqualToAnchor:contentView.topAnchor - constant:kTableViewVerticalSpacing], + constant:kTableViewLargeVerticalSpacing], [_imageView.bottomAnchor constraintLessThanOrEqualToAnchor:contentView.bottomAnchor - constant:-kTableViewVerticalSpacing], + constant:-kTableViewLargeVerticalSpacing], [_textLabel.topAnchor constraintEqualToAnchor:verticalCenteringView.topAnchor], [_textLabel.bottomAnchor @@ -185,12 +185,10 @@ constraintEqualToAnchor:contentView.centerYAnchor], [verticalCenteringView.topAnchor constraintGreaterThanOrEqualToAnchor:contentView.topAnchor - constant: - kTableViewTwoLabelsCellVerticalSpacing], + constant:kTableViewVerticalSpacing], [verticalCenteringView.bottomAnchor constraintLessThanOrEqualToAnchor:contentView.bottomAnchor - constant: - kTableViewTwoLabelsCellVerticalSpacing], + constant:kTableViewVerticalSpacing], // Set trailing anchors. [_errorIcon.trailingAnchor
diff --git a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm index 38c1f49..d16f5c3 100644 --- a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm +++ b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm
@@ -214,9 +214,9 @@ constraintEqualToAnchor:_editIconView.heightAnchor], ]]; AddOptionalVerticalPadding(contentView, _textLabel, - kTableViewOneLabelCellVerticalSpacing); + kTableViewLargeVerticalSpacing); AddOptionalVerticalPadding(contentView, _textField, - kTableViewOneLabelCellVerticalSpacing); + kTableViewLargeVerticalSpacing); [self updateForAccessibilityContentSizeCategory: UIContentSizeCategoryIsAccessibilityCategory(
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm index fb68015..bb668f9 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -643,6 +643,9 @@ } - (void)testOpeningNewTab { + // TODO(crbug.com/933953): Re-enable this test when grey_tap() issue is fixed. + EARL_GREY_TEST_DISABLED(@"Disabled due to full-configs and slimnav failures"); + [ChromeEarlGreyUI openNewTab]; // Check that the fake omnibox is here.
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h b/ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h index 98b55b9..924e65b2 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h
@@ -17,9 +17,18 @@ // value denotes that the toolbar should be completely visible, and a |progress| // value of 0.0 denotes that the toolbar should be completely hidden. // -// NOTE: Since this selector is called for every scroll offset, it's not -// optional, as checking |-respondsToSelector:| for every FullscreenUIElement -// at every scroll offset can introduce performance issues. +// This selector is called for every scroll offset, it's not optional, as +// checking |-respondsToSelector:| for every FullscreenUIElement at every scroll +// offset can introduce performance issues. +// +// If the implementation of this selector uses batched layout updates (e.g. +// updating the UI in |-layoutSubviews| or by updating constraints), then a +// layout pass should be forced using |-setNeedsLayout| and |-layoutIfNeeded|. +// This will ensure that the layout is updated for each scroll position rather +// than batching multiple fullscreen progress updates together. This is +// especially important for FullscreenUIElements that do not implement +// |-animateFullscreenWithAnimator:|, as this selctor is called by +// FullscreenUIUpdater in an animation block. - (void)updateForFullscreenProgress:(CGFloat)progress; @optional
diff --git a/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm b/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm index 2b2c5710..3049228 100644 --- a/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm
@@ -134,6 +134,8 @@ [(id<FullscreenUIElement>)view updateForFullscreenProgress:progress]; } } + [self.view setNeedsLayout]; + [self.view layoutIfNeeded]; } #pragma mark - Private Methods
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm index db900cc..7880fb8 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -153,14 +153,11 @@ } - (void)createMainBrowser { - TabModel* tabModel = - [[TabModel alloc] initWithSessionService:[SessionServiceIOS sharedService] - browserState:_browserState]; - [self setUpTabModel:tabModel + _mainBrowser = Browser::Create(_browserState); + [self setUpTabModel:_mainBrowser->GetTabModel() withBrowserState:_browserState restorePersistedState:YES]; - _mainBrowser = Browser::Create(_browserState, tabModel); // Follow loaded URLs in the main tab model to send those in case of // crashes. breakpad::MonitorURLsForTabModel(self.mainBrowser->GetTabModel()); @@ -377,13 +374,12 @@ ios::ChromeBrowserState* otrBrowserState = _browserState->GetOffTheRecordChromeBrowserState(); DCHECK(otrBrowserState); - TabModel* tabModel = - [[TabModel alloc] initWithSessionService:[SessionServiceIOS sharedService] - browserState:otrBrowserState]; - [self setUpTabModel:tabModel + + std::unique_ptr<Browser> browser = Browser::Create(otrBrowserState); + [self setUpTabModel:browser->GetTabModel() withBrowserState:otrBrowserState restorePersistedState:restorePersistedState]; - return Browser::Create(otrBrowserState, tabModel); + return browser; } - (void)setUpTabModel:(TabModel*)tabModel
diff --git a/ios/chrome/browser/ui/settings/cells/autofill_data_item.mm b/ios/chrome/browser/ui/settings/cells/autofill_data_item.mm index a08af56..9728170 100644 --- a/ios/chrome/browser/ui/settings/cells/autofill_data_item.mm +++ b/ios/chrome/browser/ui/settings/cells/autofill_data_item.mm
@@ -20,6 +20,12 @@ @implementation AutofillDataItem +@synthesize deletable = _deletable; +@synthesize GUID = _GUID; +@synthesize text = _text; +@synthesize leadingDetailText = _leadingDetailText; +@synthesize trailingDetailText = _trailingDetailText; + - (instancetype)initWithType:(NSInteger)type { self = [super initWithType:type]; if (self) { @@ -40,12 +46,6 @@ @end -#pragma mark - AutofillDataCell - -@interface AutofillDataCell () -@property(nonatomic, strong) UIStackView* mainLabelsContainer; -@end - @implementation AutofillDataCell @synthesize textLabel = _textLabel; @@ -67,13 +67,12 @@ UIView* contentView = self.contentView; _textLabel = [[UILabel alloc] init]; - _leadingDetailTextLabel = [[UILabel alloc] init]; + _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + [contentView addSubview:_textLabel]; - _mainLabelsContainer = [[UIStackView alloc] - initWithArrangedSubviews:@[ _textLabel, _leadingDetailTextLabel ]]; - _mainLabelsContainer.translatesAutoresizingMaskIntoConstraints = NO; - _mainLabelsContainer.axis = UILayoutConstraintAxisVertical; - [contentView addSubview:_mainLabelsContainer]; + _leadingDetailTextLabel = [[UILabel alloc] init]; + _leadingDetailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; + [contentView addSubview:_leadingDetailTextLabel]; _trailingDetailTextLabel = [[UILabel alloc] init]; _trailingDetailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; @@ -95,7 +94,7 @@ _leadingDetailTextLabel.numberOfLines = 0; _leadingDetailTextLabel.lineBreakMode = NSLineBreakByWordWrapping; _leadingDetailTextLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; _leadingDetailTextLabel.adjustsFontForContentSizeCategory = YES; _leadingDetailTextLabel.textColor = UIColorFromRGB(kSettingsCellsDetailTextColor); @@ -112,12 +111,16 @@ [NSLayoutConstraint activateConstraints:@[ // Set horizontal anchors. - [_mainLabelsContainer.leadingAnchor + [_textLabel.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor constant:kTableViewHorizontalSpacing], - [_mainLabelsContainer.trailingAnchor + [_textLabel.trailingAnchor constraintLessThanOrEqualToAnchor:_trailingDetailTextLabel.leadingAnchor constant:-kTableViewHorizontalSpacing], + [_leadingDetailTextLabel.leadingAnchor + constraintEqualToAnchor:_textLabel.leadingAnchor], + [_leadingDetailTextLabel.trailingAnchor + constraintEqualToAnchor:_textLabel.trailingAnchor], [_trailingDetailTextLabel.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor constant:-kTableViewHorizontalSpacing], @@ -128,18 +131,16 @@ multiplier:kDetailTextWidthMultiplier], // Set vertical anchors. - [_mainLabelsContainer.centerYAnchor - constraintEqualToAnchor:contentView.centerYAnchor], + [_leadingDetailTextLabel.topAnchor + constraintEqualToAnchor:_textLabel.bottomAnchor], [_trailingDetailTextLabel.centerYAnchor constraintEqualToAnchor:contentView.centerYAnchor], ]]; - AddOptionalVerticalPadding(contentView, _mainLabelsContainer - - , - kTableViewTwoLabelsCellVerticalSpacing); + AddOptionalVerticalPadding(contentView, _textLabel, _leadingDetailTextLabel, + kTableViewLargeVerticalSpacing); AddOptionalVerticalPadding(contentView, _trailingDetailTextLabel, - kTableViewOneLabelCellVerticalSpacing); + kTableViewLargeVerticalSpacing); } #pragma mark - UITableViewCell
diff --git a/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.mm b/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.mm index 5a2dea1..1185dc40 100644 --- a/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.mm +++ b/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.mm
@@ -77,7 +77,7 @@ constraintEqualToAnchor:_textLabel.firstBaselineAnchor], ]]; AddOptionalVerticalPadding(contentView, _textLabel, - kTableViewOneLabelCellVerticalSpacing); + kTableViewLargeVerticalSpacing); } return self; }
diff --git a/ios/chrome/browser/ui/settings/cells/passphrase_error_item.mm b/ios/chrome/browser/ui/settings/cells/passphrase_error_item.mm index 303cced..db9b230 100644 --- a/ios/chrome/browser/ui/settings/cells/passphrase_error_item.mm +++ b/ios/chrome/browser/ui/settings/cells/passphrase_error_item.mm
@@ -4,12 +4,15 @@ #import "ios/chrome/browser/ui/settings/cells/passphrase_error_item.h" -#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" - #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +namespace { +// Padding used on the leading and trailing edges of the cell. +const CGFloat kHorizontalPadding = 16; +} // namespace + @implementation PassphraseErrorItem @synthesize text = _text; @@ -62,22 +65,17 @@ [NSLayoutConstraint activateConstraints:@[ [_errorImageView.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor - constant:kTableViewHorizontalSpacing], + constant:kHorizontalPadding], [_textLabel.leadingAnchor constraintEqualToAnchor:_errorImageView.trailingAnchor - constant:kTableViewHorizontalSpacing], + constant:kHorizontalPadding], [_textLabel.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], + constant:-kHorizontalPadding], [_errorImageView.centerYAnchor constraintEqualToAnchor:contentView.centerYAnchor], - [_textLabel.topAnchor - constraintEqualToAnchor:contentView.topAnchor - constant:kTableViewOneLabelCellVerticalSpacing], - [_textLabel.bottomAnchor - constraintEqualToAnchor:contentView.bottomAnchor - constant:-kTableViewOneLabelCellVerticalSpacing], - + [_textLabel.centerYAnchor + constraintEqualToAnchor:contentView.centerYAnchor], ]]; [_errorImageView
diff --git a/ios/chrome/browser/ui/settings/cells/settings_detail_item.mm b/ios/chrome/browser/ui/settings/cells/settings_detail_item.mm index 42bd261..fc9c768 100644 --- a/ios/chrome/browser/ui/settings/cells/settings_detail_item.mm +++ b/ios/chrome/browser/ui/settings/cells/settings_detail_item.mm
@@ -7,7 +7,6 @@ #include <algorithm> #import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h" -#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" @@ -18,9 +17,16 @@ namespace { +// Padding used on the leading and trailing edges of the cell and between the +// two labels. +const CGFloat kHorizontalPadding = 16; + // Padding used between the icon and the text labels. const CGFloat kIconTrailingPadding = 12; +// Padding used on the top and bottom edges of the cell. +const CGFloat kVerticalPadding = 16; + // Size of the icon image. const CGFloat kIconImageSize = 28; @@ -135,7 +141,7 @@ // these will be active at a time, defaulting to hidden. _iconHiddenConstraint = [_labelContainerGuide.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor - constant:kTableViewHorizontalSpacing]; + constant:kHorizontalPadding]; _iconVisibleConstraint = [_labelContainerGuide.leadingAnchor constraintEqualToAnchor:_iconImageView.trailingAnchor constant:kIconTrailingPadding]; @@ -154,30 +160,29 @@ ]; _accessibilityConstraints = @[ - [_textLabel.topAnchor - constraintEqualToAnchor:self.contentView.topAnchor - constant:kTableViewLargeVerticalSpacing], + [_textLabel.topAnchor constraintEqualToAnchor:self.contentView.topAnchor + constant:kVerticalPadding], [_detailTextLabel.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor - constant:-kTableViewLargeVerticalSpacing], + constant:-kVerticalPadding], [_textLabel.bottomAnchor constraintEqualToAnchor:_detailTextLabel.topAnchor - constant:-kTableViewLargeVerticalSpacing], + constant:-kVerticalPadding], [_textLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], + constant:-kHorizontalPadding], [_detailTextLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor - constant:kTableViewHorizontalSpacing], + constant:kHorizontalPadding], [_detailTextLabel.trailingAnchor constraintLessThanOrEqualToAnchor:_labelContainerGuide.trailingAnchor - constant:-kTableViewHorizontalSpacing], + constant:-kHorizontalPadding], ]; [NSLayoutConstraint activateConstraints:@[ [_iconImageView.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor - constant:kTableViewHorizontalSpacing], + constant:kHorizontalPadding], [_iconImageView.widthAnchor constraintEqualToConstant:kIconImageSize], [_iconImageView.heightAnchor constraintEqualToConstant:kIconImageSize], @@ -186,15 +191,14 @@ constraintEqualToAnchor:_labelContainerGuide.leadingAnchor], [_labelContainerGuide.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], + constant:-kHorizontalPadding], [_iconImageView.centerYAnchor constraintEqualToAnchor:contentView.centerYAnchor], _iconHiddenConstraint, ]]; - AddOptionalVerticalPadding(contentView, _textLabel, - kTableViewOneLabelCellVerticalSpacing); + AddOptionalVerticalPadding(contentView, _textLabel, kVerticalPadding); [self updateForAccessibilityContentSizeCategory: UIContentSizeCategoryIsAccessibilityCategory( @@ -282,8 +286,8 @@ } - (CGFloat)textLabelTargetWidth { - CGFloat availableWidth = CGRectGetWidth(_labelContainerGuide.layoutFrame) - - kTableViewHorizontalSpacing; + CGFloat availableWidth = + CGRectGetWidth(_labelContainerGuide.layoutFrame) - kHorizontalPadding; CGFloat textLabelWidth = self.textLabel.frame.size.width; CGFloat detailTextLabelWidth = self.detailTextLabel.frame.size.width; @@ -296,8 +300,8 @@ } - (CGFloat)detailTextLabelTargetWidth { - CGFloat availableWidth = CGRectGetWidth(_labelContainerGuide.layoutFrame) - - kTableViewHorizontalSpacing; + CGFloat availableWidth = + CGRectGetWidth(_labelContainerGuide.layoutFrame) - kHorizontalPadding; CGFloat textLabelWidth = self.textLabel.frame.size.width; CGFloat detailTextLabelWidth = self.detailTextLabel.frame.size.width;
diff --git a/ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.mm b/ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.mm index 897985c..63effad 100644 --- a/ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.mm +++ b/ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.mm
@@ -95,20 +95,18 @@ constraintEqualToAnchor:contentView.centerYAnchor], [_imageView.topAnchor constraintGreaterThanOrEqualToAnchor:contentView.topAnchor - constant:kTableViewVerticalSpacing], + constant:kTableViewLargeVerticalSpacing], [contentView.bottomAnchor constraintGreaterThanOrEqualToAnchor:_imageView.bottomAnchor - constant:kTableViewVerticalSpacing], + constant:kTableViewLargeVerticalSpacing], [textStackView.centerYAnchor constraintEqualToAnchor:contentView.centerYAnchor], [textStackView.topAnchor constraintGreaterThanOrEqualToAnchor:contentView.topAnchor - constant: - kTableViewTwoLabelsCellVerticalSpacing], + constant:kTableViewLargeVerticalSpacing], [contentView.bottomAnchor constraintGreaterThanOrEqualToAnchor:textStackView.bottomAnchor - constant: - kTableViewTwoLabelsCellVerticalSpacing], + constant:kTableViewLargeVerticalSpacing], ]]; }
diff --git a/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.mm b/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.mm index 1f58e001..2488f97 100644 --- a/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.mm +++ b/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.mm
@@ -61,7 +61,7 @@ _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; _detailTextLabel.numberOfLines = 0; _detailTextLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; _detailTextLabel.adjustsFontForContentSizeCategory = YES; _detailTextLabel.textColor = UIColorFromRGB(kSettingsCellsDetailTextColor); [contentView addSubview:_detailTextLabel];
diff --git a/ios/chrome/browser/ui/settings/cells/settings_switch_cell.mm b/ios/chrome/browser/ui/settings/cells/settings_switch_cell.mm index 0b6c1e3..ea54139 100644 --- a/ios/chrome/browser/ui/settings/cells/settings_switch_cell.mm +++ b/ios/chrome/browser/ui/settings/cells/settings_switch_cell.mm
@@ -19,6 +19,9 @@ // Padding used between the icon and the text labels. const CGFloat kIconTrailingPadding = 12; +// Padding used on the top and bottom edges of the cell. +const CGFloat kVerticalPadding = 16; + // Size of the icon image. const CGFloat kIconImageSize = 28; } // namespace @@ -113,13 +116,13 @@ _accessibilityConstraints = @[ [_switchView.topAnchor constraintEqualToAnchor:textLayoutGuide.bottomAnchor - constant:kTableViewLargeVerticalSpacing], + constant:kVerticalPadding], [_switchView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:kTableViewHorizontalSpacing], [_switchView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor - constant:-kTableViewLargeVerticalSpacing], + constant:-kVerticalPadding], [textLayoutGuide.trailingAnchor constraintLessThanOrEqualToAnchor:self.contentView.trailingAnchor constant:-kTableViewHorizontalSpacing], @@ -160,7 +163,7 @@ } AddOptionalVerticalPadding(self.contentView, textLayoutGuide, - kTableViewOneLabelCellVerticalSpacing); + kVerticalPadding); } return self; }
diff --git a/ios/chrome/browser/ui/settings/cells/version_item.mm b/ios/chrome/browser/ui/settings/cells/version_item.mm index 6c1a69d..40cdfd4 100644 --- a/ios/chrome/browser/ui/settings/cells/version_item.mm +++ b/ios/chrome/browser/ui/settings/cells/version_item.mm
@@ -75,15 +75,10 @@ forControlEvents:UIControlEventTouchUpInside]; [self.contentView addSubview:button]; - NSLayoutConstraint* heightConstraint = [self.contentView.heightAnchor - constraintGreaterThanOrEqualToConstant:kChromeTableViewCellHeight]; - // Don't set the priority to required to avoid clashing with the estimated - // height. - heightConstraint.priority = UILayoutPriorityRequired - 1; - AddSameConstraints(button, self.contentView); [NSLayoutConstraint activateConstraints:@[ - heightConstraint, + [self.contentView.heightAnchor constraintGreaterThanOrEqualToConstant: + kTableViewHeaderFooterViewHeight], [_textLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor], [_textLabel.trailingAnchor
diff --git a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm index 6f0127e..40e5bb0 100644 --- a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
@@ -26,7 +26,7 @@ // |estimatedSection{Header|Footer}Height|. const CGFloat kDefaultHeaderFooterHeight = 10; // Estimated height of the header/footer, used to speed the constraints. -const CGFloat kEstimatedHeaderFooterHeight = 50; +const CGFloat kEstimatedHeaderFooterHeight = 35; enum SavedBarButtomItemPositionEnum { kUndefinedBarButtonItemPosition,
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm index 56f3a42..60032dfe 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm
@@ -61,7 +61,7 @@ forAxis:UILayoutConstraintAxisVertical]; self.subtitleLabel = [[UILabel alloc] init]; self.subtitleLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; self.subtitleLabel.textColor = [UIColor lightGrayColor]; [self.subtitleLabel setContentCompressionResistancePriority:UILayoutPriorityRequired
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h index dd37534..5e138dea 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h +++ b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h
@@ -10,18 +10,9 @@ // The minimum height for a TableViewHeaderFooterView. extern const CGFloat kTableViewHeaderFooterViewHeight; -// The minimum height for a TableViewCell. -extern const CGFloat kChromeTableViewCellHeight; - // The horizontal spacing between views and the container view of a cell. extern const CGFloat kTableViewHorizontalSpacing; -// The vertical spacing for a cell containing only one label. -extern const CGFloat kTableViewOneLabelCellVerticalSpacing; - -// The vertical spacing for a cell containing one label and one sub label. -extern const CGFloat kTableViewTwoLabelsCellVerticalSpacing; - // The vertical spacing between views and the container view of a cell. extern const CGFloat kTableViewVerticalSpacing;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm index 32d75077..6d1976c 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm
@@ -8,11 +8,8 @@ #error "This file requires ARC support." #endif -const CGFloat kTableViewHeaderFooterViewHeight = 48.0; -const CGFloat kChromeTableViewCellHeight = 48.0; +const CGFloat kTableViewHeaderFooterViewHeight = 44.0; const CGFloat kTableViewHorizontalSpacing = 16.0; -const CGFloat kTableViewOneLabelCellVerticalSpacing = 14.0; -const CGFloat kTableViewTwoLabelsCellVerticalSpacing = 11.0; const CGFloat kTableViewVerticalSpacing = 8.0; const CGFloat kTableViewLargeVerticalSpacing = 16.0; const CGFloat kTableViewSubViewHorizontalSpacing = 12.0;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.mm index 5282354..4a75ea3 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.mm
@@ -13,6 +13,10 @@ #error "This file requires ARC support." #endif +namespace { +const CGFloat kMinimalHeight = 48; +} // namespace + #pragma mark - TableViewDetailTextItem @implementation TableViewDetailTextItem @@ -95,23 +99,20 @@ _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; [containerView addSubview:_detailTextLabel]; - NSLayoutConstraint* heightConstraint = [self.contentView.heightAnchor - constraintGreaterThanOrEqualToConstant:kChromeTableViewCellHeight]; - // Don't set the priority to required to avoid clashing with the estimated - // height. - heightConstraint.priority = UILayoutPriorityRequired - 1; + CGFloat margin = kTableViewHorizontalSpacing; [NSLayoutConstraint activateConstraints:@[ // Minimal height. - heightConstraint, + [self.contentView.heightAnchor + constraintGreaterThanOrEqualToConstant:kMinimalHeight], // Container. [containerView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor - constant:kTableViewHorizontalSpacing], + constant:margin], [containerView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], + constant:-margin], [containerView.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor], @@ -132,8 +133,7 @@ ]]; // Make sure there are top and bottom margins of at least |margin|. - AddOptionalVerticalPadding(self.contentView, containerView, - kTableViewTwoLabelsCellVerticalSpacing); + AddOptionalVerticalPadding(self.contentView, containerView, margin); } return self; }
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_image_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_image_item.mm index 79368cf..fcfa04b 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_image_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_image_item.mm
@@ -13,6 +13,11 @@ #error "This file requires ARC support." #endif +namespace { +// Vertical spacing between label and the container view of a cell. +const CGFloat kLabelCellVerticalSpacing = 11.0; +} // namespace + @implementation TableViewImageItem @synthesize image = _image; @@ -92,12 +97,6 @@ horizontalStack.alignment = UIStackViewAlignmentCenter; [self.contentView addSubview:horizontalStack]; - - NSLayoutConstraint* heightConstraint = [self.contentView.heightAnchor - constraintGreaterThanOrEqualToConstant:kChromeTableViewCellHeight]; - // Don't set the priority to required to avoid clashing with the estimated - // height. - heightConstraint.priority = UILayoutPriorityRequired - 1; [NSLayoutConstraint activateConstraints:@[ // Horizontal Stack constraints. [horizontalStack.leadingAnchor @@ -106,15 +105,12 @@ [horizontalStack.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-kTableViewHorizontalSpacing], - [horizontalStack.centerYAnchor - constraintEqualToAnchor:self.contentView.centerYAnchor], [horizontalStack.topAnchor - constraintGreaterThanOrEqualToAnchor:self.contentView.topAnchor - constant:kTableViewVerticalSpacing], + constraintEqualToAnchor:self.contentView.topAnchor + constant:kLabelCellVerticalSpacing], [horizontalStack.bottomAnchor - constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor - constant:-kTableViewVerticalSpacing], - heightConstraint, + constraintEqualToAnchor:self.contentView.bottomAnchor + constant:-kLabelCellVerticalSpacing], ]]; } return self;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm index 558d546a..59b74fa 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm
@@ -15,6 +15,11 @@ #error "This file requires ARC support." #endif +namespace { +// Vertical spacing between label and the container view of a cell. +const CGFloat kLabelCellVerticalSpacing = 11.0; +} // namespace + #pragma mark - TableViewTextItem @implementation TableViewTextItem @@ -100,12 +105,11 @@ [_textLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:kTableViewHorizontalSpacing], - [_textLabel.topAnchor - constraintEqualToAnchor:self.contentView.topAnchor - constant:kTableViewOneLabelCellVerticalSpacing], + [_textLabel.topAnchor constraintEqualToAnchor:self.contentView.topAnchor + constant:kLabelCellVerticalSpacing], [_textLabel.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor - constant:-kTableViewOneLabelCellVerticalSpacing], + constant:-kLabelCellVerticalSpacing], [_textLabel.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-kTableViewHorizontalSpacing]
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_url_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_url_item.mm index 4bd9d67..93f7c44 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_url_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_url_item.mm
@@ -162,13 +162,13 @@ // Set font sizes using dynamic type. _titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; _titleLabel.adjustsFontForContentSizeCategory = YES; - _URLLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + _URLLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; _URLLabel.adjustsFontForContentSizeCategory = YES; _URLLabel.textColor = UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); _URLLabel.hidden = YES; _metadataLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; _metadataLabel.textColor = UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); _metadataLabel.adjustsFontForContentSizeCategory = YES; @@ -202,22 +202,6 @@ [contentView addSubview:_faviconBadgeView]; [contentView addSubview:self.horizontalStack]; - NSLayoutConstraint* heightConstraint = [self.contentView.heightAnchor - constraintGreaterThanOrEqualToConstant:kChromeTableViewCellHeight]; - // Don't set the priority to required to avoid clashing with the estimated - // height. - heightConstraint.priority = UILayoutPriorityRequired - 1; - - NSLayoutConstraint* topConstraint = [self.horizontalStack.topAnchor - constraintGreaterThanOrEqualToAnchor:self.contentView.topAnchor - constant: - kTableViewTwoLabelsCellVerticalSpacing]; - NSLayoutConstraint* bottomConstraint = [self.horizontalStack.bottomAnchor - constraintGreaterThanOrEqualToAnchor:self.contentView.bottomAnchor - constant: - - - kTableViewTwoLabelsCellVerticalSpacing]; - [NSLayoutConstraint activateConstraints:@[ // The favicon view is a fixed size, is pinned to the leading edge of the // content view, and is centered vertically. @@ -252,9 +236,12 @@ [self.horizontalStack.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-kTableViewHorizontalSpacing], - [self.horizontalStack.centerYAnchor - constraintEqualToAnchor:self.contentView.centerYAnchor], - topConstraint, bottomConstraint, heightConstraint + [self.horizontalStack.topAnchor + constraintEqualToAnchor:self.contentView.topAnchor + constant:kTableViewVerticalSpacing], + [self.horizontalStack.bottomAnchor + constraintEqualToAnchor:self.contentView.bottomAnchor + constant:-kTableViewVerticalSpacing] ]]; } return self;
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn index 6f5b50d..e87784d 100644 --- a/ios/chrome/browser/ui/tabs/BUILD.gn +++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -53,6 +53,7 @@ "//ios/chrome/browser/ui/favicon/resources:default_favicon_incognito", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/image_util", + "//ios/chrome/browser/ui/ntp:util", "//ios/chrome/browser/ui/popup_menu/public", "//ios/chrome/browser/ui/tab_grid/grid/resources:grid_cell_close_button", "//ios/chrome/browser/ui/tabs/requirements",
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm index d975e9a..7434e42 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -33,6 +33,7 @@ #import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #include "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h" #include "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" +#import "ios/chrome/browser/ui/ntp/ntp_util.h" #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_long_press_delegate.h" #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_constants.h" #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_presentation.h" @@ -1050,7 +1051,7 @@ [view setFavicon:favicon.ToUIImage()]; } - if (tab.webState->IsLoading()) + if (tab.webState->IsLoading() && !IsVisibleURLNewTabPage(tab.webState)) [view startProgressSpinner]; else [view stopProgressSpinner];
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn index 2764c29..a6420c2 100644 --- a/ios/chrome/browser/ui/toolbar/BUILD.gn +++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -121,6 +121,7 @@ "//components/bookmarks/browser", "//components/bookmarks/test", "//components/search_engines", + "//ios/chrome/browser", "//ios/chrome/browser/bookmarks", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/search_engines",
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm b/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm index d8774e0..d4b7149 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm
@@ -267,8 +267,11 @@ DCHECK(self.consumer); [self updateConsumerForWebState:self.webState]; - [self.consumer setIsNTP:IsVisibleURLNewTabPage(self.webState)]; - [self.consumer setLoadingState:self.webState->IsLoading()]; + BOOL isNTP = IsVisibleURLNewTabPage(self.webState); + [self.consumer setIsNTP:isNTP]; + // Never show the loading UI for an NTP. + BOOL isLoading = self.webState->IsLoading() && !isNTP; + [self.consumer setLoadingState:isLoading]; [self updateBookmarksForWebState:self.webState]; [self updateShareMenuForWebState:self.webState]; }
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm b/ios/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm index 7ea933d..aab848e 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm
@@ -13,6 +13,7 @@ #include "components/bookmarks/test/bookmark_test_helpers.h" #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#include "ios/chrome/browser/chrome_url_constants.h" #import "ios/chrome/browser/ui/toolbar/test/toolbar_test_navigation_manager.h" #import "ios/chrome/browser/ui/toolbar/test/toolbar_test_web_state.h" #import "ios/chrome/browser/ui/toolbar/toolbar_consumer.h" @@ -394,6 +395,19 @@ [[consumer_ verify] setLoadingState:NO]; } +// Tests the Toolbar is not updated when the Webstate observer method +// DidStartLoading is triggered by SetLoading on the NTP. +TEST_F(ToolbarMediatorTest, TestDidStartLoadingNTP) { + mediator_.webStateList = web_state_list_.get(); + SetUpActiveWebState(); + mediator_.consumer = consumer_; + + web_state_->SetLoading(false); + web_state_->SetVisibleURL(GURL(kChromeUINewTabURL)); + web_state_->SetLoading(true); + [[consumer_ verify] setLoadingState:NO]; +} + // Tests the Toolbar is updated when the Webstate observer method // DidLoadPageWithSuccess is triggered by OnPageLoaded. TEST_F(ToolbarMediatorTest, TestDidLoadPageWithSucess) {
diff --git a/ios/web/public/web_state/ui/crw_content_view.h b/ios/web/public/web_state/ui/crw_content_view.h index 3e8a092..ed38357 100644 --- a/ios/web/public/web_state/ui/crw_content_view.h +++ b/ios/web/public/web_state/ui/crw_content_view.h
@@ -27,10 +27,6 @@ // bug, where UIScrollView.content inset does not work (rdar://23584409). @property(nonatomic, assign) UIEdgeInsets contentInset; -// Returns YES if content is being displayed in the scroll view. -// TODO(stuartmorgan): See if this can be removed from the public interface. -- (BOOL)isViewAlive; - @optional // Whether or not the content view should use the content inset when setting
diff --git a/ios/web/web_state/ui/crw_web_view_content_view.mm b/ios/web/web_state/ui/crw_web_view_content_view.mm index d9a9cb4..72c35a2 100644 --- a/ios/web/web_state/ui/crw_web_view_content_view.mm +++ b/ios/web/web_state/ui/crw_web_view_content_view.mm
@@ -90,10 +90,6 @@ } } -- (BOOL)isViewAlive { - return YES; -} - - (void)setContentOffset:(CGPoint)contentOffset { if (CGPointEqualToPoint(_contentOffset, contentOffset)) return;
diff --git a/media/learning/common/learning_task.h b/media/learning/common/learning_task.h index 4c38e88..a7ca9b9f 100644 --- a/media/learning/common/learning_task.h +++ b/media/learning/common/learning_task.h
@@ -101,24 +101,16 @@ // the histogram name. std::string uma_hacky_confusion_matrix; - // RandomTree parameters - - // How RandomTree handles unknown feature values. - enum class RTUnknownValueHandling { - // Return an empty distribution as the prediction. - kEmptyDistribution, - - // Return the sum of the traversal of all splits. - kUseAllSplits, - }; - RTUnknownValueHandling rt_unknown_value_handling = - RTUnknownValueHandling::kUseAllSplits; - // RandomForest parameters // Number of trees in the random forest. size_t rf_number_of_trees = 100; + // Should ExtraTrees apply one-hot conversion automatically? RandomTree has + // been modified to support nominals directly, though it isn't exactly the + // same as one-hot conversion. It is, however, much faster. + bool use_one_hot_conversion = false; + // Reporting parameters // This is a hack for the initial media capabilities investigation. It
diff --git a/media/learning/impl/extra_trees_trainer.cc b/media/learning/impl/extra_trees_trainer.cc index 4e16aae7..b820c6a64 100644 --- a/media/learning/impl/extra_trees_trainer.cc +++ b/media/learning/impl/extra_trees_trainer.cc
@@ -34,11 +34,16 @@ if (!tree_trainer_) tree_trainer_ = std::make_unique<RandomTreeTrainer>(rng()); - // RandomTree requires one-hot vectors to properly choose split points the way - // that ExtraTrees require. - // TODO(liberato): Modify it not to need this. It's slow. - converter_ = std::make_unique<OneHotConverter>(task, training_data); - converted_training_data_ = converter_->Convert(training_data); + // We've modified RandomTree to handle nominals, so we don't need to do one- + // hot conversion normally. It's slow. However, the changes to RandomTree + // are only approximately the same thing. + if (task_.use_one_hot_conversion) { + converter_ = std::make_unique<OneHotConverter>(task, training_data); + converted_training_data_ = converter_->Convert(training_data); + task_ = converter_->converted_task(); + } else { + converted_training_data_ = training_data; + } // Start training. Send in nullptr to start the process. OnRandomTreeModel(std::move(model_cb), nullptr); @@ -52,17 +57,22 @@ // If this is the last tree, then return the finished model. if (trees_.size() == task_.rf_number_of_trees) { - std::move(model_cb).Run(std::make_unique<ConvertingModel>( - std::move(converter_), - std::make_unique<VotingEnsemble>(std::move(trees_)))); + std::unique_ptr<Model> model = + std::make_unique<VotingEnsemble>(std::move(trees_)); + // If we have a converter, then wrap everything in a ConvertingModel. + if (converter_) { + model = std::make_unique<ConvertingModel>(std::move(converter_), + std::move(model)); + } + + std::move(model_cb).Run(std::move(model)); return; } // Train the next tree. auto cb = base::BindOnce(&ExtraTreesTrainer::OnRandomTreeModel, AsWeakPtr(), std::move(model_cb)); - tree_trainer_->Train(converter_->converted_task(), converted_training_data_, - std::move(cb)); + tree_trainer_->Train(task_, converted_training_data_, std::move(cb)); } } // namespace learning
diff --git a/media/learning/impl/random_tree_trainer.cc b/media/learning/impl/random_tree_trainer.cc index 3f5713d1..88e1b97 100644 --- a/media/learning/impl/random_tree_trainer.cc +++ b/media/learning/impl/random_tree_trainer.cc
@@ -36,7 +36,6 @@ int split_index, FeatureValue split_point) : split_index_(split_index), - rt_unknown_value_handling_(task.rt_unknown_value_handling), ordering_(task.feature_descriptions[split_index].ordering), split_point_(split_point) {} @@ -47,8 +46,8 @@ FeatureValue f; switch (ordering_) { case LearningTask::Ordering::kUnordered: - // Use the nominal value directly. - f = features[split_index_]; + // Use 0 for "!=" and 1 for "==". + f = FeatureValue(features[split_index_] == split_point_); break; case LearningTask::Ordering::kNumeric: // Use 0 for "<=" and 1 for ">". @@ -58,18 +57,9 @@ auto iter = children_.find(f); - // If we've never seen this feature value, then average all our branches. - // This is an attempt to mimic one-hot encoding, where we'll take the zero - // branch but it depends on the tree structure which of the one-hot values - // we're choosing. - if (iter == children_.end()) { - switch (rt_unknown_value_handling_) { - case LearningTask::RTUnknownValueHandling::kEmptyDistribution: - return TargetDistribution(); - case LearningTask::RTUnknownValueHandling::kUseAllSplits: - return PredictDistributionWithMissingValues(features); - } - } + // If we've never seen this feature value, then return nothing. + if (iter == children_.end()) + return TargetDistribution(); return iter->second->PredictDistribution(features); } @@ -98,9 +88,6 @@ int split_index_ = -1; base::flat_map<FeatureValue, std::unique_ptr<Model>> children_; - // How we handle unknown values. - LearningTask::RTUnknownValueHandling rt_unknown_value_handling_; - // How is our feature value ordered? LearningTask::Ordering ordering_; @@ -227,6 +214,11 @@ } // Select the feature subset to consider at this leaf. + // TODO(liberato): For nominals, with one-hot encoding, we'd give an equal + // chance to each feature's value. For example, if F1 has {A, B} and F2 has + // {C,D,E,F}, then we would pick uniformly over {A,B,C,D,E,F}. However, now + // we pick between {F1, F2} then pick between either {A,B} or {C,D,E,F}. We + // do this because it's simpler and doesn't seem to hurt anything. FeatureSet feature_candidates = new_unused_set; // TODO(liberato): Let our caller override this. const size_t features_per_split = @@ -267,17 +259,6 @@ std::unique_ptr<InteriorNode> node = std::make_unique<InteriorNode>( task, best_potential_split.split_index, best_potential_split.split_point); - // Don't let the subtree use this feature if this is nominal split, since - // there's nothing left to split. For numeric splits, we might want to split - // it further. Note that if there is only one branch for this split, then - // we returned a leaf anyway. - if (task.feature_descriptions[best_potential_split.split_index].ordering == - LearningTask::Ordering::kUnordered) { - DCHECK(new_unused_set.find(best_potential_split.split_index) != - new_unused_set.end()); - new_unused_set.erase(best_potential_split.split_index); - } - for (auto& branch_iter : best_potential_split.branch_infos) { node->AddChild(branch_iter.first, Build(task, training_data, branch_iter.second.training_idx, @@ -297,18 +278,21 @@ DCHECK_GT(training_idx.size(), 0u); Split split(split_index); - base::Optional<FeatureValue> split_point; + + bool is_numeric = task.feature_descriptions[split_index].ordering == + LearningTask::Ordering::kNumeric; // TODO(liberato): Consider removing nominal feature support and RF. That // would make this code somewhat simpler. // For a numeric split, find the split point. Otherwise, we'll split on every // nominal value that this feature has in |training_data|. - if (task.feature_descriptions[split_index].ordering == - LearningTask::Ordering::kNumeric) { - split_point = - FindNumericSplitPoint(split.split_index, training_data, training_idx); - split.split_point = *split_point; + if (is_numeric) { + split.split_point = + FindSplitPoint_Numeric(split.split_index, training_data, training_idx); + } else { + split.split_point = + FindSplitPoint_Nominal(split.split_index, training_data, training_idx); } // Find the split's feature values and construct the training set for each. @@ -323,13 +307,14 @@ FeatureValue v_i = example.features[split.split_index]; // Figure out what value this example would use for splitting. For nominal, - // it's just |v_i|. For numeric, it's whether |v_i| is <= the split point - // or not (0 for <=, 1 for >). + // it's 1 or 0, based on whether |v_i| is equal to the split or not. For + // numeric, it's whether |v_i| is <= the split point or not (0 for <=, and 1 + // for >). FeatureValue split_feature; - if (split_point) - split_feature = FeatureValue(v_i > *split_point); + if (is_numeric) + split_feature = FeatureValue(v_i > split.split_point); else - split_feature = v_i; + split_feature = FeatureValue(v_i == split.split_point); // Add |v_i| to the right training set. Remember that emplace will do // nothing if the key already exists. @@ -345,18 +330,18 @@ // Figure out how good / bad this split is. switch (task.target_description.ordering) { case LearningTask::Ordering::kUnordered: - ComputeNominalSplitScore(&split, total_weight); + ComputeSplitScore_Nominal(&split, total_weight); break; case LearningTask::Ordering::kNumeric: - ComputeNumericSplitScore(&split, total_weight); + ComputeSplitScore_Numeric(&split, total_weight); break; } return split; } -void RandomTreeTrainer::ComputeNominalSplitScore(Split* split, - double total_weight) { +void RandomTreeTrainer::ComputeSplitScore_Nominal(Split* split, + double total_weight) { // Compute the nats given that we're at this node. split->nats_remaining = 0; for (auto& info_iter : split->branch_infos) { @@ -374,8 +359,8 @@ } } -void RandomTreeTrainer::ComputeNumericSplitScore(Split* split, - double total_weight) { +void RandomTreeTrainer::ComputeSplitScore_Numeric(Split* split, + double total_weight) { // Compute the nats given that we're at this node. split->nats_remaining = 0; for (auto& info_iter : split->branch_infos) { @@ -402,7 +387,7 @@ } } -FeatureValue RandomTreeTrainer::FindNumericSplitPoint( +FeatureValue RandomTreeTrainer::FindSplitPoint_Numeric( size_t split_index, const TrainingData& training_data, const std::vector<size_t>& training_idx) { @@ -444,5 +429,42 @@ return v_split; } +FeatureValue RandomTreeTrainer::FindSplitPoint_Nominal( + size_t split_index, + const TrainingData& training_data, + const std::vector<size_t>& training_idx) { + // We should not be given a training set of size 0, since there's no need to + // check an empty split. + DCHECK_GT(training_idx.size(), 0u); + + // Construct a set of all values for |training_idx|. We don't care about + // their relative frequency, since one-hot encoding doesn't. + // For example, if a feature has 10 "yes" instances and 1 "no" instance, then + // there's a 50% chance for each to be chosen here. This is because one-hot + // encoding would do roughly the same thing: when choosing features, the + // "is_yes" and "is_no" features that come out of one-hot encoding would be + // equally likely to be chosen. + // + // Important but subtle note: we can't choose a value that's been chosen + // before for this feature, since that would be like splitting on the same + // one-hot feature more than once. Luckily, we won't be asked to do that. If + // we choose "Yes" at some level in the tree, then the "==" branch will have + // trivial features which will be removed from consideration early (we never + // consider features with only one value), and the != branch won't have any + // "Yes" values for us to pick at a lower level. + std::set<FeatureValue> values; + for (size_t idx : training_idx) { + const LabelledExample& example = training_data[idx]; + values.insert(example.features[split_index]); + } + + // Select one uniformly at random. + size_t which = rng()->Generate(values.size()); + auto it = values.begin(); + for (; which > 0; it++, which--) + ; + return *it; +} + } // namespace learning } // namespace media
diff --git a/media/learning/impl/random_tree_trainer.h b/media/learning/impl/random_tree_trainer.h index 0c764bc1..3383e55 100644 --- a/media/learning/impl/random_tree_trainer.h +++ b/media/learning/impl/random_tree_trainer.h
@@ -160,15 +160,20 @@ // Fill in |nats_remaining| for |split| for a nominal target. |total_weight| // is the total weight of all instances coming into this split. - void ComputeNominalSplitScore(Split* split, double total_weight); + void ComputeSplitScore_Nominal(Split* split, double total_weight); // Fill in |nats_remaining| for |split| for a numeric target. - void ComputeNumericSplitScore(Split* split, double total_weight); + void ComputeSplitScore_Numeric(Split* split, double total_weight); + + // Compute the split point for |training_data| for a nominal feature. + FeatureValue FindSplitPoint_Nominal(size_t index, + const TrainingData& training_data, + const std::vector<size_t>& training_idx); // Compute the split point for |training_data| for a numeric feature. - FeatureValue FindNumericSplitPoint(size_t index, - const TrainingData& training_data, - const std::vector<size_t>& training_idx); + FeatureValue FindSplitPoint_Numeric(size_t index, + const TrainingData& training_data, + const std::vector<size_t>& training_idx); DISALLOW_COPY_AND_ASSIGN(RandomTreeTrainer); };
diff --git a/media/learning/impl/random_tree_trainer_unittest.cc b/media/learning/impl/random_tree_trainer_unittest.cc index c090b936..6af9e94 100644 --- a/media/learning/impl/random_tree_trainer_unittest.cc +++ b/media/learning/impl/random_tree_trainer_unittest.cc
@@ -169,30 +169,17 @@ training_data.push_back(example_1); training_data.push_back(example_2); - task_.rt_unknown_value_handling = - LearningTask::RTUnknownValueHandling::kEmptyDistribution; - std::unique_ptr<Model> model = Train(task_, training_data); - TargetDistribution distribution = + auto model = Train(task_, training_data); + auto distribution = model->PredictDistribution(FeatureVector({FeatureValue(789)})); if (ordering_ == LearningTask::Ordering::kUnordered) { - // OOV data should return an empty distribution (nominal). - EXPECT_EQ(distribution.size(), 0u); - } else { - // OOV data should end up in the |example_2| bucket, since the feature is - // numerically higher. + // OOV data could be split on either feature first, so we don't really know + // which to expect. We assert that there should be exactly one example, but + // whether it's |example_1| or |example_2| isn't clear. EXPECT_EQ(distribution.size(), 1u); - EXPECT_EQ(distribution[example_2.target_value], 1u); - } - - task_.rt_unknown_value_handling = - LearningTask::RTUnknownValueHandling::kUseAllSplits; - model = Train(task_, training_data); - distribution = model->PredictDistribution(FeatureVector({FeatureValue(789)})); - if (ordering_ == LearningTask::Ordering::kUnordered) { - // OOV data should return with the sum of all splits. - EXPECT_EQ(distribution.size(), 2u); - EXPECT_EQ(distribution[example_1.target_value], 1u); - EXPECT_EQ(distribution[example_2.target_value], 1u); + EXPECT_EQ(distribution[example_1.target_value] + + distribution[example_2.target_value], + 1u); } else { // The unknown feature is numerically higher than |example_2|, so we // expect it to fall into that bucket. @@ -212,8 +199,6 @@ training_data.push_back(example); } - task_.rt_unknown_value_handling = - LearningTask::RTUnknownValueHandling::kEmptyDistribution; std::unique_ptr<Model> model = Train(task_, training_data); for (size_t i = 0; i < 4; i++) { // Get a prediction for the |i|-th feature value.
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni index 86c0ea48..6cd039e 100644 --- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni +++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -8,7 +8,7 @@ "//chrome/common/importer/typemaps.gni", "//chrome/common/media_router/mojo/typemaps.gni", "//chrome/typemaps.gni", - "//chromecast/common/mojom/typemaps.gni", + "//chromecast/typemaps.gni", "//chromeos/typemaps.gni", "//chromeos/components/multidevice/mojom/typemaps.gni", "//chromeos/services/secure_channel/public/mojom/typemaps.gni",
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni index a7d25a1..7469312 100644 --- a/mojo/public/tools/bindings/mojom.gni +++ b/mojo/public/tools/bindings/mojom.gni
@@ -13,6 +13,7 @@ # Chrome builds. Ideally we could create some generic knobs here that could be # flipped elsewhere though. import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.gni") import("//build/config/nacl/config.gni") import("//components/nacl/features.gni") import("//third_party/jinja2/jinja2.gni") @@ -56,7 +57,7 @@ # check |target_os| explicitly, as it's consistent across all toolchains. enable_scrambled_message_ids = enable_mojom_message_id_scrambling && - (is_mac || is_win || (is_linux && !is_chromeos) || + (is_mac || is_win || (is_linux && !is_chromeos && !is_chromecast) || ((enable_nacl || is_nacl || is_nacl_nonsfi) && target_os != "chromeos")) mojom_generator_root = "//mojo/public/tools/bindings"
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index 57655c5..e39b8c4 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h
@@ -261,9 +261,12 @@ NET_ERROR(TEMPORARILY_THROTTLED, -139) // A request to create an SSL tunnel connection through the HTTPS proxy -// received a non-200 (OK) and non-407 (Proxy Auth) response. The response -// body might include a description of why the request failed. -NET_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE, -140) +// received a 302 (temporary redirect) response. The response body might +// include a description of why the request failed. +// +// TODO(https://crbug.com/928551): This is deprecated and should not be used by +// new code. +NET_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT, -140) // We were unable to sign the CertificateVerify data of an SSL client auth // handshake with the client certificate's private key.
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index 2534f30..7bff65d 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -482,10 +482,12 @@ } // start id from 1 to distinguish from NULL RequestHandle -MockHostResolverBase::MockHostResolverBase(bool use_caching) +MockHostResolverBase::MockHostResolverBase(bool use_caching, + int cache_invalidation_num) : last_request_priority_(DEFAULT_PRIORITY), synchronous_mode_(false), ondemand_mode_(false), + initial_cache_invalidation_num_(cache_invalidation_num), next_request_id_(1), num_resolve_(0), num_resolve_from_cache_(0), @@ -497,9 +499,10 @@ rules_map_[HostResolverSource::MULTICAST_DNS] = CreateCatchAllHostResolverProc(); - if (use_caching) { + if (use_caching) cache_.reset(new HostCache(kMaxCacheEntries)); - } + else + DCHECK_GE(0, cache_invalidation_num); } int MockHostResolverBase::Resolve(RequestImpl* request) { @@ -602,6 +605,18 @@ AddressList::CopyWithPort(entry->addresses().value(), host.port()); *out_stale_info = std::move(stale_info); } + + auto cache_invalidation_iterator = cache_invalidation_nums_.find(key); + if (cache_invalidation_iterator != cache_invalidation_nums_.end()) { + DCHECK_LE(1, cache_invalidation_iterator->second); + cache_invalidation_iterator->second--; + if (cache_invalidation_iterator->second == 0) { + HostCache::Entry new_entry(*entry); + cache_->Set(key, new_entry, tick_clock_->NowTicks(), + base::TimeDelta()); + cache_invalidation_nums_.erase(cache_invalidation_iterator); + } + } } } return rv; @@ -624,8 +639,11 @@ flags, source); // Storing a failure with TTL 0 so that it overwrites previous value. base::TimeDelta ttl; - if (rv == OK) + if (rv == OK) { ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); + if (initial_cache_invalidation_num_ > 0) + cache_invalidation_nums_[key] = initial_cache_invalidation_num_; + } cache_->Set(key, HostCache::Entry(rv, addr, HostCache::Entry::SOURCE_UNKNOWN), tick_clock_->NowTicks(), ttl);
diff --git a/net/dns/mock_host_resolver.h b/net/dns/mock_host_resolver.h index 2927a4b..96630e6 100644 --- a/net/dns/mock_host_resolver.h +++ b/net/dns/mock_host_resolver.h
@@ -216,12 +216,17 @@ tick_clock_ = tick_clock; } - protected: - explicit MockHostResolverBase(bool use_caching); - private: + friend class MockHostResolver; + friend class MockCachingHostResolver; + typedef std::map<size_t, RequestImpl*> RequestMap; + // If > 0, |cache_invalidation_num| is the number of times a cached entry can + // be read before it invalidates itself. Useful to force cache expiration + // scenarios. + explicit MockHostResolverBase(bool use_caching, int cache_invalidation_num); + // Handle resolution for |request|. Expected to be called only the RequestImpl // object itself. int Resolve(RequestImpl* request); @@ -253,6 +258,9 @@ rules_map_; std::unique_ptr<HostCache> cache_; + const int initial_cache_invalidation_num_; + std::map<HostCache::Key, int> cache_invalidation_nums_; + // Maintain non-owning pointers to outstanding requests and listeners to allow // completing/notifying them. The objects are owned by callers, and should be // removed from |this| on destruction by calling DetachRequest() or @@ -274,7 +282,9 @@ class MockHostResolver : public MockHostResolverBase { public: - MockHostResolver() : MockHostResolverBase(false /*use_caching*/) {} + MockHostResolver() + : MockHostResolverBase(false /*use_caching*/, + 0 /* cache_invalidation_num */) {} ~MockHostResolver() override {} }; @@ -285,7 +295,11 @@ // operation mode in case that is what you needed from the caching version). class MockCachingHostResolver : public MockHostResolverBase { public: - MockCachingHostResolver() : MockHostResolverBase(true /*use_caching*/) {} + // If > 0, |cache_invalidation_num| is the number of times a cached entry can + // be read before it invalidates itself. Useful to force cache expiration + // scenarios. + explicit MockCachingHostResolver(int cache_invalidation_num = 0) + : MockHostResolverBase(true /*use_caching*/, cache_invalidation_num) {} ~MockCachingHostResolver() override {} };
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc index 45e80ac..8f4a8622 100644 --- a/net/ftp/ftp_network_transaction.cc +++ b/net/ftp/ftp_network_transaction.cc
@@ -19,6 +19,7 @@ #include "net/base/address_list.h" #include "net/base/completion_once_callback.h" #include "net/base/escape.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/parse_number.h" #include "net/base/port_util.h" @@ -691,7 +692,7 @@ IPEndPoint ip_endpoint; result = ctrl_socket_->GetPeerAddress(&ip_endpoint); if (result == OK) { - response_.socket_address = HostPortPair::FromIPEndPoint(ip_endpoint); + response_.remote_endpoint = ip_endpoint; next_state_ = STATE_CTRL_READ; if (ip_endpoint.GetFamily() == ADDRESS_FAMILY_IPV4) {
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc index 1740da9..ce412717 100644 --- a/net/ftp/ftp_network_transaction_unittest.cc +++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -9,8 +9,8 @@ #include "base/memory/ref_counted.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "net/base/host_port_pair.h" #include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" #include "net/base/test_completion_callback.h" #include "net/dns/mock_host_resolver.h" #include "net/ftp/ftp_request_info.h" @@ -907,9 +907,10 @@ EXPECT_TRUE(transaction_->GetResponseInfo()->is_directory_listing); EXPECT_EQ(-1, transaction_->GetResponseInfo()->expected_content_size); - EXPECT_EQ((GetFamily() == AF_INET) ? "127.0.0.1" : "::1", - transaction_->GetResponseInfo()->socket_address.host()); - EXPECT_EQ(21, transaction_->GetResponseInfo()->socket_address.port()); + EXPECT_EQ( + (GetFamily() == AF_INET) ? "127.0.0.1" : "::1", + transaction_->GetResponseInfo()->remote_endpoint.ToStringWithoutPort()); + EXPECT_EQ(21, transaction_->GetResponseInfo()->remote_endpoint.port()); } TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithPasvFallback) { @@ -990,9 +991,10 @@ // We pass an artificial value of 18 as a response to the SIZE command. EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size); - EXPECT_EQ((GetFamily() == AF_INET) ? "127.0.0.1" : "::1", - transaction_->GetResponseInfo()->socket_address.host()); - EXPECT_EQ(21, transaction_->GetResponseInfo()->socket_address.port()); + EXPECT_EQ( + (GetFamily() == AF_INET) ? "127.0.0.1" : "::1", + transaction_->GetResponseInfo()->remote_endpoint.ToStringWithoutPort()); + EXPECT_EQ(21, transaction_->GetResponseInfo()->remote_endpoint.port()); } TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithPasvFallback) {
diff --git a/net/ftp/ftp_response_info.h b/net/ftp/ftp_response_info.h index 70d36536..d20249a0 100644 --- a/net/ftp/ftp_response_info.h +++ b/net/ftp/ftp_response_info.h
@@ -8,7 +8,7 @@ #include <stdint.h> #include "base/time/time.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" namespace net { @@ -37,7 +37,7 @@ bool is_directory_listing; // Remote address of the socket which fetched this resource. - HostPortPair socket_address; + IPEndPoint remote_endpoint; }; } // namespace net
diff --git a/net/http/bidirectional_stream.cc b/net/http/bidirectional_stream.cc index 3530487..404ac07 100644 --- a/net/http/bidirectional_stream.cc +++ b/net/http/bidirectional_stream.cc
@@ -420,14 +420,14 @@ StartRequest(ssl_config); } -void BidirectionalStream::OnHttpsProxyTunnelResponse( +void BidirectionalStream::OnHttpsProxyTunnelResponseRedirect( const HttpResponseInfo& response_info, const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<HttpStream> stream) { DCHECK(stream_request_); - NotifyFailed(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); + NotifyFailed(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT); } void BidirectionalStream::OnQuicBroken() {}
diff --git a/net/http/bidirectional_stream.h b/net/http/bidirectional_stream.h index 61fa08c..2cfeca0 100644 --- a/net/http/bidirectional_stream.h +++ b/net/http/bidirectional_stream.h
@@ -218,10 +218,11 @@ HttpAuthController* auth_controller) override; void OnNeedsClientAuth(const SSLConfig& used_ssl_config, SSLCertRequestInfo* cert_info) override; - void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info, - const SSLConfig& used_ssl_config, - const ProxyInfo& used_proxy_info, - std::unique_ptr<HttpStream> stream) override; + void OnHttpsProxyTunnelResponseRedirect( + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + std::unique_ptr<HttpStream> stream) override; void OnQuicBroken() override; // Helper method to notify delegate if there is an error.
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index bd10e49a..dc68d9ee 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -8381,10 +8381,12 @@ // Tests basic pickling/unpickling of HttpResponseInfo. TEST_F(HttpCacheTest, PersistHttpResponseInfo) { + const IPEndPoint expected_endpoint = + IPEndPoint(net::IPAddress(1, 2, 3, 4), 80); // Set some fields (add more if needed.) HttpResponseInfo response1; response1.was_cached = false; - response1.socket_address = HostPortPair("1.2.3.4", 80); + response1.remote_endpoint = expected_endpoint; response1.headers = new HttpResponseHeaders("HTTP/1.1 200 OK"); // Pickle. @@ -8399,8 +8401,7 @@ // Verify fields. EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag. - EXPECT_EQ("1.2.3.4", response2.socket_address.host()); - EXPECT_EQ(80, response2.socket_address.port()); + EXPECT_EQ(expected_endpoint, response2.remote_endpoint); EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); }
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 397f54b..e20860ca 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc
@@ -648,7 +648,7 @@ OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED); } -void HttpNetworkTransaction::OnHttpsProxyTunnelResponse( +void HttpNetworkTransaction::OnHttpsProxyTunnelResponseRedirect( const HttpResponseInfo& response_info, const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, @@ -668,7 +668,7 @@ stream_ = std::move(stream); stream_->SetRequestHeadersCallback(request_headers_callback_); stream_request_.reset(); // we're done with the stream request - OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); + OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT); } void HttpNetworkTransaction::OnQuicBroken() { @@ -854,11 +854,12 @@ } int HttpNetworkTransaction::DoCreateStreamComplete(int result) { - // If |result| is ERR_HTTPS_PROXY_TUNNEL_RESPONSE, then - // DoCreateStreamComplete is being called from OnHttpsProxyTunnelResponse, - // which resets the stream request first. Therefore, we have to grab the - // connection attempts in *that* function instead of here in that case. - if (result != ERR_HTTPS_PROXY_TUNNEL_RESPONSE) + // If |result| is ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT, then + // DoCreateStreamComplete is being called from + // OnHttpsProxyTunnelResponseRedirect, which resets the stream request first. + // Therefore, we have to grab the connection attempts in *that* function + // instead of here in that case. + if (result != ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) CopyConnectionAttemptsFromStreamRequest(); if (result == OK) { @@ -866,10 +867,8 @@ DCHECK(stream_.get()); } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { result = HandleCertificateRequest(result); - } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { - // Return OK and let the caller read the proxy's error page - next_state_ = STATE_NONE; - return OK; + } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) { + return DoCreateStreamCompletedTunnelResponseRedirect(); } else if (result == ERR_HTTP_1_1_REQUIRED || result == ERR_PROXY_HTTP_1_1_REQUIRED) { return HandleHttp11Required(result); @@ -1943,4 +1942,45 @@ return result; } +static HttpNetworkTransaction::TunnelRedirectHistogramValue +GetTunnelRedirectHistogramValue(bool is_main_frame, bool was_auto_detected) { + if (!is_main_frame && !was_auto_detected) + return HttpNetworkTransaction::kSubresourceByExplicitProxy; + if (is_main_frame && !was_auto_detected) + return HttpNetworkTransaction::kMainFrameByExplicitProxy; + if (!is_main_frame && was_auto_detected) + return HttpNetworkTransaction::kSubresourceByAutoDetectedProxy; + return HttpNetworkTransaction::kMainFrameByAutoDetectedProxy; +} + +// TODO(https://crbug.com/928551): Support for redirect on CONNECT is +// deprecated, and support will be removed. +// +// The code in this method handles the temporary histogramming and +// compatibility-mode policy during the phase-out. +int HttpNetworkTransaction::DoCreateStreamCompletedTunnelResponseRedirect() { + bool is_main_frame = (request_->load_flags & LOAD_MAIN_FRAME_DEPRECATED) == + LOAD_MAIN_FRAME_DEPRECATED; + bool was_auto_detected = proxy_info_.did_use_auto_detected_pac_script(); + + UMA_HISTOGRAM_ENUMERATION( + "Net.Proxy.RedirectDuringConnect", + GetTunnelRedirectHistogramValue(is_main_frame, was_auto_detected)); + + // For legacy compatibility, the proxy is allowed to redirect CONNECT + // if: + // (a) the request was for a top-level frame + // (b) the proxy server was explicitly configured (i.e. not + // auto-detected). + if (is_main_frame && !was_auto_detected) { + // Return OK and let the caller read the proxy's error page + next_state_ = STATE_NONE; + return OK; + } + + // Otherwise let the request fail. + stream_.reset(); + return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT; +} + } // namespace net
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h index 7ccc5f9..736c98f 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h
@@ -50,6 +50,16 @@ : public HttpTransaction, public HttpStreamRequest::Delegate { public: + // Enumeration used by Net.Proxy.RedirectDuringConnect. Exposed here for + // sharing by unit-tests. + enum TunnelRedirectHistogramValue { + kSubresourceByExplicitProxy = 0, + kMainFrameByExplicitProxy = 1, + kSubresourceByAutoDetectedProxy = 2, + kMainFrameByAutoDetectedProxy = 3, + kMaxValue = kMainFrameByAutoDetectedProxy + }; + HttpNetworkTransaction(RequestPriority priority, HttpNetworkSession* session); @@ -117,10 +127,11 @@ HttpAuthController* auth_controller) override; void OnNeedsClientAuth(const SSLConfig& used_ssl_config, SSLCertRequestInfo* cert_info) override; - void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info, - const SSLConfig& used_ssl_config, - const ProxyInfo& used_proxy_info, - std::unique_ptr<HttpStream> stream) override; + void OnHttpsProxyTunnelResponseRedirect( + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + std::unique_ptr<HttpStream> stream) override; void OnQuicBroken() override; void GetConnectionAttempts(ConnectionAttempts* out) const override; @@ -309,6 +320,10 @@ // "Accept-Encoding". bool ContentEncodingsValid() const; + // Logic for handling ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT seen during + // DoCreateStreamCompletedTunnel(). + int DoCreateStreamCompletedTunnelResponseRedirect(); + scoped_refptr<HttpAuthController> auth_controllers_[HttpAuth::AUTH_NUM_TARGETS];
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 9295d8cdf..b3ac220 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -39,6 +39,7 @@ #include "net/base/completion_once_callback.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" #include "net/base/net_errors.h" @@ -51,7 +52,6 @@ #include "net/base/upload_file_element_reader.h" #include "net/cert/cert_status_flags.h" #include "net/cert/mock_cert_verifier.h" -#include "net/dns/host_cache.h" #include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/http_auth_handler_digest.h" @@ -470,8 +470,8 @@ } out.status_line = response->headers->GetStatusLine(); - EXPECT_EQ("127.0.0.1", response->socket_address.host()); - EXPECT_EQ(80, response->socket_address.port()); + EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort()); + EXPECT_EQ(80, response->remote_endpoint.port()); bool got_endpoint = trans.GetRemoteEndpoint(&out.remote_endpoint_after_start); @@ -9498,7 +9498,7 @@ CONNECT_TIMING_HAS_SSL_TIMES); } -// Test an HTTPS Proxy's ability to redirect a CONNECT request +// Test that an HTTPS Proxy can redirect a CONNECT request for main frames. TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) { session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixedFromPacResult( @@ -9511,6 +9511,7 @@ session_deps_.host_resolver->set_ondemand_mode(true); HttpRequestInfo request; + request.load_flags = LOAD_MAIN_FRAME_DEPRECATED; request.method = "GET"; request.url = GURL("https://www.example.org/"); request.traffic_annotation = @@ -9582,7 +9583,7 @@ // name, and negotiate an SSL connection to it (Neither of which are done in // this case), which the DNS and SSL times for the proxy are all included in // connect_start / connect_end. See - // HttpNetworkTransaction::OnHttpsProxyTunnelResponse. + // HttpNetworkTransaction::OnHttpsProxyTunnelResponseRedirect EXPECT_TRUE(load_timing_info.connect_timing.dns_start.is_null()); EXPECT_TRUE(load_timing_info.connect_timing.dns_end.is_null()); @@ -9600,8 +9601,114 @@ EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); } -// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request +// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources. +TEST_F(HttpNetworkTransactionTest, + RedirectOfHttpsConnectSubresourceViaHttpsProxy) { + base::HistogramTester histograms; + session_deps_.proxy_resolution_service = + ProxyResolutionService::CreateFixedFromPacResult( + "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS); + TestNetLog net_log; + session_deps_.net_log = &net_log; + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite(ASYNC, 0, + "CONNECT www.example.org:443 HTTP/1.1\r\n" + "Host: www.example.org:443\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"), + }; + + MockRead data_reads[] = { + MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"), + MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"), + MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"), + }; + + SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes); + SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy + + session_deps_.socket_factory->AddSocketDataProvider(&data); + session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); + + TestCompletionCallback callback; + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); + + int rv = trans.Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT)); + + histograms.ExpectUniqueSample( + "Net.Proxy.RedirectDuringConnect", + HttpNetworkTransaction::kSubresourceByExplicitProxy, 1); +} + +// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT +// request for main frames. +TEST_F(HttpNetworkTransactionTest, + RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) { + base::HistogramTester histograms; + session_deps_.proxy_resolution_service = + ProxyResolutionService::CreateFixedFromAutoDetectedPacResult( + "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS); + TestNetLog net_log; + session_deps_.net_log = &net_log; + + HttpRequestInfo request; + request.load_flags = LOAD_MAIN_FRAME_DEPRECATED; + request.method = "GET"; + request.url = GURL("https://www.example.org/"); + request.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + + MockWrite data_writes[] = { + MockWrite(ASYNC, 0, + "CONNECT www.example.org:443 HTTP/1.1\r\n" + "Host: www.example.org:443\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"), + }; + + MockRead data_reads[] = { + MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"), + MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"), + MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"), + }; + + SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes); + SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy + + session_deps_.socket_factory->AddSocketDataProvider(&data); + session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); + + TestCompletionCallback callback; + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); + + int rv = trans.Start(&request, callback.callback(), NetLogWithSource()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + + rv = callback.WaitForResult(); + EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT)); + + histograms.ExpectUniqueSample( + "Net.Proxy.RedirectDuringConnect", + HttpNetworkTransaction::kMainFrameByAutoDetectedProxy, 1); +} + +// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request for main +// frames. TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { + base::HistogramTester histograms; session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed( "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS); TestNetLog net_log; @@ -9613,6 +9720,7 @@ HttpRequestInfo request; request.method = "GET"; + request.load_flags = LOAD_MAIN_FRAME_DEPRECATED; request.url = GURL("https://www.example.org/"); request.traffic_annotation = net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); @@ -9692,7 +9800,7 @@ // name, and negotiate an SSL connection to it (Neither of which are done in // this case), which the DNS and SSL times for the proxy are all included in // connect_start / connect_end. See - // HttpNetworkTransaction::OnHttpsProxyTunnelResponse. + // HttpNetworkTransaction::OnHttpsProxyTunnelResponseRedirect. EXPECT_TRUE(load_timing_info.connect_timing.dns_start.is_null()); EXPECT_TRUE(load_timing_info.connect_timing.dns_end.is_null()); @@ -9706,6 +9814,10 @@ EXPECT_TRUE(load_timing_info.send_start.is_null()); EXPECT_TRUE(load_timing_info.send_end.is_null()); EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); + + histograms.ExpectUniqueSample( + "Net.Proxy.RedirectDuringConnect", + HttpNetworkTransaction::kMainFrameByExplicitProxy, 1); } // Test that an HTTPS proxy's response to a CONNECT request is filtered. @@ -15744,30 +15856,11 @@ EXPECT_EQ("hello!", response_data); } -class OneTimeCachingHostResolver : public MockHostResolverBase { - public: - explicit OneTimeCachingHostResolver(const HostPortPair& host_port) - : MockHostResolverBase(/* use_caching = */ true), host_port_(host_port) {} - ~OneTimeCachingHostResolver() override = default; - - int ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const NetLogWithSource& net_log) override { - int rv = MockHostResolverBase::ResolveFromCache(info, addresses, net_log); - if (rv == OK && info.host_port_pair().Equals(host_port_)) - GetHostCache()->clear(); - return rv; - } - - private: - const HostPortPair host_port_; -}; - TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingWithHostCacheExpiration) { - // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver. - session_deps_.host_resolver = std::make_unique<OneTimeCachingHostResolver>( - HostPortPair("mail.example.com", 443)); + // Set up HostResolver to invalidate cached entries after 1 cached resolve. + session_deps_.host_resolver = + std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */); std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); AddSSLSocketData();
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc index 6c57135..68349676 100644 --- a/net/http/http_proxy_client_socket.cc +++ b/net/http/http_proxy_client_socket.cc
@@ -507,7 +507,7 @@ stream_socket_.reset(); socket_ = nullptr; is_reused_ = false; - return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; + return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT; case 407: // Proxy Authentication Required // We need this status code to allow proxy authentication. Our
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index 457b4a9..9f4509b 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -436,7 +436,7 @@ EXPECT_FALSE(handle_.socket()); } else { // Expect ProxyClientSocket to return the proxy's response, sanitized. - EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE)); + EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT)); EXPECT_TRUE(handle_.is_initialized()); ASSERT_TRUE(handle_.socket());
diff --git a/net/http/http_proxy_connect_job.cc b/net/http/http_proxy_connect_job.cc index a202d79..a820e4c8 100644 --- a/net/http/http_proxy_connect_job.cc +++ b/net/http/http_proxy_connect_job.cc
@@ -279,7 +279,7 @@ error_response_info_ = client_socket_->GetAdditionalErrorState(); if (result == OK || result == ERR_PROXY_AUTH_REQUESTED || - result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { + result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) { SetSocket(std::move(client_socket_)); } return result;
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc index 4764795..0dfb809 100644 --- a/net/http/http_response_info.cc +++ b/net/http/http_response_info.cc
@@ -229,7 +229,13 @@ uint16_t socket_address_port; if (!iter.ReadUInt16(&socket_address_port)) return false; - socket_address = HostPortPair(socket_address_host, socket_address_port); + + IPAddress ip_address; + if (ip_address.AssignFromIPLiteral(socket_address_host)) { + remote_endpoint = IPEndPoint(ip_address, socket_address_port); + } else if (ParseURLHostnameToAddress(socket_address_host, &ip_address)) { + remote_endpoint = IPEndPoint(ip_address, socket_address_port); + } // Read protocol-version. if (flags & RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL) { @@ -364,8 +370,8 @@ if (vary_data.is_valid()) vary_data.Persist(pickle); - pickle->WriteString(socket_address.host()); - pickle->WriteUInt16(socket_address.port()); + pickle->WriteString(remote_endpoint.ToStringWithoutPort()); + pickle->WriteUInt16(remote_endpoint.port()); if (was_alpn_negotiated) pickle->WriteString(alpn_negotiated_protocol);
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h index ca364d7..48fea75 100644 --- a/net/http/http_response_info.h +++ b/net/http/http_response_info.h
@@ -8,6 +8,7 @@ #include <string> #include "base/time/time.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_export.h" #include "net/base/proxy_server.h" #include "net/http/http_vary_data.h" @@ -170,7 +171,7 @@ // originally. This is true even if the response was re-validated using a // different remote address, or if some of the content came from a byte-range // request to a different address. - HostPortPair socket_address; + IPEndPoint remote_endpoint; // Protocol negotiated with the server. std::string alpn_negotiated_protocol;
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index f7158e1..4f72e404 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc
@@ -530,13 +530,13 @@ // |this| may be deleted after this call. } -void HttpStreamFactory::Job::OnHttpsProxyTunnelResponseCallback( +void HttpStreamFactory::Job::OnHttpsProxyTunnelResponseRedirectCallback( const HttpResponseInfo& response_info, std::unique_ptr<HttpStream> stream) { DCHECK_NE(job_type_, PRECONNECT); - delegate_->OnHttpsProxyTunnelResponse(this, response_info, server_ssl_config_, - proxy_info_, std::move(stream)); + delegate_->OnHttpsProxyTunnelResponseRedirect( + this, response_info, server_ssl_config_, proxy_info_, std::move(stream)); // |this| may be deleted after this call. } @@ -639,7 +639,7 @@ connection_->ssl_error_response_info().cert_request_info))); return; - case ERR_HTTPS_PROXY_TUNNEL_RESPONSE: { + case ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT: { DCHECK(connection_.get()); DCHECK(connection_->socket()); DCHECK(establishing_tunnel_); @@ -652,7 +652,7 @@ base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce( - &Job::OnHttpsProxyTunnelResponseCallback, + &Job::OnHttpsProxyTunnelResponseRedirectCallback, ptr_factory_.GetWeakPtr(), *proxy_socket->GetConnectResponseInfo(), std::make_unique<ProxyConnectRedirectHttpStream>( @@ -1096,7 +1096,7 @@ } if (result == ERR_PROXY_AUTH_REQUESTED || - result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { + result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) { DCHECK(!ssl_started); // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an // SSL socket, but there was an error before that could happen. This
diff --git a/net/http/http_stream_factory_job.h b/net/http/http_stream_factory_job.h index 4d50b0c7..7dc0399 100644 --- a/net/http/http_stream_factory_job.h +++ b/net/http/http_stream_factory_job.h
@@ -92,9 +92,9 @@ const SSLConfig& used_ssl_config, const SSLInfo& ssl_info) = 0; - // Invoked when |job| has a failure of the CONNECT request through an HTTPS - // proxy. - virtual void OnHttpsProxyTunnelResponse( + // Invoked when |job| has a failure of the CONNECT request (due to a 302 + // redirect) through an HTTPS proxy. + virtual void OnHttpsProxyTunnelResponseRedirect( Job* job, const HttpResponseInfo& response_info, const SSLConfig& used_ssl_config, @@ -302,8 +302,9 @@ void OnNeedsProxyAuthCallback(const HttpResponseInfo& response_info, HttpAuthController* auth_controller); void OnNeedsClientAuthCallback(SSLCertRequestInfo* cert_info); - void OnHttpsProxyTunnelResponseCallback(const HttpResponseInfo& response_info, - std::unique_ptr<HttpStream> stream); + void OnHttpsProxyTunnelResponseRedirectCallback( + const HttpResponseInfo& response_info, + std::unique_ptr<HttpStream> stream); void OnPreconnectsComplete(); void OnIOComplete(int result);
diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stream_factory_job_controller.cc index 333031e..7c53ba1 100644 --- a/net/http/http_stream_factory_job_controller.cc +++ b/net/http/http_stream_factory_job_controller.cc
@@ -415,7 +415,7 @@ delegate_->OnCertificateError(status, used_ssl_config, ssl_info); } -void HttpStreamFactory::JobController::OnHttpsProxyTunnelResponse( +void HttpStreamFactory::JobController::OnHttpsProxyTunnelResponseRedirect( Job* job, const HttpResponseInfo& response_info, const SSLConfig& used_ssl_config, @@ -434,8 +434,8 @@ BindJob(job); if (!request_) return; - delegate_->OnHttpsProxyTunnelResponse(response_info, used_ssl_config, - used_proxy_info, std::move(stream)); + delegate_->OnHttpsProxyTunnelResponseRedirect( + response_info, used_ssl_config, used_proxy_info, std::move(stream)); } void HttpStreamFactory::JobController::OnNeedsClientAuth(
diff --git a/net/http/http_stream_factory_job_controller.h b/net/http/http_stream_factory_job_controller.h index 6c4c2b0..5a7b0ff4d 100644 --- a/net/http/http_stream_factory_job_controller.h +++ b/net/http/http_stream_factory_job_controller.h
@@ -120,13 +120,14 @@ const SSLConfig& used_ssl_config, const SSLInfo& ssl_info) override; - // Invoked when |job| has a failure of the CONNECT request through an HTTPS - // proxy. - void OnHttpsProxyTunnelResponse(Job* job, - const HttpResponseInfo& response_info, - const SSLConfig& used_ssl_config, - const ProxyInfo& used_proxy_info, - std::unique_ptr<HttpStream> stream) override; + // Invoked when |job| has a failure of the CONNECT request (due to 302 + // redirect) through an HTTPS proxy. + void OnHttpsProxyTunnelResponseRedirect( + Job* job, + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + std::unique_ptr<HttpStream> stream) override; // Invoked when |job| raises failure for SSL Client Auth. void OnNeedsClientAuth(Job* job,
diff --git a/net/http/http_stream_factory_test_util.h b/net/http/http_stream_factory_test_util.h index c186f10..c944019 100644 --- a/net/http/http_stream_factory_test_util.h +++ b/net/http/http_stream_factory_test_util.h
@@ -93,11 +93,11 @@ SSLCertRequestInfo* cert_info)); // std::unique_ptr is not copyable and therefore cannot be mocked. - void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info, - const SSLConfig& used_ssl_config, - const ProxyInfo& used_proxy_info, - std::unique_ptr<HttpStream> stream) override { - } + void OnHttpsProxyTunnelResponseRedirect( + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + std::unique_ptr<HttpStream> stream) override {} MOCK_METHOD0(OnQuicBroken, void());
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc index 216f10b..83ace9c 100644 --- a/net/http/http_stream_factory_unittest.cc +++ b/net/http/http_stream_factory_unittest.cc
@@ -265,11 +265,11 @@ void OnNeedsClientAuth(const SSLConfig& used_ssl_config, SSLCertRequestInfo* cert_info) override {} - void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info, - const SSLConfig& used_ssl_config, - const ProxyInfo& used_proxy_info, - std::unique_ptr<HttpStream> stream) override { - } + void OnHttpsProxyTunnelResponseRedirect( + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + std::unique_ptr<HttpStream> stream) override {} void OnQuicBroken() override {}
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index 7ceff48..95a2c9f9 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc
@@ -245,7 +245,7 @@ int result = stream_socket_->GetPeerAddress(&ip_endpoint); if (result != OK) return result; - response_->socket_address = HostPortPair::FromIPEndPoint(ip_endpoint); + response_->remote_endpoint = ip_endpoint; std::string request = request_line + headers.ToString(); request_headers_length_ = request.size();
diff --git a/net/http/http_stream_request.h b/net/http/http_stream_request.h index c07e7f6..602854c 100644 --- a/net/http/http_stream_request.h +++ b/net/http/http_stream_request.h
@@ -125,9 +125,9 @@ virtual void OnNeedsClientAuth(const SSLConfig& used_ssl_config, SSLCertRequestInfo* cert_info) = 0; - // This is the failure of the CONNECT request through an HTTPS proxy. - // Headers can be read from |response_info|, while the body can be read - // from |stream|. + // This is the failure of the CONNECT request through an HTTPS proxy due to + // a 302 redirect. Headers can be read from |response_info|, while the body + // can be read from |stream|. // // |used_ssl_config| indicates the actual SSL configuration used for this // stream, since the HttpStreamRequest may have modified the configuration @@ -137,7 +137,7 @@ // since the HttpStreamRequest performs the proxy resolution. // // Ownership of |stream| is transferred to the delegate. - virtual void OnHttpsProxyTunnelResponse( + virtual void OnHttpsProxyTunnelResponseRedirect( const HttpResponseInfo& response_info, const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info,
diff --git a/net/nqe/network_quality_estimator_util_unittest.cc b/net/nqe/network_quality_estimator_util_unittest.cc index 0f464f9..c907e910 100644 --- a/net/nqe/network_quality_estimator_util_unittest.cc +++ b/net/nqe/network_quality_estimator_util_unittest.cc
@@ -6,7 +6,9 @@ #include <memory> +#include "base/optional.h" #include "base/test/scoped_task_environment.h" +#include "net/base/host_port_pair.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/dns/host_resolver.h" @@ -46,31 +48,13 @@ EXPECT_EQ(0u, mock_host_resolver.num_resolve()); - { - // Resolve example1.com so that the resolution entry is cached. - TestCompletionCallback callback; - std::unique_ptr<HostResolver::Request> request; - AddressList ignored; - int rv = mock_host_resolver.Resolve( - HostResolver::RequestInfo(HostPortPair("example1.com", 443)), - DEFAULT_PRIORITY, &ignored, callback.callback(), &request, - NetLogWithSource()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback.WaitForResult()); - } - - { - // Resolve example2.com so that the resolution entry is cached. - TestCompletionCallback callback; - std::unique_ptr<HostResolver::Request> request; - AddressList ignored; - int rv = mock_host_resolver.Resolve( - HostResolver::RequestInfo(HostPortPair("example2.com", 443)), - DEFAULT_PRIORITY, &ignored, callback.callback(), &request, - NetLogWithSource()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback.WaitForResult()); - } + // Load hostnames into HostResolver cache. + int rv = mock_host_resolver.LoadIntoCache(HostPortPair("example1.com", 443), + base::nullopt); + EXPECT_EQ(OK, rv); + rv = mock_host_resolver.LoadIntoCache(HostPortPair("example2.com", 443), + base::nullopt); + EXPECT_EQ(OK, rv); EXPECT_EQ(2u, mock_host_resolver.num_non_local_resolves()); @@ -115,19 +99,11 @@ IsPrivateHost(&mock_host_resolver, HostPortPair("example3.com", 443))); EXPECT_EQ(0u, mock_host_resolver.num_non_local_resolves()); - { - // Resolve example3.com so that the resolution entry is cached. - TestCompletionCallback callback; - std::unique_ptr<HostResolver::Request> request; - AddressList ignored; - int rv = mock_host_resolver.Resolve( - HostResolver::RequestInfo(HostPortPair("example3.com", 443)), - DEFAULT_PRIORITY, &ignored, callback.callback(), &request, - NetLogWithSource()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback.WaitForResult()); - EXPECT_EQ(1u, mock_host_resolver.num_non_local_resolves()); - } + int rv = mock_host_resolver.LoadIntoCache(HostPortPair("example3.com", 443), + base::nullopt); + EXPECT_EQ(OK, rv); + EXPECT_EQ(1u, mock_host_resolver.num_non_local_resolves()); + EXPECT_TRUE( IsPrivateHost(&mock_host_resolver, HostPortPair("example3.com", 443)));
diff --git a/net/proxy_resolution/pac_file_decider.cc b/net/proxy_resolution/pac_file_decider.cc index 88fd027..48af28f 100644 --- a/net/proxy_resolution/pac_file_decider.cc +++ b/net/proxy_resolution/pac_file_decider.cc
@@ -42,8 +42,6 @@ base::string16::npos; } -} // anonymous namespace - // This is the hard-coded location used by the DNS portion of web proxy // auto-discovery. // @@ -56,11 +54,18 @@ // // For more details, also check out this comment: // http://code.google.com/p/chromium/issues/detail?id=18575#c20 -namespace { const char kWpadUrl[] = "http://wpad/wpad.dat"; const int kQuickCheckDelayMs = 1000; + } // namespace +PacFileDataWithSource::PacFileDataWithSource() = default; +PacFileDataWithSource::~PacFileDataWithSource() = default; +PacFileDataWithSource::PacFileDataWithSource(const PacFileDataWithSource&) = + default; +PacFileDataWithSource& PacFileDataWithSource::operator=( + const PacFileDataWithSource&) = default; + std::unique_ptr<base::Value> PacFileDecider::PacSource::NetLogCallback( const GURL* effective_pac_url, NetLogCaptureMode /* capture_mode */) const { @@ -156,7 +161,7 @@ return effective_config_; } -const scoped_refptr<PacFileData>& PacFileDecider::script_data() const { +const PacFileDataWithSource& PacFileDecider::script_data() const { DCHECK_EQ(STATE_NONE, next_state_); return script_data_; } @@ -369,12 +374,13 @@ const PacSource& pac_source = current_pac_source(); // Extract the current script data. + script_data_.from_auto_detect = pac_source.type != PacSource::CUSTOM; if (fetch_pac_bytes_) { - script_data_ = PacFileData::FromUTF16(pac_script_); + script_data_.data = PacFileData::FromUTF16(pac_script_); } else { - script_data_ = pac_source.type == PacSource::CUSTOM - ? PacFileData::FromURL(pac_source.url) - : PacFileData::ForAutoDetect(); + script_data_.data = pac_source.type == PacSource::CUSTOM + ? PacFileData::FromURL(pac_source.url) + : PacFileData::ForAutoDetect(); } // Let the caller know which automatic setting we ended up initializing the
diff --git a/net/proxy_resolution/pac_file_decider.h b/net/proxy_resolution/pac_file_decider.h index fe4fbe1b..6b91d9d1 100644 --- a/net/proxy_resolution/pac_file_decider.h +++ b/net/proxy_resolution/pac_file_decider.h
@@ -36,6 +36,24 @@ class ProxyResolver; class PacFileFetcher; +// Structure that encapsulates the result a PacFileData along with an +// indication of its origin: was it obtained implicitly from auto-detect, +// or was it read from a more explicitly configured URL. +// +// Note that |!from_auto_detect| does NOT imply the script was securely +// delivered. Most commonly PAC scripts are configured from http:// URLs, +// both for auto-detect and not. +struct NET_EXPORT_PRIVATE PacFileDataWithSource { + PacFileDataWithSource(); + explicit PacFileDataWithSource(const PacFileDataWithSource&); + ~PacFileDataWithSource(); + + PacFileDataWithSource& operator=(const PacFileDataWithSource&); + + scoped_refptr<PacFileData> data; + bool from_auto_detect = false; +}; + // PacFileDecider is a helper class used by ProxyResolutionService to // determine which PAC script to use given our proxy configuration. // @@ -87,7 +105,7 @@ const ProxyConfigWithAnnotation& effective_config() const; - const scoped_refptr<PacFileData>& script_data() const; + const PacFileDataWithSource& script_data() const; void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; } @@ -197,7 +215,7 @@ // Results. ProxyConfigWithAnnotation effective_config_; - scoped_refptr<PacFileData> script_data_; + PacFileDataWithSource script_data_; std::unique_ptr<HostResolver::ResolveHostRequest> resolve_request_;
diff --git a/net/proxy_resolution/pac_file_decider_unittest.cc b/net/proxy_resolution/pac_file_decider_unittest.cc index 216d3ba..c257c2e 100644 --- a/net/proxy_resolution/pac_file_decider_unittest.cc +++ b/net/proxy_resolution/pac_file_decider_unittest.cc
@@ -215,7 +215,8 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsOk()); - EXPECT_EQ(rule.text(), decider.script_data()->utf16()); + EXPECT_EQ(rule.text(), decider.script_data().data->utf16()); + EXPECT_FALSE(decider.script_data().from_auto_detect); // Check the NetLog was filled correctly. TestNetLogEntry::List entries; @@ -253,7 +254,7 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsError(kFailedDownloading)); - EXPECT_FALSE(decider.script_data()); + EXPECT_FALSE(decider.script_data().data); // Check the NetLog was filled correctly. TestNetLogEntry::List entries; @@ -289,7 +290,7 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsError(kFailedParsing)); - EXPECT_FALSE(decider.script_data()); + EXPECT_FALSE(decider.script_data().data); } // Fail downloading the custom PAC script, because the fetcher was NULL. @@ -306,7 +307,7 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsError(ERR_UNEXPECTED)); - EXPECT_FALSE(decider.script_data()); + EXPECT_FALSE(decider.script_data().data); } // Succeeds in choosing autodetect (WPAD DNS). @@ -326,7 +327,8 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsOk()); - EXPECT_EQ(rule.text(), decider.script_data()->utf16()); + EXPECT_EQ(rule.text(), decider.script_data().data->utf16()); + EXPECT_TRUE(decider.script_data().from_auto_detect); EXPECT_TRUE(decider.effective_config().value().has_pac_url()); EXPECT_EQ(rule.url, decider.effective_config().value().pac_url()); @@ -371,7 +373,8 @@ resolver_.rules_map()[HostResolverSource::SYSTEM]->AddRule("wpad", "1.2.3.4"); EXPECT_THAT(StartDecider(), IsOk()); - EXPECT_EQ(rule_.text(), decider_->script_data()->utf16()); + EXPECT_EQ(rule_.text(), decider_->script_data().data->utf16()); + EXPECT_TRUE(decider_->script_data().from_auto_detect); EXPECT_TRUE(decider_->effective_config().value().has_pac_url()); EXPECT_EQ(rule_.url, decider_->effective_config().value().pac_url()); @@ -388,7 +391,8 @@ resolver_.ResolveAllPending(); callback_.WaitForResult(); EXPECT_FALSE(resolver_.has_pending_requests()); - EXPECT_EQ(rule_.text(), decider_->script_data()->utf16()); + EXPECT_EQ(rule_.text(), decider_->script_data().data->utf16()); + EXPECT_TRUE(decider_->script_data().from_auto_detect); EXPECT_TRUE(decider_->effective_config().value().has_pac_url()); EXPECT_EQ(rule_.url, decider_->effective_config().value().pac_url()); } @@ -500,7 +504,8 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsOk()); - EXPECT_EQ(rule.text(), decider.script_data()->utf16()); + EXPECT_EQ(rule.text(), decider.script_data().data->utf16()); + EXPECT_FALSE(decider.script_data().from_auto_detect); EXPECT_TRUE(decider.effective_config().value().has_pac_url()); EXPECT_EQ(rule.url, decider.effective_config().value().pac_url()); @@ -529,7 +534,8 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsOk()); - EXPECT_EQ(rule.text(), decider.script_data()->utf16()); + EXPECT_EQ(rule.text(), decider.script_data().data->utf16()); + EXPECT_FALSE(decider.script_data().from_auto_detect); // Verify that the effective configuration no longer contains auto detect or // any of the manual settings. @@ -592,7 +598,7 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsError(kFailedDownloading)); - EXPECT_FALSE(decider.script_data()); + EXPECT_FALSE(decider.script_data().data); } // Fails at WPAD (downloading), and fails at custom PAC (parsing). @@ -614,7 +620,7 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsError(kFailedParsing)); - EXPECT_FALSE(decider.script_data()); + EXPECT_FALSE(decider.script_data().data); } // This is a copy-paste of CustomPacFails1, with the exception that we give it @@ -642,7 +648,7 @@ IsError(ERR_IO_PENDING)); EXPECT_THAT(callback.WaitForResult(), IsError(kFailedDownloading)); - EXPECT_FALSE(decider.script_data()); + EXPECT_FALSE(decider.script_data().data); // Check the NetLog was filled correctly. TestNetLogEntry::List entries; @@ -684,7 +690,7 @@ ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta::FromSeconds(-5), true, callback.callback()), IsError(kFailedDownloading)); - EXPECT_FALSE(decider.script_data()); + EXPECT_FALSE(decider.script_data().data); // Check the NetLog was filled correctly. TestNetLogEntry::List entries; @@ -752,7 +758,8 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsOk()); - EXPECT_EQ(dhcp_fetcher.expected_text(), decider.script_data()->utf16()); + EXPECT_EQ(dhcp_fetcher.expected_text(), decider.script_data().data->utf16()); + EXPECT_TRUE(decider.script_data().from_auto_detect); EXPECT_TRUE(decider.effective_config().value().has_pac_url()); EXPECT_EQ(GURL("http://dhcppac/"), @@ -779,7 +786,7 @@ config, TRAFFIC_ANNOTATION_FOR_TESTS), base::TimeDelta(), true, callback.callback()), IsError(kFailedDownloading)); - EXPECT_FALSE(decider.script_data()); + EXPECT_FALSE(decider.script_data().data); EXPECT_FALSE(decider.effective_config().value().has_pac_url()); }
diff --git a/net/proxy_resolution/proxy_info.cc b/net/proxy_resolution/proxy_info.cc index cb0bf4eb..762756d 100644 --- a/net/proxy_resolution/proxy_info.cc +++ b/net/proxy_resolution/proxy_info.cc
@@ -8,7 +8,10 @@ namespace net { -ProxyInfo::ProxyInfo() : did_bypass_proxy_(false), did_use_pac_script_(false) {} +ProxyInfo::ProxyInfo() + : did_bypass_proxy_(false), + did_use_pac_script_(false), + did_use_auto_detected_pac_script_(false) {} ProxyInfo::ProxyInfo(const ProxyInfo& other) = default; @@ -22,6 +25,7 @@ traffic_annotation_ = other.traffic_annotation_; did_bypass_proxy_ = other.did_bypass_proxy_; did_use_pac_script_ = other.did_use_pac_script_; + did_use_auto_detected_pac_script_ = other.did_use_auto_detected_pac_script_; } void ProxyInfo::UseDirect() { @@ -88,6 +92,7 @@ traffic_annotation_.reset(); did_bypass_proxy_ = false; did_use_pac_script_ = false; + did_use_auto_detected_pac_script_ = false; } } // namespace net
diff --git a/net/proxy_resolution/proxy_info.h b/net/proxy_resolution/proxy_info.h index e3ea8da6..daa5862 100644 --- a/net/proxy_resolution/proxy_info.h +++ b/net/proxy_resolution/proxy_info.h
@@ -127,6 +127,12 @@ return did_use_pac_script_; } + // Returns true if the proxy list was obtained from a PAC script that + // was auto-detected. + bool did_use_auto_detected_pac_script() const { + return did_use_auto_detected_pac_script_; + } + // Returns the first valid proxy server. is_empty() must be false to be able // to call this function. const ProxyServer& proxy_server() const { return proxy_list_.Get(); } @@ -203,6 +209,7 @@ // Whether we used a PAC script for resolving the proxy. bool did_use_pac_script_; + bool did_use_auto_detected_pac_script_; // How long it took to resolve the proxy. Times are both null if proxy was // determined synchronously without running a PAC.
diff --git a/net/proxy_resolution/proxy_resolution_service.cc b/net/proxy_resolution/proxy_resolution_service.cc index 5aff9e25..a657d1ff 100644 --- a/net/proxy_resolution/proxy_resolution_service.cc +++ b/net/proxy_resolution/proxy_resolution_service.cc
@@ -432,6 +432,7 @@ InitProxyResolver() : proxy_resolver_factory_(nullptr), proxy_resolver_(NULL), + resolver_using_auto_detected_script_(nullptr), next_state_(STATE_NONE), quick_check_enabled_(true) {} @@ -442,8 +443,12 @@ // Begins initializing the proxy resolver; calls |callback| when done. A // ProxyResolver instance will be created using |proxy_resolver_factory| and - // returned via |proxy_resolver| if the final result is OK. + // assigned to |*proxy_resolver| if the final result is OK. + // |*resolver_using_auto_detected_script| will be set to true if + // |proxy_resolver| was initialized using script data that originates from + // proxy auto-detection. int Start(std::unique_ptr<ProxyResolver>* proxy_resolver, + bool* resolver_using_auto_detected_script, ProxyResolverFactory* proxy_resolver_factory, PacFileFetcher* pac_file_fetcher, DhcpPacFileFetcher* dhcp_pac_file_fetcher, @@ -453,6 +458,7 @@ CompletionOnceCallback callback) { DCHECK_EQ(STATE_NONE, next_state_); proxy_resolver_ = proxy_resolver; + resolver_using_auto_detected_script_ = resolver_using_auto_detected_script; proxy_resolver_factory_ = proxy_resolver_factory; decider_.reset( @@ -469,16 +475,21 @@ // Similar to Start(), however it skips the PacFileDecider stage. Instead // |effective_config|, |decider_result| and |script_data| will be used as the // inputs for initializing the ProxyResolver. A ProxyResolver instance will - // be created using |proxy_resolver_factory| and returned via - // |proxy_resolver| if the final result is OK. + // be created using |proxy_resolver_factory| and assigned to + // |*proxy_resolver| if the final result is OK. + // |*resolver_using_auto_detected_script| will be set to true if + // |proxy_resolver| was initialized using script data that originates from + // proxy auto-detection. int StartSkipDecider(std::unique_ptr<ProxyResolver>* proxy_resolver, + bool* resolver_using_auto_detected_script, ProxyResolverFactory* proxy_resolver_factory, const ProxyConfigWithAnnotation& effective_config, int decider_result, - PacFileData* script_data, + const PacFileDataWithSource& script_data, CompletionOnceCallback callback) { DCHECK_EQ(STATE_NONE, next_state_); proxy_resolver_ = proxy_resolver; + resolver_using_auto_detected_script_ = resolver_using_auto_detected_script; proxy_resolver_factory_ = proxy_resolver_factory; effective_config_ = effective_config; @@ -501,7 +512,7 @@ // Returns the PAC script data that was selected by PacFileDecider. // Should only be called upon completion of the initialization. - const scoped_refptr<PacFileData>& script_data() { + const PacFileDataWithSource& script_data() { DCHECK_EQ(STATE_NONE, next_state_); return script_data_; } @@ -583,18 +594,21 @@ } int DoCreateResolver() { - DCHECK(script_data_.get()); + DCHECK(script_data_.data); // TODO(eroman): Should log this latency to the NetLog. next_state_ = STATE_CREATE_RESOLVER_COMPLETE; return proxy_resolver_factory_->CreateProxyResolver( - script_data_, proxy_resolver_, + script_data_.data, proxy_resolver_, base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)), &create_resolver_request_); } int DoCreateResolverComplete(int result) { - if (result != OK) + if (result == OK) { + *resolver_using_auto_detected_script_ = script_data_.from_auto_detect; + } else { proxy_resolver_->reset(); + } return result; } @@ -607,12 +621,13 @@ ProxyConfigWithAnnotation config_; ProxyConfigWithAnnotation effective_config_; - scoped_refptr<PacFileData> script_data_; + PacFileDataWithSource script_data_; TimeDelta wait_delay_; std::unique_ptr<PacFileDecider> decider_; ProxyResolverFactory* proxy_resolver_factory_; std::unique_ptr<ProxyResolverFactory::Request> create_resolver_request_; std::unique_ptr<ProxyResolver>* proxy_resolver_; + bool* resolver_using_auto_detected_script_; CompletionOnceCallback callback_; State next_state_; bool quick_check_enabled_; @@ -629,7 +644,7 @@ class ProxyResolutionService::PacFileDeciderPoller { public: typedef base::Callback< - void(int, PacFileData*, const ProxyConfigWithAnnotation&)> + void(int, const PacFileDataWithSource&, const ProxyConfigWithAnnotation&)> ChangeCallback; // Builds a poller helper, and starts polling for updates. Whenever a change @@ -658,7 +673,7 @@ PacFileFetcher* pac_file_fetcher, DhcpPacFileFetcher* dhcp_pac_file_fetcher, int init_net_error, - const scoped_refptr<PacFileData>& init_script_data, + const PacFileDataWithSource& init_script_data, NetLog* net_log) : change_callback_(callback), config_(config), @@ -769,7 +784,7 @@ } bool HasScriptDataChanged(int result, - const scoped_refptr<PacFileData>& script_data) { + const PacFileDataWithSource& script_data) { if (result != last_error_) { // Something changed -- it was failing before and now it succeeded, or // conversely it succeeded before and now it failed. Or it failed in @@ -786,16 +801,17 @@ // Otherwise if it succeeded both this time and last time, we need to look // closer and see if we ended up downloading different content for the PAC // script. - return !script_data->Equals(last_script_data_.get()); + return !script_data.data->Equals(last_script_data_.data.get()) || + (script_data.from_auto_detect != last_script_data_.from_auto_detect); } void NotifyProxyResolutionServiceOfChange( int result, - const scoped_refptr<PacFileData>& script_data, + const PacFileDataWithSource& script_data, const ProxyConfigWithAnnotation& effective_config) { // Note that |this| may be deleted after calling into the // ProxyResolutionService. - change_callback_.Run(result, script_data.get(), effective_config); + change_callback_.Run(result, script_data, effective_config); } ChangeCallback change_callback_; @@ -805,7 +821,7 @@ DhcpPacFileFetcher* dhcp_pac_file_fetcher_; int last_error_; - scoped_refptr<PacFileData> last_script_data_; + PacFileDataWithSource last_script_data_; std::unique_ptr<PacFileDecider> decider_; TimeDelta next_poll_delay_; @@ -880,6 +896,7 @@ // Outstanding requests are cancelled during ~ProxyResolutionService, so this // is guaranteed to be valid throughout our lifetime. ProxyResolutionService* service_; + bool resolver_using_auto_detected_script_; CompletionOnceCallback user_callback_; ProxyInfo* results_; GURL url_; @@ -938,6 +955,8 @@ if (service_->ApplyPacBypassRules(url_, results_)) return OK; + resolver_using_auto_detected_script_ = + service_->resolver_using_auto_detected_script_; return resolver()->GetProxyForURL( url_, results_, base::Bind(&ProxyResolutionService::RequestImpl::QueryComplete, @@ -975,6 +994,8 @@ // Make a note in the results which configuration was in use at the // time of the resolve. results_->did_use_pac_script_ = true; + results_->did_use_auto_detected_pac_script_ = + resolver_using_auto_detected_script_; results_->proxy_resolve_start_time_ = creation_time_; results_->proxy_resolve_end_time_ = TimeTicks::Now(); @@ -1106,6 +1127,22 @@ // ProxyResolver dependency we give it will never be used. std::unique_ptr<ProxyConfigService> proxy_config_service( new ProxyConfigServiceFixed(ProxyConfigWithAnnotation( + ProxyConfig::CreateFromCustomPacURL( + GURL("https://my-pac-script.invalid/wpad.dat")), + traffic_annotation))); + + return std::make_unique<ProxyResolutionService>( + std::move(proxy_config_service), + std::make_unique<ProxyResolverFactoryForPacResult>(pac_string), nullptr); +} + +// static +std::unique_ptr<ProxyResolutionService> +ProxyResolutionService::CreateFixedFromAutoDetectedPacResult( + const std::string& pac_string, + const NetworkTrafficAnnotationTag& traffic_annotation) { + std::unique_ptr<ProxyConfigService> proxy_config_service( + new ProxyConfigServiceFixed(ProxyConfigWithAnnotation( ProxyConfig::CreateAutoDetect(), traffic_annotation))); return std::make_unique<ProxyResolutionService>( @@ -1656,7 +1693,8 @@ init_proxy_resolver_.reset(new InitProxyResolver()); init_proxy_resolver_->set_quick_check_enabled(quick_check_enabled_); int rv = init_proxy_resolver_->Start( - &resolver_, resolver_factory_.get(), pac_file_fetcher_.get(), + &resolver_, &resolver_using_auto_detected_script_, + resolver_factory_.get(), pac_file_fetcher_.get(), dhcp_pac_file_fetcher_.get(), net_log_, fetched_config_.value(), wait_delay, base::Bind(&ProxyResolutionService::OnInitProxyResolverComplete, @@ -1668,7 +1706,7 @@ void ProxyResolutionService::InitializeUsingDecidedConfig( int decider_result, - PacFileData* script_data, + const PacFileDataWithSource& script_data, const ProxyConfigWithAnnotation& effective_config) { DCHECK(fetched_config_); DCHECK(fetched_config_->value().HasAutomaticSettings()); @@ -1679,8 +1717,8 @@ init_proxy_resolver_.reset(new InitProxyResolver()); int rv = init_proxy_resolver_->StartSkipDecider( - &resolver_, resolver_factory_.get(), effective_config, decider_result, - script_data, + &resolver_, &resolver_using_auto_detected_script_, + resolver_factory_.get(), effective_config, decider_result, script_data, base::Bind(&ProxyResolutionService::OnInitProxyResolverComplete, base::Unretained(this)));
diff --git a/net/proxy_resolution/proxy_resolution_service.h b/net/proxy_resolution/proxy_resolution_service.h index 6d7f7ed..3ead1551 100644 --- a/net/proxy_resolution/proxy_resolution_service.h +++ b/net/proxy_resolution/proxy_resolution_service.h
@@ -41,10 +41,10 @@ class DhcpPacFileFetcher; class NetLog; +class PacFileFetcher; class ProxyDelegate; class ProxyResolverFactory; -class PacFileData; -class PacFileFetcher; +struct PacFileDataWithSource; // This class can be used to resolve the proxy server to use when loading a // HTTP(S) URL. It uses the given ProxyResolver to handle the actual proxy @@ -270,6 +270,13 @@ const std::string& pac_string, const NetworkTrafficAnnotationTag& traffic_annotation); + // Same as CreateFixedFromPacResult(), except the resulting ProxyInfo from + // resolutions will be tagged as having been auto-detected. + static std::unique_ptr<ProxyResolutionService> + CreateFixedFromAutoDetectedPacResult( + const std::string& pac_string, + const NetworkTrafficAnnotationTag& traffic_annotation); + // Creates a config service appropriate for this platform that fetches the // system proxy settings. |main_task_runner| is the thread where the consumer // of the ProxyConfigService will live. @@ -374,7 +381,7 @@ // Start the initialization skipping past the "decision" phase. void InitializeUsingDecidedConfig( int decider_result, - PacFileData* script_data, + const PacFileDataWithSource& script_data, const ProxyConfigWithAnnotation& effective_config); // NetworkChangeNotifier::IPAddressObserver @@ -398,7 +405,12 @@ std::unique_ptr<ProxyConfigService> config_service_; std::unique_ptr<ProxyResolverFactory> resolver_factory_; + + // If non-null, the initialized ProxyResolver to use for requests, and a + // boolean indicating whether it was initialized using an auto-detected + // script. std::unique_ptr<ProxyResolver> resolver_; + bool resolver_using_auto_detected_script_; // We store the proxy configuration that was last fetched from the // ProxyConfigService, as well as the resulting "effective" configuration.
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 1be12cc1..bb0e8b4 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -12,6 +12,7 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/string_split.h" #include "base/threading/thread_task_runner_handle.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" @@ -680,7 +681,7 @@ if (rv != OK) return rv; - response_info_->socket_address = HostPortPair::FromIPEndPoint(address); + response_info_->remote_endpoint = address; response_info_->connection_info = ConnectionInfoFromQuicVersion(quic_session()->GetQuicVersion()); response_info_->vary_data.Init(*request_info_,
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 334b38a..38e8c58 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -19,6 +19,7 @@ #include "base/test/metrics/histogram_tester.h" #include "net/base/chunked_upload_data_stream.h" #include "net/base/completion_once_callback.h" +#include "net/base/ip_endpoint.h" #include "net/base/mock_network_change_notifier.h" #include "net/base/test_completion_callback.h" #include "net/base/test_proxy_delegate.h" @@ -730,7 +731,7 @@ void CheckResponsePort(HttpNetworkTransaction* trans, uint16_t port) { const HttpResponseInfo* response = trans->GetResponseInfo(); ASSERT_TRUE(response != nullptr); - EXPECT_EQ(port, response->socket_address.port()); + EXPECT_EQ(port, response->remote_endpoint.port()); } void CheckWasHttpResponse(HttpNetworkTransaction* trans) { @@ -2217,13 +2218,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -2231,7 +2225,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( @@ -2309,13 +2303,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -2333,7 +2320,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -2440,13 +2427,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -2464,7 +2444,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -2584,13 +2564,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -2608,7 +2581,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -2725,13 +2698,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // Use a TestTaskRunner to avoid waiting in real time for timeouts. @@ -2745,7 +2711,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -2851,13 +2817,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // Use a TestTaskRunner to avoid waiting in real time for timeouts. @@ -2871,7 +2830,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -2982,13 +2941,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // Use a TestTaskRunner to avoid waiting in real time for timeouts. @@ -3003,7 +2955,7 @@ auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans->Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -3061,13 +3013,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); @@ -3075,7 +3020,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -3192,13 +3137,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // Use a TestTaskRunner to avoid waiting in real time for timeouts. @@ -3212,7 +3150,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -3334,13 +3272,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // Use a TestTaskRunner to avoid waiting in real time for timeouts. @@ -3354,7 +3285,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -3488,13 +3419,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // Use a TestTaskRunner to avoid waiting in real time for timeouts. @@ -3508,7 +3432,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -3641,13 +3565,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // Use a TestTaskRunner to avoid waiting in real time for timeouts. @@ -3661,7 +3578,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -3783,13 +3700,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // Use a TestTaskRunner to avoid waiting in real time for timeouts. @@ -3804,7 +3714,7 @@ auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans->Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -3879,13 +3789,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); @@ -3893,7 +3796,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -3978,13 +3881,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); @@ -3992,7 +3888,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); // Pump the message loop to get the request started. @@ -5018,13 +4914,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); AddHangingNonAlternateProtocolSocketData(); CreateSession(); @@ -5056,13 +4945,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); request_.url = GURL("http://mail.example.org/"); CreateSession(); @@ -5105,13 +4987,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -5119,7 +4994,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( @@ -5194,11 +5069,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, net_log_.bound()); AddHangingNonAlternateProtocolSocketData(); CreateSession(); @@ -5291,11 +5161,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, net_log_.bound()); AddHangingNonAlternateProtocolSocketData(); CreateSession(); @@ -5361,13 +5226,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -5375,7 +5233,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( @@ -5428,13 +5286,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -5442,7 +5293,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( @@ -5490,13 +5341,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -5504,7 +5348,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( @@ -5555,13 +5399,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); session_->quic_stream_factory()->set_require_confirmation(true); @@ -5569,7 +5406,7 @@ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); TestCompletionCallback callback; - rv = trans.Start(&request_, callback.callback(), net_log_.bound()); + int rv = trans.Start(&request_, callback.callback(), net_log_.bound()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( @@ -5930,13 +5767,6 @@ host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); // TODO(rch): Check if we need a 0RTT version of ConnectionCloseDuringConnect @@ -6011,13 +5841,6 @@ // synchronously. host_resolver_.set_synchronous_mode(true); host_resolver_.rules()->AddIPLiteralRule("myproxy.org", "192.168.0.1", ""); - HostResolver::RequestInfo info(HostPortPair("myproxy.org", 443)); - AddressList address; - std::unique_ptr<HostResolver::Request> request; - int rv = host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, - CompletionOnceCallback(), &request, - net_log_.bound()); - EXPECT_THAT(rv, IsOk()); CreateSession(); crypto_client_stream_factory_.set_handshake_mode( @@ -7122,7 +6945,7 @@ EXPECT_TRUE(response->was_alpn_negotiated); EXPECT_EQ(QuicHttpStream::ConnectionInfoFromQuicVersion(version_), response->connection_info); - EXPECT_EQ(443, response->socket_address.port()); + EXPECT_EQ(443, response->remote_endpoint.port()); } quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
diff --git a/net/quic/quic_proxy_client_socket.cc b/net/quic/quic_proxy_client_socket.cc index 48a9b7b..c21ee5c 100644 --- a/net/quic/quic_proxy_client_socket.cc +++ b/net/quic/quic_proxy_client_socket.cc
@@ -405,7 +405,7 @@ if (!SanitizeProxyRedirect(&response_)) return ERR_TUNNEL_CONNECTION_FAILED; next_state_ = STATE_DISCONNECTED; - return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; + return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT; case 407: // Proxy Authentication Required next_state_ = STATE_CONNECT_COMPLETE;
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc index 7034da4..d075d0b 100644 --- a/net/quic/quic_proxy_client_socket_unittest.cc +++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -674,7 +674,7 @@ Initialize(); - AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); + AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT); const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); ASSERT_TRUE(response != nullptr);
diff --git a/net/socket/sequenced_socket_data_unittest.cc b/net/socket/sequenced_socket_data_unittest.cc index 895d6c4..1d08a05 100644 --- a/net/socket/sequenced_socket_data_unittest.cc +++ b/net/socket/sequenced_socket_data_unittest.cc
@@ -14,11 +14,7 @@ #include "net/base/io_buffer.h" #include "net/base/test_completion_callback.h" #include "net/log/net_log_with_source.h" -#include "net/socket/client_socket_handle.h" -#include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" -#include "net/socket/transport_client_socket_pool.h" -#include "net/socket/transport_connect_job.h" #include "net/test/gtest_util.h" #include "net/test/test_with_scoped_task_environment.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" @@ -227,34 +223,16 @@ TestCompletionCallback read_callback_; scoped_refptr<IOBuffer> read_buf_; TestCompletionCallback write_callback_; - StreamSocket* sock_; - private: - MockConnect connect_data_; std::unique_ptr<SequencedSocketData> data_; - const HostPortPair endpoint_; - scoped_refptr<TransportClientSocketPool::SocketParams> tcp_params_; MockClientSocketFactory socket_factory_; - MockTransportClientSocketPool socket_pool_; - ClientSocketHandle connection_; bool expect_eof_; - DISALLOW_COPY_AND_ASSIGN(SequencedSocketDataTest); + std::unique_ptr<StreamSocket> sock_; }; -SequencedSocketDataTest::SequencedSocketDataTest() - : sock_(nullptr), - connect_data_(SYNCHRONOUS, OK), - endpoint_("www.google.com", 443), - tcp_params_(TransportClientSocketPool::SocketParams:: - CreateFromTransportSocketParams( - base::MakeRefCounted<TransportSocketParams>( - endpoint_, - false, - OnHostResolutionCallback()))), - socket_pool_(10, 10, &socket_factory_), - expect_eof_(true) {} +SequencedSocketDataTest::SequencedSocketDataTest() : expect_eof_(true) {} SequencedSocketDataTest::~SequencedSocketDataTest() { // Make sure no unexpected pending tasks will cause a failure. @@ -267,17 +245,15 @@ void SequencedSocketDataTest::Initialize(base::span<const MockRead> reads, base::span<const MockWrite> writes) { - data_.reset(new SequencedSocketData(reads, writes)); - data_->set_connect_data(connect_data_); + data_ = std::make_unique<SequencedSocketData>(MockConnect(SYNCHRONOUS, OK), + reads, writes); socket_factory_.AddSocketDataProvider(data_.get()); - - EXPECT_EQ(OK, connection_.Init( - endpoint_.ToString(), tcp_params_, LOWEST, SocketTag(), - ClientSocketPool::RespectLimits::ENABLED, - CompletionOnceCallback(), - reinterpret_cast<TransportClientSocketPool*>(&socket_pool_), - NetLogWithSource())); - sock_ = connection_.socket(); + sock_ = socket_factory_.CreateTransportClientSocket( + AddressList(IPEndPoint(IPAddress::IPv4Localhost(), 443)), + nullptr /* socket_performance_watcher */, nullptr /* net_log */, + NetLogSource()); + TestCompletionCallback callback; + EXPECT_EQ(OK, sock_->Connect(callback.callback())); } void SequencedSocketDataTest::AssertSyncReadEquals(const char* data, int len) { @@ -522,17 +498,17 @@ read_buf_ = base::MakeRefCounted<IOBuffer>(kLen4); - ReentrantHelper helper3(sock_); + ReentrantHelper helper3(sock_.get()); helper3.SetExpectedRead(kMsg3, kLen3); helper3.SetInvokeRead(read_buf_, kLen4, ERR_IO_PENDING, read_callback_.callback()); - ReentrantHelper helper2(sock_); + ReentrantHelper helper2(sock_.get()); helper2.SetExpectedRead(kMsg2, kLen2); helper2.SetInvokeRead(helper3.read_buf(), kLen3, ERR_IO_PENDING, helper3.callback()); - ReentrantHelper helper(sock_); + ReentrantHelper helper(sock_.get()); helper.SetExpectedRead(kMsg1, kLen1); helper.SetInvokeRead(helper2.read_buf(), kLen2, ERR_IO_PENDING, helper2.callback()); @@ -845,16 +821,16 @@ Initialize(base::span<MockRead>(), writes); - ReentrantHelper helper3(sock_); + ReentrantHelper helper3(sock_.get()); helper3.SetExpectedWrite(kLen3); helper3.SetInvokeWrite(kMsg4, kLen4, ERR_IO_PENDING, write_callback_.callback()); - ReentrantHelper helper2(sock_); + ReentrantHelper helper2(sock_.get()); helper2.SetExpectedWrite(kLen2); helper2.SetInvokeWrite(kMsg3, kLen3, ERR_IO_PENDING, helper3.callback()); - ReentrantHelper helper(sock_); + ReentrantHelper helper(sock_.get()); helper.SetExpectedWrite(kLen1); helper.SetInvokeWrite(kMsg2, kLen2, ERR_IO_PENDING, helper2.callback()); @@ -1050,16 +1026,16 @@ read_buf_ = base::MakeRefCounted<IOBuffer>(kLen4); - ReentrantHelper helper3(sock_); + ReentrantHelper helper3(sock_.get()); helper3.SetExpectedWrite(kLen3); helper3.SetInvokeRead(read_buf_, kLen4, ERR_IO_PENDING, read_callback_.callback()); - ReentrantHelper helper2(sock_); + ReentrantHelper helper2(sock_.get()); helper2.SetExpectedRead(kMsg2, kLen2); helper2.SetInvokeWrite(kMsg3, kLen3, ERR_IO_PENDING, helper3.callback()); - ReentrantHelper helper(sock_); + ReentrantHelper helper(sock_.get()); helper.SetExpectedWrite(kLen1); helper.SetInvokeRead(helper2.read_buf(), kLen2, ERR_IO_PENDING, helper2.callback()); @@ -1085,15 +1061,15 @@ read_buf_ = base::MakeRefCounted<IOBuffer>(kLen4); - ReentrantHelper helper3(sock_); + ReentrantHelper helper3(sock_.get()); helper3.SetExpectedWrite(kLen3); helper3.SetInvokeRead(read_buf_, kLen4, kLen4, failing_callback()); - ReentrantHelper helper2(sock_); + ReentrantHelper helper2(sock_.get()); helper2.SetExpectedRead(kMsg2, kLen2); helper2.SetInvokeWrite(kMsg3, kLen3, ERR_IO_PENDING, helper3.callback()); - ReentrantHelper helper(sock_); + ReentrantHelper helper(sock_.get()); helper.SetExpectedWrite(kLen1); helper.SetInvokeRead(helper2.read_buf(), kLen2, ERR_IO_PENDING, helper2.callback()); @@ -1122,16 +1098,16 @@ read_buf_ = base::MakeRefCounted<IOBuffer>(kLen4); - ReentrantHelper helper3(sock_); + ReentrantHelper helper3(sock_.get()); helper3.SetExpectedRead(kMsg3, kLen3); helper3.SetInvokeWrite(kMsg4, kLen4, kLen4, failing_callback()); - ReentrantHelper helper2(sock_); + ReentrantHelper helper2(sock_.get()); helper2.SetExpectedWrite(kLen2); helper2.SetInvokeRead(helper3.read_buf(), kLen3, ERR_IO_PENDING, helper3.callback()); - ReentrantHelper helper(sock_); + ReentrantHelper helper(sock_.get()); helper.SetExpectedRead(kMsg1, kLen1); helper.SetInvokeWrite(kMsg2, kLen2, ERR_IO_PENDING, helper2.callback());
diff --git a/net/socket/socks_client_socket_pool_unittest.cc b/net/socket/socks_client_socket_pool_unittest.cc deleted file mode 100644 index 76cf2a8b..0000000 --- a/net/socket/socks_client_socket_pool_unittest.cc +++ /dev/null
@@ -1,209 +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 "net/socket/socks_client_socket_pool.h" - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/containers/span.h" -#include "base/run_loop.h" -#include "base/stl_util.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "net/base/load_timing_info.h" -#include "net/base/load_timing_info_test_util.h" -#include "net/base/net_errors.h" -#include "net/base/test_completion_callback.h" -#include "net/dns/mock_host_resolver.h" -#include "net/log/net_log_source.h" -#include "net/log/net_log_with_source.h" -#include "net/socket/client_socket_factory.h" -#include "net/socket/client_socket_handle.h" -#include "net/socket/socket_tag.h" -#include "net/socket/socket_test_util.h" -#include "net/socket/socks_connect_job.h" -#include "net/socket/transport_connect_job.h" -#include "net/test/gtest_util.h" -#include "net/test/test_with_scoped_task_environment.h" -#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using net::test::IsError; -using net::test::IsOk; - -namespace net { - -namespace { - -const int kMaxSockets = 32; -const int kMaxSocketsPerGroup = 6; - -scoped_refptr<TransportSocketParams> CreateProxyHostParams() { - return new TransportSocketParams(HostPortPair("proxy", 80), false, - OnHostResolutionCallback()); -} - -scoped_refptr<SOCKSSocketParams> CreateSOCKSv5Params() { - return new SOCKSSocketParams(CreateProxyHostParams(), true /* socks_v5 */, - HostPortPair("host", 80), - TRAFFIC_ANNOTATION_FOR_TESTS); -} - -class SOCKSClientSocketPoolTest : public TestWithScopedTaskEnvironment { - protected: - class SOCKS5MockData { - public: - explicit SOCKS5MockData(IoMode mode) { - writes_.reset(new MockWrite[3]); - writes_[0] = MockWrite(mode, kSOCKS5GreetRequest, - kSOCKS5GreetRequestLength); - writes_[1] = MockWrite(mode, kSOCKS5OkRequest, kSOCKS5OkRequestLength); - writes_[2] = MockWrite(mode, 0); - - reads_.reset(new MockRead[3]); - reads_[0] = MockRead(mode, kSOCKS5GreetResponse, - kSOCKS5GreetResponseLength); - reads_[1] = MockRead(mode, kSOCKS5OkResponse, kSOCKS5OkResponseLength); - reads_[2] = MockRead(mode, 0); - - data_.reset(new StaticSocketDataProvider( - base::make_span(reads_.get(), 3), base::make_span(writes_.get(), 3))); - } - - SocketDataProvider* data_provider() { return data_.get(); } - - private: - std::unique_ptr<StaticSocketDataProvider> data_; - std::unique_ptr<MockWrite[]> writes_; - std::unique_ptr<MockRead[]> reads_; - }; - - SOCKSClientSocketPoolTest() - : transport_socket_pool_(kMaxSockets, - kMaxSocketsPerGroup, - &transport_client_socket_factory_), - pool_(kMaxSockets, - kMaxSocketsPerGroup, - &host_resolver_, - &transport_socket_pool_, - NULL, - NULL) {} - - ~SOCKSClientSocketPoolTest() override = default; - - int StartRequestV5(const std::string& group_name, RequestPriority priority) { - return test_base_.StartRequestUsingPool( - &pool_, group_name, priority, ClientSocketPool::RespectLimits::ENABLED, - CreateSOCKSv5Params()); - } - - int GetOrderOfRequest(size_t index) const { - return test_base_.GetOrderOfRequest(index); - } - - std::vector<std::unique_ptr<TestSocketRequest>>* requests() { - return test_base_.requests(); - } - - MockClientSocketFactory transport_client_socket_factory_; - MockTransportClientSocketPool transport_socket_pool_; - - MockHostResolver host_resolver_; - SOCKSClientSocketPool pool_; - ClientSocketPoolTest test_base_; -}; - -TEST_F(SOCKSClientSocketPoolTest, Simple) { - SOCKS5MockData data(SYNCHRONOUS); - data.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK)); - transport_client_socket_factory_.AddSocketDataProvider(data.data_provider()); - - ClientSocketHandle handle; - int rv = handle.Init("a", CreateSOCKSv5Params(), LOW, SocketTag(), - ClientSocketPool::RespectLimits::ENABLED, - CompletionOnceCallback(), &pool_, NetLogWithSource()); - EXPECT_THAT(rv, IsOk()); - EXPECT_TRUE(handle.is_initialized()); - EXPECT_TRUE(handle.socket()); -} - -// Test that SocketTag passed into SOCKSClientSocketPool is applied to returned -// sockets. -#if defined(OS_ANDROID) -TEST_F(SOCKSClientSocketPoolTest, Tag) { - MockTaggingClientSocketFactory socket_factory; - MockTransportClientSocketPool transport_socket_pool( - kMaxSockets, kMaxSocketsPerGroup, &socket_factory); - SOCKSClientSocketPool pool(kMaxSockets, kMaxSocketsPerGroup, &host_resolver_, - &transport_socket_pool, NULL, NULL); - SocketTag tag1(SocketTag::UNSET_UID, 0x12345678); - SocketTag tag2(getuid(), 0x87654321); - scoped_refptr<TransportSocketParams> tcp_params(new TransportSocketParams( - HostPortPair("proxy", 80), false, OnHostResolutionCallback())); - scoped_refptr<SOCKSSocketParams> params(new SOCKSSocketParams( - tcp_params, true /* socks_v5 */, HostPortPair("host", 80), - TRAFFIC_ANNOTATION_FOR_TESTS)); - - // Test socket is tagged when created synchronously. - SOCKS5MockData data_sync(SYNCHRONOUS); - data_sync.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK)); - socket_factory.AddSocketDataProvider(data_sync.data_provider()); - ClientSocketHandle handle; - int rv = handle.Init("a", params, LOW, tag1, - ClientSocketPool::RespectLimits::ENABLED, - CompletionOnceCallback(), &pool, NetLogWithSource()); - EXPECT_THAT(rv, IsOk()); - EXPECT_TRUE(handle.is_initialized()); - EXPECT_TRUE(handle.socket()); - EXPECT_EQ(socket_factory.GetLastProducedTCPSocket()->tag(), tag1); - EXPECT_TRUE( - socket_factory.GetLastProducedTCPSocket()->tagged_before_connected()); - - // Test socket is tagged when reused synchronously. - StreamSocket* socket = handle.socket(); - handle.Reset(); - rv = handle.Init("a", params, LOW, tag2, - ClientSocketPool::RespectLimits::ENABLED, - CompletionOnceCallback(), &pool, NetLogWithSource()); - EXPECT_THAT(rv, IsOk()); - EXPECT_TRUE(handle.socket()); - EXPECT_TRUE(handle.socket()->IsConnected()); - EXPECT_EQ(handle.socket(), socket); - EXPECT_EQ(socket_factory.GetLastProducedTCPSocket()->tag(), tag2); - handle.socket()->Disconnect(); - handle.Reset(); - - // Test socket is tagged when created asynchronously. - SOCKS5MockData data_async(ASYNC); - socket_factory.AddSocketDataProvider(data_async.data_provider()); - TestCompletionCallback callback; - rv = handle.Init("a", params, LOW, tag1, - ClientSocketPool::RespectLimits::ENABLED, - callback.callback(), &pool, NetLogWithSource()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - EXPECT_THAT(callback.WaitForResult(), IsOk()); - EXPECT_TRUE(handle.is_initialized()); - EXPECT_TRUE(handle.socket()); - EXPECT_EQ(socket_factory.GetLastProducedTCPSocket()->tag(), tag1); - EXPECT_TRUE( - socket_factory.GetLastProducedTCPSocket()->tagged_before_connected()); - - // Test socket is tagged when reused after being created asynchronously. - socket = handle.socket(); - handle.Reset(); - rv = handle.Init("a", params, LOW, tag2, - ClientSocketPool::RespectLimits::ENABLED, - CompletionOnceCallback(), &pool, NetLogWithSource()); - EXPECT_THAT(rv, IsOk()); - EXPECT_TRUE(handle.socket()); - EXPECT_TRUE(handle.socket()->IsConnected()); - EXPECT_EQ(handle.socket(), socket); - EXPECT_EQ(socket_factory.GetLastProducedTCPSocket()->tag(), tag2); -} -#endif - -} // namespace - -} // namespace net
diff --git a/net/socket/ssl_connect_job.cc b/net/socket/ssl_connect_job.cc index 8498ea2..0da918b 100644 --- a/net/socket/ssl_connect_job.cc +++ b/net/socket/ssl_connect_job.cc
@@ -311,7 +311,7 @@ if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { error_response_info_ = transport_socket_handle_->ssl_error_response_info(); } else if (result == ERR_PROXY_AUTH_REQUESTED || - result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { + result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) { StreamSocket* socket = transport_socket_handle_->socket(); ProxyClientSocket* tunnel_socket = static_cast<ProxyClientSocket*>(socket); error_response_info_ = *tunnel_socket->GetConnectResponseInfo();
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index 62e070b..a4ef27f 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc
@@ -17,7 +17,7 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/upload_data_stream.h" #include "net/http/http_request_headers.h" #include "net/http/http_request_info.h" @@ -322,7 +322,7 @@ int result = stream_->GetPeerAddress(&address); if (result != OK) return result; - response_info_->socket_address = HostPortPair::FromIPEndPoint(address); + response_info_->remote_endpoint = address; if (stream_->type() == SPDY_PUSH_STREAM) { // Pushed streams do not send any data, and should always be
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index 16cbd38..36bb9bcb 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -21,6 +21,7 @@ #include "net/base/chunked_upload_data_stream.h" #include "net/base/completion_once_callback.h" #include "net/base/elements_upload_data_stream.h" +#include "net/base/ip_endpoint.h" #include "net/base/proxy_delegate.h" #include "net/base/proxy_server.h" #include "net/base/request_priority.h" @@ -178,8 +179,8 @@ EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); EXPECT_TRUE(response->was_fetched_via_spdy); EXPECT_TRUE(response->was_alpn_negotiated); - EXPECT_EQ("127.0.0.1", response->socket_address.host()); - EXPECT_EQ(443, response->socket_address.port()); + EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort()); + EXPECT_EQ(443, response->remote_endpoint.port()); output_.status_line = response->headers->GetStatusLine(); output_.response_info = *response; // Make a copy so we can verify. output_.rv = ReadTransaction(trans_.get(), &output_.response_data); @@ -4865,8 +4866,8 @@ EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); EXPECT_TRUE(response->was_fetched_via_spdy); EXPECT_TRUE(response->was_alpn_negotiated); - EXPECT_EQ("127.0.0.1", response->socket_address.host()); - EXPECT_EQ(443, response->socket_address.port()); + EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort()); + EXPECT_EQ(443, response->remote_endpoint.port()); std::string response_data; rv = ReadTransaction(&trans2, &response_data); EXPECT_THAT(rv, IsOk()); @@ -4998,8 +4999,8 @@ response->connection_info); EXPECT_TRUE(response->was_alpn_negotiated); EXPECT_TRUE(request_.url.SchemeIs("https")); - EXPECT_EQ("127.0.0.1", response->socket_address.host()); - EXPECT_EQ(443, response->socket_address.port()); + EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort()); + EXPECT_EQ(443, response->remote_endpoint.port()); std::string response_data; ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk()); EXPECT_EQ("hello", response_data); @@ -5088,8 +5089,8 @@ response->connection_info); EXPECT_FALSE(response->was_alpn_negotiated); EXPECT_TRUE(request_.url.SchemeIs("https")); - EXPECT_EQ("127.0.0.1", response->socket_address.host()); - EXPECT_EQ(70, response->socket_address.port()); + EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort()); + EXPECT_EQ(70, response->remote_endpoint.port()); std::string response_data; ASSERT_THAT(ReadTransaction(helper.trans(), &response_data), IsOk()); EXPECT_EQ("hello", response_data); @@ -8126,7 +8127,7 @@ response->connection_info); EXPECT_TRUE(response->was_alpn_negotiated); EXPECT_FALSE(response->was_fetched_via_spdy); - EXPECT_EQ(70, response->socket_address.port()); + EXPECT_EQ(70, response->remote_endpoint.port()); ASSERT_TRUE(response->headers); EXPECT_EQ("HTTP/1.1 101 Switching Protocols", response->headers->GetStatusLine());
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc index 2ed9e12..79247c1 100644 --- a/net/spdy/spdy_proxy_client_socket.cc +++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -408,7 +408,7 @@ // Note that this triggers a spdy::ERROR_CODE_CANCEL. spdy_stream_->DetachDelegate(); next_state_ = STATE_DISCONNECTED; - return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; + return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT; case 407: // Proxy Authentication Required next_state_ = STATE_OPEN;
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index 75d7f9ff..ebcaea5 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -560,7 +560,7 @@ Initialize(reads, writes); - AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); + AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT); const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); ASSERT_TRUE(response != NULL);
diff --git a/net/spdy/spdy_session_pool_unittest.cc b/net/spdy/spdy_session_pool_unittest.cc index e3f28a96..d294ff9 100644 --- a/net/spdy/spdy_session_pool_unittest.cc +++ b/net/spdy/spdy_session_pool_unittest.cc
@@ -15,7 +15,6 @@ #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/traced_value.h" #include "build/build_config.h" -#include "net/base/completion_once_callback.h" #include "net/dns/host_cache.h" #include "net/http/http_network_session.h" #include "net/log/net_log_with_source.h" @@ -345,7 +344,6 @@ std::string name; std::string iplist; SpdySessionKey key; - AddressList addresses; } test_hosts[] = { {"http://www.example.org", "www.example.org", "192.0.2.33,192.168.0.1,192.168.0.5"}, @@ -362,11 +360,8 @@ // This test requires that the HostResolver cache be populated. Normal // code would have done this already, but we do it manually. - HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); - std::unique_ptr<HostResolver::Request> request; - int rv = session_deps_.host_resolver->Resolve( - info, DEFAULT_PRIORITY, &test_hosts[i].addresses, - CompletionOnceCallback(), &request, NetLogWithSource()); + int rv = session_deps_.host_resolver->LoadIntoCache( + HostPortPair(test_hosts[i].name, kTestPort), base::nullopt); EXPECT_THAT(rv, IsOk()); // Setup a SpdySessionKey. @@ -527,7 +522,6 @@ std::string name; std::string iplist; SpdySessionKey key; - AddressList addresses; } test_hosts[] = { {"www.webkit.org", "192.0.2.33,192.168.0.1,192.168.0.5"}, {"js.webkit.com", "192.168.0.4,192.168.0.1,192.0.2.33"}, @@ -540,11 +534,8 @@ // This test requires that the HostResolver cache be populated. Normal // code would have done this already, but we do it manually. - HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); - std::unique_ptr<HostResolver::Request> request; - int rv = session_deps_.host_resolver->Resolve( - info, DEFAULT_PRIORITY, &test_hosts[i].addresses, - CompletionOnceCallback(), &request, NetLogWithSource()); + int rv = session_deps_.host_resolver->LoadIntoCache( + HostPortPair(test_hosts[i].name, kTestPort), base::nullopt); EXPECT_THAT(rv, IsOk()); // Setup a SpdySessionKey @@ -593,7 +584,6 @@ std::string name; std::string iplist; SpdySessionKey key; - AddressList addresses; } test_hosts[] = { {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"}, }; @@ -604,11 +594,8 @@ session_deps_.host_resolver->rules()->AddIPLiteralRule( test_hosts[i].name, test_hosts[i].iplist, std::string()); - HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); - std::unique_ptr<HostResolver::Request> request; - int rv = session_deps_.host_resolver->Resolve( - info, DEFAULT_PRIORITY, &test_hosts[i].addresses, - CompletionOnceCallback(), &request, NetLogWithSource()); + int rv = session_deps_.host_resolver->LoadIntoCache( + HostPortPair(test_hosts[i].name, kTestPort), base::nullopt); EXPECT_THAT(rv, IsOk()); test_hosts[i].key = @@ -675,7 +662,6 @@ std::string name; std::string iplist; SpdySessionKey key; - AddressList addresses; } test_hosts[] = { {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"}, }; @@ -686,11 +672,8 @@ session_deps_.host_resolver->rules()->AddIPLiteralRule( test_hosts[i].name, test_hosts[i].iplist, std::string()); - HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); - std::unique_ptr<HostResolver::Request> request; - int rv = session_deps_.host_resolver->Resolve( - info, DEFAULT_PRIORITY, &test_hosts[i].addresses, - CompletionOnceCallback(), &request, NetLogWithSource()); + int rv = session_deps_.host_resolver->LoadIntoCache( + HostPortPair(test_hosts[i].name, kTestPort), base::nullopt); EXPECT_THAT(rv, IsOk()); test_hosts[i].key = @@ -1064,7 +1047,6 @@ std::string name; std::string iplist; SpdySessionKey key; - AddressList addresses; } test_hosts[] = { {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"}, }; @@ -1075,11 +1057,8 @@ session_deps_.host_resolver->rules()->AddIPLiteralRule( test_hosts[i].name, test_hosts[i].iplist, std::string()); - HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); - std::unique_ptr<HostResolver::Request> request; - int rv = session_deps_.host_resolver->Resolve( - info, DEFAULT_PRIORITY, &test_hosts[i].addresses, - CompletionOnceCallback(), &request, NetLogWithSource()); + int rv = session_deps_.host_resolver->LoadIntoCache( + HostPortPair(test_hosts[i].name, kTestPort), base::nullopt); EXPECT_THAT(rv, IsOk()); test_hosts[i].key =
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index e981f03e..c6eca79 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -3611,14 +3611,10 @@ SpdySessionKey key2(HostPortPair("mail.example.org", 80), ProxyServer::Direct(), PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse, SocketTag()); - HostResolver::RequestInfo info(key2.host_port_pair()); - AddressList addresses; - std::unique_ptr<HostResolver::Request> request; // Pre-populate the DNS cache, since a cached entry is required in order to // create the alias. - int rv = session_deps_.host_resolver->Resolve( - info, DEFAULT_PRIORITY, &addresses, CompletionOnceCallback(), &request, - NetLogWithSource()); + int rv = session_deps_.host_resolver->LoadIntoCache(key2.host_port_pair(), + base::nullopt); EXPECT_THAT(rv, IsOk()); // Get a session for |key2|, which should return the session created earlier.
diff --git a/net/url_request/http_with_dns_over_https_unittest.cc b/net/url_request/http_with_dns_over_https_unittest.cc index ffd641d..f04e303 100644 --- a/net/url_request/http_with_dns_over_https_unittest.cc +++ b/net/url_request/http_with_dns_over_https_unittest.cc
@@ -163,11 +163,11 @@ void OnNeedsClientAuth(const SSLConfig& used_ssl_config, SSLCertRequestInfo* cert_info) override {} - void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info, - const SSLConfig& used_ssl_config, - const ProxyInfo& used_proxy_info, - std::unique_ptr<HttpStream> stream) override { - } + void OnHttpsProxyTunnelResponseRedirect( + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + std::unique_ptr<HttpStream> stream) override {} void OnQuicBroken() override {}
diff --git a/net/url_request/test_url_fetcher_factory.cc b/net/url_request/test_url_fetcher_factory.cc index c1d1ec1..39e1f73 100644 --- a/net/url_request/test_url_fetcher_factory.cc +++ b/net/url_request/test_url_fetcher_factory.cc
@@ -17,7 +17,6 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_restrictions.h" #include "net/base/completion_once_callback.h" -#include "net/base/host_port_pair.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/upload_data_stream.h" @@ -208,9 +207,9 @@ return fake_response_headers_.get(); } -HostPortPair TestURLFetcher::GetSocketAddress() const { +IPEndPoint TestURLFetcher::GetSocketAddress() const { NOTIMPLEMENTED(); - return HostPortPair(); + return IPEndPoint(); } const ProxyServer& TestURLFetcher::ProxyServerUsed() const {
diff --git a/net/url_request/test_url_fetcher_factory.h b/net/url_request/test_url_fetcher_factory.h index 305e2f6a..695ad95 100644 --- a/net/url_request/test_url_fetcher_factory.h +++ b/net/url_request/test_url_fetcher_factory.h
@@ -20,6 +20,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "base/threading/thread_checker.h" +#include "net/base/ip_endpoint.h" #include "net/base/proxy_server.h" #include "net/http/http_request_headers.h" #include "net/http/http_status_code.h" @@ -137,7 +138,7 @@ void SaveResponseWithWriter( std::unique_ptr<URLFetcherResponseWriter> response_writer) override; HttpResponseHeaders* GetResponseHeaders() const override; - HostPortPair GetSocketAddress() const override; + IPEndPoint GetSocketAddress() const override; const ProxyServer& ProxyServerUsed() const override; bool WasFetchedViaProxy() const override; bool WasCached() const override;
diff --git a/net/url_request/url_fetcher.h b/net/url_request/url_fetcher.h index 8a037f6..5eefb7d 100644 --- a/net/url_request/url_fetcher.h +++ b/net/url_request/url_fetcher.h
@@ -14,6 +14,7 @@ #include "base/callback_forward.h" #include "base/memory/ref_counted.h" #include "base/supports_user_data.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_export.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request.h" @@ -32,7 +33,6 @@ } namespace net { -class HostPortPair; class HttpResponseHeaders; class URLFetcherDelegate; class URLFetcherResponseWriter; @@ -321,7 +321,7 @@ // Retrieve the remote socket address from the request. Must only // be called after the OnURLFetchComplete callback has run and if // the request has not failed. - virtual HostPortPair GetSocketAddress() const = 0; + virtual IPEndPoint GetSocketAddress() const = 0; // Returns the proxy server that proxied the request. Must only be called // after the OnURLFetchComplete callback has run and the request has not
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc index 1759ff54..98b1c32 100644 --- a/net/url_request/url_fetcher_core.cc +++ b/net/url_request/url_fetcher_core.cc
@@ -313,11 +313,11 @@ return response_headers_.get(); } -// TODO(panayiotis): socket_address_ is written in the IO thread, +// TODO(panayiotis): remote_endpoint_ is written in the IO thread, // if this is accessed in the UI thread, this could result in a race. // Same for response_headers_ above and was_fetched_via_proxy_ below. -HostPortPair URLFetcherCore::GetSocketAddress() const { - return socket_address_; +IPEndPoint URLFetcherCore::GetSocketAddress() const { + return remote_endpoint_; } const ProxyServer& URLFetcherCore::ProxyServerUsed() const { @@ -428,7 +428,7 @@ if (net_error == OK) { response_code_ = request_->GetResponseCode(); response_headers_ = request_->response_headers(); - socket_address_ = request_->GetSocketAddress(); + remote_endpoint_ = request_->GetResponseRemoteEndpoint(); proxy_server_ = request_->proxy_server(); was_fetched_via_proxy_ = request_->was_fetched_via_proxy(); was_cached_ = request_->was_cached();
diff --git a/net/url_request/url_fetcher_core.h b/net/url_request/url_fetcher_core.h index 89d9fa20..89c805d 100644 --- a/net/url_request/url_fetcher_core.h +++ b/net/url_request/url_fetcher_core.h
@@ -18,7 +18,7 @@ #include "base/memory/ref_counted.h" #include "base/timer/timer.h" #include "net/base/chunked_upload_data_stream.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/proxy_server.h" #include "net/http/http_request_headers.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -116,7 +116,7 @@ void SaveResponseWithWriter( std::unique_ptr<URLFetcherResponseWriter> response_writer); HttpResponseHeaders* GetResponseHeaders() const; - HostPortPair GetSocketAddress() const; + IPEndPoint GetSocketAddress() const; const ProxyServer& ProxyServerUsed() const; bool WasFetchedViaProxy() const; bool WasCached() const; @@ -265,7 +265,7 @@ bool was_cached_; int64_t received_response_content_length_; int64_t total_received_bytes_; - HostPortPair socket_address_; + IPEndPoint remote_endpoint_; bool upload_content_set_; // SetUploadData has been called std::string upload_content_; // HTTP POST payload
diff --git a/net/url_request/url_fetcher_impl.cc b/net/url_request/url_fetcher_impl.cc index 5ffd221..fa72292 100644 --- a/net/url_request/url_fetcher_impl.cc +++ b/net/url_request/url_fetcher_impl.cc
@@ -154,7 +154,7 @@ return core_->GetResponseHeaders(); } -HostPortPair URLFetcherImpl::GetSocketAddress() const { +IPEndPoint URLFetcherImpl::GetSocketAddress() const { return core_->GetSocketAddress(); }
diff --git a/net/url_request/url_fetcher_impl.h b/net/url_request/url_fetcher_impl.h index a420486..20e6706 100644 --- a/net/url_request/url_fetcher_impl.h +++ b/net/url_request/url_fetcher_impl.h
@@ -20,6 +20,7 @@ #include "base/macros.h" #include "base/sequenced_task_runner.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_export.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher.h" @@ -83,7 +84,7 @@ void SaveResponseWithWriter( std::unique_ptr<URLFetcherResponseWriter> response_writer) override; HttpResponseHeaders* GetResponseHeaders() const override; - HostPortPair GetSocketAddress() const override; + IPEndPoint GetSocketAddress() const override; const ProxyServer& ProxyServerUsed() const override; bool WasFetchedViaProxy() const override; bool WasCached() const override;
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc index 8c7283fa..eb4250b1 100644 --- a/net/url_request/url_fetcher_impl_unittest.cc +++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -1166,7 +1166,7 @@ EXPECT_EQ(test_server_->host_port_pair().port(), delegate.fetcher()->GetSocketAddress().port()); EXPECT_EQ(test_server_->host_port_pair().host(), - delegate.fetcher()->GetSocketAddress().host()); + delegate.fetcher()->GetSocketAddress().ToStringWithoutPort()); } TEST_F(URLFetcherTest, StopOnRedirect) {
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index ed6274e..66a54b3 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -20,7 +20,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "net/base/auth.h" -#include "net/base/host_port_pair.h" #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" #include "net/base/net_errors.h" @@ -387,9 +386,9 @@ } } -HostPortPair URLRequest::GetSocketAddress() const { +IPEndPoint URLRequest::GetResponseRemoteEndpoint() const { DCHECK(job_.get()); - return job_->GetSocketAddress(); + return job_->GetResponseRemoteEndpoint(); } HttpResponseHeaders* URLRequest::response_headers() const { @@ -406,11 +405,11 @@ return job_->PopulateNetErrorDetails(details); } -bool URLRequest::GetRemoteEndpoint(IPEndPoint* endpoint) const { +bool URLRequest::GetTransactionRemoteEndpoint(IPEndPoint* endpoint) const { if (!job_) return false; - return job_->GetRemoteEndpoint(endpoint); + return job_->GetTransactionRemoteEndpoint(endpoint); } void URLRequest::GetMimeType(string* mime_type) const {
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 9301dc4..33337d9 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -22,6 +22,7 @@ #include "base/time/time.h" #include "net/base/auth.h" #include "net/base/completion_callback.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_states.h" #include "net/base/load_timing_info.h" #include "net/base/net_error_details.h" @@ -53,7 +54,6 @@ namespace net { class CookieOptions; -class HostPortPair; class IOBuffer; struct LoadTimingInfo; struct RedirectInfo; @@ -512,7 +512,7 @@ // Returns the host and port that the content was fetched from. See // http_response_info.h for caveats relating to cached content. - HostPortPair GetSocketAddress() const; + IPEndPoint GetResponseRemoteEndpoint() const; // Get all response headers, as a HttpResponseHeaders object. See comments // in HttpResponseHeaders class as to the format of the data. @@ -536,14 +536,15 @@ // Gets the remote endpoint of the most recent socket that the network stack // used to make this request. // - // Note that GetSocketAddress returns the |socket_address| field from + // Note that GetResponseRemoteEndpoint returns the |socket_address| field from // HttpResponseInfo, which is only populated once the response headers are // received, and can return cached values for cache revalidation requests. - // GetRemoteEndpoint will only return addresses from the current request. + // GetTransactionRemoteEndpoint will only return addresses from the current + // request. // // Returns true and fills in |endpoint| if the endpoint is available; returns // false and leaves |endpoint| unchanged if it is unavailable. - bool GetRemoteEndpoint(IPEndPoint* endpoint) const; + bool GetTransactionRemoteEndpoint(IPEndPoint* endpoint) const; // Get the mime type. This method may only be called once the delegate's // OnResponseStarted method has been called.
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc index d1fb951..ebfc053 100644 --- a/net/url_request/url_request_ftp_job.cc +++ b/net/url_request/url_request_ftp_job.cc
@@ -92,15 +92,15 @@ *info = *http_response_info_; } -HostPortPair URLRequestFtpJob::GetSocketAddress() const { +IPEndPoint URLRequestFtpJob::GetResponseRemoteEndpoint() const { if (proxy_info_.is_direct()) { if (!ftp_transaction_) - return HostPortPair(); - return ftp_transaction_->GetResponseInfo()->socket_address; + return IPEndPoint(); + return ftp_transaction_->GetResponseInfo()->remote_endpoint; } else { if (!http_transaction_) - return HostPortPair(); - return http_transaction_->GetResponseInfo()->socket_address; + return IPEndPoint(); + return http_transaction_->GetResponseInfo()->remote_endpoint; } }
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h index 1e701c96..cfc27ff 100644 --- a/net/url_request/url_request_ftp_job.h +++ b/net/url_request/url_request_ftp_job.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "net/base/auth.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_export.h" #include "net/ftp/ftp_request_info.h" #include "net/ftp/ftp_transaction.h" @@ -42,7 +43,7 @@ bool IsSafeRedirect(const GURL& location) override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(HttpResponseInfo* info) override; - HostPortPair GetSocketAddress() const override; + IPEndPoint GetResponseRemoteEndpoint() const override; void SetPriority(RequestPriority priority) override; void Start() override; void Kill() override;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 6c00978..ad454053 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -1034,7 +1034,8 @@ load_timing_info->receive_headers_end = receive_headers_end_; } -bool URLRequestHttpJob::GetRemoteEndpoint(IPEndPoint* endpoint) const { +bool URLRequestHttpJob::GetTransactionRemoteEndpoint( + IPEndPoint* endpoint) const { if (!transaction_) return false; @@ -1380,8 +1381,8 @@ DoneWithRequest(FINISHED); } -HostPortPair URLRequestHttpJob::GetSocketAddress() const { - return response_info_ ? response_info_->socket_address : HostPortPair(); +IPEndPoint URLRequestHttpJob::GetResponseRemoteEndpoint() const { + return response_info_ ? response_info_->remote_endpoint : IPEndPoint(); } void URLRequestHttpJob::RecordTimer() {
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 0159537a..3f16164 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -17,6 +17,7 @@ #include "base/time/time.h" #include "net/base/auth.h" #include "net/base/completion_callback.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_error_details.h" #include "net/base/net_export.h" #include "net/http/http_request_info.h" @@ -107,7 +108,7 @@ bool GetCharset(std::string* charset) override; void GetResponseInfo(HttpResponseInfo* info) override; void GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; - bool GetRemoteEndpoint(IPEndPoint* endpoint) const override; + bool GetTransactionRemoteEndpoint(IPEndPoint* endpoint) const override; int GetResponseCode() const override; void PopulateNetErrorDetails(NetErrorDetails* details) const override; bool CopyFragmentOnRedirect(const GURL& location) const override; @@ -128,7 +129,7 @@ void DoneReading() override; void DoneReadingRedirectResponse() override; - HostPortPair GetSocketAddress() const override; + IPEndPoint GetResponseRemoteEndpoint() const override; void NotifyURLRequestDestroyed() override; void RecordTimer();
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index b24a0bc..85a1889 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -17,7 +17,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "net/base/auth.h" -#include "net/base/host_port_pair.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/load_states.h" @@ -176,7 +175,7 @@ // Only certain request types return more than just request start times. } -bool URLRequestJob::GetRemoteEndpoint(IPEndPoint* endpoint) const { +bool URLRequestJob::GetTransactionRemoteEndpoint(IPEndPoint* endpoint) const { return false; } @@ -284,8 +283,8 @@ return headers->response_code(); } -HostPortPair URLRequestJob::GetSocketAddress() const { - return HostPortPair(); +IPEndPoint URLRequestJob::GetResponseRemoteEndpoint() const { + return IPEndPoint(); } void URLRequestJob::OnSuspend() {
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h index f08e6e8..2b2cd17 100644 --- a/net/url_request/url_request_job.h +++ b/net/url_request/url_request_job.h
@@ -16,7 +16,7 @@ #include "base/optional.h" #include "base/power_monitor/power_observer.h" #include "net/base/completion_once_callback.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_states.h" #include "net/base/net_error_details.h" #include "net/base/net_export.h" @@ -138,7 +138,7 @@ // Gets the remote endpoint that the network stack is currently fetching the // URL from. Returns true and fills in |endpoint| if it is available; returns // false and leaves |endpoint| unchanged if it is unavailable. - virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) const; + virtual bool GetTransactionRemoteEndpoint(IPEndPoint* endpoint) const; // Populates the network error details of the most recent origin that the // network stack makes the request to. @@ -226,7 +226,7 @@ // Returns the socket address for the connection. // See url_request.h for details. - virtual HostPortPair GetSocketAddress() const; + virtual IPEndPoint GetResponseRemoteEndpoint() const; // base::PowerObserver methods: // We invoke URLRequestJob::Kill on suspend (crbug.com/4606).
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 4dda387..5c960a8 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -937,8 +937,8 @@ EXPECT_TRUE(!r->is_pending()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_EQ(d.bytes_received(), 0); - EXPECT_EQ("", r->GetSocketAddress().host()); - EXPECT_EQ(0, r->GetSocketAddress().port()); + EXPECT_TRUE(r->GetResponseRemoteEndpoint().address().empty()); + EXPECT_EQ(0, r->GetResponseRemoteEndpoint().port()); HttpRequestHeaders headers; EXPECT_FALSE(r->GetFullRequestHeaders(&headers)); @@ -980,8 +980,8 @@ EXPECT_TRUE(!r->is_pending()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_EQ(d.bytes_received(), 911); - EXPECT_EQ("", r->GetSocketAddress().host()); - EXPECT_EQ(0, r->GetSocketAddress().port()); + EXPECT_TRUE(r->GetResponseRemoteEndpoint().address().empty()); + EXPECT_EQ(0, r->GetResponseRemoteEndpoint().port()); HttpRequestHeaders headers; EXPECT_FALSE(r->GetFullRequestHeaders(&headers)); @@ -1011,8 +1011,8 @@ EXPECT_EQ(1, d.response_started_count()); EXPECT_FALSE(d.received_data_before_response()); EXPECT_EQ(d.bytes_received(), static_cast<int>(sizeof(kTestFileContent))); - EXPECT_EQ("", r->GetSocketAddress().host()); - EXPECT_EQ(0, r->GetSocketAddress().port()); + EXPECT_TRUE(r->GetResponseRemoteEndpoint().address().empty()); + EXPECT_EQ(0, r->GetResponseRemoteEndpoint().port()); HttpRequestHeaders headers; EXPECT_FALSE(r->GetFullRequestHeaders(&headers)); @@ -5106,9 +5106,9 @@ EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); EXPECT_EQ(http_test_server()->host_port_pair().host(), - r->GetSocketAddress().host()); + r->GetResponseRemoteEndpoint().ToStringWithoutPort()); EXPECT_EQ(http_test_server()->host_port_pair().port(), - r->GetSocketAddress().port()); + r->GetResponseRemoteEndpoint().port()); // TODO(eroman): Add back the NetLog tests... } @@ -5174,9 +5174,9 @@ EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); EXPECT_EQ(http_test_server()->host_port_pair().host(), - r->GetSocketAddress().host()); + r->GetResponseRemoteEndpoint().ToStringWithoutPort()); EXPECT_EQ(http_test_server()->host_port_pair().port(), - r->GetSocketAddress().port()); + r->GetResponseRemoteEndpoint().port()); } } @@ -5201,9 +5201,9 @@ EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); EXPECT_EQ(http_test_server()->host_port_pair().host(), - r->GetSocketAddress().host()); + r->GetResponseRemoteEndpoint().ToStringWithoutPort()); EXPECT_EQ(http_test_server()->host_port_pair().port(), - r->GetSocketAddress().port()); + r->GetResponseRemoteEndpoint().port()); EXPECT_TRUE(d.have_full_request_headers()); CheckFullRequestHeaders(d.full_request_headers(), test_url); @@ -5232,9 +5232,9 @@ EXPECT_FALSE(d.received_data_before_response()); EXPECT_NE(0, d.bytes_received()); EXPECT_EQ(http_test_server()->host_port_pair().host(), - r->GetSocketAddress().host()); + r->GetResponseRemoteEndpoint().ToStringWithoutPort()); EXPECT_EQ(http_test_server()->host_port_pair().port(), - r->GetSocketAddress().port()); + r->GetResponseRemoteEndpoint().port()); } } @@ -9321,9 +9321,9 @@ EXPECT_NE(0, d.bytes_received()); CheckSSLInfo(r->ssl_info()); EXPECT_EQ(test_server.host_port_pair().host(), - r->GetSocketAddress().host()); + r->GetResponseRemoteEndpoint().ToStringWithoutPort()); EXPECT_EQ(test_server.host_port_pair().port(), - r->GetSocketAddress().port()); + r->GetResponseRemoteEndpoint().port()); } } @@ -11509,9 +11509,9 @@ EXPECT_FALSE(d.received_data_before_response()); EXPECT_LT(0, d.bytes_received()); EXPECT_EQ(ftp_test_server_.host_port_pair().host(), - r->GetSocketAddress().host()); + r->GetResponseRemoteEndpoint().ToStringWithoutPort()); EXPECT_EQ(ftp_test_server_.host_port_pair().port(), - r->GetSocketAddress().port()); + r->GetResponseRemoteEndpoint().port()); } } @@ -11533,9 +11533,9 @@ EXPECT_FALSE(d.received_data_before_response()); EXPECT_EQ(GetTestFileContents(), d.data_received()); EXPECT_EQ(ftp_test_server_.host_port_pair().host(), - r->GetSocketAddress().host()); + r->GetResponseRemoteEndpoint().ToStringWithoutPort()); EXPECT_EQ(ftp_test_server_.host_port_pair().port(), - r->GetSocketAddress().port()); + r->GetResponseRemoteEndpoint().port()); } } @@ -11586,9 +11586,9 @@ EXPECT_FALSE(d.received_data_before_response()); EXPECT_EQ(GetTestFileContents(), d.data_received()); EXPECT_EQ(ftp_test_server_.host_port_pair().host(), - r->GetSocketAddress().host()); + r->GetResponseRemoteEndpoint().ToStringWithoutPort()); EXPECT_EQ(ftp_test_server_.host_port_pair().port(), - r->GetSocketAddress().port()); + r->GetResponseRemoteEndpoint().port()); LoadTimingInfo load_timing_info; r->GetLoadTimingInfo(&load_timing_info);
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc index e91f713..9ec81a6 100644 --- a/net/websockets/websocket_basic_handshake_stream.cc +++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -23,6 +23,7 @@ #include "base/time/time.h" #include "crypto/random.h" #include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_request_headers.h" #include "net/http/http_request_info.h" #include "net/http/http_response_body_drainer.h" @@ -426,7 +427,7 @@ DCHECK(http_response_info_); WebSocketDispatchOnFinishOpeningHandshake( connect_delegate_, url_, http_response_info_->headers, - http_response_info_->socket_address, http_response_info_->response_time); + http_response_info_->remote_endpoint, http_response_info_->response_time); } int WebSocketBasicHandshakeStream::ValidateResponse(int rv) {
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc index 5c44c53..f8045bff 100644 --- a/net/websockets/websocket_channel.cc +++ b/net/websockets/websocket_channel.cc
@@ -25,6 +25,7 @@ #include "base/time/time.h" #include "net/base/auth.h" #include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/http/http_util.h" @@ -206,11 +207,11 @@ int OnAuthRequired(scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) override { return creator_->OnAuthRequired(std::move(auth_info), std::move(headers), - host_port_pair, std::move(callback), + remote_endpoint, std::move(callback), credentials); } @@ -603,11 +604,11 @@ int WebSocketChannel::OnAuthRequired( scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) { return event_interface_->OnAuthRequired( - std::move(auth_info), std::move(response_headers), host_port_pair, + std::move(auth_info), std::move(response_headers), remote_endpoint, std::move(callback), credentials); }
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h index 24a4426..44f475d 100644 --- a/net/websockets/websocket_channel.h +++ b/net/websockets/websocket_channel.h
@@ -33,6 +33,7 @@ class HttpRequestHeaders; class IOBuffer; +class IPEndPoint; class NetLogWithSource; class URLRequest; class URLRequestContext; @@ -214,7 +215,7 @@ // Forwards the request to the event interface. int OnAuthRequired(scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials);
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc index b6fa071..7209658 100644 --- a/net/websockets/websocket_channel_test.cc +++ b/net/websockets/websocket_channel_test.cc
@@ -27,6 +27,7 @@ #include "base/strings/string_piece.h" #include "base/threading/thread_task_runner_handle.h" #include "net/base/completion_once_callback.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/http/http_request_headers.h" @@ -203,11 +204,11 @@ } int OnAuthRequired(scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) override { return OnAuthRequiredCalled(std::move(auth_info), - std::move(response_headers), host_port_pair, + std::move(response_headers), remote_endpoint, credentials); } @@ -219,7 +220,7 @@ MOCK_METHOD4(OnAuthRequiredCalled, int(scoped_refptr<AuthChallengeInfo>, scoped_refptr<HttpResponseHeaders>, - const HostPortPair&, + const IPEndPoint&, base::Optional<AuthCredentials>*)); }; @@ -250,7 +251,7 @@ bool fatal) override {} int OnAuthRequired(scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) override { *credentials = base::nullopt; @@ -1620,7 +1621,7 @@ auto response_headers = base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK"); auto response_info = std::make_unique<WebSocketHandshakeResponseInfo>( - GURL("ws://www.example.com/"), response_headers, HostPortPair(), + GURL("ws://www.example.com/"), response_headers, IPEndPoint(), base::Time()); connect_data_.argument_saver.connect_delegate->OnFinishOpeningHandshake( std::move(response_info)); @@ -1645,7 +1646,7 @@ auto response_headers = base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK"); auto response_info = std::make_unique<WebSocketHandshakeResponseInfo>( - url, response_headers, HostPortPair(), base::Time()); + url, response_headers, IPEndPoint(), base::Time()); connect_delegate->OnStartOpeningHandshake(std::move(request_info)); connect_delegate->OnFinishOpeningHandshake(std::move(response_info)); @@ -2969,7 +2970,7 @@ base::Optional<AuthCredentials> credentials; scoped_refptr<HttpResponseHeaders> response_headers = base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK"); - HostPortPair socket_address("127.0.0.1", 80); + IPEndPoint remote_endpoint(net::IPAddress(127, 0, 0, 1), 80); EXPECT_CALL( *event_interface_, @@ -2978,7 +2979,7 @@ CreateChannelAndConnect(); connect_data_.argument_saver.connect_delegate->OnAuthRequired( - auth_info, response_headers, socket_address, {}, &credentials); + auth_info, response_headers, remote_endpoint, {}, &credentials); } // If we receive another frame after Close, it is not valid. It is not
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc index b1ad596..9622efb 100644 --- a/net/websockets/websocket_end_to_end_test.cc +++ b/net/websockets/websocket_end_to_end_test.cc
@@ -30,6 +30,7 @@ #include "build/build_config.h" #include "net/base/auth.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/proxy_delegate.h" #include "net/base/url_util.h" #include "net/http/http_request_headers.h" @@ -127,7 +128,7 @@ int OnAuthRequired(scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) override; @@ -210,7 +211,7 @@ int ConnectTestingEventInterface::OnAuthRequired( scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) { *credentials = base::nullopt;
diff --git a/net/websockets/websocket_event_interface.h b/net/websockets/websocket_event_interface.h index 190d83b..4c3d6e3 100644 --- a/net/websockets/websocket_event_interface.h +++ b/net/websockets/websocket_event_interface.h
@@ -24,7 +24,7 @@ class AuthChallengeInfo; class AuthCredentials; -class HostPortPair; +class IPEndPoint; class HttpResponseHeaders; class IOBuffer; class SSLInfo; @@ -138,7 +138,7 @@ virtual int OnAuthRequired( scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& socket_address, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) = 0;
diff --git a/net/websockets/websocket_handshake_response_info.cc b/net/websockets/websocket_handshake_response_info.cc index d59ab1e4..90ca0e1 100644 --- a/net/websockets/websocket_handshake_response_info.cc +++ b/net/websockets/websocket_handshake_response_info.cc
@@ -15,11 +15,11 @@ WebSocketHandshakeResponseInfo::WebSocketHandshakeResponseInfo( const GURL& url, scoped_refptr<HttpResponseHeaders> headers, - const HostPortPair& socket_address, + const IPEndPoint& remote_endpoint, base::Time response_time) : url(url), headers(std::move(headers)), - socket_address(socket_address), + remote_endpoint(remote_endpoint), response_time(response_time) {} WebSocketHandshakeResponseInfo::~WebSocketHandshakeResponseInfo() = default;
diff --git a/net/websockets/websocket_handshake_response_info.h b/net/websockets/websocket_handshake_response_info.h index 90232da0..42db90b 100644 --- a/net/websockets/websocket_handshake_response_info.h +++ b/net/websockets/websocket_handshake_response_info.h
@@ -8,7 +8,7 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/time/time.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_export.h" #include "url/gurl.h" @@ -19,7 +19,7 @@ struct NET_EXPORT WebSocketHandshakeResponseInfo { WebSocketHandshakeResponseInfo(const GURL& url, scoped_refptr<HttpResponseHeaders> headers, - const HostPortPair& socket_address, + const IPEndPoint& remote_endpoint, base::Time response_time); ~WebSocketHandshakeResponseInfo(); // The request URL @@ -27,7 +27,7 @@ // HTTP response headers scoped_refptr<HttpResponseHeaders> headers; // Remote address of the socket. - HostPortPair socket_address; + IPEndPoint remote_endpoint; // The time that this response arrived base::Time response_time;
diff --git a/net/websockets/websocket_handshake_stream_create_helper_test.cc b/net/websockets/websocket_handshake_stream_create_helper_test.cc index f8a71c3..a3df7944 100644 --- a/net/websockets/websocket_handshake_stream_create_helper_test.cc +++ b/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "net/base/completion_once_callback.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/proxy_server.h" #include "net/http/http_network_session.h" @@ -99,7 +100,7 @@ int OnAuthRequired(scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& host_port_pair, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) override { *credentials = base::nullopt;
diff --git a/net/websockets/websocket_http2_handshake_stream.cc b/net/websockets/websocket_http2_handshake_stream.cc index f5e0ab8..343b4cd 100644 --- a/net/websockets/websocket_http2_handshake_stream.cc +++ b/net/websockets/websocket_http2_handshake_stream.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_request_headers.h" #include "net/http/http_request_info.h" #include "net/http/http_response_headers.h" @@ -102,7 +103,7 @@ OnFailure("Error getting IP address."); return result; } - http_response_info_->socket_address = HostPortPair::FromIPEndPoint(address); + http_response_info_->remote_endpoint = address; auto request = std::make_unique<WebSocketHandshakeRequestInfo>( request_info_->url, base::Time::Now()); @@ -378,7 +379,7 @@ DCHECK(http_response_info_); WebSocketDispatchOnFinishOpeningHandshake( connect_delegate_, request_info_->url, http_response_info_->headers, - http_response_info_->socket_address, http_response_info_->response_time); + http_response_info_->remote_endpoint, http_response_info_->response_time); } void WebSocketHttp2HandshakeStream::OnFailure(const std::string& message) {
diff --git a/net/websockets/websocket_stream.cc b/net/websockets/websocket_stream.cc index e4a3b9d..5e716880 100644 --- a/net/websockets/websocket_stream.cc +++ b/net/websockets/websocket_stream.cc
@@ -12,6 +12,7 @@ #include "base/metrics/histogram_functions.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/url_util.h" #include "net/http/http_request_headers.h" @@ -257,7 +258,8 @@ void OnFinishOpeningHandshake() { WebSocketDispatchOnFinishOpeningHandshake( connect_delegate(), url_request_->url(), - url_request_->response_headers(), url_request_->GetSocketAddress(), + url_request_->response_headers(), + url_request_->GetResponseRemoteEndpoint(), url_request_->response_time()); } @@ -414,7 +416,7 @@ // be called called during the opening handshake. int rv = owner_->connect_delegate()->OnAuthRequired( scoped_refptr<AuthChallengeInfo>(auth_info), request->response_headers(), - request->GetSocketAddress(), + request->GetResponseRemoteEndpoint(), base::BindOnce(&Delegate::OnAuthRequiredComplete, base::Unretained(this), request), &credentials); @@ -511,13 +513,13 @@ WebSocketStream::ConnectDelegate* connect_delegate, const GURL& url, const scoped_refptr<HttpResponseHeaders>& headers, - const HostPortPair& socket_address, + const IPEndPoint& remote_endpoint, base::Time response_time) { DCHECK(connect_delegate); if (headers.get()) { connect_delegate->OnFinishOpeningHandshake( std::make_unique<WebSocketHandshakeResponseInfo>( - url, headers, socket_address, response_time)); + url, headers, remote_endpoint, response_time)); } }
diff --git a/net/websockets/websocket_stream.h b/net/websockets/websocket_stream.h index 51ebac9b..867b5a9 100644 --- a/net/websockets/websocket_stream.h +++ b/net/websockets/websocket_stream.h
@@ -34,9 +34,9 @@ class AuthChallengeInfo; class AuthCredentials; -class HostPortPair; class HttpRequestHeaders; class HttpResponseHeaders; +class IPEndPoint; class NetLogWithSource; class URLRequest; class URLRequestContext; @@ -131,7 +131,7 @@ virtual int OnAuthRequired( scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) = 0; }; @@ -275,7 +275,7 @@ WebSocketStream::ConnectDelegate* connect_delegate, const GURL& gurl, const scoped_refptr<HttpResponseHeaders>& headers, - const HostPortPair& socket_address, + const IPEndPoint& remote_endpoint, base::Time response_time); } // namespace net
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc index 2a62ffd..9db4381 100644 --- a/net/websockets/websocket_stream_create_test_base.cc +++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/log/net_log_with_source.h" @@ -70,7 +71,7 @@ int OnAuthRequired(scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) override { owner_->run_loop_waiting_for_on_auth_required_.Quit();
diff --git a/net/websockets/websocket_test_util.cc b/net/websockets/websocket_test_util.cc index fafb944..5335404 100644 --- a/net/websockets/websocket_test_util.cc +++ b/net/websockets/websocket_test_util.cc
@@ -11,6 +11,7 @@ #include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_network_session.h" #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/socket/socket_test_util.h" @@ -260,7 +261,7 @@ int DummyConnectDelegate::OnAuthRequired( scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& host_port_pair, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) { return OK;
diff --git a/net/websockets/websocket_test_util.h b/net/websockets/websocket_test_util.h index 4ab42ee..7346a657 100644 --- a/net/websockets/websocket_test_util.h +++ b/net/websockets/websocket_test_util.h
@@ -35,6 +35,7 @@ class WebSocketBasicHandshakeStream; class ProxyResolutionService; class SequencedSocketData; +class IPEndPoint; struct SSLSocketDataProvider; class LinearCongruentialGenerator { @@ -196,7 +197,7 @@ bool fatal) override {} int OnAuthRequired(scoped_refptr<AuthChallengeInfo> auth_info, scoped_refptr<HttpResponseHeaders> response_headers, - const HostPortPair& host_port_pair, + const IPEndPoint& remote_endpoint, base::OnceCallback<void(const AuthCredentials*)> callback, base::Optional<AuthCredentials>* credentials) override; };
diff --git a/remoting/base/fake_oauth_token_getter.cc b/remoting/base/fake_oauth_token_getter.cc index b1b21c7..4c60e6d 100644 --- a/remoting/base/fake_oauth_token_getter.cc +++ b/remoting/base/fake_oauth_token_getter.cc
@@ -18,10 +18,10 @@ FakeOAuthTokenGetter::~FakeOAuthTokenGetter() = default; -void FakeOAuthTokenGetter::CallWithToken(const TokenCallback& on_access_token) { +void FakeOAuthTokenGetter::CallWithToken(TokenCallback on_access_token) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(on_access_token, status_, user_email_, access_token_)); + FROM_HERE, base::BindOnce(std::move(on_access_token), status_, + user_email_, access_token_)); } void FakeOAuthTokenGetter::InvalidateCache() {
diff --git a/remoting/base/fake_oauth_token_getter.h b/remoting/base/fake_oauth_token_getter.h index 0b70a09..1966f96 100644 --- a/remoting/base/fake_oauth_token_getter.h +++ b/remoting/base/fake_oauth_token_getter.h
@@ -20,7 +20,7 @@ ~FakeOAuthTokenGetter() override; // OAuthTokenGetter interface. - void CallWithToken(const TokenCallback& on_access_token) override; + void CallWithToken(TokenCallback on_access_token) override; void InvalidateCache() override; private:
diff --git a/remoting/base/oauth_token_getter.h b/remoting/base/oauth_token_getter.h index cd3eb58..361d01e 100644 --- a/remoting/base/oauth_token_getter.h +++ b/remoting/base/oauth_token_getter.h
@@ -25,14 +25,13 @@ AUTH_ERROR, }; - // TODO(crbug.com/824488): Change to use base::OnceCallback. - typedef base::Callback<void(Status status, - const std::string& user_email, - const std::string& access_token)> + typedef base::OnceCallback<void(Status status, + const std::string& user_email, + const std::string& access_token)> TokenCallback; - typedef base::Callback<void(const std::string& user_email, - const std::string& refresh_token)> + typedef base::RepeatingCallback<void(const std::string& user_email, + const std::string& refresh_token)> CredentialsUpdatedCallback; // This structure contains information required to perform authorization @@ -87,7 +86,7 @@ // Call |on_access_token| with an access token, or the failure status. virtual void CallWithToken( - const OAuthTokenGetter::TokenCallback& on_access_token) = 0; + OAuthTokenGetter::TokenCallback on_access_token) = 0; // Invalidates the cache, so the next CallWithToken() will get a fresh access // token.
diff --git a/remoting/base/oauth_token_getter_impl.cc b/remoting/base/oauth_token_getter_impl.cc index f095ccbe..5bc231b 100644 --- a/remoting/base/oauth_token_getter_impl.cc +++ b/remoting/base/oauth_token_getter_impl.cc
@@ -148,11 +148,11 @@ const std::string& user_email, const std::string& access_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - base::queue<TokenCallback> callbacks(pending_callbacks_); - pending_callbacks_ = base::queue<TokenCallback>(); + base::queue<TokenCallback> callbacks; + callbacks.swap(pending_callbacks_); while (!callbacks.empty()) { - callbacks.front().Run(status, user_email, access_token); + std::move(callbacks.front()).Run(status, user_email, access_token); callbacks.pop(); } } @@ -189,10 +189,10 @@ std::string()); } -void OAuthTokenGetterImpl::CallWithToken(const TokenCallback& on_access_token) { +void OAuthTokenGetterImpl::CallWithToken(TokenCallback on_access_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (intermediate_credentials_) { - pending_callbacks_.push(on_access_token); + pending_callbacks_.push(std::move(on_access_token)); if (!response_pending_) { GetOauthTokensFromAuthCode(); } @@ -203,13 +203,13 @@ (!authorization_credentials_->is_service_account && !email_verified_); if (need_new_auth_token) { - pending_callbacks_.push(on_access_token); + pending_callbacks_.push(std::move(on_access_token)); if (!response_pending_) { RefreshAccessToken(); } } else { - on_access_token.Run(SUCCESS, authorization_credentials_->login, - oauth_access_token_); + std::move(on_access_token) + .Run(SUCCESS, authorization_credentials_->login, oauth_access_token_); } } }
diff --git a/remoting/base/oauth_token_getter_impl.h b/remoting/base/oauth_token_getter_impl.h index bdb20080..68ef1fec 100644 --- a/remoting/base/oauth_token_getter_impl.h +++ b/remoting/base/oauth_token_getter_impl.h
@@ -42,8 +42,7 @@ ~OAuthTokenGetterImpl() override; // OAuthTokenGetter interface. - void CallWithToken( - const OAuthTokenGetter::TokenCallback& on_access_token) override; + void CallWithToken(OAuthTokenGetter::TokenCallback on_access_token) override; void InvalidateCache() override; private:
diff --git a/remoting/base/telemetry_log_writer.cc b/remoting/base/telemetry_log_writer.cc index 6b8e0ec..8054f9c 100644 --- a/remoting/base/telemetry_log_writer.cc +++ b/remoting/base/telemetry_log_writer.cc
@@ -67,7 +67,7 @@ LOG(ERROR) << "Failed to serialize log to JSON."; return; } - token_getter_->CallWithToken(base::BindRepeating( + token_getter_->CallWithToken(base::BindOnce( &TelemetryLogWriter::PostJsonToServer, base::Unretained(this), json)); }
diff --git a/remoting/client/jni/jni_oauth_token_getter.cc b/remoting/client/jni/jni_oauth_token_getter.cc index 3198018..ea6a1e8 100644 --- a/remoting/client/jni/jni_oauth_token_getter.cc +++ b/remoting/client/jni/jni_oauth_token_getter.cc
@@ -37,9 +37,12 @@ NOTREACHED(); return; } - callback->Run(status, - user_email.is_null() ? "" : ConvertJavaStringToUTF8(user_email), - token.is_null() ? "" : ConvertJavaStringToUTF8(token)); + + std::string utf8_user_email = + user_email.is_null() ? "" : ConvertJavaStringToUTF8(user_email); + std::string utf8_token = + token.is_null() ? "" : ConvertJavaStringToUTF8(token); + std::move(*callback).Run(status, utf8_user_email, utf8_token); delete callback; } @@ -52,12 +55,12 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } -void JniOAuthTokenGetter::CallWithToken(const TokenCallback& on_access_token) { +void JniOAuthTokenGetter::CallWithToken(TokenCallback on_access_token) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); JNIEnv* env = base::android::AttachCurrentThread(); - TokenCallback* callback_copy = new TokenCallback(on_access_token); - Java_JniOAuthTokenGetter_fetchAuthToken( - env, reinterpret_cast<intptr_t>(callback_copy)); + TokenCallback* callback = new TokenCallback(std::move(on_access_token)); + Java_JniOAuthTokenGetter_fetchAuthToken(env, + reinterpret_cast<intptr_t>(callback)); } void JniOAuthTokenGetter::InvalidateCache() {
diff --git a/remoting/client/jni/jni_oauth_token_getter.h b/remoting/client/jni/jni_oauth_token_getter.h index bdb0381..7328032 100644 --- a/remoting/client/jni/jni_oauth_token_getter.h +++ b/remoting/client/jni/jni_oauth_token_getter.h
@@ -31,7 +31,7 @@ ~JniOAuthTokenGetter() override; // OAuthTokenGetter overrides. - void CallWithToken(const TokenCallback& on_access_token) override; + void CallWithToken(TokenCallback on_access_token) override; void InvalidateCache() override; base::WeakPtr<JniOAuthTokenGetter> GetWeakPtr();
diff --git a/remoting/client/oauth_token_getter_proxy.cc b/remoting/client/oauth_token_getter_proxy.cc index 361412b..af04ae84 100644 --- a/remoting/client/oauth_token_getter_proxy.cc +++ b/remoting/client/oauth_token_getter_proxy.cc
@@ -14,19 +14,19 @@ namespace { void ResolveCallback( - const OAuthTokenGetter::TokenCallback& on_access_token, + OAuthTokenGetter::TokenCallback on_access_token, scoped_refptr<base::SingleThreadTaskRunner> original_task_runner, OAuthTokenGetter::Status status, const std::string& user_email, const std::string& access_token) { if (!original_task_runner->BelongsToCurrentThread()) { original_task_runner->PostTask( - FROM_HERE, - base::BindOnce(on_access_token, status, user_email, access_token)); + FROM_HERE, base::BindOnce(std::move(on_access_token), status, + user_email, access_token)); return; } - on_access_token.Run(status, user_email, access_token); + std::move(on_access_token).Run(status, user_email, access_token); } } // namespace @@ -39,21 +39,20 @@ OAuthTokenGetterProxy::~OAuthTokenGetterProxy() {} void OAuthTokenGetterProxy::CallWithToken( - const OAuthTokenGetter::TokenCallback& on_access_token) { + OAuthTokenGetter::TokenCallback on_access_token) { if (!task_runner_->BelongsToCurrentThread()) { auto task_runner_to_reply = base::ThreadTaskRunnerHandle::Get(); - // TODO(crbug.com/824488): Change to base::BindOnce(). - auto reply_callback = base::BindRepeating(&ResolveCallback, on_access_token, - task_runner_to_reply); - task_runner_->PostTask(FROM_HERE, - base::BindOnce(&OAuthTokenGetter::CallWithToken, - token_getter_, reply_callback)); + auto reply_callback = base::BindOnce( + &ResolveCallback, std::move(on_access_token), task_runner_to_reply); + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&OAuthTokenGetter::CallWithToken, + token_getter_, std::move(reply_callback))); return; } if (token_getter_) { - token_getter_->CallWithToken(on_access_token); + token_getter_->CallWithToken(std::move(on_access_token)); } }
diff --git a/remoting/client/oauth_token_getter_proxy.h b/remoting/client/oauth_token_getter_proxy.h index 2fe3199a..a246a434 100644 --- a/remoting/client/oauth_token_getter_proxy.h +++ b/remoting/client/oauth_token_getter_proxy.h
@@ -29,7 +29,7 @@ ~OAuthTokenGetterProxy() override; // OAuthTokenGetter overrides. - void CallWithToken(const TokenCallback& on_access_token) override; + void CallWithToken(TokenCallback on_access_token) override; void InvalidateCache() override; private:
diff --git a/remoting/client/oauth_token_getter_proxy_unittest.cc b/remoting/client/oauth_token_getter_proxy_unittest.cc index d9f0bdc..58caac0 100644 --- a/remoting/client/oauth_token_getter_proxy_unittest.cc +++ b/remoting/client/oauth_token_getter_proxy_unittest.cc
@@ -37,7 +37,7 @@ void ExpectInvalidateCache(); // OAuthTokenGetter overrides. - void CallWithToken(const TokenCallback& on_access_token) override; + void CallWithToken(TokenCallback on_access_token) override; void InvalidateCache() override; base::WeakPtr<FakeOAuthTokenGetter> GetWeakPtr(); @@ -66,8 +66,7 @@ const std::string& access_token) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!on_access_token_.is_null()); - on_access_token_.Run(status, user_email, access_token); - on_access_token_.Reset(); + std::move(on_access_token_).Run(status, user_email, access_token); } void FakeOAuthTokenGetter::ExpectInvalidateCache() { @@ -76,9 +75,9 @@ invalidate_cache_expected_ = true; } -void FakeOAuthTokenGetter::CallWithToken(const TokenCallback& on_access_token) { +void FakeOAuthTokenGetter::CallWithToken(TokenCallback on_access_token) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - on_access_token_ = on_access_token; + on_access_token_ = std::move(on_access_token); } void FakeOAuthTokenGetter::InvalidateCache() {
diff --git a/remoting/host/basic_desktop_environment.cc b/remoting/host/basic_desktop_environment.cc index 2622454c5..267134a 100644 --- a/remoting/host/basic_desktop_environment.cc +++ b/remoting/host/basic_desktop_environment.cc
@@ -72,7 +72,7 @@ std::unique_ptr<FileOperations> BasicDesktopEnvironment::CreateFileOperations() { - return std::make_unique<LocalFileOperations>(); + return std::make_unique<LocalFileOperations>(ui_task_runner_); } std::string BasicDesktopEnvironment::GetCapabilities() const {
diff --git a/remoting/host/file_transfer/BUILD.gn b/remoting/host/file_transfer/BUILD.gn index d898537..f542c47 100644 --- a/remoting/host/file_transfer/BUILD.gn +++ b/remoting/host/file_transfer/BUILD.gn
@@ -8,6 +8,11 @@ sources = [ "ensure_user_mac.cc", "ensure_user_win.cc", + "file_chooser_chromeos.cc", + "file_chooser_common_win.h", + "file_chooser_mac.mm", + "file_chooser_main_win.cc", + "file_chooser_win.cc", "get_desktop_directory.cc", "get_desktop_directory.h", "get_desktop_directory_win.cc", @@ -29,6 +34,11 @@ if (is_win) { sources -= [ "get_desktop_directory.cc" ] } + + if (is_desktop_linux) { + sources += [ "file_chooser_linux.cc" ] + deps += [ "//build/config/linux/gtk" ] + } } source_set("common") { @@ -45,10 +55,6 @@ "buffered_file_writer.h", "ensure_user.h", "file_chooser.h", - "file_chooser_common_win.h", - "file_chooser_mac.mm", - "file_chooser_main_win.cc", - "file_chooser_win.cc", "file_transfer_message_handler.cc", "ipc_file_operations.cc", "local_file_operations.cc", @@ -59,11 +65,6 @@ "//base", "//remoting/protocol", ] - - if (is_desktop_linux) { - sources += [ "file_chooser_linux.cc" ] - deps += [ "//build/config/linux/gtk" ] - } } source_set("test_support") { @@ -71,6 +72,8 @@ sources = [ "ensure_user_no_op.cc", + "fake_file_chooser.cc", + "fake_file_chooser.h", "fake_file_operations.cc", "fake_file_operations.h", "get_desktop_directory.cc",
diff --git a/remoting/host/file_transfer/fake_file_chooser.cc b/remoting/host/file_transfer/fake_file_chooser.cc new file mode 100644 index 0000000..f8afd08 --- /dev/null +++ b/remoting/host/file_transfer/fake_file_chooser.cc
@@ -0,0 +1,46 @@ +// Copyright 2019 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 "remoting/host/file_transfer/fake_file_chooser.h" + +#include "base/bind.h" +#include "base/no_destructor.h" +#include "base/sequenced_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "remoting/protocol/file_transfer_helpers.h" + +namespace remoting { + +namespace { + +FileChooser::Result& StaticResult() { + static base::NoDestructor<FileChooser::Result> result( + protocol::MakeFileTransferError( + FROM_HERE, protocol::FileTransfer_Error_Type_CANCELED)); + return *result; +} + +} // namespace + +std::unique_ptr<FileChooser> FileChooser::Create( + scoped_refptr<base::SequencedTaskRunner> ui_task_runner, + ResultCallback callback) { + return std::make_unique<FakeFileChooser>(std::move(callback)); +} + +FakeFileChooser::FakeFileChooser(FileChooser::ResultCallback callback) + : callback_(std::move(callback)) {} + +FakeFileChooser::~FakeFileChooser() = default; + +void FakeFileChooser::Show() { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback_), StaticResult())); +} + +void FakeFileChooser::SetResult(FileChooser::Result result) { + StaticResult() = std::move(result); +} + +} // namespace remoting
diff --git a/remoting/host/file_transfer/fake_file_chooser.h b/remoting/host/file_transfer/fake_file_chooser.h new file mode 100644 index 0000000..a50a902 --- /dev/null +++ b/remoting/host/file_transfer/fake_file_chooser.h
@@ -0,0 +1,33 @@ +// Copyright 2019 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 REMOTING_HOST_FILE_TRANSFER_FAKE_FILE_CHOOSER_H_ +#define REMOTING_HOST_FILE_TRANSFER_FAKE_FILE_CHOOSER_H_ + +#include "base/macros.h" +#include "remoting/host/file_transfer/file_chooser.h" + +namespace remoting { + +class FakeFileChooser : public FileChooser { + public: + explicit FakeFileChooser(ResultCallback callback); + + ~FakeFileChooser() override; + + // FileChooser implementation. + void Show() override; + + // The result that usages of FakeFileChooser should return. + static void SetResult(FileChooser::Result result); + + private: + ResultCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(FakeFileChooser); +}; + +} // namespace remoting + +#endif // REMOTING_HOST_FILE_TRANSFER_FAKE_FILE_CHOOSER_H_
diff --git a/remoting/host/file_transfer/fake_file_operations.cc b/remoting/host/file_transfer/fake_file_operations.cc index 3377ff5..041700cd6 100644 --- a/remoting/host/file_transfer/fake_file_operations.cc +++ b/remoting/host/file_transfer/fake_file_operations.cc
@@ -83,7 +83,7 @@ FROM_HERE, base::BindOnce(&FakeFileWriter::DoOpen, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); -}; +} void FakeFileOperations::FakeFileWriter::WriteChunk(std::string data, Callback callback) {
diff --git a/remoting/host/file_transfer/file_chooser_chromeos.cc b/remoting/host/file_transfer/file_chooser_chromeos.cc new file mode 100644 index 0000000..c15b8fd --- /dev/null +++ b/remoting/host/file_transfer/file_chooser_chromeos.cc
@@ -0,0 +1,17 @@ +// Copyright 2019 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 "base/logging.h" +#include "remoting/host/file_transfer/file_chooser.h" + +namespace remoting { + +std::unique_ptr<FileChooser> FileChooser::Create( + scoped_refptr<base::SequencedTaskRunner> ui_task_runner, + ResultCallback callback) { + NOTIMPLEMENTED(); + return nullptr; +} + +} // namespace remoting
diff --git a/remoting/host/file_transfer/file_chooser_win.cc b/remoting/host/file_transfer/file_chooser_win.cc index 95481807..c2c6480 100644 --- a/remoting/host/file_transfer/file_chooser_win.cc +++ b/remoting/host/file_transfer/file_chooser_win.cc
@@ -137,16 +137,16 @@ // Currently, WaitForExit returns immediately if GetExitCodeProcess fails, // so GetLastError should still be relevant. PLOG(ERROR) << "Failed to check exit status"; + process_.Close(); std::move(callback_).Run(MakeFileTransferError( FROM_HERE, protocol::FileTransfer_Error_Type_UNEXPECTED_ERROR)); - process_.Close(); return; } if (exit_code != ERROR_SUCCESS) { LOG(ERROR) << "Error running dialog process:" << exit_code; + process_.Close(); std::move(callback_).Run(MakeFileTransferError( FROM_HERE, protocol::FileTransfer_Error_Type_UNEXPECTED_ERROR)); - process_.Close(); return; } process_.Close();
diff --git a/remoting/host/file_transfer/local_file_operations.cc b/remoting/host/file_transfer/local_file_operations.cc index d840e7a..844f496 100644 --- a/remoting/host/file_transfer/local_file_operations.cc +++ b/remoting/host/file_transfer/local_file_operations.cc
@@ -22,6 +22,7 @@ #include "build/build_config.h" #include "remoting/base/result.h" #include "remoting/host/file_transfer/ensure_user.h" +#include "remoting/host/file_transfer/file_chooser.h" #include "remoting/host/file_transfer/get_desktop_directory.h" #include "remoting/protocol/file_transfer_helpers.h" @@ -43,12 +44,70 @@ } } +scoped_refptr<base::SequencedTaskRunner> CreateFileTaskRunner() { +#if defined(OS_WIN) + // On Windows, we use user impersonation to write files as the currently + // logged-in user, while the process as a whole runs as SYSTEM. Since user + // impersonation is per-thread on Windows, we need a dedicated thread to + // ensure that no other code is accidentally run with the wrong privileges. + return base::CreateSingleThreadTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, + base::SingleThreadTaskRunnerThreadMode::DEDICATED); +#else + return base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); +#endif +} + +class LocalFileReader : public FileOperations::Reader { + public: + explicit LocalFileReader( + scoped_refptr<base::SequencedTaskRunner> ui_task_runner); + ~LocalFileReader() override; + + // FileOperations::Reader implementation. + void Open(OpenCallback callback) override; + void ReadChunk(std::size_t size, ReadCallback callback) override; + const base::FilePath& filename() const override; + std::uint64_t size() const override; + FileOperations::State state() const override; + + private: + void OnEnsureUserResult(OpenCallback callback, + protocol::FileTransferResult<Monostate> result); + void OnFileChooserResult(OpenCallback callback, FileChooser::Result result); + void OnOpenResult(OpenCallback callback, base::File::Error error); + void OnGetInfoResult(OpenCallback callback, + base::File::Error error, + const base::File::Info& info); + void OnReadResult(ReadCallback callback, + base::File::Error error, + const char* data, + int bytes_read); + + void SetState(FileOperations::State state); + + base::FilePath filename_; + std::uint64_t size_ = 0; + std::uint64_t offset_ = 0; + FileOperations::State state_ = FileOperations::kCreated; + + scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; + scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + std::unique_ptr<FileChooser> file_chooser_; + base::Optional<base::FileProxy> file_proxy_; + SEQUENCE_CHECKER(sequence_checker_); + base::WeakPtrFactory<LocalFileReader> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(LocalFileReader); +}; + class LocalFileWriter : public FileOperations::Writer { public: LocalFileWriter(); ~LocalFileWriter() override; - // FileOperations::Writer implementation + // FileOperations::Writer implementation. void Open(const base::FilePath& filename, Callback callback) override; void WriteChunk(std::string data, Callback callback) override; void Close(Callback callback) override; @@ -93,6 +152,150 @@ DISALLOW_COPY_AND_ASSIGN(LocalFileWriter); }; +LocalFileReader::LocalFileReader( + scoped_refptr<base::SequencedTaskRunner> ui_task_runner) + : ui_task_runner_(std::move(ui_task_runner)), weak_ptr_factory_(this) {} + +LocalFileReader::~LocalFileReader() = default; + +void LocalFileReader::Open(OpenCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(FileOperations::kCreated, state_); + SetState(FileOperations::kBusy); + file_task_runner_ = CreateFileTaskRunner(); + file_proxy_.emplace(file_task_runner_.get()); + base::PostTaskAndReplyWithResult( + file_task_runner_.get(), FROM_HERE, base::BindOnce(&EnsureUserContext), + base::BindOnce(&LocalFileReader::OnEnsureUserResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void LocalFileReader::ReadChunk(std::size_t size, ReadCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(FileOperations::kReady, state_); + SetState(FileOperations::kBusy); + file_proxy_->Read( + offset_, size, + base::BindOnce(&LocalFileReader::OnReadResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +const base::FilePath& LocalFileReader::filename() const { + return filename_; +} + +uint64_t LocalFileReader::size() const { + return size_; +} + +FileOperations::State LocalFileReader::state() const { + return state_; +} + +void LocalFileReader::OnEnsureUserResult( + FileOperations::Reader::OpenCallback callback, + protocol::FileTransferResult<Monostate> result) { + if (!result) { + SetState(FileOperations::kFailed); + std::move(callback).Run(std::move(result.error())); + return; + } + + file_chooser_ = FileChooser::Create( + ui_task_runner_, + base::BindOnce(&LocalFileReader::OnFileChooserResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + file_chooser_->Show(); +} + +void LocalFileReader::OnFileChooserResult(OpenCallback callback, + FileChooser::Result result) { + file_chooser_.reset(); + if (!result) { + SetState(FileOperations::kFailed); + std::move(callback).Run(std::move(result.error())); + return; + } + + filename_ = result->BaseName(); + file_proxy_->CreateOrOpen( + *result, base::File::FLAG_OPEN | base::File::FLAG_READ, + base::BindOnce(&LocalFileReader::OnOpenResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void LocalFileReader::OnOpenResult(OpenCallback callback, + base::File::Error error) { + if (error != base::File::FILE_OK) { + SetState(FileOperations::kFailed); + std::move(callback).Run(protocol::MakeFileTransferError( + FROM_HERE, FileErrorToResponseErrorType(error), error)); + return; + } + + file_proxy_->GetInfo(base::BindOnce(&LocalFileReader::OnGetInfoResult, + weak_ptr_factory_.GetWeakPtr(), + std::move(callback))); +} + +void LocalFileReader::OnGetInfoResult(OpenCallback callback, + base::File::Error error, + const base::File::Info& info) { + if (error != base::File::FILE_OK) { + SetState(FileOperations::kFailed); + std::move(callback).Run(protocol::MakeFileTransferError( + FROM_HERE, FileErrorToResponseErrorType(error), error)); + return; + } + + size_ = info.size; + + SetState(FileOperations::kReady); + std::move(callback).Run(kSuccessTag); +} + +void LocalFileReader::OnReadResult(ReadCallback callback, + base::File::Error error, + const char* data, + int bytes_read) { + if (error != base::File::FILE_OK) { + SetState(FileOperations::kFailed); + std::move(callback).Run(protocol::MakeFileTransferError( + FROM_HERE, FileErrorToResponseErrorType(error), error)); + return; + } + + offset_ += bytes_read; + SetState(bytes_read > 0 ? FileOperations::kReady : FileOperations::kComplete); + + // The read buffer is provided and owned by FileProxy, so there's no way to + // avoid a copy, here. + std::move(callback).Run(std::string(data, bytes_read)); +} + +void LocalFileReader::SetState(FileOperations::State state) { + switch (state) { + case FileOperations::kCreated: + NOTREACHED(); // Can never return to initial state. + break; + case FileOperations::kReady: + DCHECK_EQ(FileOperations::kBusy, state_); + break; + case FileOperations::kBusy: + DCHECK(state_ == FileOperations::kCreated || + state_ == FileOperations::kReady); + break; + case FileOperations::kComplete: + DCHECK_EQ(FileOperations::kBusy, state_); + break; + case FileOperations::kFailed: + // Any state can change to kFailed. + break; + } + + state_ = state; +} + LocalFileWriter::LocalFileWriter() : weak_ptr_factory_(this) {} LocalFileWriter::~LocalFileWriter() { @@ -103,18 +306,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(FileOperations::kCreated, state_); SetState(FileOperations::kBusy); -#if defined(OS_WIN) - // On Windows, we use user impersonation to write files as the currently - // logged-in user, while the process as a whole runs as SYSTEM. Since user - // impersonation is per-thread on Windows, we need a dedicated thread to - // ensure that no other code is accidentally run with the wrong privileges. - file_task_runner_ = base::CreateSingleThreadTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, - base::SingleThreadTaskRunnerThreadMode::DEDICATED); -#else - file_task_runner_ = base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); -#endif + file_task_runner_ = CreateFileTaskRunner(); file_proxy_.emplace(file_task_runner_.get()); base::PostTaskAndReplyWithResult( file_task_runner_.get(), FROM_HERE, base::BindOnce([] { @@ -366,9 +558,14 @@ } // namespace +LocalFileOperations::LocalFileOperations( + scoped_refptr<base::SequencedTaskRunner> ui_task_runner) + : ui_task_runner_(std::move(ui_task_runner)) {} + +LocalFileOperations::~LocalFileOperations() = default; + std::unique_ptr<FileOperations::Reader> LocalFileOperations::CreateReader() { - NOTIMPLEMENTED(); - return nullptr; + return std::make_unique<LocalFileReader>(ui_task_runner_); } std::unique_ptr<FileOperations::Writer> LocalFileOperations::CreateWriter() {
diff --git a/remoting/host/file_transfer/local_file_operations.h b/remoting/host/file_transfer/local_file_operations.h index bcb20124..d0ce5f1 100644 --- a/remoting/host/file_transfer/local_file_operations.h +++ b/remoting/host/file_transfer/local_file_operations.h
@@ -8,6 +8,8 @@ #include <memory> #include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "base/sequenced_task_runner.h" #include "remoting/host/file_transfer/file_operations.h" namespace remoting { @@ -17,14 +19,17 @@ class LocalFileOperations : public FileOperations { public: - LocalFileOperations() = default; - ~LocalFileOperations() override = default; + explicit LocalFileOperations( + scoped_refptr<base::SequencedTaskRunner> ui_task_runner); + ~LocalFileOperations() override; // FileOperations implementation. std::unique_ptr<Reader> CreateReader() override; std::unique_ptr<Writer> CreateWriter() override; private: + scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; + DISALLOW_COPY_AND_ASSIGN(LocalFileOperations); };
diff --git a/remoting/host/file_transfer/local_file_operations_unittest.cc b/remoting/host/file_transfer/local_file_operations_unittest.cc index c382eea..7f6038a1 100644 --- a/remoting/host/file_transfer/local_file_operations_unittest.cc +++ b/remoting/host/file_transfer/local_file_operations_unittest.cc
@@ -11,10 +11,27 @@ #include "base/path_service.h" #include "base/test/scoped_path_override.h" #include "base/test/scoped_task_environment.h" +#include "remoting/host/file_transfer/fake_file_chooser.h" #include "testing/gtest/include/gtest/gtest.h" namespace remoting { +namespace { + +// BindOnce disallows binding lambdas with captures. This is reasonable in +// production code, as it requires one to either explicitly pass owned objects +// or pointers using Owned, Unretained, et cetera. This helps to avoid use- +// after-free bugs in async code. In test code, though, where the lambda is +// immediately invoked in the test method using, e.g., RunUntilIdle, the ability +// to capture can make the code much easier to read and write. +template <typename T> +auto BindLambda(T lambda) { + return base::BindOnce(&T::operator(), + base::Owned(new auto(std::move(lambda)))); +} + +} // namespace + class LocalFileOperationsTest : public testing::Test { public: LocalFileOperationsTest(); @@ -56,7 +73,8 @@ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED), // Points DIR_USER_DESKTOP at a scoped temporary directory. scoped_path_override_(base::DIR_USER_DESKTOP), - file_operations_(std::make_unique<LocalFileOperations>()) {} + file_operations_(std::make_unique<LocalFileOperations>( + scoped_task_environment_.GetMainThreadTaskRunner())) {} void LocalFileOperationsTest::SetUp() {} @@ -182,4 +200,139 @@ ASSERT_TRUE(base::IsDirectoryEmpty(TestDir())); } +// Verifies that a file can be successfully opened for reading. +TEST_F(LocalFileOperationsTest, OpensReader) { + base::FilePath path = TestDir().Append(kTestFilename); + std::string contents = kTestDataOne + kTestDataTwo + kTestDataThree; + ASSERT_EQ(static_cast<int>(contents.size()), + base::WriteFile(path, contents.data(), contents.size())); + + std::unique_ptr<FileOperations::Reader> reader = + file_operations_->CreateReader(); + + FakeFileChooser::SetResult(path); + base::Optional<FileOperations::Reader::OpenResult> open_result; + ASSERT_EQ(FileOperations::kCreated, reader->state()); + reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) { + open_result = std::move(result); + })); + ASSERT_EQ(FileOperations::kBusy, reader->state()); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(FileOperations::kReady, reader->state()); + ASSERT_TRUE(open_result); + ASSERT_TRUE(*open_result); + EXPECT_EQ(kTestFilename, reader->filename()); + EXPECT_EQ(contents.size(), reader->size()); +} + +// Verifies that a file can be successfully read in three chunks. +TEST_F(LocalFileOperationsTest, ReadsThreeChunks) { + base::FilePath path = TestDir().Append(kTestFilename); + std::string contents = kTestDataOne + kTestDataTwo + kTestDataThree; + ASSERT_EQ(static_cast<int>(contents.size()), + base::WriteFile(path, contents.data(), contents.size())); + + std::unique_ptr<FileOperations::Reader> reader = + file_operations_->CreateReader(); + + FakeFileChooser::SetResult(path); + base::Optional<FileOperations::Reader::OpenResult> open_result; + reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) { + open_result = std::move(result); + })); + scoped_task_environment_.RunUntilIdle(); + ASSERT_TRUE(open_result && *open_result); + + for (const auto& chunk : {kTestDataOne, kTestDataTwo, kTestDataThree}) { + base::Optional<FileOperations::Reader::ReadResult> read_result; + reader->ReadChunk( + chunk.size(), + BindLambda([&](FileOperations::Reader::ReadResult result) { + read_result = std::move(result); + })); + ASSERT_EQ(FileOperations::kBusy, reader->state()); + scoped_task_environment_.RunUntilIdle(); + ASSERT_EQ(FileOperations::kReady, reader->state()); + ASSERT_TRUE(read_result); + ASSERT_TRUE(*read_result); + EXPECT_EQ(chunk, **read_result); + } +} + +// Verifies proper EOF handling. +TEST_F(LocalFileOperationsTest, ReaderHandlesEof) { + base::FilePath path = TestDir().Append(kTestFilename); + std::string contents = kTestDataOne + kTestDataTwo + kTestDataThree; + ASSERT_EQ(static_cast<int>(contents.size()), + base::WriteFile(path, contents.data(), contents.size())); + + std::unique_ptr<FileOperations::Reader> reader = + file_operations_->CreateReader(); + + FakeFileChooser::SetResult(path); + base::Optional<FileOperations::Reader::OpenResult> open_result; + reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) { + open_result = std::move(result); + })); + scoped_task_environment_.RunUntilIdle(); + ASSERT_TRUE(open_result && *open_result); + + base::Optional<FileOperations::Reader::ReadResult> read_result; + reader->ReadChunk( + contents.size() + 5, // Attempt to read more than is in file. + BindLambda([&](FileOperations::Reader::ReadResult result) { + read_result = std::move(result); + })); + scoped_task_environment_.RunUntilIdle(); + ASSERT_EQ(FileOperations::kReady, reader->state()); + ASSERT_TRUE(read_result && *read_result); + EXPECT_EQ(contents, **read_result); + + read_result.reset(); + reader->ReadChunk(5, + BindLambda([&](FileOperations::Reader::ReadResult result) { + read_result = std::move(result); + })); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(FileOperations::kComplete, reader->state()); + ASSERT_TRUE(read_result && *read_result); + EXPECT_EQ(std::size_t{0}, (*read_result)->size()); +} + +// Verifies cancellation is propagated. +TEST_F(LocalFileOperationsTest, ReaderCancels) { + std::unique_ptr<FileOperations::Reader> reader = + file_operations_->CreateReader(); + + FakeFileChooser::SetResult(protocol::MakeFileTransferError( + FROM_HERE, protocol::FileTransfer_Error_Type_CANCELED)); + base::Optional<FileOperations::Reader::OpenResult> open_result; + reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) { + open_result = std::move(result); + })); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(FileOperations::kFailed, reader->state()); + ASSERT_TRUE(open_result); + ASSERT_FALSE(*open_result); + EXPECT_EQ(protocol::FileTransfer_Error_Type_CANCELED, + open_result->error().type()); +} + +// Verifies failure when file doesn't exist. +TEST_F(LocalFileOperationsTest, FileNotFound) { + std::unique_ptr<FileOperations::Reader> reader = + file_operations_->CreateReader(); + + // Currently non-existent file. + FakeFileChooser::SetResult(TestDir().Append(kTestFilename)); + base::Optional<FileOperations::Reader::OpenResult> open_result; + reader->Open(BindLambda([&](FileOperations::Reader::OpenResult result) { + open_result = std::move(result); + })); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(FileOperations::kFailed, reader->state()); + ASSERT_TRUE(open_result); + ASSERT_FALSE(*open_result); +} + } // namespace remoting
diff --git a/remoting/host/gcd_rest_client.cc b/remoting/host/gcd_rest_client.cc index 0120d08..cbd3a42 100644 --- a/remoting/host/gcd_rest_client.cc +++ b/remoting/host/gcd_rest_client.cc
@@ -82,7 +82,7 @@ resource_request_->method = "POST"; token_getter_->CallWithToken( - base::Bind(&GcdRestClient::OnTokenReceived, base::Unretained(this))); + base::BindOnce(&GcdRestClient::OnTokenReceived, base::Unretained(this))); } void GcdRestClient::SetClockForTest(base::Clock* clock) {
diff --git a/remoting/host/signaling_connector.cc b/remoting/host/signaling_connector.cc index 530bfa6..397ea44 100644 --- a/remoting/host/signaling_connector.cc +++ b/remoting/host/signaling_connector.cc
@@ -175,7 +175,7 @@ if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { HOST_LOG << "Attempting to connect signaling."; - oauth_token_getter_->CallWithToken(base::Bind( + oauth_token_getter_->CallWithToken(base::BindOnce( &SignalingConnector::OnAccessToken, weak_factory_.GetWeakPtr())); } }
diff --git a/remoting/ios/facade/ios_oauth_token_getter.h b/remoting/ios/facade/ios_oauth_token_getter.h index 7ad1fa8..684f25d 100644 --- a/remoting/ios/facade/ios_oauth_token_getter.h +++ b/remoting/ios/facade/ios_oauth_token_getter.h
@@ -20,7 +20,7 @@ ~IosOauthTokenGetter() override; // OAuthTokenGetter overrides. - void CallWithToken(const TokenCallback& on_access_token) override; + void CallWithToken(TokenCallback on_access_token) override; void InvalidateCache() override; base::WeakPtr<IosOauthTokenGetter> GetWeakPtr();
diff --git a/remoting/ios/facade/ios_oauth_token_getter.mm b/remoting/ios/facade/ios_oauth_token_getter.mm index 1f60af2..d9d542f 100644 --- a/remoting/ios/facade/ios_oauth_token_getter.mm +++ b/remoting/ios/facade/ios_oauth_token_getter.mm
@@ -20,9 +20,8 @@ IosOauthTokenGetter::~IosOauthTokenGetter() {} -void IosOauthTokenGetter::CallWithToken(const TokenCallback& on_access_token) { - // This forces the block to copy the callback instead of just the reference. - TokenCallback on_access_token_copied = on_access_token; +void IosOauthTokenGetter::CallWithToken(TokenCallback on_access_token) { + __block TokenCallback block_callback = std::move(on_access_token); [RemotingService.instance.authentication callbackWithAccessToken:^(RemotingAuthenticationStatus status, NSString* userEmail, NSString* accessToken) { @@ -40,9 +39,9 @@ default: NOTREACHED(); } - on_access_token_copied.Run(oauth_status, - base::SysNSStringToUTF8(userEmail), - base::SysNSStringToUTF8(accessToken)); + std::move(block_callback) + .Run(oauth_status, base::SysNSStringToUTF8(userEmail), + base::SysNSStringToUTF8(accessToken)); }]; }
diff --git a/remoting/ios/facade/remoting_oauth_authentication.mm b/remoting/ios/facade/remoting_oauth_authentication.mm index 7f25698..a33a7c02 100644 --- a/remoting/ios/facade/remoting_oauth_authentication.mm +++ b/remoting/ios/facade/remoting_oauth_authentication.mm
@@ -170,7 +170,7 @@ // Be careful here since a failure to reset onAccessToken will end up with // retain cycle and memory leakage. if (_tokenGetter) { - _tokenGetter->CallWithToken(base::BindRepeating( + _tokenGetter->CallWithToken(base::BindOnce( ^(remoting::OAuthTokenGetter::Status status, const std::string& user_email, const std::string& access_token) { onAccessToken(oauthStatusToRemotingAuthenticationStatus(status),
diff --git a/remoting/protocol/http_ice_config_request.cc b/remoting/protocol/http_ice_config_request.cc index 13f02b5..241b9055 100644 --- a/remoting/protocol/http_ice_config_request.cc +++ b/remoting/protocol/http_ice_config_request.cc
@@ -75,7 +75,7 @@ on_ice_config_callback_ = callback; if (oauth_token_getter_) { - oauth_token_getter_->CallWithToken(base::Bind( + oauth_token_getter_->CallWithToken(base::BindOnce( &HttpIceConfigRequest::OnOAuthToken, weak_factory_.GetWeakPtr())); } else { SendRequest();
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc index a4124ba..ba2d363 100644 --- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
@@ -140,9 +140,6 @@ case __NR_socket: #endif - // Ptrace is allowed so the Breakpad Microdumper can fork in a renderer - // and then ptrace the parent. - case __NR_ptrace: override_and_allow = true; break; } @@ -152,6 +149,12 @@ return Allow(); } + // Ptrace is allowed so the crash reporter can fork in a renderer + // and then ptrace the parent. https://crbug.com/933418 + if (sysno == __NR_ptrace) { + return RestrictPtrace(); + } + // https://crbug.com/644759 if (sysno == __NR_rt_tgsigqueueinfo) { const Arg<pid_t> tgid(0);
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc index 5adc1a7a..7514f9a 100644 --- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc +++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -33,6 +33,7 @@ #define SECCOMP_MESSAGE_IOCTL_CONTENT "ioctl() failure" #define SECCOMP_MESSAGE_KILL_CONTENT "(tg)kill() failure" #define SECCOMP_MESSAGE_FUTEX_CONTENT "futex() failure" +#define SECCOMP_MESSAGE_PTRACE_CONTENT "ptrace() failure" namespace { @@ -305,6 +306,19 @@ _exit(1); } +intptr_t SIGSYSPtraceFailure(const struct arch_seccomp_data& args, + void* /* aux */) { + static const char kSeccompPtraceError[] = + __FILE__ ":**CRASHING**:" SECCOMP_MESSAGE_PTRACE_CONTENT "\n"; + WriteToStdErr(kSeccompPtraceError, sizeof(kSeccompPtraceError) - 1); + SetSeccompCrashKey(args); + volatile int ptrace_op = args.args[0]; + volatile char* addr = reinterpret_cast<volatile char*>(ptrace_op & 0xFFF); + *addr = '\0'; + for (;;) + _exit(1); +} + intptr_t SIGSYSSchedHandler(const struct arch_seccomp_data& args, void* aux) { switch (args.nr) { @@ -363,6 +377,10 @@ return bpf_dsl::Trap(SIGSYSFutexFailure, NULL); } +bpf_dsl::ResultExpr CrashSIGSYSPtrace() { + return bpf_dsl::Trap(SIGSYSPtraceFailure, NULL); +} + bpf_dsl::ResultExpr RewriteSchedSIGSYS() { return bpf_dsl::Trap(SIGSYSSchedHandler, NULL); } @@ -401,4 +419,8 @@ return SECCOMP_MESSAGE_FUTEX_CONTENT; } +const char* GetPtraceErrorMessageContentForTests() { + return SECCOMP_MESSAGE_PTRACE_CONTENT; +} + } // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h index b32fd6fe..baac3b6 100644 --- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h +++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
@@ -25,8 +25,8 @@ SANDBOX_EXPORT intptr_t CrashSIGSYS_Handler(const struct arch_seccomp_data& args, void* aux); -// The following three handlers are suitable to report failures with the -// clone(), prctl() and ioctl() system calls respectively. +// The following seven handlers are suitable to report failures for specific +// system calls with additional information. // The crashing address will be (clone_flags & 0xFFFFFF), where clone_flags is // the clone(2) argument, extracted from |args|. @@ -48,6 +48,10 @@ // argument. SANDBOX_EXPORT intptr_t SIGSYSFutexFailure(const struct arch_seccomp_data& args, void* aux); +// The crashing address will be (op & 0xFFF), where op is the second +// argument. +SANDBOX_EXPORT intptr_t +SIGSYSPtraceFailure(const struct arch_seccomp_data& args, void* aux); // If the syscall is not being called on the current tid, crashes in the same // way as CrashSIGSYS_Handler. Otherwise, returns the result of calling the // syscall with the pid argument set to 0 (which for these calls means the @@ -66,6 +70,7 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSIoctl(); SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSKill(); SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSFutex(); +SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSPtrace(); SANDBOX_EXPORT bpf_dsl::ResultExpr RewriteSchedSIGSYS(); // Allocates a crash key so that Seccomp information can be recorded. @@ -79,6 +84,7 @@ SANDBOX_EXPORT const char* GetIoctlErrorMessageContentForTests(); SANDBOX_EXPORT const char* GetKillErrorMessageContentForTests(); SANDBOX_EXPORT const char* GetFutexErrorMessageContentForTests(); +SANDBOX_EXPORT const char* GetPtraceErrorMessageContentForTests(); } // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc index 2577f02f..ecd6e339 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -6,7 +6,6 @@ #include <errno.h> #include <fcntl.h> -#include <fcntl.h> #include <linux/net.h> #include <sched.h> #include <signal.h> @@ -31,9 +30,10 @@ #include "sandbox/linux/system_headers/linux_syscalls.h" #include "sandbox/linux/system_headers/linux_time.h" -// PNaCl toolchain does not provide sys/ioctl.h header. +// PNaCl toolchain does not provide sys/ioctl.h and sys/ptrace.h headers. #if !defined(OS_NACL_NONSFI) #include <sys/ioctl.h> +#include <sys/ptrace.h> #endif #if defined(OS_ANDROID) @@ -383,4 +383,25 @@ return If(AnyOf(pid == 0, pid == target_pid), Allow()).Else(Error(EPERM)); } +#if !defined(OS_NACL_NONSFI) +ResultExpr RestrictPtrace() { + const Arg<int> request(0); + return Switch(request).CASES(( +#if !defined(__aarch64__) + PTRACE_GETREGS, + PTRACE_GETFPREGS, + PTRACE_GET_THREAD_AREA, +#endif +#if defined(__arm__) + PTRACE_GETVFPREGS, +#endif + PTRACE_GETREGSET, + PTRACE_PEEKDATA, + PTRACE_ATTACH, + PTRACE_DETACH), + Allow()) + .Default(CrashSIGSYSPtrace()); +} +#endif // defined(OS_NACL_NONSFI) + } // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h index 71c56093..cb563df 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
@@ -103,6 +103,10 @@ // gracefully; see crbug.com/160157. SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPrlimit(pid_t target_pid); +// Restrict ptrace() to just read operations that are needed for crash +// reporting. See https://crbug.com/933418 for details. +SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPtrace(); + } // namespace sandbox. #endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc index 8fff3f1..073df00 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
@@ -5,14 +5,20 @@ #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" #include <errno.h> +#include <fcntl.h> +#include <linux/elf.h> #include <sched.h> +#include <sys/prctl.h> +#include <sys/ptrace.h> #include <sys/resource.h> #include <sys/syscall.h> #include <sys/types.h> +#include <sys/user.h> #include <time.h> #include <unistd.h> #include "base/bind.h" +#include "base/posix/eintr_wrapper.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" #include "base/system/sys_info.h" @@ -242,6 +248,231 @@ getrusage(RUSAGE_CHILDREN, &usage); } +// ptace() Tests /////////////////////////////////////////////////////////////// + +// Tests for ptrace involve a slightly complex setup in order to properly test +// ptrace and the variety of ways it is access-checked. The BPF_TEST macro, +// the body of which already runs in its own process, spawns another process +// called the "tracee". The "tracee" then spawns another process called the +// "tracer". The child then traces the parent and performs the test operations. +// The tracee must be careful to un-stop the tracer if the tracee expects to +// die. + +class RestrictPtracePolicy : public bpf_dsl::Policy { + public: + RestrictPtracePolicy() = default; + ~RestrictPtracePolicy() override = default; + + ResultExpr EvaluateSyscall(int sysno) const override { + switch (sysno) { + case __NR_ptrace: + return RestrictPtrace(); + default: + return Allow(); + } + } +}; + +constexpr char kExitPtraceChildClean = '!'; + +class PtraceTestHarness { + public: + using PtraceChildTracerFunc = void (*)(pid_t tracee); + + PtraceTestHarness(PtraceChildTracerFunc tracer_func, bool expect_death) + : tracer_func_(tracer_func), expect_death_(expect_death) {} + ~PtraceTestHarness() = default; + + void Run() { + // Fork the tracee process that will be traced by its child. + pid_t pid = fork(); + BPF_ASSERT_GE(pid, 0); + + if (pid == 0) { + RunTracee(); + } else { + // The tracee should always exit cleanly. + int status = 0; + int rv = waitpid(pid, &status, 0); + BPF_ASSERT_EQ(pid, rv); + BPF_ASSERT_EQ(0, WEXITSTATUS(status)); + } + } + + private: + void RunTracee() { + // Create a communications pipe between tracer and tracee. + int rv = pipe2(pipes_, O_NONBLOCK); + BPF_ASSERT_EQ(0, rv); + + // Pipes for redirecting output. + int output_pipes[2]; + BPF_ASSERT_EQ(0, pipe(output_pipes)); + + // Create the tracer process. + pid_t pid = fork(); + BPF_ASSERT_GE(pid, 0); + + if (pid == 0) { + // Close the pipe read ends and redirect output. + close(pipes_[0]); + close(output_pipes[0]); + + close(STDOUT_FILENO); + dup2(output_pipes[1], STDOUT_FILENO); + + close(STDERR_FILENO); + dup2(output_pipes[1], STDERR_FILENO); + + RunTracer(); + + close(output_pipes[1]); + } else { + close(pipes_[1]); + close(output_pipes[1]); + + // Ensure the tracer can trace the tracee. This may fail on systems + // without YAMA, so the result is not checked. + prctl(PR_SET_PTRACER, pid); + + char c = 0; + while (c != kExitPtraceChildClean) { + // Read from the control channel in a non-blocking fashion. + // If no data are present, loop. + ignore_result(read(pipes_[0], &c, 1)); + + // Poll the exit status of the child. + int status = 0; + rv = waitpid(pid, &status, WNOHANG); + if (rv != 0) { + BPF_ASSERT_EQ(pid, rv); + CheckTracerStatus(status, output_pipes[0]); + _exit(0); + } + } + + _exit(0); + } + } + + void RunTracer() { + pid_t ppid = getppid(); + BPF_ASSERT_NE(0, ppid); + + // Attach to the tracee and then call out to the test function. + BPF_ASSERT_EQ(0, ptrace(PTRACE_ATTACH, ppid, nullptr, nullptr)); + + tracer_func_(ppid); + + BPF_ASSERT_EQ(1, HANDLE_EINTR(write(pipes_[1], &kExitPtraceChildClean, 1))); + close(pipes_[1]); + + _exit(0); + } + + void CheckTracerStatus(int status, int output_pipe) { + // The child has exited. Test that it did so in the way we were + // expecting. + if (expect_death_) { + // This duplicates a bit of what //sandbox/linux/tests/unit_tests.cc does + // but that code is not shareable here. + std::string output; + const size_t kBufferSize = 1024; + size_t total_bytes_read = 0; + ssize_t read_this_pass = 0; + do { + output.resize(output.size() + kBufferSize); + read_this_pass = HANDLE_EINTR( + read(output_pipe, &output[total_bytes_read], kBufferSize)); + if (read_this_pass >= 0) { + total_bytes_read += read_this_pass; + output.resize(total_bytes_read); + } + } while (read_this_pass > 0); + +#if !defined(SANDBOX_USES_BASE_TEST_SUITE) + const bool subprocess_got_sigsegv = + WIFSIGNALED(status) && (SIGSEGV == WTERMSIG(status)); +#else + // This hack is required when a signal handler is installed + // for SEGV that will _exit(1). + const bool subprocess_got_sigsegv = + WIFEXITED(status) && (1 == WEXITSTATUS(status)); +#endif + BPF_ASSERT(subprocess_got_sigsegv); + BPF_ASSERT_NE(output.find(GetPtraceErrorMessageContentForTests()), + std::string::npos); + } else { + BPF_ASSERT(WIFEXITED(status)); + BPF_ASSERT_EQ(0, WEXITSTATUS(status)); + } + } + + PtraceChildTracerFunc tracer_func_; + bool expect_death_; + int pipes_[2]; + + DISALLOW_COPY_AND_ASSIGN(PtraceTestHarness); +}; + +BPF_TEST_C(ParameterRestrictions, + ptrace_getregs_allowed, + RestrictPtracePolicy) { + auto tracer = [](pid_t pid) { +#if defined(__arm__) + user_regs regs; +#else + user_regs_struct regs; +#endif + iovec iov; + iov.iov_base = ®s; + iov.iov_len = sizeof(regs); + BPF_ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, + reinterpret_cast<void*>(NT_PRSTATUS), &iov)); + + BPF_ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, nullptr, nullptr)); + }; + PtraceTestHarness(tracer, false).Run(); +} + +BPF_TEST_C(ParameterRestrictions, + ptrace_syscall_blocked, + RestrictPtracePolicy) { + auto tracer = [](pid_t pid) { + // The tracer is about to die. Make sure the tracee is not stopped so it + // can reap it and inspect its death signal. + kill(pid, SIGCONT); + + BPF_ASSERT_NE(0, ptrace(PTRACE_SYSCALL, 0, nullptr, nullptr)); + }; + PtraceTestHarness(tracer, true).Run(); +} + +BPF_TEST_C(ParameterRestrictions, + ptrace_setregs_blocked, + RestrictPtracePolicy) { + auto tracer = [](pid_t pid) { +#if defined(__arm__) + user_regs regs; +#else + user_regs_struct regs; +#endif + iovec iov; + iov.iov_base = ®s; + iov.iov_len = sizeof(regs); + BPF_ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, + reinterpret_cast<void*>(NT_PRSTATUS), &iov)); + + // The tracer is about to die. Make sure the tracee is not stopped so it + // can reap it and inspect its death signal. + kill(pid, SIGCONT); + + BPF_ASSERT_NE(0, ptrace(PTRACE_SETREGSET, pid, + reinterpret_cast<void*>(NT_PRSTATUS), &iov)); + }; + PtraceTestHarness(tracer, true).Run(); +} + } // namespace } // namespace sandbox
diff --git a/services/content/navigable_contents_impl.cc b/services/content/navigable_contents_impl.cc index 9095aae..4c27a5e 100644 --- a/services/content/navigable_contents_impl.cc +++ b/services/content/navigable_contents_impl.cc
@@ -58,12 +58,12 @@ delegate_->GoBack(std::move(callback)); } -void NavigableContentsImpl::CreateView(bool in_service_process, +void NavigableContentsImpl::CreateView(bool use_window_service, CreateViewCallback callback) { DCHECK(native_content_view_); #if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - if (!in_service_process) { + if (use_window_service) { remote_view_provider_ = std::make_unique<views::RemoteViewProvider>(native_content_view_); remote_view_provider_->GetEmbedToken( @@ -72,7 +72,7 @@ return; } #else - if (!in_service_process) { + if (use_window_service) { DLOG(ERROR) << "Remote NavigableContentsView clients are not supported on " << "this platform."; return;
diff --git a/services/content/public/cpp/navigable_contents.cc b/services/content/public/cpp/navigable_contents.cc index 6a0e715..5035763 100644 --- a/services/content/public/cpp/navigable_contents.cc +++ b/services/content/public/cpp/navigable_contents.cc
@@ -36,7 +36,7 @@ if (!view_) { view_ = base::WrapUnique(new NavigableContentsView(this)); contents_->CreateView( - NavigableContentsView::IsClientRunningInServiceProcess(), + ShouldUseWindowService(), base::BindOnce(&NavigableContents::OnEmbedTokenReceived, base::Unretained(this))); } @@ -65,6 +65,18 @@ contents_->FocusThroughTabTraversal(reverse); } +void NavigableContents::ForceUseWindowService() { + // This should only be called before |view_| is created. + DCHECK(!view_); + + force_use_window_service_ = true; +} + +bool NavigableContents::ShouldUseWindowService() const { + return !NavigableContentsView::IsClientRunningInServiceProcess() || + force_use_window_service_; +} + void NavigableContents::ClearViewFocus() { if (view_) view_->ClearNativeFocus();
diff --git a/services/content/public/cpp/navigable_contents.h b/services/content/public/cpp/navigable_contents.h index ae675b0..b805d4b5 100644 --- a/services/content/public/cpp/navigable_contents.h +++ b/services/content/public/cpp/navigable_contents.h
@@ -69,6 +69,13 @@ // being done via Tab-key cycling or a similar mechanism. void FocusThroughTabTraversal(bool reverse); + // Force NavigableContents to use Window Service for embedding. Note this must + // be called before its view is created. + void ForceUseWindowService(); + + // Whether to use Window Service for embedding. + bool ShouldUseWindowService() const; + private: // mojom::NavigableContentsClient: void ClearViewFocus() override; @@ -94,6 +101,8 @@ ui::AXTreeID content_ax_tree_id_; + bool force_use_window_service_ = false; + DISALLOW_COPY_AND_ASSIGN(NavigableContents); };
diff --git a/services/content/public/cpp/navigable_contents_view.cc b/services/content/public/cpp/navigable_contents_view.cc index 8c1ef02..75b7e99 100644 --- a/services/content/public/cpp/navigable_contents_view.cc +++ b/services/content/public/cpp/navigable_contents_view.cc
@@ -164,7 +164,7 @@ : contents_(contents) { #if defined(TOOLKIT_VIEWS) && defined(USE_AURA) #if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - if (!IsClientRunningInServiceProcess()) { + if (contents_->ShouldUseWindowService()) { RemoteViewManager* manager = GetRemoteViewManager().get(); if (manager) view_ = manager->CreateRemoteViewHost(); @@ -201,7 +201,7 @@ const base::UnguessableToken& token) { #if defined(TOOLKIT_VIEWS) #if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - if (!IsClientRunningInServiceProcess()) { + if (contents_->ShouldUseWindowService()) { RemoteViewManager* manager = GetRemoteViewManager().get(); if (manager) { manager->EmbedUsingToken(view_.get(), token);
diff --git a/services/content/public/mojom/navigable_contents.mojom b/services/content/public/mojom/navigable_contents.mojom index d90f305..adc9294 100644 --- a/services/content/public/mojom/navigable_contents.mojom +++ b/services/content/public/mojom/navigable_contents.mojom
@@ -37,14 +37,13 @@ // be given to Mus in order to authorize embedding of that visual // representation within the client application's own window tree. // - // |in_service_process| must be true iff the client calling this method is - // running in the same process as the Content Service. This can be known in - // the client by calling - // |NavigableContentsView::IsClientRunningInServiceProcess()|. + // |use_window_service| is true when the client calling this method wants to + // use Window Service for embedding. This is the case when the client and the + // Content Service are using different window trees. // - // TODO(https://crbug.com/874143): Remove the |in_service_process| flag once + // TODO(https://crbug.com/874143): Remove the |use_window_service| flag once // we have more widely available UI Service support. - CreateView(bool in_service_process) + CreateView(bool use_window_service) => (mojo_base.mojom.UnguessableToken embed_token); // Attempts to transfer global input focus to the navigated contents if they
diff --git a/services/media_session/BUILD.gn b/services/media_session/BUILD.gn index 3228a8b..8646487 100644 --- a/services/media_session/BUILD.gn +++ b/services/media_session/BUILD.gn
@@ -25,6 +25,7 @@ "//mojo/public/cpp/bindings", "//services/media_session/public/cpp", "//services/media_session/public/mojom", + "//skia", ] public_deps = [
diff --git a/services/media_session/DEPS b/services/media_session/DEPS index b8a225f..de074ee 100644 --- a/services/media_session/DEPS +++ b/services/media_session/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+jni", "+ui/gfx", + "+third_party/skia/include", ]
diff --git a/services/media_session/public/cpp/media_image_manager.cc b/services/media_session/public/cpp/media_image_manager.cc index b0f312b..b4b825c 100644 --- a/services/media_session/public/cpp/media_image_manager.cc +++ b/services/media_session/public/cpp/media_image_manager.cc
@@ -37,8 +37,35 @@ return base::ToLowerASCII(path.substr(pos)); } +double GetImageDominantSizeScore(int min_size, + int ideal_size, + const gfx::Size& size) { + int dominant_size = std::max(size.width(), size.height()); + + // If the size is "any". + if (dominant_size == 0) + return 0.8; + + // Ignore images that are too small. + if (dominant_size < min_size) + return 0; + + if (dominant_size <= ideal_size) + return 0.8 * (dominant_size - min_size) / (ideal_size - min_size) + 0.2; + + return 1.0 * ideal_size / dominant_size; +} + } // namespace +// static +double MediaImageManager::GetImageSizeScore(int min_size, + int ideal_size, + const gfx::Size& size) { + return GetImageDominantSizeScore(min_size, ideal_size, size) * + GetImageAspectRatioScore(size); +} + MediaImageManager::MediaImageManager(int min_size, int ideal_size) : min_size_(min_size), ideal_size_(ideal_size) {} @@ -66,8 +93,10 @@ if (image.sizes.empty()) { best_size_score = kDefaultImageSizeScore; } else { - for (auto& size : image.sizes) - best_size_score = std::max(best_size_score, GetImageSizeScore(size)); + for (auto& size : image.sizes) { + best_size_score = std::max( + best_size_score, GetImageSizeScore(min_size_, ideal_size_, size)); + } } double type_score = kDefaultTypeScore; @@ -81,28 +110,6 @@ return best_size_score * type_score; } -double MediaImageManager::GetImageSizeScore(const gfx::Size& size) const { - return GetImageDominantSizeScore(size) * GetImageAspectRatioScore(size); -} - -double MediaImageManager::GetImageDominantSizeScore( - const gfx::Size& size) const { - int dominant_size = std::max(size.width(), size.height()); - - // If the size is "any". - if (dominant_size == 0) - return 0.8; - - // Ignore images that are too small. - if (dominant_size < min_size_) - return 0; - - if (dominant_size <= ideal_size_) - return 0.8 * (dominant_size - min_size_) / (ideal_size_ - min_size_) + 0.2; - - return 1.0 * ideal_size_ / dominant_size; -} - // static base::Optional<double> MediaImageManager::GetImageExtensionScore( const GURL& url) {
diff --git a/services/media_session/public/cpp/media_image_manager.h b/services/media_session/public/cpp/media_image_manager.h index be2285e..a8bc41d 100644 --- a/services/media_session/public/cpp/media_image_manager.h +++ b/services/media_session/public/cpp/media_image_manager.h
@@ -45,6 +45,12 @@ // the short edge length by the long edge. class COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaImageManager { public: + // Returns the image size score as a double between 0 and 1. The score will + // be calculated using the size scoring algorithm described above. + static double GetImageSizeScore(int min_size, + int ideal_size, + const gfx::Size& size); + // The |min_size| is the min size of the images to select in px. The // |ideal_size| is the ideal size of the images to select in px. MediaImageManager(int min_size, int ideal_size); @@ -62,10 +68,6 @@ double GetImageScore(const MediaImage& image) const; - double GetImageSizeScore(const gfx::Size& size) const; - - double GetImageDominantSizeScore(const gfx::Size& size) const; - static base::Optional<double> GetImageExtensionScore(const GURL& url); static base::Optional<double> GetImageTypeScore(const base::string16& type);
diff --git a/services/media_session/public/cpp/media_session.typemap b/services/media_session/public/cpp/media_session.typemap index 0eec57c..8549fc5 100644 --- a/services/media_session/public/cpp/media_session.typemap +++ b/services/media_session/public/cpp/media_session.typemap
@@ -6,17 +6,20 @@ public_headers = [ "//services/media_session/public/cpp/media_image.h", "//services/media_session/public/cpp/media_metadata.h", + "//third_party/skia/include/core/SkBitmap.h", ] traits_headers = [ "//services/media_session/public/cpp/media_session_mojom_traits.h" ] public_deps = [ "//services/media_session/public/cpp", + "//skia", ] deps = [ "//ui/gfx/geometry/mojo:struct_traits", ] type_mappings = [ "media_session.mojom.MediaImage=media_session::MediaImage", + "media_session.mojom.MediaImageBitmap=SkBitmap[nullable_is_same_type]", "media_session.mojom.MediaMetadata=media_session::MediaMetadata", ] sources = [
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.cc b/services/media_session/public/cpp/media_session_mojom_traits.cc index ae4d1a4..5ce8c2ef 100644 --- a/services/media_session/public/cpp/media_session_mojom_traits.cc +++ b/services/media_session/public/cpp/media_session_mojom_traits.cc
@@ -5,6 +5,7 @@ #include "services/media_session/public/cpp/media_session_mojom_traits.h" #include "mojo/public/cpp/base/string16_mojom_traits.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/mojo/geometry_struct_traits.h" #include "url/mojom/url_gurl_mojom_traits.h" @@ -45,4 +46,43 @@ return true; } +// static +const base::span<const uint8_t> +StructTraits<media_session::mojom::MediaImageBitmapDataView, + SkBitmap>::pixel_data(const SkBitmap& r) { + const SkImageInfo& info = r.info(); + DCHECK_EQ(info.colorType(), kRGBA_8888_SkColorType); + + return base::make_span(static_cast<uint8_t*>(r.getPixels()), + r.computeByteSize()); +} + +// static +bool StructTraits<media_session::mojom::MediaImageBitmapDataView, SkBitmap>:: + Read(media_session::mojom::MediaImageBitmapDataView data, SkBitmap* out) { + mojo::ArrayDataView<uint8_t> pixel_data; + data.GetPixelDataDataView(&pixel_data); + + SkImageInfo info = SkImageInfo::Make( + data.width(), data.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType); + if (info.computeByteSize(info.minRowBytes()) > pixel_data.size()) { + // Insufficient buffer size. + return false; + } + + // Create the SkBitmap object which wraps the arc bitmap pixels. This + // doesn't copy and |data| and |bitmap| share the buffer. + SkBitmap bitmap; + if (!bitmap.installPixels(info, const_cast<uint8_t*>(pixel_data.data()), + info.minRowBytes())) { + // Error in installing pixels. + return false; + } + + // Copy the pixels with converting color type. + SkImageInfo image_info = info.makeColorType(kN32_SkColorType); + return out->tryAllocPixels(image_info) && + bitmap.readPixels(image_info, out->getPixels(), out->rowBytes(), 0, 0); +} + } // namespace mojo
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.h b/services/media_session/public/cpp/media_session_mojom_traits.h index 9d82bab..aa9e067 100644 --- a/services/media_session/public/cpp/media_session_mojom_traits.h +++ b/services/media_session/public/cpp/media_session_mojom_traits.h
@@ -7,6 +7,7 @@ #include <vector> +#include "base/containers/span.h" #include "services/media_session/public/mojom/media_session.mojom.h" namespace mojo { @@ -58,6 +59,19 @@ media_session::MediaMetadata* out); }; +// TODO(beccahughes): de-dupe this with ArcBitmap. +template <> +struct StructTraits<media_session::mojom::MediaImageBitmapDataView, SkBitmap> { + static const base::span<const uint8_t> pixel_data(const SkBitmap& r); + static int width(const SkBitmap& r) { return r.width(); } + static int height(const SkBitmap& r) { return r.height(); } + + static bool Read(media_session::mojom::MediaImageBitmapDataView data, + SkBitmap* out); + + static bool IsNull(const SkBitmap& r) { return r.isNull(); } +}; + } // namespace mojo #endif // SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_
diff --git a/services/media_session/public/cpp/test/mock_media_session.h b/services/media_session/public/cpp/test/mock_media_session.h index 99d46e7..97d408a 100644 --- a/services/media_session/public/cpp/test/mock_media_session.h +++ b/services/media_session/public/cpp/test/mock_media_session.h
@@ -120,9 +120,12 @@ void SkipAd() override {} void Seek(base::TimeDelta seek_time) override; void Stop(SuspendType type) override; + void GetMediaImageBitmap(const MediaImage& image, + int minimum_size_px, + int desired_size_px, + GetMediaImageBitmapCallback callback) override {} void SetIsControllable(bool value); - void SetPreferStop(bool value) { prefer_stop_ = value; } void AbandonAudioFocusFromClient();
diff --git a/services/media_session/public/mojom/media_session.mojom b/services/media_session/public/mojom/media_session.mojom index eb748ae..4be0ea8 100644 --- a/services/media_session/public/mojom/media_session.mojom +++ b/services/media_session/public/mojom/media_session.mojom
@@ -56,6 +56,15 @@ mojo_base.mojom.String16 source_title; }; +// A bitmap image. We use this instead of SkImage or skia.image.Bitmap so we can +// use it in ARC and we do not use ArcBitmap because we need to use it in the +// service. +struct MediaImageBitmap { + int32 width; + int32 height; + array<uint8> pixel_data; // Must be ARGB_8888 +}; + // Contains state information about a MediaSession. struct MediaSessionInfo { [Extensible] @@ -129,7 +138,7 @@ // WebContents or ARC app. // TODO(https://crbug.com/875004): migrate media session from content/public // to mojo. -// Next Method ID: 12 +// Next Method ID: 13 interface MediaSession { [Extensible] enum SuspendType { @@ -186,4 +195,12 @@ // Skip ad. SkipAd@11(); + + // Gets/Downloads the bitmap version of a MediaImage at least + // |minimum_size_px| and closest to |desired_size_px|. If the download + // failed, was too small or the image did not come from the media session + // then returns a null image. + GetMediaImageBitmap@12( + MediaImage image, int32 minimum_size_px, int32 desired_size_px) + => (MediaImageBitmap? image); };
diff --git a/services/network/public/cpp/net_ipc_param_traits.cc b/services/network/public/cpp/net_ipc_param_traits.cc index 2863a92b..7556baa 100644 --- a/services/network/public/cpp/net_ipc_param_traits.cc +++ b/services/network/public/cpp/net_ipc_param_traits.cc
@@ -164,6 +164,50 @@ l->append(p.ToString()); } +void ParamTraits<net::IPEndPoint>::Write(base::Pickle* m, const param_type& p) { + WriteParam(m, p.address()); + WriteParam(m, p.port()); +} + +bool ParamTraits<net::IPEndPoint>::Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* p) { + net::IPAddress address; + uint16_t port; + if (!ReadParam(m, iter, &address) || !ReadParam(m, iter, &port)) + return false; + + *p = net::IPEndPoint(address, port); + return true; +} + +void ParamTraits<net::IPEndPoint>::Log(const param_type& p, std::string* l) { + LogParam("IPEndPoint:" + p.ToString(), l); +} + +void ParamTraits<net::IPAddress>::Write(base::Pickle* m, const param_type& p) { + base::StackVector<uint8_t, 16> bytes; + for (uint8_t byte : p.bytes()) + bytes->push_back(byte); + WriteParam(m, bytes); +} + +bool ParamTraits<net::IPAddress>::Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* p) { + base::StackVector<uint8_t, 16> bytes; + if (!ReadParam(m, iter, &bytes)) + return false; + if (bytes->size() > 16) + return false; + *p = net::IPAddress(bytes->data(), bytes->size()); + return true; +} + +void ParamTraits<net::IPAddress>::Log(const param_type& p, std::string* l) { + LogParam("IPAddress:" + (p.empty() ? "(empty)" : p.ToString()), l); +} + void ParamTraits<net::HttpRequestHeaders>::Write(base::Pickle* m, const param_type& p) { WriteParam(m, static_cast<int>(p.GetHeaderVector().size()));
diff --git a/services/network/public/cpp/net_ipc_param_traits.h b/services/network/public/cpp/net_ipc_param_traits.h index c52e6035..8db5f62c 100644 --- a/services/network/public/cpp/net_ipc_param_traits.h +++ b/services/network/public/cpp/net_ipc_param_traits.h
@@ -13,6 +13,8 @@ #include "ipc/param_traits_macros.h" #include "net/base/auth.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" #include "net/base/proxy_server.h" #include "net/base/request_priority.h" #include "net/cert/cert_verify_result.h" @@ -104,6 +106,26 @@ }; template <> +struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::IPEndPoint> { + typedef net::IPEndPoint param_type; + static void Write(base::Pickle* m, const param_type& p); + static bool Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* p); + static void Log(const param_type& p, std::string* l); +}; + +template <> +struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::IPAddress> { + typedef net::IPAddress param_type; + static void Write(base::Pickle* m, const param_type& p); + static bool Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* p); + static void Log(const param_type& p, std::string* l); +}; + +template <> struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::HttpRequestHeaders> { typedef net::HttpRequestHeaders param_type; static void Write(base::Pickle* m, const param_type& p);
diff --git a/services/network/public/cpp/network_ipc_param_traits.h b/services/network/public/cpp/network_ipc_param_traits.h index a6e7c30..059d735 100644 --- a/services/network/public/cpp/network_ipc_param_traits.h +++ b/services/network/public/cpp/network_ipc_param_traits.h
@@ -12,7 +12,7 @@ #include "ipc/ipc_param_traits.h" #include "ipc/param_traits_macros.h" #include "net/base/auth.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/proxy_server.h" #include "net/base/request_priority.h" #include "net/cert/cert_verify_result.h" @@ -158,7 +158,7 @@ IPC_STRUCT_TRAITS_MEMBER(was_alternate_protocol_available) IPC_STRUCT_TRAITS_MEMBER(connection_info) IPC_STRUCT_TRAITS_MEMBER(alpn_negotiated_protocol) - IPC_STRUCT_TRAITS_MEMBER(socket_address) + IPC_STRUCT_TRAITS_MEMBER(remote_endpoint) IPC_STRUCT_TRAITS_MEMBER(was_fetched_via_cache) IPC_STRUCT_TRAITS_MEMBER(proxy_server) IPC_STRUCT_TRAITS_MEMBER(was_fetched_via_service_worker)
diff --git a/services/network/public/cpp/p2p_param_traits.cc b/services/network/public/cpp/p2p_param_traits.cc index 37c6c5c..54990d1 100644 --- a/services/network/public/cpp/p2p_param_traits.cc +++ b/services/network/public/cpp/p2p_param_traits.cc
@@ -5,60 +5,7 @@ #include "services/network/public/cpp/p2p_param_traits.h" #include "ipc/ipc_message_utils.h" -#include "net/base/ip_address.h" -#include "net/base/ip_endpoint.h" - -namespace IPC { - -void ParamTraits<net::IPEndPoint>::Write(base::Pickle* m, const param_type& p) { - WriteParam(m, p.address()); - WriteParam(m, p.port()); -} - -bool ParamTraits<net::IPEndPoint>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - net::IPAddress address; - uint16_t port; - if (!ReadParam(m, iter, &address) || !ReadParam(m, iter, &port)) - return false; - if (!address.empty() && !address.IsValid()) - return false; - - *p = net::IPEndPoint(address, port); - return true; -} - -void ParamTraits<net::IPEndPoint>::Log(const param_type& p, std::string* l) { - LogParam("IPEndPoint:" + p.ToString(), l); -} - -void ParamTraits<net::IPAddress>::Write(base::Pickle* m, const param_type& p) { - base::StackVector<uint8_t, 16> bytes; - for (uint8_t byte : p.bytes()) - bytes->push_back(byte); - WriteParam(m, bytes); -} - -bool ParamTraits<net::IPAddress>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - base::StackVector<uint8_t, 16> bytes; - if (!ReadParam(m, iter, &bytes)) - return false; - if (bytes->size() && bytes->size() != net::IPAddress::kIPv4AddressSize && - bytes->size() != net::IPAddress::kIPv6AddressSize) { - return false; - } - *p = net::IPAddress(bytes->data(), bytes->size()); - return true; -} - -void ParamTraits<net::IPAddress>::Log(const param_type& p, std::string* l) { - LogParam("IPAddress:" + (p.empty() ? "(empty)" : p.ToString()), l); -} - -} // namespace IPC +#include "services/network/public/cpp/net_ipc_param_traits.h" // Generation of IPC definitions.
diff --git a/services/network/public/cpp/p2p_param_traits.h b/services/network/public/cpp/p2p_param_traits.h index 7d1fe868..e236d37 100644 --- a/services/network/public/cpp/p2p_param_traits.h +++ b/services/network/public/cpp/p2p_param_traits.h
@@ -25,35 +25,6 @@ #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT COMPONENT_EXPORT(NETWORK_CPP_BASE) -namespace net { -class IPAddress; -class IPEndPoint; -} // namespace net - -namespace IPC { - -template <> -struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::IPEndPoint> { - typedef net::IPEndPoint param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<net::IPAddress> { - typedef net::IPAddress param_type; - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p); - static void Log(const param_type& p, std::string* l); -}; - -} // namespace IPC - #endif // INTERNAL_SERVICES_NETWORK_PUBLIC_CPP_P2P_PARAM_TRAITS_H_ IPC_ENUM_TRAITS_MAX_VALUE(network::P2PSocketType, network::P2P_SOCKET_TYPE_LAST)
diff --git a/services/network/public/cpp/resource_response.cc b/services/network/public/cpp/resource_response.cc index e39fbb9e..3178a62 100644 --- a/services/network/public/cpp/resource_response.cc +++ b/services/network/public/cpp/resource_response.cc
@@ -36,7 +36,7 @@ head.was_alternate_protocol_available; new_response->head.connection_info = head.connection_info; new_response->head.alpn_negotiated_protocol = head.alpn_negotiated_protocol; - new_response->head.socket_address = head.socket_address; + new_response->head.remote_endpoint = head.remote_endpoint; new_response->head.was_fetched_via_cache = head.was_fetched_via_cache; new_response->head.proxy_server = head.proxy_server; new_response->head.was_fetched_via_service_worker =
diff --git a/services/network/public/cpp/resource_response_info.h b/services/network/public/cpp/resource_response_info.h index 0f4df4b..344a6fa 100644 --- a/services/network/public/cpp/resource_response_info.h +++ b/services/network/public/cpp/resource_response_info.h
@@ -13,7 +13,7 @@ #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" -#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_timing_info.h" #include "net/base/proxy_server.h" #include "net/cert/ct_policy_status.h" @@ -103,7 +103,7 @@ std::string alpn_negotiated_protocol; // Remote address of the socket which fetched this resource. - net::HostPortPair socket_address; + net::IPEndPoint remote_endpoint; // True if the response came from cache. bool was_fetched_via_cache = false;
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index d128bcec..ab4ceb8 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -58,6 +58,7 @@ ] public_deps = [ + ":mojom_ip_address", "//url/mojom:url_mojom_gurl", "//url/mojom:url_mojom_origin", ]
diff --git a/services/network/public/mojom/websocket.mojom b/services/network/public/mojom/websocket.mojom index bc9bde7..b1e6952 100644 --- a/services/network/public/mojom/websocket.mojom +++ b/services/network/public/mojom/websocket.mojom
@@ -6,6 +6,7 @@ import "url/mojom/url.mojom"; import "services/network/public/mojom/network_param.mojom"; +import "services/network/public/mojom/ip_endpoint.mojom"; enum WebSocketMessageType { CONTINUATION, @@ -33,7 +34,7 @@ HttpVersion http_version; int32 status_code; string status_text; - HostPortPair socket_address; + IPEndPoint remote_endpoint; array<HttpHeader> headers; string headers_text; }; @@ -45,7 +46,7 @@ // authentication. OnAuthRequired(AuthChallengeInfo info, HttpResponseHeaders headers, - HostPortPair socket_address) => (AuthCredentials? credentials); + IPEndPoint remote_endpoint) => (AuthCredentials? credentials); }; interface WebSocketClient {
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 703072d4..06909a0 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -22,6 +22,7 @@ #include "base/time/time.h" #include "mojo/public/cpp/system/simple_watcher.h" #include "net/base/elements_upload_data_stream.h" +#include "net/base/ip_endpoint.h" #include "net/base/mime_sniffer.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_file_element_reader.h" @@ -73,7 +74,7 @@ response->head.alpn_negotiated_protocol = response_info.alpn_negotiated_protocol; response->head.connection_info = response_info.connection_info; - response->head.socket_address = response_info.socket_address; + response->head.remote_endpoint = response_info.remote_endpoint; response->head.was_fetched_via_cache = request->was_cached(); response->head.proxy_server = request->proxy_server(); response->head.network_accessed = response_info.network_accessed;
diff --git a/services/network/websocket.cc b/services/network/websocket.cc index 16c598c..218637a 100644 --- a/services/network/websocket.cc +++ b/services/network/websocket.cc
@@ -20,6 +20,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "net/base/auth.h" #include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" @@ -104,7 +105,7 @@ int OnAuthRequired( scoped_refptr<net::AuthChallengeInfo> auth_info, scoped_refptr<net::HttpResponseHeaders> response_headers, - const net::HostPortPair& host_port_pair, + const net::IPEndPoint& remote_endpoint, base::OnceCallback<void(const net::AuthCredentials*)> callback, base::Optional<net::AuthCredentials>* credentials) override; @@ -250,7 +251,7 @@ response_to_pass->status_code = response->headers->response_code(); response_to_pass->status_text = response->headers->GetStatusText(); response_to_pass->http_version = response->headers->GetHttpVersion(); - response_to_pass->socket_address = response->socket_address; + response_to_pass->remote_endpoint = response->remote_endpoint; size_t iter = 0; std::string name, value; std::string headers_text = @@ -286,7 +287,7 @@ int WebSocket::WebSocketEventHandler::OnAuthRequired( scoped_refptr<net::AuthChallengeInfo> auth_info, scoped_refptr<net::HttpResponseHeaders> response_headers, - const net::HostPortPair& host_port_pair, + const net::IPEndPoint& remote_endpoint, base::OnceCallback<void(const net::AuthCredentials*)> callback, base::Optional<net::AuthCredentials>* credentials) { DVLOG(3) << "WebSocketEventHandler::OnAuthRequired" @@ -297,7 +298,7 @@ } impl_->auth_handler_->OnAuthRequired( - std::move(auth_info), std::move(response_headers), host_port_pair, + std::move(auth_info), std::move(response_headers), remote_endpoint, base::BindOnce(&WebSocket::OnAuthRequiredComplete, impl_->weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc index 5f98984..4b104adf 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
@@ -7,7 +7,7 @@ #include <stdint.h> #include <memory> -#include "base/debug/elf_reader_linux.h" +#include "base/debug/elf_reader.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/format_macros.h" @@ -69,11 +69,12 @@ ModuleData module_data; Dl_info dl_info; if (dladdr(&__ehdr_start, &dl_info)) { - base::Optional<std::string> build_id = - base::debug::ReadElfBuildId(&__ehdr_start); - if (build_id) { + base::debug::ElfBuildIdBuffer build_id; + size_t build_id_length = + base::debug::ReadElfBuildId(&__ehdr_start, true, build_id); + if (build_id_length) { module_data.path = dl_info.dli_fname; - module_data.build_id = *build_id; + module_data.build_id = std::string(build_id, build_id_length); } } return module_data;
diff --git a/services/tracing/agent_registry.cc b/services/tracing/agent_registry.cc index 759aacc7..f1e4764 100644 --- a/services/tracing/agent_registry.cc +++ b/services/tracing/agent_registry.cc
@@ -16,6 +16,8 @@ namespace tracing { +const int32_t kAgentResponseTimeoutInSeconds = 10; + AgentRegistry::AgentEntry::AgentEntry(size_t id, AgentRegistry* agent_registry, mojom::AgentPtr agent, @@ -40,10 +42,17 @@ base::OnceClosure closure) { DCHECK_EQ(0u, closures_.count(closure_name)); closures_[closure_name] = std::move(closure); + + // Adding a disconnect closure means we're waiting for a response from the + // agent. If the client becomes unresponsive, we disconnect it. + timer_.Start(FROM_HERE, + base::TimeDelta::FromSeconds(kAgentResponseTimeoutInSeconds), + this, &AgentRegistry::AgentEntry::OnConnectionError); } bool AgentRegistry::AgentEntry::RemoveDisconnectClosure( const void* closure_name) { + timer_.Stop(); return closures_.erase(closure_name) > 0; }
diff --git a/services/tracing/agent_registry.h b/services/tracing/agent_registry.h index c2b4150..cb701f3 100644 --- a/services/tracing/agent_registry.h +++ b/services/tracing/agent_registry.h
@@ -12,6 +12,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/service_manager/public/cpp/identity.h" #include "services/tracing/public/mojom/tracing.mojom.h" @@ -53,6 +54,7 @@ const mojom::TraceDataType type_; const base::ProcessId pid_; std::map<const void*, base::OnceClosure> closures_; + base::RepeatingTimer timer_; DISALLOW_COPY_AND_ASSIGN(AgentEntry); };
diff --git a/services/tracing/coordinator.cc b/services/tracing/coordinator.cc index 821f0de4..b426897 100644 --- a/services/tracing/coordinator.cc +++ b/services/tracing/coordinator.cc
@@ -37,11 +37,18 @@ const char kMetadataTraceLabel[] = "metadata"; const char kRequestBufferUsageClosureName[] = "RequestBufferUsageClosure"; +const char kStartTracingClosureName[] = "StartTracingClosure"; +const int32_t kBeginTracingTimeoutInSeconds = 10; } // namespace namespace tracing { +// static +const void* Coordinator::GetStartTracingClosureName() { + return &kStartTracingClosureName; +} + class Coordinator::TraceStreamer : public base::SupportsWeakPtr<TraceStreamer> { public: // Constructed on |main_task_runner_|. @@ -269,9 +276,9 @@ Coordinator::Coordinator(AgentRegistry* agent_registry, const base::RepeatingClosure& on_disconnect_callback) - : on_disconnect_callback_(std::move(on_disconnect_callback)), + : task_runner_(base::SequencedTaskRunnerHandle::Get()), + on_disconnect_callback_(std::move(on_disconnect_callback)), binding_(this), - task_runner_(base::SequencedTaskRunnerHandle::Get()), // USER_VISIBLE because the task posted from StopAndFlushInternal() is // required to stop tracing from the UI. // TODO(fdoray): Once we have support for dynamic priorities @@ -294,10 +301,14 @@ } void Coordinator::Reset() { + start_tracing_callback_timer_.Stop(); + if (!stop_and_flush_callback_.is_null()) { base::ResetAndReturn(&stop_and_flush_callback_) .Run(base::Value(base::Value::Type::DICTIONARY)); } + if (!start_tracing_callback_.is_null()) + base::ResetAndReturn(&start_tracing_callback_).Run(false); if (!request_buffer_usage_callback_.is_null()) base::ResetAndReturn(&request_buffer_usage_callback_).Run(false, 0, 0); @@ -326,8 +337,11 @@ &Coordinator::OnClientConnectionError, base::Unretained(this))); } -void Coordinator::StartTracing(const std::string& config) { - if ((is_tracing_ && config == config_)) { +void Coordinator::StartTracing(const std::string& config, + StartTracingCallback callback) { + bool is_initializing = !start_tracing_callback_.is_null(); + if (is_initializing || (is_tracing_ && config == config_)) { + std::move(callback).Run(config == config_); return; } @@ -338,13 +352,113 @@ base::BindRepeating(&Coordinator::SendStartTracingToAgent, weak_ptr_factory_.GetWeakPtr()), false /* call_on_new_agents_only */); + + SetStartTracingCallback(std::move(callback)); +} + +void Coordinator::SetStartTracingCallback(StartTracingCallback callback) { + start_tracing_callback_ = std::move(callback); + CallStartTracingCallbackIfNeeded(); + + if (!start_tracing_callback_) + return; + + // We can't know for sure whether all processses we request + // to connect to the tracing service will connect back, or + // if all the connected services will ACK our BeginTracing + // request eventually, so we'll add a timeout for that case. + start_tracing_callback_timer_.Start( + FROM_HERE, base::TimeDelta::FromSeconds(kBeginTracingTimeoutInSeconds), + this, &Coordinator::OnBeginTracingTimeout); +} + +void Coordinator::OnBeginTracingTimeout() { + if (start_tracing_callback_) + std::move(start_tracing_callback_).Run(true); +} + +void Coordinator::CallStartTracingCallbackIfNeeded() { + // We still have processes we've asked to begin tracing and + // need ACKs from. + if (agent_registry_->HasDisconnectClosure(&kStartTracingClosureName)) + return; + + // We're still waiting for the list of PIDs of the currently + // running services. + if (pending_currently_running_pids_) + return; + + // We're still waiting for processes to connect to the + // service. + for (auto& pid : pending_connected_pids_) { + if (parsed_config_.process_filter_config().IsEnabled(pid)) + return; + } + + if (start_tracing_callback_) + std::move(start_tracing_callback_).Run(true); + + start_tracing_callback_timer_.Stop(); +} + +void Coordinator::AddExpectedPID(base::ProcessId pid) { + if (!pid) + return; + + bool pid_is_connected = false; + agent_registry_->ForAllAgents( + [&pid_is_connected, pid](AgentRegistry::AgentEntry* agent_entry) { + if (pid == agent_entry->pid()) + pid_is_connected = true; + }); + + if (!pid_is_connected) + pending_connected_pids_.insert(pid); +} + +void Coordinator::RemoveExpectedPID(base::ProcessId pid) { + pending_connected_pids_.erase(pid); + CallStartTracingCallbackIfNeeded(); +} + +void Coordinator::FinishedReceivingRunningPIDs() { + pending_currently_running_pids_ = false; + CallStartTracingCallbackIfNeeded(); +} + +void Coordinator::ClearConnectedPIDs() { + if (!pending_connected_pids_.empty()) { + pending_connected_pids_.clear(); + CallStartTracingCallbackIfNeeded(); + } } void Coordinator::SendStartTracingToAgent( AgentRegistry::AgentEntry* agent_entry) { + if (agent_entry->HasDisconnectClosure(&kStartTracingClosureName)) + return; if (!parsed_config_.process_filter_config().IsEnabled(agent_entry->pid())) return; - agent_entry->agent()->StartTracing(config_, TRACE_TIME_TICKS_NOW()); + agent_entry->AddDisconnectClosure( + &kStartTracingClosureName, + base::BindOnce(&Coordinator::OnTracingStarted, + weak_ptr_factory_.GetWeakPtr(), + base::Unretained(agent_entry), false)); + RemoveExpectedPID(agent_entry->pid()); + + agent_entry->agent()->StartTracing( + config_, TRACE_TIME_TICKS_NOW(), + base::BindRepeating(&Coordinator::OnTracingStarted, + weak_ptr_factory_.GetWeakPtr(), + base::Unretained(agent_entry))); +} + +void Coordinator::OnTracingStarted(AgentRegistry::AgentEntry* agent_entry, + bool success) { + bool removed = + agent_entry->RemoveDisconnectClosure(&kStartTracingClosureName); + DCHECK(removed); + CallStartTracingCallbackIfNeeded(); } void Coordinator::StopAndFlush(mojo::ScopedDataPipeProducerHandle stream, @@ -363,6 +477,12 @@ DCHECK(!trace_streamer_); DCHECK(stream.is_valid()); is_tracing_ = false; + // If we get a Stop call and this is non-empty, it means we either + // hit a timeout waiting for processes to connect, or the trace + // client sent a stop without waiting for the BeginTracing callback + // to happen. In either case, we don't want/need to wait for additional + // processes to connect anymore. + ClearConnectedPIDs(); trace_streamer_.reset(new Coordinator::TraceStreamer( std::move(stream), agent_label, task_runner_, @@ -372,6 +492,18 @@ } void Coordinator::StopAndFlushInternal() { + if (start_tracing_callback_) { + // We received a |StopAndFlush| command before receiving |StartTracing| acks + // from all agents. Let's retry after a delay. + task_runner_->PostDelayedTask( + FROM_HERE, + base::BindRepeating(&Coordinator::StopAndFlushInternal, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds( + mojom::kStopTracingRetryTimeMilliseconds)); + return; + } + size_t num_initialized_agents = agent_registry_->SetAgentInitializationCallback( base::BindRepeating(&Coordinator::SendStopTracingToAgent,
diff --git a/services/tracing/coordinator.h b/services/tracing/coordinator.h index 1bd8890..50b5381 100644 --- a/services/tracing/coordinator.h +++ b/services/tracing/coordinator.h
@@ -14,6 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" +#include "base/timer/timer.h" #include "base/trace_event/trace_config.h" #include "base/values.h" #include "mojo/public/cpp/system/data_pipe.h" @@ -50,10 +51,24 @@ bool IsConnected(); + void AddExpectedPID(base::ProcessId pid); + void RemoveExpectedPID(base::ProcessId pid); + void FinishedReceivingRunningPIDs(); + protected: ~Coordinator() override; + static const void* GetStartTracingClosureName(); + virtual void OnClientConnectionError(); + void CallStartTracingCallbackIfNeeded(); + void OnBeginTracingTimeout(); + void SetStartTracingCallback(StartTracingCallback callback); + void ClearConnectedPIDs(); + + base::trace_event::TraceConfig parsed_config_; + StartTracingCallback start_tracing_callback_; + const scoped_refptr<base::SequencedTaskRunner> task_runner_; private: friend std::default_delete<Coordinator>; @@ -64,7 +79,8 @@ void Reset(); // mojom::Coordinator - void StartTracing(const std::string& config) override; + void StartTracing(const std::string& config, + StartTracingCallback callback) override; void StopAndFlush(mojo::ScopedDataPipeProducerHandle stream, StopAndFlushCallback callback) override; void StopAndFlushAgent(mojo::ScopedDataPipeProducerHandle stream, @@ -75,6 +91,7 @@ // Internal methods for collecting events from agents. void SendStartTracingToAgent(AgentRegistry::AgentEntry* agent_entry); + void OnTracingStarted(AgentRegistry::AgentEntry* agent_entry, bool success); void StopAndFlushInternal(); void SendStopTracingToAgent(AgentRegistry::AgentEntry* agent_entry); void SendStopTracingWithNoOpRecorderToAgent( @@ -89,14 +106,15 @@ base::RepeatingClosure on_disconnect_callback_; mojo::Binding<mojom::Coordinator> binding_; - const scoped_refptr<base::SequencedTaskRunner> task_runner_; const scoped_refptr<base::SequencedTaskRunner> backend_task_runner_; AgentRegistry* agent_registry_; std::string config_; - base::trace_event::TraceConfig parsed_config_; bool is_tracing_ = false; std::unique_ptr<TraceStreamer> trace_streamer_; + std::set<base::ProcessId> pending_connected_pids_; + bool pending_currently_running_pids_ = true; + base::OneShotTimer start_tracing_callback_timer_; StopAndFlushCallback stop_and_flush_callback_; // For computing trace buffer usage.
diff --git a/services/tracing/coordinator_test_util.cc b/services/tracing/coordinator_test_util.cc index edac52b..41bdee5 100644 --- a/services/tracing/coordinator_test_util.cc +++ b/services/tracing/coordinator_test_util.cc
@@ -24,6 +24,7 @@ void CoordinatorTestUtil::SetUp() { agent_registry_ = std::make_unique<AgentRegistry>(); output_ = ""; + tracing_begin_callback_received_ = false; } // testing::Test @@ -73,9 +74,18 @@ return agents_.back().get(); } -void CoordinatorTestUtil::StartTracing(std::string config) { +void CoordinatorTestUtil::StartTracing(std::string config, + bool expected_response) { wait_for_data_closure_ = tracing_loop_.QuitClosure(); - coordinator_->StartTracing(config); + + coordinator_->StartTracing( + config, base::BindRepeating( + [](bool expected, bool* tracing_begin_callback_received, + bool actual) { + EXPECT_EQ(expected, actual); + *tracing_begin_callback_received = true; + }, + expected_response, &tracing_begin_callback_received_)); } std::string CoordinatorTestUtil::StopAndFlush() {
diff --git a/services/tracing/coordinator_test_util.h b/services/tracing/coordinator_test_util.h index 5aaf9ff..21c08625 100644 --- a/services/tracing/coordinator_test_util.h +++ b/services/tracing/coordinator_test_util.h
@@ -39,7 +39,7 @@ MockAgent* AddObjectAgent(); MockAgent* AddStringAgent(); - void StartTracing(std::string config); + void StartTracing(std::string config, bool expected_response); std::string StopAndFlush(); void IsTracing(bool expected_response); @@ -49,6 +49,9 @@ void CheckDisconnectClosures(size_t num_agents); AgentRegistry* agent_registry() { return agent_registry_.get(); } + bool tracing_begin_callback_received() const { + return tracing_begin_callback_received_; + } protected: std::unique_ptr<Coordinator> coordinator_; @@ -63,6 +66,7 @@ base::RunLoop tracing_loop_; base::RepeatingClosure wait_for_data_closure_; std::string output_; + bool tracing_begin_callback_received_ = false; }; } // namespace tracing
diff --git a/services/tracing/coordinator_unittest.cc b/services/tracing/coordinator_unittest.cc index 9d91e910..beb9bca 100644 --- a/services/tracing/coordinator_unittest.cc +++ b/services/tracing/coordinator_unittest.cc
@@ -19,6 +19,7 @@ CoordinatorTestUtil::SetUp(); coordinator_ = std::make_unique<Coordinator>(agent_registry(), base::RepeatingClosure()); + coordinator_->FinishedReceivingRunningPIDs(); } void TearDown() override { CoordinatorTestUtil::TearDown(); } }; @@ -26,7 +27,7 @@ TEST_F(CoordinatorTest, StartTracingSimple) { base::RunLoop run_loop; auto* agent = AddArrayAgent(); - StartTracing("*"); + StartTracing("*", true); run_loop.RunUntilIdle(); // The agent should have received exactly one call from the coordinator. @@ -37,7 +38,7 @@ TEST_F(CoordinatorTest, StartTracingTwoAgents) { base::RunLoop run_loop; auto* agent1 = AddArrayAgent(); - StartTracing("*"); + StartTracing("*", true); auto* agent2 = AddStringAgent(); run_loop.RunUntilIdle(); @@ -52,13 +53,13 @@ base::RunLoop run_loop1; auto* agent1 = AddArrayAgent(static_cast<base::ProcessId>(1)); auto* agent2 = AddArrayAgent(static_cast<base::ProcessId>(2)); - StartTracing("{\"included_process_ids\":[2,4]}"); + StartTracing("{\"included_process_ids\":[2,4]}", true); run_loop1.RunUntilIdle(); base::RunLoop run_loop2; auto* agent3 = AddArrayAgent(static_cast<base::ProcessId>(3)); auto* agent4 = AddArrayAgent(static_cast<base::ProcessId>(4)); - StartTracing("{\"included_process_ids\":[4,6]}"); + StartTracing("{\"included_process_ids\":[4,6]}", true); run_loop2.RunUntilIdle(); base::RunLoop run_loop3; @@ -67,27 +68,38 @@ run_loop3.RunUntilIdle(); // StartTracing should only be received by agents 2, 4, and 6. - // Agent 4 should receive StartTracing twice, as it's - // included in both configs. EXPECT_EQ(0u, agent1->call_stat().size()); EXPECT_EQ(1u, agent2->call_stat().size()); EXPECT_EQ("StartTracing", agent2->call_stat()[0]); EXPECT_EQ(0u, agent3->call_stat().size()); - EXPECT_EQ(2u, agent4->call_stat().size()); + EXPECT_EQ(1u, agent4->call_stat().size()); EXPECT_EQ("StartTracing", agent4->call_stat()[0]); - EXPECT_EQ("StartTracing", agent4->call_stat()[1]); EXPECT_EQ(0u, agent5->call_stat().size()); EXPECT_EQ(1u, agent6->call_stat().size()); EXPECT_EQ("StartTracing", agent6->call_stat()[0]); } +TEST_F(CoordinatorTest, StartTracingWithDifferentConfigs) { + base::RunLoop run_loop; + auto* agent = AddArrayAgent(); + StartTracing("config 1", true); + // The 2nd |StartTracing| should return false. + StartTracing("config 2", false); + run_loop.RunUntilIdle(); + + // The agent should have received exactly one call from the coordinator + // because the 2nd |StartTracing| was aborted. + EXPECT_EQ(1u, agent->call_stat().size()); + EXPECT_EQ("StartTracing", agent->call_stat()[0]); +} + TEST_F(CoordinatorTest, StartTracingWithSameConfigs) { base::RunLoop run_loop; auto* agent = AddArrayAgent(); - StartTracing("config"); - // The 2nd |StartTracing| should succeed when we are not trying to change + StartTracing("config", true); + // The 2nd |StartTracing| should return true when we are not trying to change // the config. - StartTracing("config"); + StartTracing("config", true); run_loop.RunUntilIdle(); // The agent should have received exactly one call from the coordinator @@ -101,7 +113,7 @@ agent->data_.push_back("\"content\":{\"a\":1}"); agent->data_.push_back("\"name\":\"etw\""); - StartTracing("config"); + StartTracing("config", true); std::string output = StopAndFlush(); EXPECT_EQ("{\"systemTraceEvents\":{\"content\":{\"a\":1},\"name\":\"etw\"}}", @@ -122,7 +134,7 @@ agent2->data_.push_back("e3"); agent2->data_.push_back("e4"); - StartTracing("config"); + StartTracing("config", true); std::string output = StopAndFlush(); // |output| should be of the form {"traceEvents":[ei,ej,ek,el]}, where @@ -156,7 +168,7 @@ agent2->data_.push_back("e3"); agent2->data_.push_back("e4"); - StartTracing("config"); + StartTracing("config", true); std::string output = StopAndFlush(); EXPECT_TRUE(output == "{\"traceEvents\":[e1,e2],\"power\":\"e3e4\"}" || @@ -177,7 +189,7 @@ agent->data_.push_back("event"); agent->metadata_.SetString("key", "value"); - StartTracing("config"); + StartTracing("config", true); std::string output = StopAndFlush(); // Metadata is written at after trace data. @@ -191,7 +203,7 @@ TEST_F(CoordinatorTest, IsTracing) { base::RunLoop run_loop; AddArrayAgent(); - StartTracing("config"); + StartTracing("config", true); IsTracing(true); run_loop.RunUntilIdle(); } @@ -238,7 +250,8 @@ TEST_F(CoordinatorTest, LateAgents) { auto* agent1 = AddArrayAgent(); - StartTracing("config"); + + StartTracing("config", true); StopAndFlush(); base::RunLoop run_loop; @@ -256,4 +269,31 @@ EXPECT_EQ("StopAndFlush", agent2->call_stat()[0]); } +TEST_F(CoordinatorTest, WaitForSpecificPIDs) { + coordinator_->AddExpectedPID(42); + coordinator_->AddExpectedPID(4242); + + auto* agent1 = AddArrayAgent(42); + StartTracing("config", true); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(tracing_begin_callback_received()); + + auto* agent2 = AddArrayAgent(4242); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(tracing_begin_callback_received()); + + StopAndFlush(); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(2u, agent1->call_stat().size()); + EXPECT_EQ("StartTracing", agent1->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent1->call_stat()[1]); + + EXPECT_EQ(2u, agent2->call_stat().size()); + EXPECT_EQ("StartTracing", agent2->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent2->call_stat()[1]); +} + } // namespace tracing
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.cc b/services/tracing/perfetto/perfetto_tracing_coordinator.cc index f159631..cacdcd1 100644 --- a/services/tracing/perfetto/perfetto_tracing_coordinator.cc +++ b/services/tracing/perfetto/perfetto_tracing_coordinator.cc
@@ -14,6 +14,7 @@ #include "mojo/public/cpp/system/data_pipe_utils.h" #include "services/tracing/perfetto/json_trace_exporter.h" #include "services/tracing/perfetto/perfetto_service.h" +#include "services/tracing/public/mojom/constants.mojom.h" #include "services/tracing/public/mojom/perfetto_service.mojom.h" #include "third_party/perfetto/include/perfetto/tracing/core/consumer.h" #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h" @@ -197,6 +198,11 @@ binding_(this), weak_factory_(this) { DETACH_FROM_SEQUENCE(sequence_checker_); + + agent_registry->SetAgentInitializationCallback( + base::BindRepeating(&PerfettoTracingCoordinator::OnNewAgentConnected, + weak_factory_.GetWeakPtr()), + false /* call_on_new_agents_only */); } PerfettoTracingCoordinator::~PerfettoTracingCoordinator() { @@ -219,11 +225,46 @@ base::Unretained(this))); } -void PerfettoTracingCoordinator::StartTracing(const std::string& config) { +void PerfettoTracingCoordinator::StartTracing(const std::string& config, + StartTracingCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + parsed_config_ = base::trace_event::TraceConfig(config); tracing_session_ = std::make_unique<TracingSession>( config, base::BindOnce(&PerfettoTracingCoordinator::OnTracingOverCallback, weak_factory_.GetWeakPtr())); + + SetStartTracingCallback(std::move(callback)); +} + +void PerfettoTracingCoordinator::OnNewAgentConnected( + AgentRegistry::AgentEntry* agent_entry) { + // TODO(oysteine): While we're still using the Agent + // system as a fallback when using Perfetto, rather than + // the browser directly using a Consumer interface, we have to + // attempt to linearize with newly connected agents so we only + // call the BeginTracing callback when we can be fairly sure + // that all current agents have registered with Perfetto and + // started tracing if requested. We do this linearization + // by calling RequestBufferStatus but just throwing away the + // result. + auto closure = base::BindRepeating( + [](base::WeakPtr<PerfettoTracingCoordinator> coordinator, + AgentRegistry::AgentEntry* agent_entry, uint32_t capacity, + uint32_t count) { + bool removed = + agent_entry->RemoveDisconnectClosure(GetStartTracingClosureName()); + DCHECK(removed); + + if (coordinator) { + coordinator->RemoveExpectedPID(agent_entry->pid()); + } + }, + weak_factory_.GetWeakPtr(), base::Unretained(agent_entry)); + + agent_entry->AddDisconnectClosure(GetStartTracingClosureName(), + base::BindOnce(closure, 0, 0)); + + agent_entry->agent()->RequestBufferStatus(closure); } void PerfettoTracingCoordinator::OnTracingOverCallback() { @@ -235,8 +276,25 @@ void PerfettoTracingCoordinator::StopAndFlush( mojo::ScopedDataPipeProducerHandle stream, StopAndFlushCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(tracing_session_); + StopAndFlushAgent(std::move(stream), "", std::move(callback)); +} + +void PerfettoTracingCoordinator::StopAndFlushInternal( + mojo::ScopedDataPipeProducerHandle stream, + StopAndFlushCallback callback) { + if (start_tracing_callback_) { + // We received a |StopAndFlush| command before receiving |StartTracing| acks + // from all agents. Let's retry after a delay. + task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&PerfettoTracingCoordinator::StopAndFlushInternal, + weak_factory_.GetWeakPtr(), std::move(stream), + std::move(callback)), + base::TimeDelta::FromMilliseconds( + mojom::kStopTracingRetryTimeMilliseconds)); + return; + } + tracing_session_->StopAndFlush(std::move(stream), std::move(callback)); } @@ -244,7 +302,11 @@ mojo::ScopedDataPipeProducerHandle stream, const std::string& agent_label, StopAndFlushCallback callback) { - NOTREACHED(); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(tracing_session_); + + ClearConnectedPIDs(); + StopAndFlushInternal(std::move(stream), std::move(callback)); } void PerfettoTracingCoordinator::IsTracing(IsTracingCallback callback) {
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.h b/services/tracing/perfetto/perfetto_tracing_coordinator.h index 6db0495..554346b 100644 --- a/services/tracing/perfetto/perfetto_tracing_coordinator.h +++ b/services/tracing/perfetto/perfetto_tracing_coordinator.h
@@ -37,7 +37,8 @@ // mojom::Coordinator implementation. // Called by the tracing controller. - void StartTracing(const std::string& config) override; + void StartTracing(const std::string& config, + StartTracingCallback callback) override; void StopAndFlush(mojo::ScopedDataPipeProducerHandle stream, StopAndFlushCallback callback) override; void StopAndFlushAgent(mojo::ScopedDataPipeProducerHandle stream, @@ -49,6 +50,9 @@ private: void OnTracingOverCallback(); void OnClientConnectionError() override; + void OnNewAgentConnected(AgentRegistry::AgentEntry* agent_entry); + void StopAndFlushInternal(mojo::ScopedDataPipeProducerHandle stream, + StopAndFlushCallback callback); mojo::Binding<mojom::Coordinator> binding_;
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator_unittest.cc b/services/tracing/perfetto/perfetto_tracing_coordinator_unittest.cc index 6f6f4e7..ac471fd 100644 --- a/services/tracing/perfetto/perfetto_tracing_coordinator_unittest.cc +++ b/services/tracing/perfetto/perfetto_tracing_coordinator_unittest.cc
@@ -18,6 +18,7 @@ CoordinatorTestUtil::SetUp(); coordinator_ = std::make_unique<PerfettoTracingCoordinator>( agent_registry(), base::RepeatingClosure()); + coordinator_->FinishedReceivingRunningPIDs(); } void TearDown() override { CoordinatorTestUtil::TearDown(); } }; @@ -26,7 +27,7 @@ auto* agent = AddArrayAgent(); agent->data_.push_back("e1"); - StartTracing("{\"trace_buffer_size_in_kb\":4}"); + StartTracing("{\"trace_buffer_size_in_kb\":4}", true); std::string output = StopAndFlush(); auto json_value = base::JSONReader::Read(output);
diff --git a/services/tracing/public/cpp/base_agent.cc b/services/tracing/public/cpp/base_agent.cc index 0e14ac9..d31c1a9b2 100644 --- a/services/tracing/public/cpp/base_agent.cc +++ b/services/tracing/public/cpp/base_agent.cc
@@ -39,7 +39,10 @@ } void BaseAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) {} + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) { + std::move(callback).Run(true /* success */); +} void BaseAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {}
diff --git a/services/tracing/public/cpp/base_agent.h b/services/tracing/public/cpp/base_agent.h index dc1325d..8be2cf54 100644 --- a/services/tracing/public/cpp/base_agent.h +++ b/services/tracing/public/cpp/base_agent.h
@@ -35,7 +35,8 @@ // tracing::mojom::Agent: void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) override; void StopAndFlush(tracing::mojom::RecorderPtr recorder) override; void RequestBufferStatus( Agent::RequestBufferStatusCallback callback) override;
diff --git a/services/tracing/public/cpp/trace_event_agent.cc b/services/tracing/public/cpp/trace_event_agent.cc index 88e25d8..94cc70a 100644 --- a/services/tracing/public/cpp/trace_event_agent.cc +++ b/services/tracing/public/cpp/trace_event_agent.cc
@@ -72,7 +72,8 @@ } void TraceEventAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + StartTracingCallback callback) { DCHECK(!recorder_); #if defined(__native_client__) // NaCl and system times are offset by a bit, so subtract some time from @@ -87,6 +88,7 @@ enabled_tracing_modes_ |= base::trace_event::TraceLog::FILTERING_MODE; base::trace_event::TraceLog::GetInstance()->SetEnabled( trace_config, enabled_tracing_modes_); + std::move(callback).Run(true); } void TraceEventAgent::StopAndFlush(mojom::RecorderPtr recorder) {
diff --git a/services/tracing/public/cpp/trace_event_agent.h b/services/tracing/public/cpp/trace_event_agent.h index 1a7c8915..70063d2 100644 --- a/services/tracing/public/cpp/trace_event_agent.h +++ b/services/tracing/public/cpp/trace_event_agent.h
@@ -49,7 +49,8 @@ // mojom::Agent void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + StartTracingCallback callback) override; void StopAndFlush(mojom::RecorderPtr recorder) override; void RequestBufferStatus(RequestBufferStatusCallback callback) override;
diff --git a/services/tracing/public/cpp/trace_event_agent_unittest.cc b/services/tracing/public/cpp/trace_event_agent_unittest.cc index 443dd11..9749aac3 100644 --- a/services/tracing/public/cpp/trace_event_agent_unittest.cc +++ b/services/tracing/public/cpp/trace_event_agent_unittest.cc
@@ -90,7 +90,8 @@ void StartTracing(const std::string& categories) { TraceEventAgent::GetInstance()->StartTracing( base::trace_event::TraceConfig(categories, "").ToString(), - base::TimeTicks::Now()); + base::TimeTicks::Now(), + base::BindRepeating([](bool success) { EXPECT_TRUE(success); })); } void StopAndFlush(base::Closure quit_closure) {
diff --git a/services/tracing/public/mojom/constants.mojom b/services/tracing/public/mojom/constants.mojom index d258406d..f62a072 100644 --- a/services/tracing/public/mojom/constants.mojom +++ b/services/tracing/public/mojom/constants.mojom
@@ -4,6 +4,8 @@ module tracing.mojom; +const uint32 kStopTracingRetryTimeMilliseconds = 100; + const string kServiceName = "tracing"; // The label of agents that provide trace data of the format explained in
diff --git a/services/tracing/public/mojom/tracing.mojom b/services/tracing/public/mojom/tracing.mojom index 8c081774..3c282c4 100644 --- a/services/tracing/public/mojom/tracing.mojom +++ b/services/tracing/public/mojom/tracing.mojom
@@ -39,7 +39,8 @@ // close the recorder connection to signal the tracing service that no more data // will be sent. interface Agent { - StartTracing(string config, mojo_base.mojom.TimeTicks coordinator_time); + StartTracing(string config, mojo_base.mojom.TimeTicks coordinator_time) + => (bool success); StopAndFlush(Recorder recorder); RequestBufferStatus() => (uint32 capacity, uint32 count); }; @@ -60,7 +61,7 @@ // The return value is false if tracing is already enabled with a different // config. Otherwise, true is returned as soon as the service receives acks // from all existing agents and agents that connect during |StartTracing|. - StartTracing(string config); + StartTracing(string config) => (bool success); StopAndFlush(handle<data_pipe_producer> stream) => (mojo_base.mojom.DictionaryValue metadata); // Same as |StopAndFlush| but only write data from a certain |agent_label| to
diff --git a/services/tracing/test_util.cc b/services/tracing/test_util.cc index e514302..1bce1291 100644 --- a/services/tracing/test_util.cc +++ b/services/tracing/test_util.cc
@@ -21,8 +21,10 @@ } void MockAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + StartTracingCallback cb) { call_stat_.push_back("StartTracing"); + std::move(cb).Run(true); } void MockAgent::StopAndFlush(mojom::RecorderPtr recorder) {
diff --git a/services/tracing/test_util.h b/services/tracing/test_util.h index 948f30c..821a7eb0 100644 --- a/services/tracing/test_util.h +++ b/services/tracing/test_util.h
@@ -37,7 +37,8 @@ private: // mojom::Agent void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + StartTracingCallback cb) override; void StopAndFlush(mojom::RecorderPtr recorder) override; void RequestBufferStatus(RequestBufferStatusCallback cb) override;
diff --git a/services/tracing/tracing_service.cc b/services/tracing/tracing_service.cc index 1a08557..d277c63 100644 --- a/services/tracing/tracing_service.cc +++ b/services/tracing/tracing_service.cc
@@ -4,6 +4,7 @@ #include "services/tracing/tracing_service.h" +#include <map> #include <utility> #include <vector> @@ -25,10 +26,12 @@ class ServiceListener : public service_manager::mojom::ServiceManagerListener { public: ServiceListener(service_manager::Connector* connector, - AgentRegistry* agent_registry) + AgentRegistry* agent_registry, + Coordinator* coordinator) : binding_(this), connector_(connector), - agent_registry_(agent_registry) { + agent_registry_(agent_registry), + coordinator_(coordinator) { service_manager::mojom::ServiceManagerPtr service_manager; connector_->BindInterface(service_manager::mojom::kServiceName, &service_manager); @@ -58,31 +61,75 @@ traced_process->ConnectToTracingService(std::move(new_connection_request)); } + size_t CountServicesWithPID(uint32_t pid) { + return std::count_if(service_pid_map_.begin(), service_pid_map_.end(), + [pid](decltype(service_pid_map_)::value_type p) { + return p.second == pid; + }); + } + + void ServiceAddedWithPID(const service_manager::Identity& identity, + uint32_t pid) { + service_pid_map_[identity] = pid; + // First service with this PID added; expect a connection from it. + if (CountServicesWithPID(pid) == 1) { + coordinator_->AddExpectedPID(pid); + ConnectProcessToTracingService(identity); + } + } + + void ServiceRemoved(const service_manager::Identity& identity) { + auto entry = service_pid_map_.find(identity); + if (entry != service_pid_map_.end()) { + uint32_t pid = entry->second; + service_pid_map_.erase(entry); + // Last entry with this PID removed; stop expecting it + // to connect to the tracing service. + if (CountServicesWithPID(pid) == 0) { + coordinator_->RemoveExpectedPID(pid); + } + } + } + // service_manager::mojom::ServiceManagerListener implementation. void OnInit(std::vector<service_manager::mojom::RunningServiceInfoPtr> running_services) override { for (auto& service : running_services) { - ConnectProcessToTracingService(service->identity); + if (service->pid) { + ServiceAddedWithPID(service->identity, service->pid); + } } + + coordinator_->FinishedReceivingRunningPIDs(); + } + + void OnServicePIDReceived(const service_manager::Identity& identity, + uint32_t pid) override { + ServiceAddedWithPID(identity, pid); + } + + void OnServiceFailedToStart( + const service_manager::Identity& identity) override { + ServiceRemoved(identity); + } + + void OnServiceStopped(const service_manager::Identity& identity) override { + ServiceRemoved(identity); } void OnServiceStarted(const service_manager::Identity& identity, uint32_t pid) override { - ConnectProcessToTracingService(identity); } void OnServiceCreated( service_manager::mojom::RunningServiceInfoPtr service) override {} - void OnServicePIDReceived(const service_manager::Identity& identity, - uint32_t pid) override {} - void OnServiceFailedToStart( - const service_manager::Identity& identity) override {} - void OnServiceStopped(const service_manager::Identity& identity) override {} private: mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_; service_manager::Connector* connector_; AgentRegistry* agent_registry_; + Coordinator* coordinator_; + std::map<service_manager::Identity, uint32_t> service_pid_map_; }; TracingService::TracingService(service_manager::mojom::ServiceRequest request) @@ -105,7 +152,7 @@ registry_.AddInterface( base::BindRepeating(&PerfettoTracingCoordinator::BindCoordinatorRequest, base::Unretained(perfetto_coordinator.get()))); - perfetto_tracing_coordinator_ = std::move(perfetto_coordinator); + tracing_coordinator_ = std::move(perfetto_coordinator); } else { auto tracing_coordinator = std::make_unique<Coordinator>( tracing_agent_registry_.get(), @@ -118,7 +165,8 @@ } service_listener_ = std::make_unique<ServiceListener>( - service_binding_.GetConnector(), tracing_agent_registry_.get()); + service_binding_.GetConnector(), tracing_agent_registry_.get(), + tracing_coordinator_.get()); } void TracingService::OnBindInterface(
diff --git a/services/tracing/tracing_service.h b/services/tracing/tracing_service.h index 298c504..0ff7bbfa3 100644 --- a/services/tracing/tracing_service.h +++ b/services/tracing/tracing_service.h
@@ -22,7 +22,6 @@ namespace tracing { class ServiceListener; -class PerfettoTracingCoordinator; class TracingService : public service_manager::Service { public: @@ -47,7 +46,6 @@ registry_; std::unique_ptr<tracing::AgentRegistry> tracing_agent_registry_; std::unique_ptr<Coordinator> tracing_coordinator_; - std::unique_ptr<PerfettoTracingCoordinator> perfetto_tracing_coordinator_; std::unique_ptr<ServiceListener> service_listener_;
diff --git a/services/ws/ime/ime_unittest.cc b/services/ws/ime/ime_unittest.cc index 4c59e2cb..bc03cf6 100644 --- a/services/ws/ime/ime_unittest.cc +++ b/services/ws/ime/ime_unittest.cc
@@ -50,7 +50,7 @@ void DispatchKeyEventPostIME( std::unique_ptr<ui::Event> event, DispatchKeyEventPostIMECallback callback) override { - std::move(callback).Run(false); + std::move(callback).Run(false, false); } void EnsureCaretNotInRect(const gfx::Rect& rect) override {} void SetEditableSelectionRange(const gfx::Range& range) override {}
diff --git a/services/ws/ime/test_ime_driver/test_ime_driver.cc b/services/ws/ime/test_ime_driver/test_ime_driver.cc index 2ad7862d..bc946a9 100644 --- a/services/ws/ime/test_ime_driver/test_ime_driver.cc +++ b/services/ws/ime/test_ime_driver/test_ime_driver.cc
@@ -41,16 +41,17 @@ // Using base::Unretained is safe because |client_| is owned by this class. client_->DispatchKeyEventPostIME( std::move(key_event), - base::BindOnce(&TestInputMethod::PostProcssKeyEvent, + base::BindOnce(&TestInputMethod::PostProcessKeyEvent, base::Unretained(this), std::move(cloned_event), std::move(callback))); } void CancelComposition() override { NOTIMPLEMENTED_LOG_ONCE(); } void ShowVirtualKeyboardIfEnabled() override { NOTIMPLEMENTED_LOG_ONCE(); } - void PostProcssKeyEvent(std::unique_ptr<ui::Event> key_event, - ProcessKeyEventCallback callback, - bool stopped_propagation) { + void PostProcessKeyEvent(std::unique_ptr<ui::Event> key_event, + ProcessKeyEventCallback callback, + bool handled, + bool stopped_propagation) { // Ignore any events with modifiers set. This is useful for running things // like ash_shell_with_content and having accelerators (such as control-n) // work.
diff --git a/services/ws/public/mojom/ime/ime.mojom b/services/ws/public/mojom/ime/ime.mojom index 8028b6d..b8bb278 100644 --- a/services/ws/public/mojom/ime/ime.mojom +++ b/services/ws/public/mojom/ime/ime.mojom
@@ -235,8 +235,13 @@ // for more details. InsertChar(ui.mojom.Event event); - // Dispatch a key event skipping IME. Returns true if event was consumed. - DispatchKeyEventPostIME(ui.mojom.Event event) => (bool stopped_propagation); + // Dispatch a key event after minimal processing by the IME. The results of + // the callback indicated whether the event was handled, and whether any + // further processing should be performed. That is, if |stopped_propagation| + // is true, IME does no further processing. + DispatchKeyEventPostIME(ui.mojom.Event event) => ( + bool handled, + bool stopped_propagation); // Ensure the caret is not in |rect|. |rect| is in dip screen coordinates // and may extend beyond the bounds of this TextInputClient.
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index cab2430..1c48acc 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -170,10 +170,6 @@ #define SK_SUPPORT_LEGACY_AAA_CHOICE #endif -#ifndef SK_SUPPORT_LEGACY_TEXTBLOBCACHEDIFFCANVAS_CONSTRUCTOR -#define SK_SUPPORT_LEGACY_TEXTBLOBCACHEDIFFCANVAS_CONSTRUCTOR -#endif - // We're turning this off indefinitely, // until we can figure out some fundamental problems with its approach. //
diff --git a/styleguide/web/web.md b/styleguide/web/web.md index 9724ebf..62e86bf 100644 --- a/styleguide/web/web.md +++ b/styleguide/web/web.md
@@ -248,7 +248,7 @@ readability. * Prefer `rgb()` or `rgba()` with decimal values instead of hex notation - (`#rrggbb`) because alpha can be more easily added. + (`#rrggbb`). * Exception: shades of gray (i.e. `#333`) * If the hex value is `#rrggbb`, use the shorthand notation `#rgb`.
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 9d2e2bd..386f1e3 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -10054,6 +10054,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ], "scripts": [ @@ -10928,6 +10935,16 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "args": [ + "--test-launcher-print-test-stdio=always" + ], + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ] }, @@ -11538,6 +11555,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ] }, @@ -12151,6 +12175,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ], "scripts": [ @@ -12735,6 +12766,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ] }, @@ -13348,6 +13386,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ] }, @@ -13964,6 +14009,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ] }, @@ -22804,6 +22856,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ] },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 3fa3edc2..fe02df0 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -6588,6 +6588,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ], "isolated_scripts": [ @@ -10789,6 +10796,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ], "isolated_scripts": [
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 9d4ac2c9..2f54501 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -1660,6 +1660,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ], "isolated_scripts": [ @@ -2459,6 +2466,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ], "isolated_scripts": [ @@ -3187,6 +3201,13 @@ "can_use_on_swarming_builders": true }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "xr_browser_tests" } ], "isolated_scripts": [ @@ -4378,6 +4399,18 @@ ] }, "test": "wtf_unittests" + }, + { + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "xr_browser_tests" } ], "isolated_scripts": [
diff --git a/testing/buildbot/filters/chromeos.mash.fyi.interactive_ui_tests.filter b/testing/buildbot/filters/chromeos.mash.fyi.interactive_ui_tests.filter index bca197b..eaa6a2a 100644 --- a/testing/buildbot/filters/chromeos.mash.fyi.interactive_ui_tests.filter +++ b/testing/buildbot/filters/chromeos.mash.fyi.interactive_ui_tests.filter
@@ -95,6 +95,10 @@ # MouseEventsTest -MouseEventsTest.ClickAndDoubleClick -MouseEventsTest.ContextMenu +-MouseEventsTest.MouseOver # CrashInFlightChange::ChangeFailed() -FlashFullscreenInteractiveBrowserTest.FullscreenWithinTab_EscapeKeyExitsFullscreen + +#Flaky https://crbug.com/933847 +-LocationIconViewTest.HideOnSecondClick
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index ac9b571a..a19d5df 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3755,6 +3755,12 @@ }, }, + 'linux_specific_xr_gtests': { + 'xr_browser_tests': { + 'test': 'xr_browser_tests', + } + }, + 'mac_specific_chromium_gtests': { 'sandbox_mac_unittests': {}, }, @@ -4564,6 +4570,7 @@ 'chromium_gtests_for_linux_and_chromeos_only', 'chromium_gtests_for_win_and_linux_only', 'linux_flavor_specific_chromium_gtests', + 'linux_specific_xr_gtests', 'network_service_gtests', 'non_android_chromium_gtests', 'non_android_and_cast_and_chromeos_chromium_gtests',
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index f4f9ce2..b3787a4 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -27,7 +27,6 @@ "//base", "//courgette:courgette_lib", ] - additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ] } fuzzer_test("language_detection_fuzzer") {
diff --git a/testing/trigger_scripts/base_test_triggerer.py b/testing/trigger_scripts/base_test_triggerer.py index b95c9dc1..e576e338 100755 --- a/testing/trigger_scripts/base_test_triggerer.py +++ b/testing/trigger_scripts/base_test_triggerer.py
@@ -206,10 +206,11 @@ pass def select_config_indices(self, args, verbose): - # Main implementation for base class to determine what - # configs to trigger jobs on from self._bot_configs. - # Returns a list of indices into the self._bot_configs and - # len(self.indices_to_trigger(args)) == len(selected_indices). + # Main implementation for base class to determine which bot config to + # trigger for each shard. + # + # Returns a list of tuples (shard_index, bot_config_index). + # bot_config_index is an index into self._bot_configs pass def indices_to_trigger(self, args): @@ -250,25 +251,23 @@ merged_json = {} # Choose selected configs for this run of the test suite. - selected_configs = self.select_config_indices(args, verbose) - for i in self.indices_to_trigger(args): + for shard_index, bot_index in self.select_config_indices(args, verbose): # For each shard that we're going to distribute, do the following: # 1. Pick which bot configuration to use. # 2. Insert that bot configuration's dimensions as command line # arguments, and invoke "swarming.py trigger". - bot_index = selected_configs[i] # Holds the results of the swarming.py trigger call. try: json_temp = self.make_temp_file(prefix='base_trigger_dimensions', suffix='.json') - args_to_pass = self.modify_args(filtered_remaining_args, bot_index, i, - args.shards, json_temp) + args_to_pass = self.modify_args(filtered_remaining_args, bot_index, + shard_index, args.shards, json_temp) ret = self.run_swarming(args_to_pass, verbose) if ret: sys.stderr.write('Failed to trigger a task, aborting\n') return ret result_json = self.read_json_from_temp_file(json_temp) - if i == 0: + if shard_index == 0: # Copy the entire JSON -- in particular, the "request" # dictionary -- from shard 0. "swarming.py collect" uses # some keys from this dictionary, in particular related to @@ -278,8 +277,8 @@ # which will be handled specially. merged_json['tasks'] = {} for k, v in result_json['tasks'].items(): - v['shard_index'] = i - merged_json['tasks'][k + ':%d:%d' % (i, args.shards)] = v + v['shard_index'] = shard_index + merged_json['tasks'][k + ':%d:%d' % (shard_index, args.shards)] = v finally: self.delete_temp_file(json_temp) self.write_json_to_file(merged_json, args.dump_json)
diff --git a/testing/trigger_scripts/perf_device_trigger.py b/testing/trigger_scripts/perf_device_trigger.py index e890acb..964167c4 100755 --- a/testing/trigger_scripts/perf_device_trigger.py +++ b/testing/trigger_scripts/perf_device_trigger.py
@@ -115,10 +115,12 @@ def select_config_indices(self, args, verbose): if args.multiple_trigger_configs: + configs = [] # If specific bot ids were passed in, we want to trigger a job for # every valid config regardless of health status since # each config represents exactly one bot in the perf swarming pool. - return range(len(self.indices_to_trigger(args))) + for index in range(len(self.indices_to_trigger(args))): + configs.append((index, index)) return self._select_config_indices_with_soft_affinity(args, verbose) def _select_config_indices_with_soft_affinity(self, args, verbose): @@ -176,8 +178,8 @@ # Now populate the indices into the bot_configs array selected_configs = [] for shard_index in self.indices_to_trigger(args): - selected_configs.append(self._find_bot_config_index( - shard_to_bot_assignment_map[shard_index].id())) + selected_configs.append((shard_index, self._find_bot_config_index( + shard_to_bot_assignment_map[shard_index].id()))) if verbose: self._print_device_affinity_info( shard_to_bot_assignment_map,
diff --git a/testing/trigger_scripts/trigger_multiple_dimensions.py b/testing/trigger_scripts/trigger_multiple_dimensions.py index 4fd765a..d4d26f5 100755 --- a/testing/trigger_scripts/trigger_multiple_dimensions.py +++ b/testing/trigger_scripts/trigger_multiple_dimensions.py
@@ -113,8 +113,9 @@ def select_config_indices(self, args, verbose): selected_indices = [] - for _ in self.indices_to_trigger(args): - selected_indices.append(self.pick_bot_configuration(verbose)) + for shard_index in self.indices_to_trigger(args): + selected_indices.append( + (shard_index, self.pick_bot_configuration(verbose))) return selected_indices def prune_test_specific_configs(self, args, verbose):
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn index 99748c1f..01171e5 100644 --- a/third_party/android_deps/BUILD.gn +++ b/third_party/android_deps/BUILD.gn
@@ -539,6 +539,7 @@ aar_path = "libs/com_google_ar_core/core-1.6.0.aar" info_path = "libs/com_google_ar_core/com_google_ar_core.info" extract_native_libraries = true + split_compat_class_names = [ "com/google/ar/core/InstallActivity" ] } java_prebuilt("com_google_dagger_dagger_java") {
diff --git a/third_party/blink/common/frame/user_activation_state.cc b/third_party/blink/common/frame/user_activation_state.cc index ace8e45..88686ae 100644 --- a/third_party/blink/common/frame/user_activation_state.cc +++ b/third_party/blink/common/frame/user_activation_state.cc
@@ -9,7 +9,7 @@ // The expiry time should be long enough to allow network round trips even in a // very slow connection (to support xhr-like calls with user activation), yet // not too long to make an "unattneded" page feel activated. -constexpr base::TimeDelta kActivationLifespan = base::TimeDelta::FromSeconds(1); +constexpr base::TimeDelta kActivationLifespan = base::TimeDelta::FromSeconds(5); void UserActivationState::Activate() { has_been_active_ = true;
diff --git a/third_party/blink/common/frame/user_activation_state_unittest.cc b/third_party/blink/common/frame/user_activation_state_unittest.cc index 30bc7b47..16780b4 100644 --- a/third_party/blink/common/frame/user_activation_state_unittest.cc +++ b/third_party/blink/common/frame/user_activation_state_unittest.cc
@@ -65,7 +65,7 @@ user_activation_state.Activate(); // Right before activation expiry, both bits remain set. - AdvanceClock(base::TimeDelta::FromMilliseconds(999)); + AdvanceClock(base::TimeDelta::FromMilliseconds(4999)); EXPECT_TRUE(user_activation_state.HasBeenActive()); EXPECT_TRUE(user_activation_state.IsActive()); @@ -99,7 +99,7 @@ // An activation is not consumable after expiry. user_activation_state.Activate(); - AdvanceClock(base::TimeDelta::FromSeconds(1)); + AdvanceClock(base::TimeDelta::FromSeconds(5)); EXPECT_FALSE(user_activation_state.ConsumeIfActive()); // Consecutive activations within expiry is consumable only once.
diff --git a/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom b/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom index 19485a1..fdfcf38 100644 --- a/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom +++ b/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom
@@ -20,4 +20,7 @@ // not delivered to a certain DocumentInterfaceBroker implementation. interface FrameHostTestInterface { Ping(url.mojom.Url source_url, string source_event); + // Used in tests to distinguish between the different implementations + // and verify that interface requests are routed to the proper override. + GetName() => (string name); };
diff --git a/third_party/blink/public/platform/web_rtc_rtp_receiver.h b/third_party/blink/public/platform/web_rtc_rtp_receiver.h index 816c9950..0307271 100644 --- a/third_party/blink/public/platform/web_rtc_rtp_receiver.h +++ b/third_party/blink/public/platform/web_rtc_rtp_receiver.h
@@ -10,6 +10,7 @@ #include "third_party/blink/public/platform/web_rtc_stats.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_vector.h" +#include "third_party/webrtc/api/dtls_transport_interface.h" #include "third_party/webrtc/api/rtp_parameters.h" namespace blink { @@ -29,6 +30,11 @@ // Two |WebRTCRtpReceiver|s referencing the same WebRTC-layer receiver have // the same |id|. virtual uintptr_t Id() const = 0; + virtual rtc::scoped_refptr<webrtc::DtlsTransportInterface> + DtlsTransport() = 0; + // Note: For convenience, DtlsTransportInformation always returns a value. + // The information is only interesting if DtlsTransport() is non-null. + virtual webrtc::DtlsTransportInformation DtlsTransportInformation() = 0; virtual const WebMediaStreamTrack& Track() const = 0; virtual WebVector<WebString> StreamIds() const = 0; virtual WebVector<std::unique_ptr<WebRTCRtpSource>> GetSources() = 0;
diff --git a/third_party/blink/public/platform/web_rtc_rtp_sender.h b/third_party/blink/public/platform/web_rtc_rtp_sender.h index 1be1836a..4b17890 100644 --- a/third_party/blink/public/platform/web_rtc_rtp_sender.h +++ b/third_party/blink/public/platform/web_rtc_rtp_sender.h
@@ -9,6 +9,7 @@ #include "third_party/blink/public/platform/web_rtc_stats.h" #include "third_party/blink/public/platform/web_rtc_void_request.h" #include "third_party/blink/public/platform/web_string.h" +#include "third_party/webrtc/api/dtls_transport_interface.h" #include "third_party/webrtc/api/rtp_parameters.h" namespace blink { @@ -29,6 +30,11 @@ // same |id|. IDs are guaranteed to be unique amongst senders but they are // allowed to be reused after a sender is destroyed. virtual uintptr_t Id() const = 0; + virtual rtc::scoped_refptr<webrtc::DtlsTransportInterface> + DtlsTransport() = 0; + // Note: For convenience, DtlsTransportInformation always returns a value. + // The information is only interesting if DtlsTransport() is non-null. + virtual webrtc::DtlsTransportInformation DtlsTransportInformation() = 0; virtual WebMediaStreamTrack Track() const = 0; virtual WebVector<WebString> StreamIds() const = 0; // TODO(hbos): Replace WebRTCVoidRequest by something resolving promises based
diff --git a/third_party/blink/public/web/web_document_loader.h b/third_party/blink/public/web/web_document_loader.h index f8e4ad8b..88b836a 100644 --- a/third_party/blink/public/web/web_document_loader.h +++ b/third_party/blink/public/web/web_document_loader.h
@@ -93,10 +93,6 @@ virtual bool HasUnreachableURL() const = 0; virtual WebURL UnreachableURL() const = 0; - // Allows the embedder to append redirects to the chain as a navigation - // is starting, in case it is being transferred from another process. - virtual void AppendRedirect(const WebURL&) = 0; - // Returns all redirects that occurred (both client and server) before // at last committing the current page. This will contain one entry // for each intermediate URL, and one entry for the last URL (so if
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h index 42de1cd7..a7da4679 100644 --- a/third_party/blink/public/web/web_widget.h +++ b/third_party/blink/public/web/web_widget.h
@@ -101,6 +101,9 @@ virtual void BeginFrame(base::TimeTicks last_frame_time, bool record_main_frame_metrics) {} + // Called after UpdateAllLifecyclePhases has run in response to a BeginFrame. + virtual void DidBeginFrame() {} + // Called when main frame metrics are desired. The local frame's UKM // aggregator must be informed that collection is starting for the // frame.
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 1301cca..54df489 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -41,6 +41,7 @@ #include "services/resource_coordinator/public/mojom/coordination_unit.mojom-blink.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h" #include "third_party/blink/public/mojom/net/ip_address_space.mojom-blink.h" #include "third_party/blink/public/platform/interface_provider.h" #include "third_party/blink/public/platform/modules/insecure_input/insecure_input_service.mojom-blink.h" @@ -7500,6 +7501,13 @@ return is_secure; } +mojo::ScopedMessagePipeHandle Document::SetDocumentInterfaceBrokerForTesting( + mojo::ScopedMessagePipeHandle blink_handle) { + DCHECK(GetFrame()); + return GetFrame()->SetDocumentInterfaceBrokerForTesting( + std::move(blink_handle)); +} + void Document::DidEnforceInsecureRequestPolicy() { if (!GetFrame()) return; @@ -7597,6 +7605,20 @@ return &GetFrame()->GetInterfaceProvider(); } +mojom::blink::DocumentInterfaceBroker* Document::GetDocumentInterfaceBroker() { + if (!GetFrame()) + return nullptr; + + return &GetFrame()->GetDocumentInterfaceBroker(); +} + +void Document::BindDocumentInterfaceBroker( + mojo::ScopedMessagePipeHandle js_handle) { + if (!GetFrame()) + return; + GetFrame()->BindDocumentInterfaceBroker(std::move(js_handle)); +} + FrameOrWorkerScheduler* Document::GetScheduler() { DCHECK(IsMainThread());
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index fa6f25f..2576389 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -1320,6 +1320,11 @@ secure_context_state_ = state; } + void BindDocumentInterfaceBroker(mojo::ScopedMessagePipeHandle js_handle); + + mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting( + mojo::ScopedMessagePipeHandle blink_handle); + CanvasFontCache* GetCanvasFontCache(); // Used by unit tests so that all parsing will be main thread for @@ -1386,6 +1391,7 @@ CoreProbeSink* GetProbeSink() final; service_manager::InterfaceProvider* GetInterfaceProvider() final; + mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() final; // Set an explicit feature policy on this document in response to an HTTP // Feature-Policy header. This will be relayed to the embedder through the
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.h b/third_party/blink/renderer/core/execution_context/execution_context.h index 01728a3..bf229e57 100644 --- a/third_party/blink/renderer/core/execution_context/execution_context.h +++ b/third_party/blink/renderer/core/execution_context/execution_context.h
@@ -61,6 +61,12 @@ namespace blink { +namespace mojom { +namespace blink { +class DocumentInterfaceBroker; +} // namespace blink +} // namespace mojom + class ContentSecurityPolicy; class ContentSecurityPolicyDelegate; class CoreProbeSink; @@ -261,6 +267,10 @@ return nullptr; } + virtual mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() { + return nullptr; + } + virtual FrameOrWorkerScheduler* GetScheduler() = 0; virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner( TaskType) = 0;
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc index 038c3479..8da56d9 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -1087,6 +1087,30 @@ return document_interface_broker_.get(); } +void LocalFrameClientImpl::BindDocumentInterfaceBroker( + mojo::ScopedMessagePipeHandle js_handle) { + document_interface_broker_bindings_.AddBinding( + this, mojom::blink::DocumentInterfaceBrokerRequest(std::move(js_handle))); +} + +mojo::ScopedMessagePipeHandle +LocalFrameClientImpl::SetDocumentInterfaceBrokerForTesting( + mojo::ScopedMessagePipeHandle blink_handle) { + // Ensure all pending calls get dispatched before the implementation swap + document_interface_broker_bindings_.FlushForTesting(); + + mojom::blink::DocumentInterfaceBrokerPtr test_broker( + mojom::blink::DocumentInterfaceBrokerPtrInfo( + std::move(blink_handle), + mojom::blink::DocumentInterfaceBroker::Version_)); + + mojo::ScopedMessagePipeHandle real_handle = + document_interface_broker_.PassInterface().PassHandle(); + document_interface_broker_ = std::move(test_broker); + + return real_handle; +} + AssociatedInterfaceProvider* LocalFrameClientImpl::GetRemoteNavigationAssociatedInterfaces() { return web_frame_->Client()->GetRemoteNavigationAssociatedInterfaces(); @@ -1185,7 +1209,7 @@ const { DCHECK(web_frame_->GetFrame()->IsMainFrame()); return web_frame_->OpenerFeatureState(); -}; +} STATIC_ASSERT_ENUM(DownloadCrossOriginRedirects::kFollow, WebLocalFrameClient::CrossOriginRedirects::kFollow);
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h index 58e1a06..2943e35 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -259,8 +259,21 @@ service_manager::InterfaceProvider* GetInterfaceProvider() override; + // Binds |js_handle| to the current implementation bound to + // |document_interface_broker_| to share the same broker between C++ and + // JavaScript clients. + void BindDocumentInterfaceBroker( + mojo::ScopedMessagePipeHandle js_handle) override; + mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() override; + // Binds |document_interface_broker_| to |blink_handle|. Used in tests to set + // a custom override for DocumentInterfaceBroker methods. Returns the handle + // to the previously bound 'production' implementation, which will be used to + // forward the calls to methods that have not been overridden. + mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting( + mojo::ScopedMessagePipeHandle blink_handle) override; + AssociatedInterfaceProvider* GetRemoteNavigationAssociatedInterfaces() override; @@ -304,6 +317,18 @@ const FeaturePolicy::FeatureState& GetOpenerFeatureState() const override; private: + struct DocumentInterfaceBrokerForwarderTraits { + using Interface = mojom::blink::DocumentInterfaceBroker; + using PointerType = WeakPersistent<LocalFrameClientImpl>; + static bool IsNull(PointerType ptr) { + return !ptr || !ptr->document_interface_broker_; + } + static Interface* GetRawPointer(PointerType* ptr) { + return (*ptr)->GetDocumentInterfaceBroker(); + } + }; + friend struct DocumentInterfaceBrokerForwarderTraits; + bool IsLocalFrameClientImpl() const override { return true; } WebDevToolsAgentImpl* DevToolsAgent(); @@ -315,6 +340,19 @@ blink::UserAgentMetadata user_agent_metadata_; mojom::blink::DocumentInterfaceBrokerPtr document_interface_broker_; + + // |document_interface_broker_bindings_| basically just forwards the broker + // methods to GetDocumentInterfaceBroker() + // via DocumentInterfaceBrokerForwarderTraits. + // Used to connect JavaScript clients of DocumentInterfaceBroker with the same + // implementation that |document_interface_broker_| is bound to. + using DocumentInterfaceBrokerBinding = + mojo::Binding<mojom::blink::DocumentInterfaceBroker, + DocumentInterfaceBrokerForwarderTraits>; + mojo::BindingSetBase<mojom::blink::DocumentInterfaceBroker, + DocumentInterfaceBrokerBinding, + void> + document_interface_broker_bindings_; }; DEFINE_TYPE_CASTS(LocalFrameClientImpl,
diff --git a/third_party/blink/renderer/core/exported/web_document_loader_impl.cc b/third_party/blink/renderer/core/exported/web_document_loader_impl.cc index 074d8bc9..b8c8d9b 100644 --- a/third_party/blink/renderer/core/exported/web_document_loader_impl.cc +++ b/third_party/blink/renderer/core/exported/web_document_loader_impl.cc
@@ -91,10 +91,6 @@ return DocumentLoader::UnreachableURL(); } -void WebDocumentLoaderImpl::AppendRedirect(const WebURL& url) { - DocumentLoader::AppendRedirect(url); -} - void WebDocumentLoaderImpl::RedirectChain(WebVector<WebURL>& result) const { result.Assign(redirect_chain_); }
diff --git a/third_party/blink/renderer/core/exported/web_document_loader_impl.h b/third_party/blink/renderer/core/exported/web_document_loader_impl.h index ff9185c5..067d6af3 100644 --- a/third_party/blink/renderer/core/exported/web_document_loader_impl.h +++ b/third_party/blink/renderer/core/exported/web_document_loader_impl.h
@@ -67,7 +67,6 @@ const WebURLResponse& GetResponse() const override; bool HasUnreachableURL() const override; WebURL UnreachableURL() const override; - void AppendRedirect(const WebURL&) override; void RedirectChain(WebVector<WebURL>&) const override; bool IsClientRedirect() const override; bool ReplacesCurrentHistoryItem() const override;
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 e9544783..87d0dccc 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -4551,9 +4551,8 @@ KURL(document_loader->GetUrl())); } -TEST_F(WebFrameTest, AppendRedirects) { - const std::string first_url = "about:blank"; - const std::string second_url = "http://internal.test"; +TEST_F(WebFrameTest, RedirectChainContainsInitialUrl) { + const std::string first_url = "data:text/html,foo"; frame_test_helpers::WebViewHelper web_view_helper; web_view_helper.InitializeAndLoad(first_url); @@ -4561,13 +4560,11 @@ WebDocumentLoader* document_loader = web_view_helper.LocalMainFrame()->GetDocumentLoader(); ASSERT_TRUE(document_loader); - document_loader->AppendRedirect(ToKURL(second_url)); WebVector<WebURL> redirects; document_loader->RedirectChain(redirects); - ASSERT_EQ(2U, redirects.size()); + ASSERT_EQ(1U, redirects.size()); EXPECT_EQ(ToKURL(first_url), KURL(redirects[0])); - EXPECT_EQ(ToKURL(second_url), KURL(redirects[1])); } TEST_F(WebFrameTest, IframeRedirect) { @@ -10689,8 +10686,11 @@ void ExecuteScriptOnMainFrame(const WebScriptSource& script) { MainFrame()->ExecuteScript(script); + MainFrame()->View()->MainFrameWidget()->BeginFrame(base::TimeTicks::Now(), + false); MainFrame()->View()->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); + MainFrame()->View()->MainFrameWidget()->DidBeginFrame(); RunPendingTasks(); } @@ -10780,8 +10780,11 @@ void ExecuteScriptOnMainFrame(const WebScriptSource& script) { MainFrame()->ExecuteScript(script); + MainFrame()->View()->MainFrameWidget()->BeginFrame(base::TimeTicks::Now(), + false); MainFrame()->View()->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); + MainFrame()->View()->MainFrameWidget()->DidBeginFrame(); RunPendingTasks(); }
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 6674869..4321830 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1521,6 +1521,13 @@ PageWidgetDelegate::Animate(*AsView().page, last_frame_time); } +void WebViewImpl::DidBeginFrame() { + DCHECK(MainFrameImpl()->GetFrame()); + DocumentLifecycle::AllowThrottlingScope throttling_scope( + MainFrameImpl()->GetFrame()->GetDocument()->Lifecycle()); + PageWidgetDelegate::DidBeginFrame(*MainFrameImpl()->GetFrame()); +} + void WebViewImpl::BeginRafAlignedInput() { raf_aligned_input_start_time_ = CurrentTimeTicks(); }
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 46a12c4..0a44b85 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -432,6 +432,7 @@ void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) override; void BeginFrame(base::TimeTicks last_frame_time, bool record_main_frame_metrics) override; + void DidBeginFrame() override; void BeginRafAlignedInput() override; void EndRafAlignedInput() override; void RecordStartOfFrameMetrics() override; @@ -484,6 +485,7 @@ friend class WebView; // So WebView::Create can call our constructor friend class WebViewFrameWidget; friend class WTF::RefCounted<WebViewImpl>; + friend class SimCompositor; WebViewImpl(WebViewClient*, bool is_hidden,
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index fb56f4d..c6fbff59 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1288,12 +1288,25 @@ return *Client()->GetInterfaceProvider(); } +void LocalFrame::BindDocumentInterfaceBroker( + mojo::ScopedMessagePipeHandle js_handle) { + DCHECK(Client()); + Client()->BindDocumentInterfaceBroker(std::move(js_handle)); +} + mojom::blink::DocumentInterfaceBroker& LocalFrame::GetDocumentInterfaceBroker() { DCHECK(Client()); return *Client()->GetDocumentInterfaceBroker(); } +mojo::ScopedMessagePipeHandle LocalFrame::SetDocumentInterfaceBrokerForTesting( + mojo::ScopedMessagePipeHandle blink_handle) { + DCHECK(Client()); + return Client()->SetDocumentInterfaceBrokerForTesting( + std::move(blink_handle)); +} + AssociatedInterfaceProvider* LocalFrame::GetRemoteNavigationAssociatedInterfaces() { DCHECK(Client());
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index 0c22e2b..21ed7af 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -303,7 +303,10 @@ bool CanNavigate(const Frame&, const KURL& destination_url = KURL()); service_manager::InterfaceProvider& GetInterfaceProvider(); + void BindDocumentInterfaceBroker(mojo::ScopedMessagePipeHandle js_handle); mojom::blink::DocumentInterfaceBroker& GetDocumentInterfaceBroker(); + mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting( + mojo::ScopedMessagePipeHandle blink_handle); InterfaceRegistry* GetInterfaceRegistry() { return interface_registry_; } // Returns an AssociatedInterfaceProvider the frame can use to request
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index bf43fca..0e269f0 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -381,10 +381,26 @@ return nullptr; } + // Binds |js_handle| to the currently bound implementation of + // DocumentInterfaceBroker to share the same broker between C++ and JavaScript + // clients. + virtual void BindDocumentInterfaceBroker( + mojo::ScopedMessagePipeHandle js_handle) {} + virtual mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() { return nullptr; } + // Used in tests to set a custom override for DocumentInterfaceBroker methods. + // |blink_handle| is bound to the test implementation on the caller side. + // Returns the handle to the previously bound 'production' implementation, + // which will be used to forward the calls to methods that have not been + // overridden. + virtual mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting( + mojo::ScopedMessagePipeHandle blink_handle) { + return mojo::ScopedMessagePipeHandle(); + } + virtual AssociatedInterfaceProvider* GetRemoteNavigationAssociatedInterfaces() { return nullptr;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index f5ce434..2612a2d 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1037,6 +1037,29 @@ return frame_->GetDocument()->Lifecycle(); } +void LocalFrameView::RunPostLifecycleSteps() { + RunIntersectionObserverSteps(); + UpdateThrottlingStatusForSubtree(); +} + +void LocalFrameView::RunIntersectionObserverSteps() { +#if DCHECK_IS_ON() + bool was_dirty = NeedsLayout(); +#endif + if (ShouldThrottleRendering() || Lifecycle().LifecyclePostponed() || + !frame_->GetDocument()->IsActive()) { + return; + } + TRACE_EVENT0("blink,benchmark", + "LocalFrameView::UpdateViewportIntersectionsForSubtree"); + SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(), + LocalFrameUkmAggregator::kIntersectionObservation); + UpdateViewportIntersectionsForSubtree(); +#if DCHECK_IS_ON() + DCHECK(was_dirty || !NeedsLayout()); +#endif +} + LayoutSVGRoot* LocalFrameView::EmbeddedReplacedContent() const { auto* layout_view = this->GetLayoutView(); if (!layout_view) @@ -2187,17 +2210,6 @@ // Run the lifecycle updates. UpdateLifecyclePhasesInternal(target_state); - // Update intersection observations if needed. - if (target_state == DocumentLifecycle::kPaintClean) { - TRACE_EVENT0("blink,benchmark", - "LocalFrameView::UpdateViewportIntersectionsForSubtree"); - SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(), - LocalFrameUkmAggregator::kIntersectionObservation); - UpdateViewportIntersectionsForSubtree(); - } - - UpdateThrottlingStatusForSubtree(); - ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { for (auto& observer : frame_view.lifecycle_observers_) observer->DidFinishLifecycleUpdate();
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index 4eac4650..b4db161 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -370,6 +370,12 @@ // desired state. bool UpdateLifecycleToLayoutClean(); + // This for doing work that needs to run synchronously at the end of lifecyle + // updates, but needs to happen outside of the lifecycle code. It's OK to + // schedule another animation frame here, but the layout tree should not be + // invalidated. + void RunPostLifecycleSteps(); + void ScheduleVisualUpdateForPaintInvalidationIfNeeded(); bool InvalidateViewportConstrainedObjects(); @@ -811,6 +817,8 @@ DocumentLifecycle& Lifecycle() const; + void RunIntersectionObserverSteps(); + // Methods to do point conversion via layoutObjects, in order to take // transforms into account. IntRect ConvertToContainingEmbeddedContentView(const IntRect&) const;
diff --git a/third_party/blink/renderer/core/frame/root_frame_viewport.h b/third_party/blink/renderer/core/frame/root_frame_viewport.h index a18c1ed..6fcf6ff 100644 --- a/third_party/blink/renderer/core/frame/root_frame_viewport.h +++ b/third_party/blink/renderer/core/frame/root_frame_viewport.h
@@ -8,6 +8,7 @@ #include "base/single_thread_task_runner.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/scroll/scrollable_area.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" namespace blink {
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index 8fab72df..1b9051f 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -300,6 +300,11 @@ GetPage()->GetValidationMessageClient().LayoutOverlay(); } +void WebFrameWidgetImpl::DidBeginFrame() { + DCHECK(LocalRootImpl()->GetFrame()); + PageWidgetDelegate::DidBeginFrame(*LocalRootImpl()->GetFrame()); +} + void WebFrameWidgetImpl::BeginRafAlignedInput() { raf_aligned_input_start_time_ = CurrentTimeTicks(); }
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index 0ae71d3..8c6b4ea 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -85,6 +85,7 @@ void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final; void BeginFrame(base::TimeTicks last_frame_time, bool record_main_frame_metrics) override; + void DidBeginFrame() override; void BeginRafAlignedInput() override; void EndRafAlignedInput() override; void RecordStartOfFrameMetrics() override;
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc index a688b04b..2d35cf4 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -61,6 +61,10 @@ web_view_->BeginFrame(last_frame_time, record_main_frame_metrics); } +void WebViewFrameWidget::DidBeginFrame() { + web_view_->DidBeginFrame(); +} + void WebViewFrameWidget::BeginRafAlignedInput() { web_view_->BeginRafAlignedInput(); }
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h index f14a81cd..5ea0099 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -50,6 +50,7 @@ void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final; void BeginFrame(base::TimeTicks last_frame_time, bool record_main_frame_metrics) override; + void DidBeginFrame() override; void BeginRafAlignedInput() override; void EndRafAlignedInput() override; void RecordStartOfFrameMetrics() override;
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index fff9cac..f41de290 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -994,44 +994,47 @@ } bool HTMLCanvasElement::ShouldAccelerate(AccelerationCriteria criteria) const { - if (base::FeatureList::IsEnabled(features::kAlwaysAccelerateCanvas)) - return true; - - if (context_ && !Is2d()) - return false; - - // The following is necessary for handling the special case of canvases in the - // dev tools overlay, which run in a process that supports accelerated 2d - // canvas but in a special compositing context that does not. - if (GetLayoutBox() && !GetLayoutBox()->HasAcceleratedCompositing()) - return false; - - base::CheckedNumeric<int> checked_canvas_pixel_count = Size().Width(); - checked_canvas_pixel_count *= Size().Height(); - if (!checked_canvas_pixel_count.IsValid()) - return false; - int canvas_pixel_count = checked_canvas_pixel_count.ValueOrDie(); - - // Do not use acceleration for small canvas. - if (criteria != kIgnoreResourceLimitCriteria) { - Settings* settings = GetDocument().GetSettings(); - if (!settings || - canvas_pixel_count < settings->GetMinimumAccelerated2dCanvasSize()) { + // With this feature enabled we want to accelerate canvases whenever we can. + // This does not include when the context_provider CANNOT accelerated + // canvases. + if (!base::FeatureList::IsEnabled(features::kAlwaysAccelerateCanvas)) { + if (context_ && !Is2d()) return false; + + // The following is necessary for handling the special case of canvases in + // the dev tools overlay, which run in a process that supports accelerated + // 2d canvas but in a special compositing context that does not. + if (GetLayoutBox() && !GetLayoutBox()->HasAcceleratedCompositing()) + return false; + + base::CheckedNumeric<int> checked_canvas_pixel_count = Size().Width(); + checked_canvas_pixel_count *= Size().Height(); + if (!checked_canvas_pixel_count.IsValid()) + return false; + int canvas_pixel_count = checked_canvas_pixel_count.ValueOrDie(); + + // Do not use acceleration for small canvas. + if (criteria != kIgnoreResourceLimitCriteria) { + Settings* settings = GetDocument().GetSettings(); + if (!settings || + canvas_pixel_count < settings->GetMinimumAccelerated2dCanvasSize()) { + return false; + } + + // When GPU allocated memory runs low (due to having created too many + // accelerated canvases), the compositor starves and browser becomes + // laggy. Thus, we should stop allocating more GPU memory to new canvases + // created when the current memory usage exceeds the threshold. + if (global_gpu_memory_usage_ >= kMaxGlobalGPUMemoryUsage) + return false; + + // Allocating too many GPU resources can makes us run into the driver's + // resource limits. So we need to keep the number of texture resources + // under tight control + if (global_accelerated_context_count_ >= + kMaxGlobalAcceleratedResourceCount) + return false; } - - // When GPU allocated memory runs low (due to having created too many - // accelerated canvases), the compositor starves and browser becomes laggy. - // Thus, we should stop allocating more GPU memory to new canvases created - // when the current memory usage exceeds the threshold. - if (global_gpu_memory_usage_ >= kMaxGlobalGPUMemoryUsage) - return false; - - // Allocating too many GPU resources can makes us run into the driver's - // resource limits. So we need to keep the number of texture resources - // under tight control - if (global_accelerated_context_count_ >= kMaxGlobalAcceleratedResourceCount) - return false; } // Avoid creating |contextProvider| until we're sure we want to try use it,
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 9eb9c7c..2175d3a 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -365,12 +365,15 @@ UpdateContainerPolicy(); + KURL url_to_request = url.IsNull() ? BlankURL() : url; if (ContentFrame()) { // TODO(sclittle): Support lazily loading frame navigations. WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; if (replace_current_item) frame_load_type = WebFrameLoadType::kReplaceCurrentItem; - ContentFrame()->ScheduleNavigation(GetDocument(), url, frame_load_type, + + ContentFrame()->ScheduleNavigation(GetDocument(), url_to_request, + frame_load_type, UserGestureStatus::kNone); return true; } @@ -388,7 +391,7 @@ if (!child_frame) return false; - ResourceRequest request(url.IsNull() ? BlankURL() : url); + ResourceRequest request(url_to_request); network::mojom::ReferrerPolicy policy = ReferrerPolicyAttribute(); request.SetReferrerPolicy(policy);
diff --git a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc index 95ab1b98..a3a6006 100644 --- a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
@@ -351,7 +351,6 @@ } void InspectorEmulationAgent::PrepareRequest( - ExecutionContext* execution_context, DocumentLoader* loader, ResourceRequest& request, const FetchInitiatorInfo& initiator_info,
diff --git a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h index 0adea50e..739bf8c0 100644 --- a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h
@@ -17,7 +17,6 @@ namespace blink { class DocumentLoader; -class ExecutionContext; class ResourceRequest; class WebLocalFrameImpl; class WebViewImpl; @@ -81,8 +80,7 @@ void ApplyAcceptLanguageOverride(String* accept_lang); void ApplyUserAgentOverride(String* user_agent); void FrameStartedLoading(LocalFrame*); - void PrepareRequest(ExecutionContext*, - DocumentLoader*, + void PrepareRequest(DocumentLoader*, ResourceRequest&, const FetchInitiatorInfo&, ResourceType);
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc index 26a5180..0c59b00 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -711,9 +711,9 @@ } void InspectorNetworkAgent::DidBlockRequest( - ExecutionContext* execution_context, const ResourceRequest& request, DocumentLoader* loader, + const KURL& fetch_context_url, const FetchInitiatorInfo& initiator_info, ResourceRequestBlockedReason reason, ResourceType resource_type) { @@ -721,7 +721,7 @@ InspectorPageAgent::ResourceType type = InspectorPageAgent::ToResourceType(resource_type); - WillSendRequestInternal(execution_context, identifier, loader, request, + WillSendRequestInternal(identifier, loader, fetch_context_url, request, ResourceResponse(), initiator_info, type); String request_id = IdentifiersFactory::RequestId(loader, identifier); @@ -744,9 +744,9 @@ } void InspectorNetworkAgent::WillSendRequestInternal( - ExecutionContext* execution_context, unsigned long identifier, DocumentLoader* loader, + const KURL& fetch_context_url, const ResourceRequest& request, const ResourceResponse& redirect_response, const FetchInitiatorInfo& initiator_info, @@ -762,8 +762,8 @@ else if (request.HttpBody()) post_data = request.HttpBody()->DeepCopy(); - resources_data_->ResourceCreated(execution_context, request_id, loader_id, - request.Url(), post_data); + resources_data_->ResourceCreated(request_id, loader_id, request.Url(), + post_data); if (initiator_info.name == fetch_initiator_type_names::kXmlhttprequest) type = InspectorPageAgent::kXHRResource; else if (initiator_info.name == fetch_initiator_type_names::kFetch) @@ -800,9 +800,9 @@ request_info->setIsLinkPreload(true); String resource_type = InspectorPageAgent::ResourceTypeJson(type); - String documentURL = - loader ? UrlWithoutFragment(loader->Url()).GetString() - : UrlWithoutFragment(execution_context->Url()).GetString(); + String documentURL = loader + ? UrlWithoutFragment(loader->Url()).GetString() + : UrlWithoutFragment(fetch_context_url).GetString(); Maybe<String> maybe_frame_id; if (!frame_id.IsEmpty()) maybe_frame_id = frame_id; @@ -823,7 +823,6 @@ } void InspectorNetworkAgent::WillSendNavigationRequest( - ExecutionContext* execution_context, unsigned long identifier, DocumentLoader* loader, const KURL& url, @@ -839,14 +838,12 @@ post_data = data->PostData(); else if (http_body) post_data = http_body->DeepCopy(); - resources_data_->ResourceCreated(execution_context, request_id, loader_id, - url, post_data); + resources_data_->ResourceCreated(request_id, loader_id, url, post_data); resources_data_->SetResourceType(request_id, InspectorPageAgent::kDocumentResource); } void InspectorNetworkAgent::PrepareRequest( - ExecutionContext* execution_context, DocumentLoader* loader, ResourceRequest& request, const FetchInitiatorInfo& initiator_info, @@ -892,9 +889,9 @@ } void InspectorNetworkAgent::WillSendRequest( - ExecutionContext* execution_context, unsigned long identifier, DocumentLoader* loader, + const KURL& fetch_context_url, const ResourceRequest& request, const ResourceResponse& redirect_response, const FetchInitiatorInfo& initiator_info, @@ -906,7 +903,7 @@ InspectorPageAgent::ResourceType type = InspectorPageAgent::ToResourceType(resource_type); - WillSendRequestInternal(execution_context, identifier, loader, request, + WillSendRequestInternal(identifier, loader, fetch_context_url, request, redirect_response, initiator_info, type); } @@ -1111,18 +1108,16 @@ return loader && loader->MainResourceIdentifier() == identifier; } -void InspectorNetworkAgent::WillLoadXHR(XMLHttpRequest* xhr, - ThreadableLoaderClient* client, +void InspectorNetworkAgent::WillLoadXHR(ExecutionContext* execution_context, const AtomicString& method, const KURL& url, bool async, EncodedFormData* form_data, const HTTPHeaderMap& headers, bool include_credentials) { - DCHECK(xhr); DCHECK(!pending_request_); pending_xhr_replay_data_ = XHRReplayData::Create( - method, UrlWithoutFragment(url), async, + execution_context, method, UrlWithoutFragment(url), async, form_data ? form_data->DeepCopy() : nullptr, include_credentials); for (const auto& header : headers) pending_xhr_replay_data_->AddHeader(header.key, header.value); @@ -1431,8 +1426,8 @@ if (!xhr_replay_data || !data) return Response::Error("Given id does not correspond to XHR"); - ExecutionContext* execution_context = data->GetExecutionContext(); - if (execution_context->IsContextDestroyed()) { + ExecutionContext* execution_context = xhr_replay_data->GetExecutionContext(); + if (!execution_context || execution_context->IsContextDestroyed()) { resources_data_->SetXHRReplayData(request_id, nullptr); return Response::Error("Document is already detached"); }
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.h b/third_party/blink/renderer/core/inspector/inspector_network_agent.h index 0c316a4..eb734dc 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.h
@@ -85,29 +85,27 @@ void Restore() override; // Probes. - void DidBlockRequest(ExecutionContext*, - const ResourceRequest&, + void DidBlockRequest(const ResourceRequest&, DocumentLoader*, + const KURL& fetch_context_url, const FetchInitiatorInfo&, ResourceRequestBlockedReason, ResourceType); void DidChangeResourcePriority(DocumentLoader*, unsigned long identifier, ResourceLoadPriority); - void PrepareRequest(ExecutionContext*, - DocumentLoader*, + void PrepareRequest(DocumentLoader*, ResourceRequest&, const FetchInitiatorInfo&, ResourceType); - void WillSendRequest(ExecutionContext*, - unsigned long identifier, + void WillSendRequest(unsigned long identifier, DocumentLoader*, + const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirect_response, const FetchInitiatorInfo&, ResourceType); - void WillSendNavigationRequest(ExecutionContext*, - unsigned long identifier, + void WillSendNavigationRequest(unsigned long identifier, DocumentLoader*, const KURL&, const AtomicString& http_method, @@ -147,8 +145,7 @@ void ShouldBlockRequest(const KURL&, bool* result); void ShouldBypassServiceWorker(bool* result); - void WillLoadXHR(XMLHttpRequest*, - ThreadableLoaderClient*, + void WillLoadXHR(ExecutionContext*, const AtomicString& method, const KURL&, bool async, @@ -249,9 +246,9 @@ private: void Enable(); - void WillSendRequestInternal(ExecutionContext*, - unsigned long identifier, + void WillSendRequestInternal(unsigned long identifier, DocumentLoader*, + const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirect_response, const FetchInitiatorInfo&,
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index cac3881c..4ab01fa 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -102,9 +102,9 @@ } void InspectorTraceEvents::WillSendRequest( - ExecutionContext*, unsigned long identifier, DocumentLoader* loader, + const KURL& fetch_context_url, const ResourceRequest& request, const ResourceResponse& redirect_response, const FetchInitiatorInfo&, @@ -117,7 +117,6 @@ } void InspectorTraceEvents::WillSendNavigationRequest( - ExecutionContext*, unsigned long identifier, DocumentLoader* loader, const KURL& url,
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.h b/third_party/blink/renderer/core/inspector/inspector_trace_events.h index 0d766d2..c197b83 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.h +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.h
@@ -83,15 +83,14 @@ public: InspectorTraceEvents() = default; - void WillSendRequest(ExecutionContext*, - unsigned long identifier, + void WillSendRequest(unsigned long identifier, DocumentLoader*, + const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirect_response, const FetchInitiatorInfo&, ResourceType); - void WillSendNavigationRequest(ExecutionContext*, - unsigned long identifier, + void WillSendNavigationRequest(unsigned long identifier, DocumentLoader*, const KURL&, const AtomicString& http_method,
diff --git a/third_party/blink/renderer/core/inspector/network_resources_data.cc b/third_party/blink/renderer/core/inspector/network_resources_data.cc index 838eae7..93c79f1 100644 --- a/third_party/blink/renderer/core/inspector/network_resources_data.cc +++ b/third_party/blink/renderer/core/inspector/network_resources_data.cc
@@ -42,13 +42,15 @@ } // static -XHRReplayData* XHRReplayData::Create(const AtomicString& method, +XHRReplayData* XHRReplayData::Create(ExecutionContext* execution_context, + const AtomicString& method, const KURL& url, bool async, scoped_refptr<EncodedFormData> form_data, bool include_credentials) { - return MakeGarbageCollected<XHRReplayData>( - method, url, async, std::move(form_data), include_credentials); + return MakeGarbageCollected<XHRReplayData>(execution_context, method, url, + async, std::move(form_data), + include_credentials); } void XHRReplayData::AddHeader(const AtomicString& key, @@ -56,12 +58,14 @@ headers_.Set(key, value); } -XHRReplayData::XHRReplayData(const AtomicString& method, +XHRReplayData::XHRReplayData(ExecutionContext* execution_context, + const AtomicString& method, const KURL& url, bool async, scoped_refptr<EncodedFormData> form_data, bool include_credentials) - : method_(method), + : execution_context_(execution_context), + method_(method), url_(url), async_(async), form_data_(form_data), @@ -70,7 +74,6 @@ // ResourceData NetworkResourcesData::ResourceData::ResourceData( NetworkResourcesData* network_resources_data, - ExecutionContext* execution_context, const String& request_id, const String& loader_id, const KURL& requested_url) @@ -84,8 +87,7 @@ http_status_code_(0), raw_header_size_(0), pending_encoded_data_length_(0), - cached_resource_(nullptr), - execution_context_(execution_context) {} + cached_resource_(nullptr) {} void NetworkResourcesData::ResourceData::Trace(blink::Visitor* visitor) { visitor->Trace(network_resources_data_); @@ -93,7 +95,6 @@ visitor->template RegisterWeakMembers< NetworkResourcesData::ResourceData, &NetworkResourcesData::ResourceData::ClearWeakMembers>(this); - visitor->Trace(execution_context_); } void NetworkResourcesData::ResourceData::SetContent(const String& content, @@ -200,14 +201,13 @@ } void NetworkResourcesData::ResourceCreated( - ExecutionContext* context, const String& request_id, const String& loader_id, const KURL& requested_url, scoped_refptr<EncodedFormData> post_data) { EnsureNoDataForRequestId(request_id); ResourceData* data = MakeGarbageCollected<ResourceData>( - this, context, request_id, loader_id, requested_url); + this, request_id, loader_id, requested_url); request_id_to_resource_data_map_.Set(request_id, data); if (post_data && PrepareToAddResourceData(request_id, post_data->SizeInBytes())) {
diff --git a/third_party/blink/renderer/core/inspector/network_resources_data.h b/third_party/blink/renderer/core/inspector/network_resources_data.h index 3ae0ffe..7c6e373 100644 --- a/third_party/blink/renderer/core/inspector/network_resources_data.h +++ b/third_party/blink/renderer/core/inspector/network_resources_data.h
@@ -51,19 +51,23 @@ class XHRReplayData final : public GarbageCollectedFinalized<XHRReplayData> { public: - static XHRReplayData* Create(const AtomicString& method, + static XHRReplayData* Create(ExecutionContext*, + const AtomicString& method, const KURL&, bool async, scoped_refptr<EncodedFormData>, bool include_credentials); - XHRReplayData(const AtomicString& method, + XHRReplayData(ExecutionContext*, + const AtomicString& method, const KURL&, bool async, scoped_refptr<EncodedFormData>, bool include_credentials); void AddHeader(const AtomicString& key, const AtomicString& value); + + ExecutionContext* GetExecutionContext() const { return execution_context_; } const AtomicString& Method() const { return method_; } const KURL& Url() const { return url_; } bool Async() const { return async_; } @@ -71,9 +75,12 @@ const HTTPHeaderMap& Headers() const { return headers_; } bool IncludeCredentials() const { return include_credentials_; } - virtual void Trace(blink::Visitor*) {} + virtual void Trace(blink::Visitor* visitor) { + visitor->Trace(execution_context_); + } private: + WeakMember<ExecutionContext> execution_context_; AtomicString method_; KURL url_; bool async_; @@ -90,7 +97,6 @@ public: ResourceData(NetworkResourcesData*, - ExecutionContext*, const String& request_id, const String& loader_id, const KURL&); @@ -167,7 +173,6 @@ post_data_ = post_data; } EncodedFormData* PostData() const { return post_data_.get(); } - ExecutionContext* GetExecutionContext() const { return execution_context_; } void Trace(blink::Visitor*); private: @@ -200,7 +205,6 @@ scoped_refptr<BlobDataHandle> downloaded_file_blob_; Vector<AtomicString> certificate_; scoped_refptr<EncodedFormData> post_data_; - Member<ExecutionContext> execution_context_; }; static NetworkResourcesData* Create(size_t total_buffer_size, @@ -212,8 +216,7 @@ NetworkResourcesData(size_t total_buffer_size, size_t resource_buffer_size); ~NetworkResourcesData(); - void ResourceCreated(ExecutionContext*, - const String& request_id, + void ResourceCreated(const String& request_id, const String& loader_id, const KURL&, scoped_refptr<EncodedFormData>);
diff --git a/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc b/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc index 441e05e..179d0296 100644 --- a/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc +++ b/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
@@ -53,18 +53,20 @@ // static WorkerInspectorController* WorkerInspectorController::Create( WorkerThread* thread, + const KURL& url, scoped_refptr<InspectorTaskRunner> inspector_task_runner, std::unique_ptr<WorkerDevToolsParams> devtools_params) { WorkerThreadDebugger* debugger = WorkerThreadDebugger::From(thread->GetIsolate()); return debugger ? MakeGarbageCollected<WorkerInspectorController>( - thread, debugger, std::move(inspector_task_runner), + thread, url, debugger, std::move(inspector_task_runner), std::move(devtools_params)) : nullptr; } WorkerInspectorController::WorkerInspectorController( WorkerThread* thread, + const KURL& url, WorkerThreadDebugger* debugger, scoped_refptr<InspectorTaskRunner> inspector_task_runner, std::unique_ptr<WorkerDevToolsParams> devtools_params) @@ -77,7 +79,7 @@ if (auto* scope = DynamicTo<WorkerGlobalScope>(thread->GlobalScope())) { worker_devtools_token_ = devtools_params->devtools_worker_token; parent_devtools_token_ = scope->GetParentDevToolsToken(); - url_ = scope->Url(); + url_ = url; worker_thread_id_ = thread->GetPlatformThreadId(); } scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
diff --git a/third_party/blink/renderer/core/inspector/worker_inspector_controller.h b/third_party/blink/renderer/core/inspector/worker_inspector_controller.h index a154fe38..b9e5efc 100644 --- a/third_party/blink/renderer/core/inspector/worker_inspector_controller.h +++ b/third_party/blink/renderer/core/inspector/worker_inspector_controller.h
@@ -60,10 +60,12 @@ public: static WorkerInspectorController* Create( WorkerThread*, + const KURL&, scoped_refptr<InspectorTaskRunner>, std::unique_ptr<WorkerDevToolsParams>); WorkerInspectorController(WorkerThread*, + const KURL&, WorkerThreadDebugger*, scoped_refptr<InspectorTaskRunner>, std::unique_ptr<WorkerDevToolsParams>);
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index 39c6896..bfa6a13 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -74,7 +74,6 @@ struct SameSizeAsLayoutBlock : public LayoutBox { LayoutObjectChildList children; - std::unique_ptr<NGConstraintSpace> cached_constraint_space_; uint32_t bitfields; }; @@ -471,7 +470,6 @@ ClearLayoutOverflow(); height_available_to_children_changed_ = false; - cached_constraint_space_.reset(); NotifyDisplayLockDidLayout(); } @@ -2114,14 +2112,6 @@ return layout_block; } -const NGConstraintSpace* LayoutBlock::CachedConstraintSpace() const { - return cached_constraint_space_.get(); -} - -void LayoutBlock::SetCachedConstraintSpace(const NGConstraintSpace& space) { - cached_constraint_space_.reset(new NGConstraintSpace(space)); -} - bool LayoutBlock::RecalcNormalFlowChildLayoutOverflowIfNeeded( LayoutObject* layout_object) { if (layout_object->IsOutOfFlowPositioned())
diff --git a/third_party/blink/renderer/core/layout/layout_block.h b/third_party/blink/renderer/core/layout/layout_block.h index 5422b712..12d6d78 100644 --- a/third_party/blink/renderer/core/layout/layout_block.h +++ b/third_party/blink/renderer/core/layout/layout_block.h
@@ -33,7 +33,6 @@ struct PaintInfo; class LineLayoutBox; -class NGConstraintSpace; class WordMeasurement; typedef WTF::ListHashSet<LayoutBox*, 16> TrackedLayoutBoxListHashSet; @@ -320,9 +319,6 @@ LayoutUnit AvailableLogicalHeightForPercentageComputation() const; bool HasDefiniteLogicalHeight() const; - const NGConstraintSpace* CachedConstraintSpace() const; - void SetCachedConstraintSpace(const NGConstraintSpace& space); - protected: bool RecalcNormalFlowChildLayoutOverflowIfNeeded(LayoutObject*); void RecalcNormalFlowChildVisualOverflowIfNeeded(LayoutObject*); @@ -555,7 +551,6 @@ virtual bool UpdateLogicalWidthAndColumnWidth(); LayoutObjectChildList children_; - std::unique_ptr<NGConstraintSpace> cached_constraint_space_; unsigned has_margin_before_quirk_ : 1; // Note these quirk values can't be put
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index e9898db..39a2a07 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -2545,16 +2545,6 @@ return nullptr; } -scoped_refptr<const NGLayoutResult> -LayoutBlockFlow::CachedLayoutResultForTesting() { - return nullptr; -} - -void LayoutBlockFlow::SetCachedLayoutResult(const NGLayoutResult&, - const NGBreakToken*) {} - -void LayoutBlockFlow::ClearCachedLayoutResult() {} - bool LayoutBlockFlow::AreCachedLinesValidFor(const NGConstraintSpace&) const { return false; }
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h index dfab3b9..ddd9f6f4 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.h +++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -461,10 +461,6 @@ virtual scoped_refptr<const NGLayoutResult> CachedLayoutResult( const NGConstraintSpace&, const NGBreakToken*); - virtual scoped_refptr<const NGLayoutResult> CachedLayoutResultForTesting(); - virtual void SetCachedLayoutResult(const NGLayoutResult&, - const NGBreakToken*); - virtual void ClearCachedLayoutResult(); virtual bool AreCachedLinesValidFor(const NGConstraintSpace&) const; virtual void WillCollectInlines() {} virtual void SetPaintFragment(const NGBlockBreakToken*,
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index eb1e0dd2..f87b471 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -62,6 +62,7 @@ #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h" #include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h" +#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h" #include "third_party/blink/renderer/core/layout/shapes/shape_outside_info.h" #include "third_party/blink/renderer/core/page/autoscroll_controller.h" #include "third_party/blink/renderer/core/page/page.h" @@ -97,7 +98,7 @@ LayoutUnit intrinsic_content_logical_height; LayoutRectOutsets margin_box_outsets; LayoutUnit preferred_logical_width[2]; - void* pointers[4]; + void* pointers[5]; }; static_assert(sizeof(LayoutBox) == sizeof(SameSizeAsLayoutBox), @@ -758,6 +759,17 @@ Layer()->UpdateTransformationMatrix(); Layer()->UpdateSizeAndScrollingAfterLayout(); } + + // When we've finished layout, if we aren't a LayoutNG object, we need to + // reset our cached layout result. LayoutNG inside of + // |NGBlockNode::RunOldLayout| will call |LayoutBox::SetCachedLayoutResult| + // with a new synthesized layout result. + // + // We also want to make sure that if our entrance point into layout changes, + // e.g. an OOF-positioned object is laid out by an NG containing block, then + // Legacy, then NG again, NG won't use a stale layout result. + if (!IsLayoutNGObject()) + cached_layout_result_.reset(); } LayoutUnit LayoutBox::LogicalHeightWithVisibleOverflow() const { @@ -2294,6 +2306,20 @@ DCHECK(new_value ? !first_paint_fragment_ : !inline_box_wrapper_); } +void LayoutBox::SetCachedLayoutResult(const NGLayoutResult& layout_result, + const NGBreakToken* break_token) { + if (break_token) + return; + if (layout_result.Status() != NGLayoutResult::kSuccess) + return; + if (!layout_result.HasValidConstraintSpaceForCaching()) + return; + if (layout_result.GetConstraintSpaceForCaching().IsIntermediateLayout()) + return; + + cached_layout_result_ = &layout_result; +} + void LayoutBox::PositionLineBox(InlineBox* box) { if (IsOutOfFlowPositioned()) { // Cache the x position only if we were an INLINE type originally.
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index 4cbb7949..c994e8f 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -31,7 +31,7 @@ #include "third_party/blink/renderer/core/layout/layout_box_model_object.h" #include "third_party/blink/renderer/core/layout/min_max_size.h" #include "third_party/blink/renderer/core/layout/overflow_model.h" -#include "third_party/blink/renderer/platform/scroll/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/wtf/compiler.h" namespace blink { @@ -40,6 +40,8 @@ class LayoutBlockFlow; class LayoutMultiColumnSpannerPlaceholder; struct BoxLayoutExtraInput; +class NGBreakToken; +class NGLayoutResult; struct NGPhysicalBoxStrut; class ShapeOutsideInfo; @@ -904,6 +906,11 @@ NGPaintFragment* FirstInlineFragment() const final; void SetFirstInlineFragment(NGPaintFragment*) final; + void SetCachedLayoutResult(const NGLayoutResult&, const NGBreakToken*); + const NGLayoutResult* GetCachedLayoutResult() const { + return cached_layout_result_.get(); + } + void SetSpannerPlaceholder(LayoutMultiColumnSpannerPlaceholder&); void ClearSpannerPlaceholder(); LayoutMultiColumnSpannerPlaceholder* SpannerPlaceholder() const final { @@ -1836,6 +1843,7 @@ }; std::unique_ptr<LayoutBoxRareData> rare_data_; + scoped_refptr<const NGLayoutResult> cached_layout_result_; }; DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutBox, IsBox());
diff --git a/third_party/blink/renderer/core/layout/layout_file_upload_control.h b/third_party/blink/renderer/core/layout/layout_file_upload_control.h index 3e84094..c98f4553 100644 --- a/third_party/blink/renderer/core/layout/layout_file_upload_control.h +++ b/third_party/blink/renderer/core/layout/layout_file_upload_control.h
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/layout/layout_block_flow.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" namespace blink {
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc index 9f66a53..f790c756 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -776,29 +776,31 @@ intrinsic_size_along_main_axis_.erase(&child); } -bool LayoutFlexibleBox::CanAvoidLayoutForNGChild( - const LayoutBox& child_box) const { - if (!child_box.IsLayoutNGMixin()) +bool LayoutFlexibleBox::CanAvoidLayoutForNGChild(const LayoutBox& child) const { + if (!child.IsLayoutNGMixin()) return false; - const LayoutBlockFlow& child(ToLayoutBlockFlow(child_box)); - // If the last layout was done with a different override size, - // or different definite-ness, we need to force-relayout so - // that percentage sizes are resolved correctly. - const NGConstraintSpace* old_space = child.CachedConstraintSpace(); - if (!old_space) + + // If the last layout was done with a different override size, or different + // definite-ness, we need to force-relayout so that percentage sizes are + // resolved correctly. + const NGLayoutResult* cached_layout_result = child.GetCachedLayoutResult(); + if (!cached_layout_result) return false; - if (old_space->IsFixedSizeInline() != child.HasOverrideLogicalWidth()) + + const NGConstraintSpace& old_space = + cached_layout_result->GetConstraintSpaceForCaching(); + if (old_space.IsFixedSizeInline() != child.HasOverrideLogicalWidth()) return false; - if (old_space->IsFixedSizeBlock() != child.HasOverrideLogicalHeight()) + if (old_space.IsFixedSizeBlock() != child.HasOverrideLogicalHeight()) return false; - if (old_space->FixedSizeBlockIsDefinite() != + if (old_space.FixedSizeBlockIsDefinite() != UseOverrideLogicalHeightForPerentageResolution(child)) return false; if (child.HasOverrideLogicalWidth() && - old_space->AvailableSize().inline_size != child.OverrideLogicalWidth()) + old_space.AvailableSize().inline_size != child.OverrideLogicalWidth()) return false; if (child.HasOverrideLogicalHeight() && - old_space->AvailableSize().block_size != child.OverrideLogicalHeight()) + old_space.AvailableSize().block_size != child.OverrideLogicalHeight()) return false; return true; }
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 702635a..c483bbde 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1544,10 +1544,17 @@ } bool LayoutObject::HasNonZeroEffectiveOpacity() const { - PropertyTreeState paint_properties = EnclosingLayer() - ->GetLayoutObject() - .FirstFragment() - .LocalBorderBoxProperties(); + const FragmentData& fragment = + EnclosingLayer()->GetLayoutObject().FirstFragment(); + + // This can happen for an iframe element which is outside the viewport and has + // therefore never been painted. In that case, we do the safe thing -- report + // it as having non-zero opacity -- since this method is used by + // IntersectionObserver to detect occlusion. + if (!fragment.HasLocalBorderBoxProperties()) + return true; + + PropertyTreeState paint_properties = fragment.LocalBorderBoxProperties(); for (const auto* effect = &paint_properties.Effect().Unalias(); effect; effect = SafeUnalias(effect->Parent())) {
diff --git a/third_party/blink/renderer/core/layout/layout_table.h b/third_party/blink/renderer/core/layout/layout_table.h index f8b75d1..6b13951 100644 --- a/third_party/blink/renderer/core/layout/layout_table.h +++ b/third_party/blink/renderer/core/layout/layout_table.h
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/layout/layout_block.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink {
diff --git a/third_party/blink/renderer/core/layout/layout_view.h b/third_party/blink/renderer/core/layout/layout_view.h index ac72bdf..7a99216 100644 --- a/third_party/blink/renderer/core/layout/layout_view.h +++ b/third_party/blink/renderer/core/layout/layout_view.h
@@ -29,6 +29,7 @@ #include "third_party/blink/renderer/core/layout/layout_block_flow.h" #include "third_party/blink/renderer/core/layout/layout_state.h" #include "third_party/blink/renderer/core/scroll/scrollable_area.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/heap/handle.h" namespace blink {
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc index c3fb581..0031829c 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -68,9 +68,11 @@ // cache evolves. template <typename Base> const NGPhysicalBoxFragment* LayoutNGMixin<Base>::CurrentFragment() const { - if (cached_result_) - return ToNGPhysicalBoxFragment(cached_result_->PhysicalFragment()); - return nullptr; + const NGLayoutResult* cached_layout_result = Base::GetCachedLayoutResult(); + if (!cached_layout_result) + return nullptr; + + return ToNGPhysicalBoxFragment(cached_layout_result->PhysicalFragment()); } template <typename Base> @@ -276,37 +278,27 @@ if (Base::NeedsLayout() && !NeedsRelativePositionedLayoutOnly()) return nullptr; - if (!cached_result_) - return nullptr; - - const NGConstraintSpace& old_space = - cached_result_->GetConstraintSpaceForCaching(); - if (!new_space.MaySkipLayout(old_space)) + const NGLayoutResult* cached_layout_result = Base::GetCachedLayoutResult(); + if (!cached_layout_result) return nullptr; // If we have an orthogonal flow root descendant, we don't attempt to cache // our layout result. This is because the initial containing block size may // have changed, having a high likelihood of changing the size of the // orthogonal flow root. - if (cached_result_->HasOrthogonalFlowRoots()) + if (cached_layout_result->HasOrthogonalFlowRoots()) return nullptr; - if (!new_space.AreSizesEqual(old_space)) { - // We need to descend all the way down into BODY if we're in quirks mode, - // since it magically follows the viewport size. - if (NGBlockNode(this).IsQuirkyAndFillsViewport()) - return nullptr; + if (!MaySkipLayout(NGBlockNode(this), *cached_layout_result, new_space)) + return nullptr; - // If the available / percentage sizes have changed in a way that may affect - // layout, we cannot re-use the previous result. - if (SizeMayChange(Base::StyleRef(), new_space, old_space, *cached_result_)) - return nullptr; - } + const NGConstraintSpace& old_space = + cached_layout_result->GetConstraintSpaceForCaching(); // Check BFC block offset. Even if they don't match, there're some cases we // can still reuse the fragment. base::Optional<LayoutUnit> bfc_block_offset = - cached_result_->BfcBlockOffset(); + cached_layout_result->BfcBlockOffset(); if (new_space.BfcOffset().block_offset != old_space.BfcOffset().block_offset) { // Earlier floats may affect this box if block offset changes. @@ -336,45 +328,20 @@ // The checks above should be enough to bail if layout is incomplete, but // let's verify: - DCHECK(IsBlockLayoutComplete(old_space, *cached_result_)); - return base::AdoptRef(new NGLayoutResult(*cached_result_, bfc_block_offset)); -} - -template <typename Base> -void LayoutNGMixin<Base>::SetCachedLayoutResult( - const NGLayoutResult& layout_result, - const NGBreakToken* break_token) { - if (break_token) - return; - if (layout_result.Status() != NGLayoutResult::kSuccess) - return; - if (!layout_result.HasValidConstraintSpaceForCaching()) - return; - if (layout_result.GetConstraintSpaceForCaching().IsIntermediateLayout()) - return; - - cached_result_ = &layout_result; -} - -template <typename Base> -void LayoutNGMixin<Base>::ClearCachedLayoutResult() { - cached_result_.reset(); -} - -template <typename Base> -scoped_refptr<const NGLayoutResult> -LayoutNGMixin<Base>::CachedLayoutResultForTesting() { - return cached_result_; + DCHECK(IsBlockLayoutComplete(old_space, *cached_layout_result)); + return base::AdoptRef( + new NGLayoutResult(*cached_layout_result, bfc_block_offset)); } template <typename Base> bool LayoutNGMixin<Base>::AreCachedLinesValidFor( const NGConstraintSpace& new_space) const { - if (!cached_result_) + const NGLayoutResult* cached_layout_result = Base::GetCachedLayoutResult(); + if (!cached_layout_result) return false; const NGConstraintSpace& old_space = - cached_result_->GetConstraintSpaceForCaching(); + cached_layout_result->GetConstraintSpaceForCaching(); if (new_space.AvailableSize().inline_size != old_space.AvailableSize().inline_size) @@ -387,11 +354,11 @@ // Any floats might need to move, causing lines to wrap differently, needing // re-layout. - if (!cached_result_->ExclusionSpace().IsEmpty()) + if (!cached_layout_result->ExclusionSpace().IsEmpty()) return false; // Propagating OOF needs re-layout. - if (!cached_result_->OutOfFlowPositionedDescendants().IsEmpty()) + if (!cached_layout_result->OutOfFlowPositionedDescendants().IsEmpty()) return false; return true;
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h index 8c4b8a3..286ad73 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
@@ -65,13 +65,8 @@ const NGConstraintSpace&, const NGBreakToken*) final; - void SetCachedLayoutResult(const NGLayoutResult&, const NGBreakToken*) final; - void ClearCachedLayoutResult() final; bool AreCachedLinesValidFor(const NGConstraintSpace&) const final; - // For testing only. - scoped_refptr<const NGLayoutResult> CachedLayoutResultForTesting() final; - NGPaintFragment* PaintFragment() const final { return paint_fragment_.get(); } void SetPaintFragment(const NGBlockBreakToken*, scoped_refptr<const NGPhysicalFragment>) final; @@ -100,8 +95,6 @@ MarkingBehavior marking_behavior) final; std::unique_ptr<NGInlineNodeData> ng_inline_node_data_; - - scoped_refptr<const NGLayoutResult> cached_result_; scoped_refptr<NGPaintFragment> paint_fragment_; friend class NGBaseLayoutAlgorithmTest;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 17ead23..6f4eb40 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -238,9 +238,8 @@ const NGConstraintSpace& constraint_space, const NGBreakToken* break_token) { // Use the old layout code and synthesize a fragment. - if (!CanUseNewLayout()) { + if (!CanUseNewLayout()) return RunOldLayout(constraint_space); - } LayoutBlockFlow* block_flow = box_->IsLayoutNGMixin() ? ToLayoutBlockFlow(box_) : nullptr; @@ -895,17 +894,22 @@ DCHECK(!box_->IsLayoutBlock() || ToLayoutBlock(box_)->CreatesNewFormattingContext()); - WritingMode writing_mode = Style().GetWritingMode(); - LayoutBlock* block = box_->IsLayoutBlock() ? ToLayoutBlock(box_) : nullptr; - const NGConstraintSpace* old_space = - block ? block->CachedConstraintSpace() : nullptr; - if (!old_space || box_->NeedsLayout() || *old_space != constraint_space) { + scoped_refptr<const NGLayoutResult> layout_result = + box_->GetCachedLayoutResult(); + + // We need to force a layout on the child if the constraint space given will + // change the layout. + bool needs_force_relayout = + layout_result && !MaySkipLayout(*this, *layout_result, constraint_space); + + if (box_->NeedsLayout() || !layout_result || needs_force_relayout) { BoxLayoutExtraInput input(*box_); input.containing_block_content_inline_size = CalculateAvailableInlineSizeForLegacy(*box_, constraint_space); input.containing_block_content_block_size = CalculateAvailableBlockSizeForLegacy(*box_, constraint_space); + WritingMode writing_mode = Style().GetWritingMode(); if (LayoutObject* containing_block = box_->ContainingBlock()) { if (!IsParallelWritingMode(containing_block->StyleRef().GetWritingMode(), writing_mode)) { @@ -925,32 +929,34 @@ // Using |LayoutObject::LayoutIfNeeded| save us a little bit of overhead, // compared to |LayoutObject::ForceChildLayout|. DCHECK(!box_->IsLayoutNGMixin()); - if (box_->NeedsLayout()) + if (box_->NeedsLayout() && !needs_force_relayout) box_->LayoutIfNeeded(); else box_->ForceChildLayout(); - if (block) - block->SetCachedConstraintSpace(constraint_space); + // Synthesize a new layout result. + NGLogicalSize box_size(box_->LogicalWidth(), box_->LogicalHeight()); + // TODO(kojii): Implement use_first_line_style. + NGBoxFragmentBuilder builder(*this, box_->Style(), &constraint_space, + writing_mode, box_->StyleRef().Direction()); + builder.SetIsNewFormattingContext( + constraint_space.IsNewFormattingContext()); + builder.SetIsOldLayoutRoot(); + builder.SetInlineSize(box_size.inline_size); + builder.SetBlockSize(box_size.block_size); + NGBoxStrut borders(box_->BorderStart(), box_->BorderEnd(), + box_->BorderBefore(), box_->BorderAfter()); + builder.SetBorders(borders); + NGBoxStrut padding(box_->PaddingStart(), box_->PaddingEnd(), + box_->PaddingBefore(), box_->PaddingAfter()); + builder.SetPadding(padding); + + CopyBaselinesFromOldLayout(constraint_space, &builder); + layout_result = builder.ToBoxFragment(); + + box_->SetCachedLayoutResult(*layout_result, /* break_token */ nullptr); } - NGLogicalSize box_size(box_->LogicalWidth(), box_->LogicalHeight()); - // TODO(kojii): Implement use_first_line_style. - NGBoxFragmentBuilder builder(*this, box_->Style(), &constraint_space, - writing_mode, box_->StyleRef().Direction()); - builder.SetIsNewFormattingContext(constraint_space.IsNewFormattingContext()); - builder.SetIsOldLayoutRoot(); - builder.SetInlineSize(box_size.inline_size); - builder.SetBlockSize(box_size.block_size); - NGBoxStrut borders(box_->BorderStart(), box_->BorderEnd(), - box_->BorderBefore(), box_->BorderAfter()); - builder.SetBorders(borders); - NGBoxStrut padding(box_->PaddingStart(), box_->PaddingEnd(), - box_->PaddingBefore(), box_->PaddingAfter()); - builder.SetPadding(padding); - CopyBaselinesFromOldLayout(constraint_space, &builder); - - scoped_refptr<const NGLayoutResult> layout_result = builder.ToBoxFragment(); UpdateShapeOutsideInfoIfNeeded( *layout_result, constraint_space.PercentageResolutionInlineSize());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc index 34d0d0b6..0804510 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
@@ -6,9 +6,146 @@ #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h" #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h" +#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h" namespace blink { +namespace { + +inline bool InlineLengthMayChange(const Length& length, + LengthResolveType type, + const NGConstraintSpace& new_space, + const NGConstraintSpace& old_space) { + // Percentage inline margins will affect the size if the size is unspecified + // (auto and similar). So we need to check both available size and the + // percentage resolution size in that case. + bool is_unspecified = + (length.IsAuto() && type != LengthResolveType::kMinSize) || + length.IsFitContent() || length.IsFillAvailable(); + if (is_unspecified) { + if (new_space.AvailableSize().inline_size != + old_space.AvailableSize().inline_size) + return true; + } + if (is_unspecified || length.IsPercentOrCalc()) { + if (new_space.PercentageResolutionInlineSize() != + old_space.PercentageResolutionInlineSize()) + return true; + } + return false; +} + +inline bool BlockLengthMayChange(const Length& length, + const NGConstraintSpace& new_space, + const NGConstraintSpace& old_space) { + if (length.IsFillAvailable()) { + if (new_space.AvailableSize().block_size != + old_space.AvailableSize().block_size) + return true; + } + return false; +} + +// Return true if it's possible (but not necessarily guaranteed) that the new +// constraint space will give a different size compared to the old one, when +// computed style and child content remain unchanged. +bool SizeMayChange(const ComputedStyle& style, + const NGConstraintSpace& new_space, + const NGConstraintSpace& old_space, + const NGLayoutResult& layout_result) { + DCHECK_EQ(new_space.IsFixedSizeInline(), old_space.IsFixedSizeInline()); + DCHECK_EQ(new_space.IsFixedSizeBlock(), old_space.IsFixedSizeBlock()); + + // Go through all length properties, and, depending on length type + // (percentages, auto, etc.), check whether the constraint spaces differ in + // such a way that the resulting size *may* change. There are currently many + // possible false-positive situations here, as we don't rule out length + // changes that won't have any effect on the final size (e.g. if inline-size + // is 100px, max-inline-size is 50%, and percentage resolution inline size + // changes from 1000px to 500px). If the constraint space has "fixed" size in + // a dimension, we can skip checking properties in that dimension and just + // look for available size changes, since that's how a "fixed" constraint + // space works. + if (new_space.IsFixedSizeInline()) { + if (new_space.AvailableSize().inline_size != + old_space.AvailableSize().inline_size) + return true; + } else { + if (InlineLengthMayChange(style.LogicalWidth(), + LengthResolveType::kContentSize, new_space, + old_space) || + InlineLengthMayChange(style.LogicalMinWidth(), + LengthResolveType::kMinSize, new_space, + old_space) || + InlineLengthMayChange(style.LogicalMaxWidth(), + LengthResolveType::kMaxSize, new_space, + old_space)) + return true; + } + + if (new_space.IsFixedSizeBlock()) { + if (new_space.AvailableSize().block_size != + old_space.AvailableSize().block_size) + return true; + } else { + if (BlockLengthMayChange(style.LogicalHeight(), new_space, old_space) || + BlockLengthMayChange(style.LogicalMinHeight(), new_space, old_space) || + BlockLengthMayChange(style.LogicalMaxHeight(), new_space, old_space)) + return true; + // We only need to check if the PercentageResolutionBlockSizes match if the + // layout result has explicitly marked itself as dependent. + if (layout_result.DependsOnPercentageBlockSize()) { + if (new_space.PercentageResolutionBlockSize() != + old_space.PercentageResolutionBlockSize()) + return true; + if (new_space.ReplacedPercentageResolutionBlockSize() != + old_space.ReplacedPercentageResolutionBlockSize()) + return true; + } + } + + if (new_space.PercentageResolutionInlineSize() != + old_space.PercentageResolutionInlineSize()) { + // Percentage-based padding is resolved against the inline content box size + // of the containing block. + if (style.PaddingTop().IsPercentOrCalc() || + style.PaddingRight().IsPercentOrCalc() || + style.PaddingBottom().IsPercentOrCalc() || + style.PaddingLeft().IsPercentOrCalc()) + return true; + } + + return false; +} + +} // namespace + +bool MaySkipLayout(const NGBlockNode node, + const NGLayoutResult& cached_layout_result, + const NGConstraintSpace& new_space) { + DCHECK_EQ(cached_layout_result.Status(), NGLayoutResult::kSuccess); + DCHECK(cached_layout_result.HasValidConstraintSpaceForCaching()); + + const NGConstraintSpace& old_space = + cached_layout_result.GetConstraintSpaceForCaching(); + if (!new_space.MaySkipLayout(old_space)) + return false; + + if (!new_space.AreSizesEqual(old_space)) { + // We need to descend all the way down into BODY if we're in quirks mode, + // since it magically follows the viewport size. + if (node.IsQuirkyAndFillsViewport()) + return false; + + // If the available / percentage sizes have changed in a way that may affect + // layout, we cannot re-use the previous result. + if (SizeMayChange(node.Style(), new_space, old_space, cached_layout_result)) + return false; + } + + return true; +} + bool IsBlockLayoutComplete(const NGConstraintSpace& space, const NGLayoutResult& result) { if (result.Status() != NGLayoutResult::kSuccess)
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h index f93fc5e..1a880d9 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
@@ -5,15 +5,24 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_UTILS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_UTILS_H_ +#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h" + namespace blink { class NGConstraintSpace; class NGLayoutResult; +// Returns true if for a given |new_space|, the |node| will provide the same +// |NGLayoutResult| as |cached_layout_result|, and therefore might be able to +// skip layout. +bool MaySkipLayout(const NGBlockNode node, + const NGLayoutResult& cached_layout_result, + const NGConstraintSpace& new_space); + // Return true if layout is considered complete. In some cases we require more // than one layout pass. -// This function never considers intermediate layouts -// (space,IsIntermediateLayout()) to be complete. +// This function never considers intermediate layouts with +// |NGConstraintSpace::IsIntermediateLayout| to be complete. bool IsBlockLayoutComplete(const NGConstraintSpace&, const NGLayoutResult&); } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc index a5df118a..61fb484 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -11,7 +11,6 @@ #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h" #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h" #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h" -#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h" #include "third_party/blink/renderer/core/layout/ng/ng_space_utils.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" @@ -52,40 +51,6 @@ } } -inline bool InlineLengthMayChange(const Length& length, - LengthResolveType type, - const NGConstraintSpace& new_space, - const NGConstraintSpace& old_space) { - // Percentage inline margins will affect the size if the size is unspecified - // (auto and similar). So we need to check both available size and the - // percentage resolution size in that case. - bool is_unspecified = - (length.IsAuto() && type != LengthResolveType::kMinSize) || - length.IsFitContent() || length.IsFillAvailable(); - if (is_unspecified) { - if (new_space.AvailableSize().inline_size != - old_space.AvailableSize().inline_size) - return true; - } - if (is_unspecified || length.IsPercentOrCalc()) { - if (new_space.PercentageResolutionInlineSize() != - old_space.PercentageResolutionInlineSize()) - return true; - } - return false; -} - -inline bool BlockLengthMayChange(const Length& length, - const NGConstraintSpace& new_space, - const NGConstraintSpace& old_space) { - if (length.IsFillAvailable()) { - if (new_space.AvailableSize().block_size != - old_space.AvailableSize().block_size) - return true; - } - return false; -} - } // anonymous namespace bool NeedMinMaxSizeForContentContribution(WritingMode mode, @@ -750,75 +715,6 @@ return NGLogicalSize(*replaced_inline, *replaced_block); } -bool SizeMayChange(const ComputedStyle& style, - const NGConstraintSpace& new_space, - const NGConstraintSpace& old_space, - const NGLayoutResult& layout_result) { - DCHECK_EQ(new_space.IsFixedSizeInline(), old_space.IsFixedSizeInline()); - DCHECK_EQ(new_space.IsFixedSizeBlock(), old_space.IsFixedSizeBlock()); - - // Go through all length properties, and, depending on length type - // (percentages, auto, etc.), check whether the constraint spaces differ in - // such a way that the resulting size *may* change. There are currently many - // possible false-positive situations here, as we don't rule out length - // changes that won't have any effect on the final size (e.g. if inline-size - // is 100px, max-inline-size is 50%, and percentage resolution inline size - // changes from 1000px to 500px). If the constraint space has "fixed" size in - // a dimension, we can skip checking properties in that dimension and just - // look for available size changes, since that's how a "fixed" constraint - // space works. - if (new_space.IsFixedSizeInline()) { - if (new_space.AvailableSize().inline_size != - old_space.AvailableSize().inline_size) - return true; - } else { - if (InlineLengthMayChange(style.LogicalWidth(), - LengthResolveType::kContentSize, new_space, - old_space) || - InlineLengthMayChange(style.LogicalMinWidth(), - LengthResolveType::kMinSize, new_space, - old_space) || - InlineLengthMayChange(style.LogicalMaxWidth(), - LengthResolveType::kMaxSize, new_space, - old_space)) - return true; - } - - if (new_space.IsFixedSizeBlock()) { - if (new_space.AvailableSize().block_size != - old_space.AvailableSize().block_size) - return true; - } else { - if (BlockLengthMayChange(style.LogicalHeight(), new_space, old_space) || - BlockLengthMayChange(style.LogicalMinHeight(), new_space, old_space) || - BlockLengthMayChange(style.LogicalMaxHeight(), new_space, old_space)) - return true; - // We only need to check if the PercentageResolutionBlockSizes match if the - // layout result has explicitly marked itself as dependent. - if (layout_result.DependsOnPercentageBlockSize()) { - if (new_space.PercentageResolutionBlockSize() != - old_space.PercentageResolutionBlockSize()) - return true; - if (new_space.ReplacedPercentageResolutionBlockSize() != - old_space.ReplacedPercentageResolutionBlockSize()) - return true; - } - } - - if (new_space.PercentageResolutionInlineSize() != - old_space.PercentageResolutionInlineSize()) { - // Percentage-based padding is resolved against the inline content box size - // of the containing block. - if (style.PaddingTop().IsPercentOrCalc() || - style.PaddingRight().IsPercentOrCalc() || - style.PaddingBottom().IsPercentOrCalc() || - style.PaddingLeft().IsPercentOrCalc()) - return true; - } - - return false; -} - int ResolveUsedColumnCount(int computed_count, LayoutUnit computed_size, LayoutUnit used_gap,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h index 5d5b7be..4e43161 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h +++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
@@ -24,7 +24,6 @@ class NGConstraintSpace; class NGBlockNode; class NGLayoutInputNode; -class NGLayoutResult; // LengthResolvePhase indicates what type of layout pass we are currently in. // This changes how lengths are resolved. kIntrinsic must be used during the @@ -159,14 +158,6 @@ const NGConstraintSpace&, const base::Optional<MinMaxSize>&); -// Return true if it's possible (but not necessarily guaranteed) that the new -// constraint space will give a different size compared to the old one, when -// computed style and child content remain unchanged. -bool SizeMayChange(const ComputedStyle&, - const NGConstraintSpace& new_space, - const NGConstraintSpace& old_space, - const NGLayoutResult& layout_result); - // Based on available inline size, CSS computed column-width, CSS computed // column-count and CSS used column-gap, return CSS used column-count. CORE_EXPORT int ResolveUsedColumnCount(int computed_count,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc index ee842b08..b24174f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc
@@ -59,7 +59,7 @@ Element* rel = GetDocument().getElementById("rel"); LayoutBlockFlow* block_flow = ToLayoutBlockFlow(rel->GetLayoutObject()); scoped_refptr<const NGLayoutResult> result = - block_flow->CachedLayoutResultForTesting(); + block_flow->GetCachedLayoutResult(); EXPECT_TRUE(result); EXPECT_EQ(result->OutOfFlowPositionedDescendants().size(), (size_t)2);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h index 9eaf65e..cd599b5 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -9,7 +9,7 @@ #include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h" -#include "third_party/blink/renderer/platform/scroll/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" namespace blink {
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index d2defcc..b14d85c 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -162,6 +162,7 @@ unreachable_url_ = params_->unreachable_url; previews_state_ = params_->previews_state; + // See WebNavigationParams for special case explanations. if (!params_->is_static_data && url_.IsAboutSrcdocURL()) { loading_srcdoc_ = true; // TODO(dgozman): instead of reaching to the owner here, we could instead: @@ -184,6 +185,21 @@ WebNavigationParams::FillStaticResponse( params_.get(), "text/html", "UTF-8", base::make_span(encoded_srcdoc.data(), encoded_srcdoc.length())); + } else if (!params_->is_static_data && fetcher_->Archive()) { + // If we have an archive loaded in some ancestor frame, we should + // retrieve document content from that archive. This is different from + // loading an archive into this frame, which will be handled separately + // once we load the body and parse it as an archive. + params_->body_loader.reset(); + ArchiveResource* archive_resource = + fetcher_->Archive()->SubresourceForURL(url_); + if (archive_resource) { + SharedBuffer* archive_data = archive_resource->Data(); + WebNavigationParams::FillStaticResponse( + params_.get(), archive_resource->MimeType(), + archive_resource->TextEncoding(), + base::make_span(archive_data->Data(), archive_data->size())); + } } WebNavigationTimings& timings = params_->navigation_timings; @@ -218,11 +234,36 @@ // The document URL needs to be added to the head of the list as that is // where the redirects originated. if (is_client_redirect_) - AppendRedirect(frame_->GetDocument()->Url()); + redirect_chain_.push_back(frame_->GetDocument()->Url()); if (!params_->origin_to_commit.IsNull()) origin_to_commit_ = params_->origin_to_commit.Get()->IsolatedCopy(); + loading_url_as_empty_document_ = + !params_->is_static_data && WillLoadUrlAsEmpty(url_); + + if (!loading_url_as_empty_document_) { + content_security_policy_ = + CreateCSP(params_->response.ToResourceResponse(), origin_policy_); + if (!content_security_policy_) { + // Loading the document was blocked by the CSP check. Pretend that + // this was an empty document instead and don't reuse the + // original URL (https://crbug.com/622385). + // TODO(mkwst): Remove this once XFO moves to the browser. + // https://crbug.com/555418. + was_blocked_after_csp_ = true; + KURL blocked_url = SecurityOrigin::UrlWithUniqueOpaqueOrigin(); + original_url_ = blocked_url; + url_ = blocked_url; + params_->url = blocked_url; + WebNavigationParams::FillStaticResponse(params_.get(), "text/html", + "UTF-8", ""); + } + } + + if (!GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument()) + redirect_chain_.push_back(url_); + probe::lifecycleEvent(frame_, this, "init", CurrentTimeTicksInSeconds()); } @@ -368,8 +409,8 @@ } redirect_chain_.clear(); if (is_client_redirect_) - AppendRedirect(old_url); - AppendRedirect(new_url); + redirect_chain_.push_back(old_url); + redirect_chain_.push_back(new_url); SetHistoryItemStateForCommit( history_item_.Get(), type, @@ -620,7 +661,7 @@ CHECK(SecurityOrigin::Create(current_request_url)->CanDisplay(url_)); DCHECK(!GetTiming().FetchStart().is_null()); - AppendRedirect(url_); + redirect_chain_.push_back(url_); GetTiming().AddRedirect(current_request_url, url_); // If a redirection happens during a back/forward navigation, don't restore @@ -683,64 +724,35 @@ return true; } -void DocumentLoader::CancelLoadAfterCSPDenied( - const ResourceResponse& response) { - was_blocked_after_csp_ = true; - - // Pretend that this was an empty HTTP 200 response. Don't reuse the original - // URL for the empty page (https://crbug.com/622385). - // - // TODO(mkwst): Remove this once XFO moves to the browser. - // https://crbug.com/555418. - content_security_policy_.Clear(); - KURL blocked_url = SecurityOrigin::UrlWithUniqueOpaqueOrigin(); - original_url_ = blocked_url; - url_ = blocked_url; - redirect_chain_.pop_back(); - AppendRedirect(blocked_url); - response_ = ResourceResponse(blocked_url); - response_.SetMimeType("text/html"); - FinishedLoading(CurrentTimeTicks()); -} - -bool DocumentLoader::HandleResponse(const ResourceResponse& response) { - DCHECK(frame_); - application_cache_host_->DidReceiveResponseForMainResource(response); - - content_security_policy_ = ContentSecurityPolicy::Create(); - content_security_policy_->SetOverrideURLForSelf(response.CurrentRequestUrl()); - - AtomicString mixed_content_header = response.HttpHeaderField("mixed-content"); - if (EqualIgnoringASCIICase(mixed_content_header, "noupgrade")) { - frame_->GetDocument()->SetMixedAutoupgradeOptOut(true); - } +ContentSecurityPolicy* DocumentLoader::CreateCSP( + const ResourceResponse& response, + const String& origin_policy_string) { + ContentSecurityPolicy* csp = ContentSecurityPolicy::Create(); + csp->SetOverrideURLForSelf(response.CurrentRequestUrl()); if (!frame_->GetSettings()->BypassCSP()) { - content_security_policy_->DidReceiveHeaders( - ContentSecurityPolicyResponseHeaders(response)); + csp->DidReceiveHeaders(ContentSecurityPolicyResponseHeaders(response)); // Handle OriginPolicy. We can skip the entire block if the OP policies have // already been passed down. - if (!content_security_policy_->HasPolicyFromSource( + if (!csp->HasPolicyFromSource( kContentSecurityPolicyHeaderSourceOriginPolicy)) { - std::unique_ptr<OriginPolicy> origin_policy = - OriginPolicy::From(StringUTF8Adaptor(origin_policy_).AsStringPiece()); + std::unique_ptr<OriginPolicy> origin_policy = OriginPolicy::From( + StringUTF8Adaptor(origin_policy_string).AsStringPiece()); if (origin_policy) { - for (auto csp : origin_policy->GetContentSecurityPolicies()) { - content_security_policy_->DidReceiveHeader( - WTF::String::FromUTF8(csp.policy.data(), csp.policy.length()), - csp.report_only ? kContentSecurityPolicyHeaderTypeReport - : kContentSecurityPolicyHeaderTypeEnforce, - kContentSecurityPolicyHeaderSourceOriginPolicy); + for (auto policy : origin_policy->GetContentSecurityPolicies()) { + csp->DidReceiveHeader(WTF::String::FromUTF8(policy.policy.data(), + policy.policy.length()), + policy.report_only + ? kContentSecurityPolicyHeaderTypeReport + : kContentSecurityPolicyHeaderTypeEnforce, + kContentSecurityPolicyHeaderSourceOriginPolicy); } } } } - if (!content_security_policy_->AllowAncestors(frame_, - response.CurrentRequestUrl())) { - CancelLoadAfterCSPDenied(response); - return false; - } + if (!csp->AllowAncestors(frame_, response.CurrentRequestUrl())) + return nullptr; if (!frame_->GetSettings()->BypassCSP() && !GetFrameLoader().RequiredCSP().IsEmpty()) { @@ -748,17 +760,16 @@ frame_->Tree().Parent()->GetSecurityContext()->GetSecurityOrigin(); if (ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy( response, parent_security_origin)) { - content_security_policy_->AddPolicyFromHeaderValue( - GetFrameLoader().RequiredCSP(), - kContentSecurityPolicyHeaderTypeEnforce, - kContentSecurityPolicyHeaderSourceHTTP); + csp->AddPolicyFromHeaderValue(GetFrameLoader().RequiredCSP(), + kContentSecurityPolicyHeaderTypeEnforce, + kContentSecurityPolicyHeaderSourceHTTP); } else { ContentSecurityPolicy* required_csp = ContentSecurityPolicy::Create(); required_csp->AddPolicyFromHeaderValue( GetFrameLoader().RequiredCSP(), kContentSecurityPolicyHeaderTypeEnforce, kContentSecurityPolicyHeaderSourceHTTP); - if (!required_csp->Subsumes(*content_security_policy_)) { + if (!required_csp->Subsumes(*csp)) { String message = "Refused to display '" + response.CurrentRequestUrl().ElidedString() + "' because it has not opted-into the following policy " @@ -768,11 +779,21 @@ kSecurityMessageSource, kErrorMessageLevel, message, response.CurrentRequestUrl(), this, MainResourceIdentifier()); frame_->GetDocument()->AddConsoleMessage(console_message); - CancelLoadAfterCSPDenied(response); - return false; + return nullptr; } } } + return csp; +} + +bool DocumentLoader::HandleResponse(const ResourceResponse& response) { + DCHECK(frame_); + application_cache_host_->DidReceiveResponseForMainResource(response); + + AtomicString mixed_content_header = response.HttpHeaderField("mixed-content"); + if (EqualIgnoringASCIICase(mixed_content_header, "noupgrade")) { + frame_->GetDocument()->SetMixedAutoupgradeOptOut(true); + } // Pre-commit state, count usage the use counter associated with "this" // (provisional document loader) instead of frame_'s document loader. @@ -849,7 +870,7 @@ InstallNewDocument( Url(), initiator_origin, owner_document, - frame_->ShouldReuseDefaultView(Url(), GetContentSecurityPolicy()) + frame_->ShouldReuseDefaultView(Url(), content_security_policy_.Get()) ? WebGlobalObjectReusePolicy::kUseExisting : WebGlobalObjectReusePolicy::kCreateNew, mime_type, encoding, InstallNewDocumentReason::kNavigation, @@ -927,10 +948,6 @@ data_buffer_->Clear(); } -void DocumentLoader::AppendRedirect(const KURL& url) { - redirect_chain_.push_back(url); -} - void DocumentLoader::StopLoading() { fetcher_->StopFetching(); body_loader_.reset(); @@ -1020,31 +1037,13 @@ DCHECK(params_); state_ = kProvisional; - if (!params_->is_static_data && WillLoadUrlAsEmpty(url_)) { + if (loading_url_as_empty_document_) { LoadEmpty(); return; } - // See WebNavigationParams for special case explanations. - if (params_->is_static_data) { + if (params_->is_static_data) has_substitute_data_ = true; - } else if (fetcher_->Archive()) { - // If we have an archive loaded in some ancestor frame, we should - // retrieve document content from that archive. This is different from - // loading an archive into this frame, which will be handled separately - // once we load the body and parse it as an archive. - params_->body_loader.reset(); - ArchiveResource* archive_resource = - fetcher_->Archive()->SubresourceForURL(url_); - if (archive_resource) { - SharedBuffer* archive_data = archive_resource->Data(); - WebNavigationParams::FillStaticResponse( - params_.get(), archive_resource->MimeType(), - archive_resource->TextEncoding(), - base::make_span(archive_data->Data(), archive_data->size())); - } - } - body_loader_ = std::move(params_->body_loader); if (!body_loader_) { // TODO(dgozman): we should try to get rid of this case. @@ -1088,7 +1087,7 @@ GetFrameLoader().Progress().WillStartLoading(main_resource_identifier_, ResourceLoadPriority::kVeryHigh); - probe::willSendNavigationRequest(GetFrame()->GetDocument(), + probe::willSendNavigationRequest(probe::ToCoreProbeSink(GetFrame()), main_resource_identifier_, this, url_, http_method_, http_body_.get()); @@ -1109,7 +1108,7 @@ http_content_type_ = g_null_atom; // TODO(dgozman): check whether clearing origin policy is intended behavior. origin_policy_ = String(); - probe::willSendNavigationRequest(GetFrame()->GetDocument(), + probe::willSendNavigationRequest(probe::ToCoreProbeSink(GetFrame()), main_resource_identifier_, this, url_, http_method_, http_body_.get()); ResourceResponse redirect_response =
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index 8960d67..1aab175 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -187,8 +187,6 @@ return application_cache_host_.Get(); } - void AppendRedirect(const KURL&); - ClientHintsPreferences& GetClientHintsPreferences() { return client_hints_preferences_; } @@ -291,6 +289,8 @@ void CommitData(const char* bytes, size_t length); + ContentSecurityPolicy* CreateCSP(const ResourceResponse&, + const String& origin_policy_string); void StartLoadingInternal(); void FinishedLoading(TimeTicks finish_time); void CancelLoadAfterCSPDenied(const ResourceResponse&); @@ -429,6 +429,7 @@ bool listing_ftp_directory_ = false; bool loading_mhtml_archive_ = false; bool loading_srcdoc_ = false; + bool loading_url_as_empty_document_ = false; unsigned long main_resource_identifier_ = 0; scoped_refptr<ResourceTimingInfo> navigation_timing_info_; bool report_timing_info_to_parent_ = false;
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc index 00d219e..694085f 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -429,8 +429,8 @@ WebScopedVirtualTimePauser::VirtualTaskDuration::kNonInstant); } - probe::prepareRequest(GetFrame()->GetDocument(), MasterDocumentLoader(), - request, initiator_info, resource_type); + probe::prepareRequest(Probe(), MasterDocumentLoader(), request, + initiator_info, resource_type); // ServiceWorker hook ups. if (MasterDocumentLoader()->GetServiceWorkerNetworkProvider()) { @@ -462,9 +462,9 @@ GetFrame()->Loader().Progress().WillStartLoading(identifier, request.Priority()); } - probe::willSendRequest(GetFrame()->GetDocument(), identifier, - MasterDocumentLoader(), request, redirect_response, - initiator_info, resource_type); + probe::willSendRequest(Probe(), identifier, MasterDocumentLoader(), Url(), + request, redirect_response, initiator_info, + resource_type); if (IdlenessDetector* idleness_detector = GetFrame()->GetIdlenessDetector()) idleness_detector->OnWillSendRequest(MasterDocumentLoader()->Fetcher()); if (frame_or_imported_document_->GetDocument()) { @@ -664,8 +664,7 @@ } } - if (resource->IsLoadEventBlockingResourceType()) - frame_or_imported_document_->GetDocument()->CheckCompleted(); + frame_or_imported_document_->GetDocument()->CheckCompleted(); } void FrameFetchContext::DidObserveLoadingBehavior( @@ -957,9 +956,9 @@ ResourceType resource_type) const { if (GetResourceFetcherProperties().IsDetached()) return; - probe::didBlockRequest(GetFrame()->GetDocument(), resource_request, - MasterDocumentLoader(), fetch_initiator_info, - blocked_reason, resource_type); + probe::didBlockRequest(Probe(), resource_request, MasterDocumentLoader(), + Url(), fetch_initiator_info, blocked_reason, + resource_type); } bool FrameFetchContext::ShouldBypassMainWorldCSP() const {
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 3c083f9..1d8f9e8 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -1019,8 +1019,6 @@ provisional_document_loader_ = Client()->CreateDocumentLoader( frame_, navigation_type, std::move(navigation_params), std::move(extra_data)); - provisional_document_loader_->AppendRedirect( - provisional_document_loader_->Url()); if (history_item) provisional_document_loader_->SetItemForHistoryNavigation(history_item); @@ -1101,8 +1099,6 @@ provisional_document_loader_ = Client()->CreateDocumentLoader( frame_, info.navigation_type, std::move(navigation_params), std::move(extra_data)); - provisional_document_loader_->AppendRedirect( - provisional_document_loader_->Url()); frame_->GetFrameScheduler()->DidStartProvisionalLoad(frame_->IsMainFrame()); probe::didStartProvisionalLoad(frame_); virtual_time_pauser_.PauseVirtualTime();
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc index e286ce62..2a508a0 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -79,6 +79,8 @@ } // Step 13.3. "Set worker global scope's url to response's url." [spec text] + global_scope_->InitializeURL(response_url); + // Step 13.4. "Set worker global scope's HTTPS state to response's HTTPS // state." [spec text]
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc index a686f1c..aabef2993 100644 --- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -20,7 +20,9 @@ #include "third_party/blink/renderer/core/workers/worker_content_settings_client.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h" #include "third_party/blink/renderer/platform/network/network_state_notifier.h" #include "third_party/blink/renderer/platform/network/network_utils.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -93,7 +95,7 @@ const FetchInitiatorInfo& fetch_initiator_info, ResourceRequestBlockedReason blocked_reason, ResourceType resource_type) const { - probe::didBlockRequest(global_scope_, resource_request, nullptr, + probe::didBlockRequest(Probe(), resource_request, nullptr, Url(), fetch_initiator_info, blocked_reason, resource_type); } @@ -164,7 +166,9 @@ } const KURL& WorkerFetchContext::Url() const { - return global_scope_->Url(); + return GetResourceFetcherProperties() + .GetFetchClientSettingsObject() + .GlobalObjectUrl(); } const SecurityOrigin* WorkerFetchContext::GetParentSecurityOrigin() const { @@ -198,7 +202,7 @@ WrappedResourceRequest webreq(request); web_context_->WillSendRequest(webreq); - probe::prepareRequest(global_scope_, nullptr, request, initiator_info, + probe::prepareRequest(Probe(), nullptr, request, initiator_info, resource_type); } @@ -219,7 +223,7 @@ const ResourceResponse& redirect_response, ResourceType resource_type, const FetchInitiatorInfo& initiator_info) { - probe::willSendRequest(global_scope_, identifier, nullptr, request, + probe::willSendRequest(Probe(), identifier, nullptr, Url(), request, redirect_response, initiator_info, resource_type); }
diff --git a/third_party/blink/renderer/core/mojo/mojo.cc b/third_party/blink/renderer/core/mojo/mojo.cc index 2cb32825..d57a82e 100644 --- a/third_party/blink/renderer/core/mojo/mojo.cc +++ b/third_party/blink/renderer/core/mojo/mojo.cc
@@ -5,9 +5,11 @@ #include "third_party/blink/renderer/core/mojo/mojo.h" #include <string> +#include <utility> #include "mojo/public/cpp/system/message_pipe.h" #include "services/service_manager/public/cpp/interface_provider.h" +#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h" #include "third_party/blink/public/platform/interface_provider.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/core/dom/document.h" @@ -114,4 +116,31 @@ } } +// static +MojoHandle* Mojo::getDocumentInterfaceBrokerHandle(ScriptState* script_state) { + ExecutionContext* execution_context = ExecutionContext::From(script_state); + DCHECK(execution_context); + Document* document = static_cast<Document*>(execution_context); + DCHECK(document); + + mojo::MessagePipe pipe; + document->BindDocumentInterfaceBroker(std::move(pipe.handle0)); + return MojoHandle::Create(mojo::ScopedHandle::From(std::move(pipe.handle1))); +} + +// static +MojoHandle* Mojo::replaceDocumentInterfaceBrokerForTesting( + ScriptState* script_state, + MojoHandle* test_broker_handle) { + ExecutionContext* execution_context = ExecutionContext::From(script_state); + DCHECK(execution_context); + Document* document = static_cast<Document*>(execution_context); + DCHECK(document); + + return MojoHandle::Create( + mojo::ScopedHandle::From(document->SetDocumentInterfaceBrokerForTesting( + mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle( + test_broker_handle->TakeHandle().release().value()))))); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/mojo/mojo.h b/third_party/blink/renderer/core/mojo/mojo.h index a81831c..dc38c5a 100644 --- a/third_party/blink/renderer/core/mojo/mojo.h +++ b/third_party/blink/renderer/core/mojo/mojo.h
@@ -55,6 +55,9 @@ const String& interface_name, MojoHandle*, const String& scope); + static MojoHandle* getDocumentInterfaceBrokerHandle(ScriptState*); + static MojoHandle* replaceDocumentInterfaceBrokerForTesting(ScriptState*, + MojoHandle*); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/mojo/mojo.idl b/third_party/blink/renderer/core/mojo/mojo.idl index 294f0b8..162c2fe 100644 --- a/third_party/blink/renderer/core/mojo/mojo.idl +++ b/third_party/blink/renderer/core/mojo/mojo.idl
@@ -47,4 +47,6 @@ static MojoCreateSharedBufferResult createSharedBuffer(unsigned long numBytes); [CallWith=ScriptState] static void bindInterface(DOMString interfaceName, MojoHandle request_handle, optional MojoScope scope = "context"); + [CallWith=ScriptState] static MojoHandle getDocumentInterfaceBrokerHandle(); + [CallWith=ScriptState] static MojoHandle replaceDocumentInterfaceBrokerForTesting(MojoHandle test_broker_handle); };
diff --git a/third_party/blink/renderer/core/page/page_widget_delegate.cc b/third_party/blink/renderer/core/page/page_widget_delegate.cc index 50d836f5..4d98a13c 100644 --- a/third_party/blink/renderer/core/page/page_widget_delegate.cc +++ b/third_party/blink/renderer/core/page/page_widget_delegate.cc
@@ -74,6 +74,11 @@ } } +void PageWidgetDelegate::DidBeginFrame(LocalFrame& root) { + if (LocalFrameView* frame_view = root.View()) + frame_view->RunPostLifecycleSteps(); +} + void PageWidgetDelegate::PaintContent(cc::PaintCanvas* canvas, const WebRect& rect, LocalFrame& root) {
diff --git a/third_party/blink/renderer/core/page/page_widget_delegate.h b/third_party/blink/renderer/core/page/page_widget_delegate.h index 926e97e..774b64a 100644 --- a/third_party/blink/renderer/core/page/page_widget_delegate.h +++ b/third_party/blink/renderer/core/page/page_widget_delegate.h
@@ -34,6 +34,7 @@ #include "third_party/blink/public/platform/web_coalesced_input_event.h" #include "third_party/blink/public/web/web_widget.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace cc { class PaintCanvas; @@ -73,6 +74,8 @@ // Common implementation of WebViewImpl and WebPagePopupImpl. class CORE_EXPORT PageWidgetDelegate { + STATIC_ONLY(PageWidgetDelegate); + public: static void Animate(Page&, base::TimeTicks monotonic_frame_begin_time); @@ -85,6 +88,9 @@ WebWidget::LifecycleUpdate requested_update, WebWidget::LifecycleUpdateReason reason); + // See comment of WebWidget::DidBeginFrame + static void DidBeginFrame(LocalFrame& root); + // See documents of methods with the same names in FrameView class. static void PaintContent(cc::PaintCanvas*, const WebRect&, LocalFrame& root); // See FIXME in the function body about nullptr |root|. @@ -92,9 +98,6 @@ PageWidgetEventHandler&, const WebCoalescedInputEvent& coalesced_event, LocalFrame* root); - - private: - PageWidgetDelegate() {} }; } // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h index 8d77719..ca37e5c2 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h
@@ -7,6 +7,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" namespace cc { @@ -20,6 +21,8 @@ // TODO(kenrb): This class could be temporary depending on how // https://crbug.com/680606 is resolved. class CORE_EXPORT ScrollingCoordinatorContext final { + USING_FAST_MALLOC(ScrollingCoordinatorContext); + public: ScrollingCoordinatorContext() {} virtual ~ScrollingCoordinatorContext() {}
diff --git a/third_party/blink/renderer/core/page/slot_scoped_traversal.h b/third_party/blink/renderer/core/page/slot_scoped_traversal.h index 88c2bfc..9b8728b 100644 --- a/third_party/blink/renderer/core/page/slot_scoped_traversal.h +++ b/third_party/blink/renderer/core/page/slot_scoped_traversal.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SLOT_SCOPED_TRAVERSAL_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink { @@ -13,6 +14,8 @@ class HTMLSlotElement; class CORE_EXPORT SlotScopedTraversal { + STATIC_ONLY(SlotScopedTraversal); + public: static HTMLSlotElement* FindScopeOwnerSlot(const Element&); static Element* NearestInclusiveAncestorAssignedToSlot(const Element&);
diff --git a/third_party/blink/renderer/core/paint/clip_rects_cache.h b/third_party/blink/renderer/core/paint/clip_rects_cache.h index 65f97d3..833c66d2 100644 --- a/third_party/blink/renderer/core/paint/clip_rects_cache.h +++ b/third_party/blink/renderer/core/paint/clip_rects_cache.h
@@ -8,7 +8,7 @@ #include "third_party/blink/renderer/core/paint/clip_rects.h" #if DCHECK_IS_ON() -#include "third_party/blink/renderer/platform/scroll/scroll_types.h" // For OverlayScrollbarClipBehavior. +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" // For OverlayScrollbarClipBehavior. #endif namespace blink {
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 0e82d5a..2b90f50 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -60,6 +60,7 @@ #include "third_party/blink/renderer/core/paint/paint_result.h" #include "third_party/blink/renderer/platform/graphics/compositing_reasons.h" #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h" #include "third_party/blink/renderer/platform/wtf/allocator.h"
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper.h b/third_party/blink/renderer/core/paint/paint_layer_clipper.h index e566327..86f9cc8 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_clipper.h +++ b/third_party/blink/renderer/core/paint/paint_layer_clipper.h
@@ -48,7 +48,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/paint/clip_rects_cache.h" #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" -#include "third_party/blink/renderer/platform/scroll/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" namespace blink {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h index 02651d0..de833994 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -51,9 +51,9 @@ #include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h" #include "third_party/blink/renderer/core/paint/paint_layer_fragment.h" #include "third_party/blink/renderer/core/scroll/scrollable_area.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/persistent.h" -#include "third_party/blink/renderer/platform/scroll/scroll_types.h" namespace blink {
diff --git a/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc index e1dc05f..f69506cf 100644 --- a/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc
@@ -24,19 +24,19 @@ static constexpr TimeDelta kTimerDelay = TimeDelta::FromSeconds(1); constexpr size_t kTextNodeNumberLimit = 5000; -static bool LargeTextOnTop(const std::unique_ptr<TextRecord>& a, - const std::unique_ptr<TextRecord>& b) { - return a->first_size < b->first_size; +static bool LargeTextFirst(const base::WeakPtr<TextRecord>& a, + const base::WeakPtr<TextRecord>& b) { + return a->first_size > b->first_size; } -static bool LateTextOnTop(const std::unique_ptr<TextRecord>& a, - const std::unique_ptr<TextRecord>& b) { - return a->first_paint_time < b->first_paint_time; +static bool LateTextFirst(const base::WeakPtr<TextRecord>& a, + const base::WeakPtr<TextRecord>& b) { + return a->first_paint_time > b->first_paint_time; } TextPaintTimingDetector::TextPaintTimingDetector(LocalFrameView* frame_view) - : largest_text_heap_(&LargeTextOnTop), - latest_text_heap_(&LateTextOnTop), + : size_ordered_set_(&LargeTextFirst), + time_ordered_set_(&LateTextFirst), timer_(frame_view->GetFrame().GetTaskRunner(TaskType::kInternalDefault), this, &TextPaintTimingDetector::TimerFired), @@ -127,18 +127,10 @@ void TextPaintTimingDetector::NotifyNodeRemoved(DOMNodeId node_id) { if (!is_recording_) return; - for (TextRecord& record : texts_to_record_swap_time_) { - if (record.node_id == node_id) - record.node_id = kInvalidDOMNodeId; - } - if (recorded_text_node_ids_.find(node_id) == recorded_text_node_ids_.end()) + if (id_record_map_.find(node_id) == id_record_map_.end()) return; - // We assume that removed nodes' id would not be recycled, and it's expensive - // to remove records from largest_text_heap_ and latest_text_heap_, so we - // intentionally keep the records of removed nodes in largest_text_heap_ and - // latest_text_heap_. - recorded_text_node_ids_.erase(node_id); - if (recorded_text_node_ids_.size() == 0) { + detached_ids_.insert(node_id); + if (id_record_map_.size() - detached_ids_.size() == 0) { const bool largest_text_paint_invalidated = largest_text_paint_ != base::TimeTicks(); const bool last_text_paint_invalidated = @@ -174,15 +166,16 @@ // consumed in a callback earlier than this one. That violates the assumption // that only one or zero callback will be called after one OnPaintFinished. DCHECK_GT(texts_to_record_swap_time_.size(), 0UL); - for (TextRecord& record : texts_to_record_swap_time_) { - if (record.node_id == kInvalidDOMNodeId) - continue; - record.first_paint_time = timestamp; - recorded_text_node_ids_.insert(record.node_id); - largest_text_heap_.push(std::make_unique<TextRecord>(record)); - latest_text_heap_.push(std::make_unique<TextRecord>(record)); + while (texts_to_record_swap_time_.size() > 0) { + DOMNodeId node_id = texts_to_record_swap_time_.front(); + DCHECK(id_record_map_.Contains(node_id)); + TextRecord* record = id_record_map_.at(node_id); + record->first_paint_time = timestamp; + size_ordered_set_.insert(record->AsWeakPtr()); + time_ordered_set_.insert(record->AsWeakPtr()); + + texts_to_record_swap_time_.pop(); } - texts_to_record_swap_time_.clear(); awaiting_swap_promise_ = false; } @@ -201,9 +194,12 @@ // early-returns if the text has been recorded. if (size_zero_node_ids_.find(node_id) != size_zero_node_ids_.end()) return; - if (recorded_text_node_ids_.find(node_id) != recorded_text_node_ids_.end()) + // The node is reattached. + if (id_record_map_.Contains(node_id) && detached_ids_.Contains(node_id)) + detached_ids_.erase(node_id); + if (id_record_map_.find(node_id) != id_record_map_.end()) return; - // When node_id is not found in recorded_text_node_ids_, this invalidation is + // When node_id is not found in id_record_map_, this invalidation is // the text's first invalidation. uint64_t rect_size = 0; @@ -221,27 +217,27 @@ size_zero_node_ids_.insert(node_id); } else { // Non-trivial text is found. - TextRecord record; - record.node_id = node_id; - record.first_size = rect_size; + std::unique_ptr<TextRecord> record = std::make_unique<TextRecord>(); + record->node_id = node_id; + record->first_size = rect_size; #ifndef NDEBUG if (object.IsText()) { - record.text = ToLayoutText(&object)->GetText(); + record->text = ToLayoutText(&object)->GetText(); } else if (object.IsFileUploadControl()) { - record.text = ToLayoutFileUploadControl(&object)->FileTextValue(); + record->text = ToLayoutFileUploadControl(&object)->FileTextValue(); } else { - record.text = String("NON-TEXT_OBJECT"); + record->text = String("NON-TEXT_OBJECT"); } #endif - texts_to_record_swap_time_.push_back(record); + id_record_map_.insert(node_id, std::move(record)); + texts_to_record_swap_time_.push(node_id); } - if (recorded_text_node_ids_.size() + size_zero_node_ids_.size() + - texts_to_record_swap_time_.size() >= + if (id_record_map_.size() + size_zero_node_ids_.size() >= kTextNodeNumberLimit) { TRACE_EVENT_INSTANT2("loading", "TextPaintTimingDetector::OverNodeLimit", TRACE_EVENT_SCOPE_THREAD, "recorded_node_count", - recorded_text_node_ids_.size(), "size_zero_node_count", + id_record_map_.size(), "size_zero_node_count", size_zero_node_ids_.size()); StopRecordEntries(); } @@ -253,22 +249,22 @@ } TextRecord* TextPaintTimingDetector::FindLargestPaintCandidate() { - return FindCandidate(largest_text_heap_); + return FindCandidate(size_ordered_set_); } TextRecord* TextPaintTimingDetector::FindLastPaintCandidate() { - return FindCandidate(latest_text_heap_); + return FindCandidate(time_ordered_set_); } -TextRecord* TextPaintTimingDetector::FindCandidate(TextRecordHeap& heap) { - while (!heap.empty() && - !recorded_text_node_ids_.Contains(heap.top()->node_id)) { - // If recorded_text_node_ids_ doesn't have record.node_id, the node has - // been deleted. We discard the records of deleted node. - heap.pop(); +TextRecord* TextPaintTimingDetector::FindCandidate( + const TextRecordSet& ordered_set) { + for (auto it = ordered_set.begin(); it != ordered_set.end(); ++it) { + if (detached_ids_.Contains((*it)->node_id) || + (*it)->first_paint_time.is_null()) + continue; + DCHECK(id_record_map_.Contains((*it)->node_id)); + return (*it).get(); } - if (!heap.empty()) - return heap.top().get(); return nullptr; }
diff --git a/third_party/blink/renderer/core/paint/text_paint_timing_detector.h b/third_party/blink/renderer/core/paint/text_paint_timing_detector.h index 0ef8460..e349e49 100644 --- a/third_party/blink/renderer/core/paint/text_paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/text_paint_timing_detector.h
@@ -18,9 +18,11 @@ class LocalFrameView; class PropertyTreeState; -struct TextRecord { +class TextRecord : public base::SupportsWeakPtr<TextRecord> { + public: DOMNodeId node_id = kInvalidDOMNodeId; uint64_t first_size = 0; + // This is treated as unset. base::TimeTicks first_paint_time = base::TimeTicks(); #ifndef NDEBUG String text = ""; @@ -53,12 +55,10 @@ using ReportTimeCallback = WTF::CrossThreadFunction<void(WebLayerTreeView::SwapResult, base::TimeTicks)>; - using TextRecordHeapComparator = bool (*)(const std::unique_ptr<TextRecord>&, - const std::unique_ptr<TextRecord>&); - using TextRecordHeap = - std::priority_queue<std::unique_ptr<TextRecord>, - std::vector<std::unique_ptr<TextRecord>>, - TextRecordHeapComparator>; + using TextRecordSetComparator = bool (*)(const base::WeakPtr<TextRecord>&, + const base::WeakPtr<TextRecord>&); + using TextRecordSet = + std::set<base::WeakPtr<TextRecord>, TextRecordSetComparator>; friend class TextPaintTimingDetectorTest; public: @@ -87,15 +87,16 @@ void ReportSwapTime(WebLayerTreeView::SwapResult result, base::TimeTicks timestamp); void RegisterNotifySwapTime(ReportTimeCallback callback); - TextRecord* FindCandidate(TextRecordHeap& heap); void OnLargestTextDetected(const TextRecord&); void OnLastTextDetected(const TextRecord&); + TextRecord* FindCandidate(const TextRecordSet& ordered_set); - HashSet<DOMNodeId> recorded_text_node_ids_; + HashMap<DOMNodeId, std::unique_ptr<TextRecord>> id_record_map_; HashSet<DOMNodeId> size_zero_node_ids_; - TextRecordHeap largest_text_heap_; - TextRecordHeap latest_text_heap_; - std::vector<TextRecord> texts_to_record_swap_time_; + HashSet<DOMNodeId> detached_ids_; + TextRecordSet size_ordered_set_; + TextRecordSet time_ordered_set_; + std::queue<DOMNodeId> texts_to_record_swap_time_; // Make sure that at most one swap promise is ongoing. bool awaiting_swap_promise_ = false;
diff --git a/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc index b78708c..047f613 100644 --- a/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc +++ b/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
@@ -28,10 +28,20 @@ return GetFrameView().GetPaintTimingDetector(); } - unsigned CountRecords() { + unsigned CountVisibleTexts() { + return GetPaintTimingDetector() + .GetTextPaintTimingDetector() + .id_record_map_.size() - + GetPaintTimingDetector() + .GetTextPaintTimingDetector() + .detached_ids_.size(); + ; + } + + unsigned CountDetachedTexts() { return GetPaintTimingDetector() .GetTextPaintTimingDetector() - .recorded_text_node_ids_.size(); + .detached_ids_.size(); } void InvokeCallback() { @@ -145,7 +155,8 @@ GetDocument().getElementById("parent")->RemoveChild( GetDocument().getElementById("remove")); InvokeCallback(); - EXPECT_EQ(CountRecords(), 0u); + EXPECT_EQ(CountVisibleTexts(), 0u); + EXPECT_EQ(CountDetachedTexts(), 1u); } TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_LargestText) { @@ -191,6 +202,35 @@ EXPECT_GE(time3, second_last); } +// There is a risk that a text that is just recorded is selected to be the +// metric candidate. The algorithm should skip the text record if its paint time +// hasn't been recorded yet. +TEST_F(TextPaintTimingDetectorTest, PendingTextIsLargest) { + SetBodyInnerHTML(R"HTML( + )HTML"); + AppendDivElementToBody("text"); + GetFrameView().UpdateAllLifecyclePhases( + DocumentLifecycle::LifecycleUpdateReason::kTest); + // We do not call swap-time callback here in order to not set the paint time. + EXPECT_FALSE(TextRecordOfLargestTextPaint()); +} + +// The same node may be visited by recordText for twice before the paint time +// is set. In some previous design, this caused the node to be recorded twice. +TEST_F(TextPaintTimingDetectorTest, VisitSameNodeTwiceBeforePaintTimeIsSet) { + SetBodyInnerHTML(R"HTML( + )HTML"); + Element* text = AppendDivElementToBody("text"); + GetFrameView().UpdateAllLifecyclePhases( + DocumentLifecycle::LifecycleUpdateReason::kTest); + // Change a property of the text to trigger repaint. + text->setAttribute(html_names::kStyleAttr, AtomicString("color:red;")); + GetFrameView().UpdateAllLifecyclePhases( + DocumentLifecycle::LifecycleUpdateReason::kTest); + InvokeCallback(); + EXPECT_EQ(TextRecordOfLargestTextPaint()->node_id, NodeIdOfText(text)); +} + TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_ReportFirstPaintTime) { TimeTicks time1 = CurrentTimeTicks(); SetBodyInnerHTML(R"HTML( @@ -365,10 +405,10 @@ // tracking node while layout ng is using the layout text as the tracking // node. if (RuntimeEnabledFeatures::LayoutNGEnabled()) { - EXPECT_EQ(CountRecords(), 1u); + EXPECT_EQ(CountVisibleTexts(), 1u); } else { // The text and the elllipsis are recorded. - EXPECT_EQ(CountRecords(), 2u); + EXPECT_EQ(CountVisibleTexts(), 2u); } } @@ -377,7 +417,7 @@ Element* element = GetDocument().QuerySelector("input"); UpdateAllLifecyclePhasesAndSimulateSwapTime(); - EXPECT_EQ(CountRecords(), 1u); + EXPECT_EQ(CountVisibleTexts(), 1u); EXPECT_EQ(TextRecordOfLargestTextPaint()->node_id, DOMNodeIds::IdForNode(element)); } @@ -393,7 +433,7 @@ )HTML"); UpdateAllLifecyclePhasesAndSimulateSwapTime(); - EXPECT_EQ(CountRecords(), 0u); + EXPECT_EQ(CountVisibleTexts(), 0u); } TEST_F(TextPaintTimingDetectorTest, CaptureSVGText) { @@ -407,7 +447,7 @@ ToSVGTextContentElement(GetDocument().QuerySelector("text")); UpdateAllLifecyclePhasesAndSimulateSwapTime(); - EXPECT_EQ(CountRecords(), 1u); + EXPECT_EQ(CountVisibleTexts(), 1u); EXPECT_EQ(TextRecordOfLargestTextPaint()->node_id, NodeIdOfText(elem)); }
diff --git a/third_party/blink/renderer/core/probe/core_probes.pidl b/third_party/blink/renderer/core/probe/core_probes.pidl index 92ca4aa0..63f2a98 100644 --- a/third_party/blink/renderer/core/probe/core_probes.pidl +++ b/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -89,11 +89,11 @@ void didPaint(LocalFrame*, const cc::Layer*, const LayoutRect&); void applyAcceptLanguageOverride(ExecutionContext*, String* acceptLanguage); void applyUserAgentOverride(CoreProbeSink*, String* userAgent); - void didBlockRequest([Keep] ExecutionContext*, const ResourceRequest&, DocumentLoader*, const FetchInitiatorInfo&, ResourceRequestBlockedReason, ResourceType); + void didBlockRequest(CoreProbeSink*, const ResourceRequest&, DocumentLoader*, const KURL& fetch_context_url, const FetchInitiatorInfo&, ResourceRequestBlockedReason, ResourceType); void didChangeResourcePriority(LocalFrame*, DocumentLoader*, unsigned long identifier, ResourceLoadPriority loadPriority); - void prepareRequest([Keep] ExecutionContext*, DocumentLoader*, ResourceRequest&, const FetchInitiatorInfo&, ResourceType); - void willSendRequest([Keep] ExecutionContext*, unsigned long identifier, DocumentLoader*, const ResourceRequest&, const ResourceResponse& redirectResponse, const FetchInitiatorInfo&, ResourceType); - void willSendNavigationRequest([Keep] ExecutionContext*, unsigned long identifier, DocumentLoader*, const KURL&, const AtomicString& http_method, EncodedFormData*); + void prepareRequest(CoreProbeSink*, DocumentLoader*, ResourceRequest&, const FetchInitiatorInfo&, ResourceType); + void willSendRequest(CoreProbeSink*, unsigned long identifier, DocumentLoader*, const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirectResponse, const FetchInitiatorInfo&, ResourceType); + void willSendNavigationRequest(CoreProbeSink*, unsigned long identifier, DocumentLoader*, const KURL&, const AtomicString& http_method, EncodedFormData*); void markResourceAsCached(LocalFrame*, DocumentLoader*, unsigned long identifier); void didReceiveResourceResponse(CoreProbeSink*, unsigned long identifier, DocumentLoader*, const ResourceResponse&, Resource*); void didReceiveData(CoreProbeSink*, unsigned long identifier, DocumentLoader*, const char* data, uint64_t dataLength); @@ -104,7 +104,7 @@ void didFailLoading(CoreProbeSink*, unsigned long identifier, DocumentLoader*, const ResourceError&); void willSendEventSourceRequest(ExecutionContext*, ThreadableLoaderClient* eventSource); void willDispatchEventSourceEvent(ExecutionContext*, unsigned long identifier, const AtomicString& eventName, const AtomicString& eventId, const String& data); - void willLoadXHR(ExecutionContext*, XMLHttpRequest* xhr, ThreadableLoaderClient* client, const AtomicString& method, const KURL& url, bool async, EncodedFormData* form_data, const HTTPHeaderMap& headers, bool includeCredentials); + void willLoadXHR([Keep] ExecutionContext*, const AtomicString& method, const KURL& url, bool async, EncodedFormData* form_data, const HTTPHeaderMap& headers, bool includeCredentials); void didFinishXHR(ExecutionContext*, XMLHttpRequest* xhr); void scriptImported(ExecutionContext*, unsigned long identifier, const String& sourceString); void scriptExecutionBlockedByCSP(ExecutionContext*, const String& directiveText);
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.h b/third_party/blink/renderer/core/scroll/scrollable_area.h index 084ee25..5b483fa1 100644 --- a/third_party/blink/renderer/core/scroll/scrollable_area.h +++ b/third_party/blink/renderer/core/scroll/scrollable_area.h
@@ -32,9 +32,9 @@ #include "third_party/blink/renderer/platform/geometry/layout_rect.h" #include "third_party/blink/renderer/platform/graphics/color.h" #include "third_party/blink/renderer/platform/graphics/compositor_element_id.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" -#include "third_party/blink/renderer/platform/scroll/scroll_types.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/testing/page_test_base.cc b/third_party/blink/renderer/core/testing/page_test_base.cc index 5698d8f..8c8e8b25 100644 --- a/third_party/blink/renderer/core/testing/page_test_base.cc +++ b/third_party/blink/renderer/core/testing/page_test_base.cc
@@ -117,6 +117,7 @@ void PageTestBase::UpdateAllLifecyclePhasesForTest() { GetDocument().View()->UpdateAllLifecyclePhases( DocumentLifecycle::LifecycleUpdateReason::kTest); + GetDocument().View()->RunPostLifecycleSteps(); } StyleEngine& PageTestBase::GetStyleEngine() {
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc index e06c443..ec460ab 100644 --- a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc +++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -60,14 +60,9 @@ last_frame_time_ += base::TimeDelta::FromSecondsD(time_delta_in_seconds); - SimCanvas::Commands commands; - paint_commands_ = &commands; - layer_tree_view_->layer_tree_host()->Composite(last_frame_time_, /*raster=*/false); - - paint_commands_ = nullptr; - return commands; + return PaintFrame(); } SimCanvas::Commands SimCompositor::PaintFrame() { @@ -104,7 +99,6 @@ web_view_->MainFrameWidget()->BeginFrame(last_frame_time_, false); web_view_->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); - *paint_commands_ = PaintFrame(); } } // namespace blink
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.h b/third_party/blink/renderer/core/testing/sim/sim_compositor.h index 466733e..259e28e 100644 --- a/third_party/blink/renderer/core/testing/sim/sim_compositor.h +++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.h
@@ -98,6 +98,7 @@ void RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) override; void BeginMainFrame(base::TimeTicks frame_time) override; + void DidBeginMainFrame() override { web_view_->DidBeginFrame(); } WebViewImpl* web_view_ = nullptr; content::LayerTreeView* layer_tree_view_ = nullptr; @@ -106,10 +107,6 @@ base::TimeTicks last_frame_time_; - // During BeginFrame(), painting is done, and the result is stored here to - // be returned from BeginFrame(). - SimCanvas::Commands* paint_commands_; - std::unique_ptr<cc::ScopedDeferMainFrameUpdate> scoped_defer_main_frame_update_; };
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index 926ed473..8834dae 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -95,6 +95,11 @@ InstanceCounters::kWorkerGlobalScopeCounter); } +NOINLINE const KURL& WorkerGlobalScope::Url() const { + CHECK(url_.IsValid()); + return url_; +} + KURL WorkerGlobalScope::CompleteURL(const String& url) const { // Always return a null URL when passed a null string. // FIXME: Should we change the KURL constructor to have this behavior? @@ -104,6 +109,22 @@ return KURL(BaseURL(), url); } +const KURL& WorkerGlobalScope::BaseURL() const { + return Url(); +} + +NOINLINE void WorkerGlobalScope::InitializeURL(const KURL& url) { + CHECK(url_.IsNull()); + DCHECK(url.IsValid()); + if (GetSecurityOrigin()->IsOpaque()) { + DCHECK(SecurityOrigin::Create(url)->IsOpaque()); + } else { + DCHECK(GetSecurityOrigin()->IsSameSchemeHostPort( + SecurityOrigin::Create(url).get())); + } + url_ = url; +} + void WorkerGlobalScope::Dispose() { DCHECK(IsContextThread()); closing_ = true; @@ -120,7 +141,7 @@ WorkerLocation* WorkerGlobalScope::location() const { if (!location_) - location_ = WorkerLocation::Create(url_); + location_ = WorkerLocation::Create(Url()); return location_.Get(); } @@ -424,9 +445,11 @@ classic_script_loader->SourceText()); // Step 12.3. "Set worker global scope's url to response's url." + InitializeURL(classic_script_loader->ResponseURL()); + // Step 12.4. "Set worker global scope's HTTPS state to response's HTTPS // state." - // These are done in the constructor of WorkerGlobalScope. + // This is done in the constructor of WorkerGlobalScope. // Step 12.5. "Set worker global scope's referrer policy to the result of // parsing the `Referrer-Policy` header of response." @@ -501,7 +524,6 @@ creation_params->worker_clients, std::move(creation_params->web_worker_fetch_context), thread->GetWorkerReportingProxy()), - url_(creation_params->script_url), script_type_(creation_params->script_type), user_agent_(creation_params->user_agent), parent_devtools_token_(creation_params->parent_devtools_token), @@ -517,7 +539,8 @@ : creation_params->agent_cluster_id) { InstanceCounters::IncrementCounter( InstanceCounters::kWorkerGlobalScopeCounter); - scoped_refptr<SecurityOrigin> security_origin = SecurityOrigin::Create(url_); + scoped_refptr<SecurityOrigin> security_origin = + SecurityOrigin::Create(creation_params->script_url); if (creation_params->starter_origin) { security_origin->TransferPrivilegesFrom( creation_params->starter_origin->CreatePrivilegeData()); @@ -535,12 +558,14 @@ BindContentSecurityPolicyToExecutionContext(); SetWorkerSettings(std::move(creation_params->worker_settings)); - // Set the referrer policy here for workers whose script is fetched on the - // main thread. For off-the-main-thread fetches, it is instead set after the - // script is fetched. + // Set the URL and referrer policy here for workers whose script is fetched + // on the main thread. For off-the-main-thread fetches, they are instead set + // after the script is fetched. if (creation_params->off_main_thread_fetch_option == - OffMainThreadWorkerScriptFetchOption::kDisabled) + OffMainThreadWorkerScriptFetchOption::kDisabled) { + InitializeURL(creation_params->script_url); SetReferrerPolicy(creation_params->referrer_policy); + } SetAddressSpace(creation_params->address_space); OriginTrialContext::AddTokens(this,
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h index 192a99e..a581a4d0 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -112,17 +112,19 @@ ExceptionState&); // ExecutionContext - const KURL& Url() const final { return url_; } + const KURL& Url() const final; KURL CompleteURL(const String&) const final; bool IsWorkerGlobalScope() const final { return true; } bool IsContextThread() const final; - const KURL& BaseURL() const final { return url_; } + const KURL& BaseURL() const final; String UserAgent() const final { return user_agent_; } HttpsState GetHttpsState() const override { return https_state_; } const base::UnguessableToken& GetAgentClusterID() const final { return agent_cluster_id_; } + void InitializeURL(const KURL& url); + DOMTimerCoordinator* Timers() final { return &timers_; } SecurityContext& GetSecurityContext() final { return *this; } void AddConsoleMessage(ConsoleMessage*) final; @@ -239,7 +241,7 @@ // ExecutionContext EventTarget* ErrorEventTarget() final { return this; } - const KURL url_; + KURL url_; const mojom::ScriptType script_type_; const String user_agent_; const base::UnguessableToken parent_devtools_token_;
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc index 56e3b3c..b832979 100644 --- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -158,7 +158,7 @@ const Member<WorkerOrWorkletGlobalScope> global_scope_for_logging_; }; -}; // namespace +} // namespace WorkerOrWorkletGlobalScope::WorkerOrWorkletGlobalScope( v8::Isolate* isolate,
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc index 184e25a1..e55b9984 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -447,6 +447,9 @@ } GetWorkerBackingThread().BackingThread().AddTaskObserver(this); + // TODO(crbug.com/866666): Ideally this URL should be the response URL of + // the worker top-level script, while currently can be the request URL + // for off-the-main-thread top-level script fetch cases. const KURL url_for_debugger = global_scope_creation_params->script_url; console_message_storage_ = MakeGarbageCollected<ConsoleMessageStorage>(); @@ -455,7 +458,8 @@ worker_reporting_proxy_.DidCreateWorkerGlobalScope(GlobalScope()); worker_inspector_controller_ = WorkerInspectorController::Create( - this, inspector_task_runner_, std::move(devtools_params)); + this, url_for_debugger, inspector_task_runner_, + std::move(devtools_params)); // Since context initialization below may fail, we should notify debugger // about the new worker thread separately, so that it can resolve it by id
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 13fad22..fe5a798 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -1069,8 +1069,8 @@ request.SetExternalRequestStateFromRequestorAddressSpace( execution_context.GetSecurityContext().AddressSpace()); - probe::willLoadXHR(&execution_context, this, this, method_, url_, async_, - http_body.get(), request_headers_, with_credentials_); + probe::willLoadXHR(&execution_context, method_, url_, async_, http_body.get(), + request_headers_, with_credentials_); if (http_body) { DCHECK_NE(method_, http_names::kGET);
diff --git a/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css b/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css index 365d09a..5cbb2c7f 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css +++ b/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
@@ -383,19 +383,19 @@ background-image: url(Images/popoverArrows.png); } -.force-white-icons [is=ui-icon].spritesheet-smallicons, [is=ui-icon].force-white-icons.spritesheet-smallicons, -theme-preserve { +:host-context(.force-white-icons) [is=ui-icon].spritesheet-smallicons, .force-white-icons [is=ui-icon].spritesheet-smallicons, [is=ui-icon].force-white-icons.spritesheet-smallicons, -theme-preserve { -webkit-mask-image: -webkit-image-set(url(Images/smallIcons.png) 1x, url(Images/smallIcons_2x.png) 2x); -webkit-mask-position: var(--spritesheet-position); background: #fafafa !important; } -.force-white-icons [is=ui-icon].spritesheet-largeicons, [is=ui-icon].force-white-icons.spritesheet-largeicons, -theme-preserve { +:host-context(.force-white-icons) [is=ui-icon].spritesheet-largeicons, .force-white-icons [is=ui-icon].spritesheet-largeicons, [is=ui-icon].force-white-icons.spritesheet-largeicons, -theme-preserve { -webkit-mask-image: -webkit-image-set(url(Images/largeIcons.png) 1x, url(Images/largeIcons_2x.png) 2x); -webkit-mask-position: var(--spritesheet-position); background: #fafafa !important; } -.force-white-icons [is=ui-icon].spritesheet-mediumicons, [is=ui-icon].force-white-icons.spritesheet-mediumicons, -theme-preserve { +:host-context(.force-white-icons) [is=ui-icon].spritesheet-mediumicon, .force-white-icons [is=ui-icon].spritesheet-mediumicons, [is=ui-icon].force-white-icons.spritesheet-mediumicons, -theme-preserve { -webkit-mask-image: -webkit-image-set(url(Images/mediumIcons.png) 1x, url(Images/mediumIcons_2x.png) 2x); -webkit-mask-position: var(--spritesheet-position); background: #fafafa !important;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc index 059ad04..f09d9ff 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc
@@ -100,6 +100,11 @@ return native_transport_.get(); } +void RTCDtlsTransport::ChangeState(webrtc::DtlsTransportInformation info) { + DCHECK(current_state_.state() != webrtc::DtlsTransportState::kClosed); + current_state_ = info; +} + // Implementation of DtlsTransportProxy::Delegate void RTCDtlsTransport::OnStartCompleted(webrtc::DtlsTransportInformation info) { current_state_ = info;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.h b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.h index 523aa04..c8093e5 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.h
@@ -64,6 +64,8 @@ ExecutionContext* GetExecutionContext() const override; // For garbage collection. void Trace(blink::Visitor* visitor) override; + // Others + void ChangeState(webrtc::DtlsTransportInformation info); webrtc::DtlsTransportInterface* native_transport(); private:
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc index 0b1230d..132466f 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -1171,49 +1171,6 @@ user_media_controller->HasRequestedUserMedia(); } -RTCDtlsTransport* RTCPeerConnection::LookupDtlsTransportByMid(String mid) { - if (mid.IsNull()) - return nullptr; - webrtc::PeerConnectionInterface* native_pc = - peer_handler_->NativePeerConnection(); - if (!native_pc) - return nullptr; - auto native_transport = - native_pc->LookupDtlsTransportByMid(std::string(mid.Utf8().data())); - if (!native_transport) - return nullptr; - // Check for previously created RTCDtlsTransport objects referencing - // this transport. - auto transport_lookup_result = dtls_transports_by_mid_.find(mid); - if (transport_lookup_result != dtls_transports_by_mid_.end()) { - if (transport_lookup_result->value->native_transport() != - native_transport.get()) { - // The mid's transport has changed. Erase the reference to - // the old transport, and continue. - dtls_transports_by_mid_.erase(transport_lookup_result); - } else { - return transport_lookup_result->value; - } - } - - // Check if the same transport has been returned for another mid. - for (auto const& transport_iterator : dtls_transports_by_mid_) { - if (transport_iterator.value->native_transport() == - native_transport.get()) { - // insert might invalidate the iterator (or not), so be safe. - RTCDtlsTransport* transport = transport_iterator.value; - dtls_transports_by_mid_.insert(mid, transport); - return transport; - } - } - // The transport is previously unseen. Create object and hold on to - // a reference to it. - RTCDtlsTransport* transport = MakeGarbageCollected<RTCDtlsTransport>( - GetExecutionContext(), native_transport); - dtls_transports_by_mid_.insert(mid, transport); - return transport; -} - void RTCPeerConnection::ReportSetSdpUsage( SetSdpOperationType operation_type, const RTCSessionDescriptionInit* session_description_init) const { @@ -2346,7 +2303,7 @@ HeapVector<Member<RTCRtpReceiver>>::iterator RTCPeerConnection::FindReceiver( const WebRTCRtpReceiver& web_receiver) { for (auto* it = rtp_receivers_.begin(); it != rtp_receivers_.end(); ++it) { - if ((*it)->web_receiver().Id() == web_receiver.Id()) + if ((*it)->web_receiver()->Id() == web_receiver.Id()) return it; } return rtp_receivers_.end(); @@ -2391,6 +2348,9 @@ DCHECK_EQ(sender->web_sender()->Id(), web_sender->Id()); sender->SetTrack(track); } + sender->set_transport(CreateOrUpdateDtlsTransport( + sender->web_sender()->DtlsTransport(), + sender->web_sender()->DtlsTransportInformation())); return sender; } @@ -2425,9 +2385,12 @@ } else { // Update existing receiver is a no-op. receiver = *receiver_it; - DCHECK_EQ(receiver->web_receiver().Id(), web_receiver->Id()); + DCHECK_EQ(receiver->web_receiver()->Id(), web_receiver->Id()); DCHECK_EQ(receiver->track(), track); // Its track should never change. } + receiver->set_transport(CreateOrUpdateDtlsTransport( + receiver->web_receiver()->DtlsTransport(), + receiver->web_receiver()->DtlsTransportInformation())); return receiver; } @@ -2459,6 +2422,27 @@ return transceiver; } +RTCDtlsTransport* RTCPeerConnection::CreateOrUpdateDtlsTransport( + rtc::scoped_refptr<webrtc::DtlsTransportInterface> native_transport, + const webrtc::DtlsTransportInformation& information) { + if (!native_transport.get()) { + return nullptr; + } + auto transport_locator = + dtls_transports_by_native_transport_.find(native_transport); + if (transport_locator != dtls_transports_by_native_transport_.end()) { + auto transport = transport_locator->value; + transport->ChangeState(information); + return transport; + } + RTCDtlsTransport* transport = MakeGarbageCollected<RTCDtlsTransport>( + GetExecutionContext(), native_transport); + dtls_transports_by_native_transport_.insert(native_transport.get(), + transport); + transport->ChangeState(information); + return transport; +} + RTCDTMFSender* RTCPeerConnection::createDTMFSender( MediaStreamTrack* track, ExceptionState& exception_state) { @@ -3076,7 +3060,7 @@ visitor->Trace(rtp_receivers_); visitor->Trace(transceivers_); visitor->Trace(scheduled_events_); - visitor->Trace(dtls_transports_by_mid_); + visitor->Trace(dtls_transports_by_native_transport_); EventTargetWithInlineData::Trace(visitor); ContextLifecycleObserver::Trace(visitor); MediaStreamObserver::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h index 5d72237..a4d24017 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
@@ -404,6 +404,12 @@ RTCRtpTransceiver* CreateOrUpdateTransceiver( std::unique_ptr<WebRTCRtpTransceiver>); + // Creates or updates the RTCDtlsTransport object corresponding to the + // given webrtc::DtlsTransportInterface object. + RTCDtlsTransport* CreateOrUpdateDtlsTransport( + rtc::scoped_refptr<webrtc::DtlsTransportInterface>, + const webrtc::DtlsTransportInformation& info); + // Update the |receiver->streams()| to the streams indicated by |stream_ids|, // adding to |remove_list| and |add_list| accordingly. // https://w3c.github.io/webrtc-pc/#set-associated-remote-streams @@ -481,10 +487,11 @@ HeapVector<Member<RTCRtpReceiver>> rtp_receivers_; HeapVector<Member<RTCRtpTransceiver>> transceivers_; - // A map of all transports that have been looked up by MID. - // A transport may be referenced by more than one mid, so may - // be present multiple times in the table. - HeapHashMap<String, Member<RTCDtlsTransport>> dtls_transports_by_mid_; + // A map of all webrtc::DtlsTransports that have a corresponding + // RTCDtlsTransport object. Garbage collection will remove map entries + // when they are no longer in use. + HeapHashMap<webrtc::DtlsTransportInterface*, WeakMember<RTCDtlsTransport>> + dtls_transports_by_native_transport_; std::unique_ptr<WebRTCPeerConnectionHandler> peer_handler_;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc index b540e08..960c004 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -7,6 +7,7 @@ #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_media_stream_track.h" #include "third_party/blink/public/platform/web_rtc_rtp_source.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h" @@ -36,9 +37,7 @@ } RTCDtlsTransport* RTCRtpReceiver::transport() { - if (!transceiver_) - return nullptr; - return pc_->LookupDtlsTransportByMid(transceiver_->mid()); + return transport_; } RTCDtlsTransport* RTCRtpReceiver::rtcp_transport() { @@ -90,8 +89,8 @@ return promise; } -const WebRTCRtpReceiver& RTCRtpReceiver::web_receiver() const { - return *receiver_; +WebRTCRtpReceiver* RTCRtpReceiver::web_receiver() { + return receiver_.get(); } MediaStreamVector RTCRtpReceiver::streams() const { @@ -106,6 +105,10 @@ transceiver_ = transceiver; } +void RTCRtpReceiver::set_transport(RTCDtlsTransport* transport) { + transport_ = transport; +} + void RTCRtpReceiver::UpdateSourcesIfNeeded() { if (!web_sources_needs_updating_) return; @@ -128,6 +131,7 @@ void RTCRtpReceiver::Trace(blink::Visitor* visitor) { visitor->Trace(pc_); visitor->Trace(track_); + visitor->Trace(transport_); visitor->Trace(streams_); visitor->Trace(transceiver_); ScriptWrappable::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h index 60a17bf..ea1d6a7 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h
@@ -48,10 +48,11 @@ HeapVector<Member<RTCRtpContributingSource>> getContributingSources(); ScriptPromise getStats(ScriptState*); - const WebRTCRtpReceiver& web_receiver() const; + WebRTCRtpReceiver* web_receiver(); MediaStreamVector streams() const; void set_streams(MediaStreamVector streams); void set_transceiver(RTCRtpTransceiver*); + void set_transport(RTCDtlsTransport*); void UpdateSourcesIfNeeded(); void Trace(blink::Visitor*) override; @@ -62,6 +63,7 @@ std::unique_ptr<WebRTCRtpReceiver> receiver_; Member<MediaStreamTrack> track_; + Member<RTCDtlsTransport> transport_; MediaStreamVector streams_; // The current SSRCs and CSRCs. getSynchronizationSources() returns the SSRCs
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc index 9d91211..dde55c4 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/modules/mediastream/media_stream_track.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h" @@ -311,9 +312,7 @@ } RTCDtlsTransport* RTCRtpSender::transport() { - if (!transceiver_) - return nullptr; - return pc_->LookupDtlsTransportByMid(transceiver_->mid()); + return transport_; } RTCDtlsTransport* RTCRtpSender::rtcp_transport() { @@ -477,6 +476,10 @@ transceiver_ = transceiver; } +void RTCRtpSender::set_transport(RTCDtlsTransport* transport) { + transport_ = transport; +} + RTCDTMFSender* RTCRtpSender::dtmf() { // Lazy initialization of dtmf_ to avoid overhead when not used. if (!dtmf_ && kind_ == "audio") { @@ -494,6 +497,7 @@ void RTCRtpSender::Trace(blink::Visitor* visitor) { visitor->Trace(pc_); visitor->Trace(track_); + visitor->Trace(transport_); visitor->Trace(dtmf_); visitor->Trace(streams_); visitor->Trace(last_returned_parameters_);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h index 1abbf95a..c216bec 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h
@@ -64,6 +64,7 @@ MediaStreamVector streams() const; void set_streams(MediaStreamVector streams); void set_transceiver(RTCRtpTransceiver*); + void set_transport(RTCDtlsTransport*); void Trace(blink::Visitor*) override; @@ -74,6 +75,7 @@ // a copy here as long as we support Plan B. String kind_; Member<MediaStreamTrack> track_; + Member<RTCDtlsTransport> transport_; Member<RTCDTMFSender> dtmf_; MediaStreamVector streams_; Member<RTCRtpSendParameters> last_returned_parameters_;
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.cc b/third_party/blink/renderer/modules/xr/xr_frame.cc index a625f45..ae05c995 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.cc +++ b/third_party/blink/renderer/modules/xr/xr_frame.cc
@@ -10,12 +10,26 @@ #include "third_party/blink/renderer/modules/xr/xr_session.h" #include "third_party/blink/renderer/modules/xr/xr_view.h" #include "third_party/blink/renderer/modules/xr/xr_viewer_pose.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" namespace blink { +namespace { + +const char kInactiveFrame[] = + "XRFrame access outside the callback that produced it is invalid."; +} + XRFrame::XRFrame(XRSession* session) : session_(session) {} -XRViewerPose* XRFrame::getViewerPose(XRReferenceSpace* reference_space) const { +XRViewerPose* XRFrame::getViewerPose(XRReferenceSpace* reference_space, + ExceptionState& exception_state) const { + if (!active_) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + kInactiveFrame); + return nullptr; + } + session_->LogGetPose(); // Must use a reference space created from the same session. @@ -46,7 +60,14 @@ } XRInputPose* XRFrame::getInputPose(XRInputSource* input_source, - XRReferenceSpace* reference_space) const { + XRReferenceSpace* reference_space, + ExceptionState& exception_state) const { + if (!active_) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + kInactiveFrame); + return nullptr; + } + if (!input_source || !reference_space) { return nullptr; } @@ -123,6 +144,10 @@ base_pose_matrix_ = TransformationMatrix::Create(base_pose_matrix); } +void XRFrame::Deactivate() { + active_ = false; +} + void XRFrame::Trace(blink::Visitor* visitor) { visitor->Trace(session_); ScriptWrappable::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.h b/third_party/blink/renderer/modules/xr/xr_frame.h index 82adf5c..06e0a8f 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.h +++ b/third_party/blink/renderer/modules/xr/xr_frame.h
@@ -14,6 +14,7 @@ namespace blink { +class ExceptionState; class XRViewerPose; class XRInputPose; class XRInputSource; @@ -28,16 +29,21 @@ XRSession* session() const { return session_; } - XRViewerPose* getViewerPose(XRReferenceSpace*) const; - XRInputPose* getInputPose(XRInputSource*, XRReferenceSpace*) const; + XRViewerPose* getViewerPose(XRReferenceSpace*, ExceptionState&) const; + XRInputPose* getInputPose(XRInputSource*, + XRReferenceSpace*, + ExceptionState&) const; void SetBasePoseMatrix(const TransformationMatrix&); void Trace(blink::Visitor*) override; + void Deactivate(); + private: const Member<XRSession> session_; std::unique_ptr<TransformationMatrix> base_pose_matrix_; + bool active_ = true; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.idl b/third_party/blink/renderer/modules/xr/xr_frame.idl index 2235225a..48d98f3 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.idl +++ b/third_party/blink/renderer/modules/xr/xr_frame.idl
@@ -10,7 +10,7 @@ ] interface XRFrame { readonly attribute XRSession session; - XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); - XRInputPose? getInputPose(XRInputSource inputSource, + [RaisesException] XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); + [RaisesException] XRInputPose? getInputPose(XRInputSource inputSource, XRReferenceSpace referenceSpace); };
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc index a7f7d75..035c618 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.cc +++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -613,6 +613,9 @@ // OnFrameEnd if it's still valid. if (!ended_) frame_base_layer->OnFrameEnd(); + + // Ensure the XRFrame cannot be used outside the callbacks. + presentation_frame->Deactivate(); } } @@ -725,6 +728,9 @@ if (event->defaultPrevented()) input_source->selection_cancelled = true; + + // Ensure the frame cannot be used outside of the event handler. + event->frame()->Deactivate(); } void XRSession::OnSelectEnd(XRInputSource* input_source) { @@ -747,6 +753,9 @@ if (event->defaultPrevented()) input_source->selection_cancelled = true; + + // Ensure the frame cannot be used outside of the event handler. + event->frame()->Deactivate(); } void XRSession::OnSelect(XRInputSource* input_source) { @@ -764,6 +773,9 @@ XRInputSourceEvent* event = CreateInputSourceEvent(event_type_names::kSelect, input_source); DispatchEvent(*event); + + // Ensure the frame cannot be used outside of the event handler. + event->frame()->Deactivate(); } }
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index ce65cbaf..95c652e 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1106,6 +1106,7 @@ "graphics/replaying_canvas.cc", "graphics/replaying_canvas.h", "graphics/scoped_interpolation_quality.h", + "graphics/scroll_types.h", "graphics/skia/image_pixel_locker.cc", "graphics/skia/image_pixel_locker.h", "graphics/skia/sk_size_hash.h", @@ -1856,6 +1857,7 @@ "//services/viz/public/interfaces:interfaces_blink", "//skia", "//skia:skcms", + "//skia:test_fonts", "//testing/gmock", "//testing/gtest", "//third_party:freetype_harfbuzz", @@ -1963,6 +1965,7 @@ test("blink_fuzzer_unittests") { deps = [ ":test_support", + "//skia:test_fonts", "//third_party/blink/public:test_support", ]
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc index 06930f5..0cdd260a 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
@@ -626,8 +626,11 @@ HarfBuzzShaper shaper(string); scoped_refptr<ShapeResult> result = ShapeWithParameter(&shaper); EXPECT_EQ(length, result->NumCharacters()); -#if defined(OS_LINUX) - // Linux doesn't have glyphs. We can't test RunInfo without all glyphs. +#if defined(OS_LINUX) || defined(OS_FUCHSIA) + // Linux and Fuchsia use Lohit Devanagari. When using that font the shaper + // returns 32767 glyphs instead of 32769. + // TODO(crbug.com/933551): Add Noto Sans Devanagari to + // //third_party/test_fonts and use it here. if (result->NumGlyphs() != length) return; #endif @@ -1476,8 +1479,8 @@ } // TODO(crbug.com/870712): This test fails due to font fallback differences on -// Android. -#if defined(OS_ANDROID) +// Android and Fuchsia. +#if defined(OS_ANDROID) || defined(OS_FUCHSIA) #define MAYBE_SafeToBreakArabicCommonLigatures \ DISABLED_SafeToBreakArabicCommonLigatures #else
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h index a7db4f1..a1dd661 100644 --- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h +++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_ANIMATION_WORKLET_MUTATOR_DISPATCHER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_ANIMATION_WORKLET_MUTATOR_DISPATCHER_H_ +#include "base/bind.h" #include "third_party/blink/renderer/platform/graphics/animation_worklet_mutators_state.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -14,11 +15,20 @@ public: virtual ~AnimationWorkletMutatorDispatcher() = default; + using AsyncMutationCompleteCallback = base::OnceCallback<void(MutateStatus)>; + // Run the animation frame callbacks from all connected AnimationWorklets. virtual void MutateSynchronously( std::unique_ptr<AnimationWorkletDispatcherInput>) = 0; - virtual void MutateAsynchronously( - std::unique_ptr<AnimationWorkletDispatcherInput>) = 0; + + // Queues the animation frame callbacks from all connected AnimationWorklets. + // The queuing strategy determines what action to take when busy servicing + // another request. The callback is triggered on completion or canceling of + // the mutation cycle. Returns true if mutations results are expected. + virtual bool MutateAsynchronously( + std::unique_ptr<AnimationWorkletDispatcherInput>, + MutateQueuingStrategy, + AsyncMutationCompleteCallback) = 0; // Returns true if Mutate may do something if called 'now'. virtual bool HasMutators() = 0;
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc index 02b1d00..2c08c50 100644 --- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc +++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
@@ -122,25 +122,41 @@ base::TimeDelta::FromMilliseconds(100), 50); } -void AnimationWorkletMutatorDispatcherImpl::MutateAsynchronously( - std::unique_ptr<AnimationWorkletDispatcherInput> mutator_input) { - if (mutator_map_.IsEmpty() || !mutator_input) - return; +bool AnimationWorkletMutatorDispatcherImpl::MutateAsynchronously( + std::unique_ptr<AnimationWorkletDispatcherInput> mutator_input, + MutateQueuingStrategy queuing_strategy, + AsyncMutationCompleteCallback done_callback) { DCHECK(client_); DCHECK(host_queue_->BelongsToCurrentThread()); + if (mutator_map_.IsEmpty() || !mutator_input) + return false; + if (!mutator_input_map_.IsEmpty()) { - // Still running mutations from a previous frame. Skip this frame to avoid - // lagging behind. - // TODO(kevers): Consider queuing pending mutation cycle. A pending tree - // mutation should likely be queued an active tree mutation cycle is still - // running. - return; + // Still running mutations from a previous frame. + if (queuing_strategy == MutateQueuingStrategy::kDrop) { + // Skip this frame to avoid lagging behind. + return false; + } + DCHECK(queuing_strategy == MutateQueuingStrategy::kQueueAndReplace); + DCHECK(!queued_mutator_input_); + // Preemptive queue. + queued_mutator_input_.reset(mutator_input.release()); + queued_on_async_mutation_complete_ = std::move(done_callback); + return true; } mutator_input_map_ = CreateInputMap(*mutator_input); if (mutator_input_map_.IsEmpty()) - return; + return false; + MutateAsynchronouslyInternal(std::move(done_callback)); + return true; +} + +void AnimationWorkletMutatorDispatcherImpl::MutateAsynchronouslyInternal( + AsyncMutationCompleteCallback done_callback) { + DCHECK(host_queue_->BelongsToCurrentThread()); + on_async_mutation_complete_ = std::move(done_callback); int next_async_mutation_id = GetNextAsyncMutationId(); TRACE_EVENT_ASYNC_BEGIN0("cc", "AnimationWorkletMutatorDispatcherImpl::MutateAsync", @@ -158,7 +174,6 @@ }, host_queue_, weak_factory_.GetWeakPtr(), next_async_mutation_id); - client_->NotifyAnimationsPending(); RequestMutations(std::move(on_done)); } @@ -167,10 +182,17 @@ DCHECK(client_); DCHECK(host_queue_->BelongsToCurrentThread()); ApplyMutationsOnHostThread(); - client_->NotifyAnimationsReady(); + auto done_callback = std::move(on_async_mutation_complete_); + if (queued_mutator_input_.get()) { + mutator_input_map_ = CreateInputMap(*queued_mutator_input_); + queued_mutator_input_.reset(); + // Trigger queued mutation request. + MutateAsynchronouslyInternal(std::move(queued_on_async_mutation_complete_)); + } TRACE_EVENT_ASYNC_END0("cc", "AnimationWorkletMutatorDispatcherImpl::MutateAsync", async_mutation_id); + std::move(done_callback).Run(MutateStatus::kCompleted); // TODO(kevers): Add UMA metric to track the asynchronous mutate duration. } @@ -229,6 +251,11 @@ DCHECK(outputs_->get().IsEmpty()); int num_requests = mutator_map_.size(); + if (num_requests == 0) { + std::move(done_callback).Run(); + return; + } + int next_request_index = 0; outputs_->get().Grow(num_requests); base::RepeatingClosure on_mutator_done = base::BarrierClosure(
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h index 1184e5b..fa90bbd 100644 --- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h +++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h
@@ -51,8 +51,9 @@ void MutateSynchronously( std::unique_ptr<AnimationWorkletDispatcherInput>) override; - void MutateAsynchronously( - std::unique_ptr<AnimationWorkletDispatcherInput>) override; + bool MutateAsynchronously(std::unique_ptr<AnimationWorkletDispatcherInput>, + MutateQueuingStrategy, + AsyncMutationCompleteCallback) override; // TODO(majidvp): Remove when timeline inputs are known. bool HasMutators() override; @@ -91,11 +92,13 @@ InputMap CreateInputMap(AnimationWorkletDispatcherInput& mutator_input) const; - // Dispatches mutation update requests. The callback is triggered once - // all mutation updates have been computed on the animation worklet thread - // associated with the last mutation to complete. + // Dispatches mutation update requests. The callback is triggered once all + // mutation updates have been computed and it runs on the animation worklet + // thread associated with the last mutation to complete. void RequestMutations(WTF::CrossThreadClosure done_callback); + void MutateAsynchronouslyInternal(AsyncMutationCompleteCallback); + void AsyncMutationsDone(int async_mutation_id); void ApplyMutationsOnHostThread(); @@ -131,6 +134,20 @@ // the mutation cycle. scoped_refptr<OutputVectorRef> outputs_; + // Input queued for the next mutation cycle, which will automatically be + // triggered at the completion of the current cycle. Only one collection of + // inputs can be queued at any point in time. In a typical frame, we expect + // one request for the active tree, and one for the pending tree. The active + // tree mutation is best effort will be dropped when busy. A pending tree + // mutation is queued to ensure initial values are resolved. The pending tree + // activation is blocked until the previous request completes preventing the + // need to queue multiple requests. + std::unique_ptr<AnimationWorkletDispatcherInput> queued_mutator_input_; + + // Active and queued callbacks for the completion of an async mutation cycle. + AsyncMutationCompleteCallback on_async_mutation_complete_; + AsyncMutationCompleteCallback queued_on_async_mutation_complete_; + base::WeakPtrFactory<AnimationWorkletMutatorDispatcherImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AnimationWorkletMutatorDispatcherImpl);
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc index 7426c6d..d77bd6f 100644 --- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc +++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
@@ -57,18 +57,34 @@ return std::unique_ptr<AnimationWorkletOutput>(MutateRef(*input)); } + // Blocks the worklet thread by posting a task that will complete only when + // signaled. This blocking ensures that tests of async mutations do not + // encounter race conditions when validating queuing strategies. + void BlockWorkletThread() { + PostCrossThreadTask( + *expected_runner_, FROM_HERE, + CrossThreadBind( + [](base::WaitableEvent* start_processing_event) { + start_processing_event->Wait(); + }, + WTF::CrossThreadUnretained(&start_processing_event_))); + } + + void UnblockWorkletThread() { start_processing_event_.Signal(); } + MOCK_CONST_METHOD0(GetWorkletId, int()); MOCK_METHOD1(MutateRef, AnimationWorkletOutput*(const AnimationWorkletInput&)); scoped_refptr<base::SingleThreadTaskRunner> expected_runner_; + base::WaitableEvent start_processing_event_; }; class MockCompositorMutatorClient : public CompositorMutatorClient { public: MockCompositorMutatorClient( std::unique_ptr<AnimationWorkletMutatorDispatcherImpl> mutator) - : CompositorMutatorClient(std::move(mutator)), done_event_(nullptr) {} + : CompositorMutatorClient(std::move(mutator)) {} ~MockCompositorMutatorClient() override {} // gmock cannot mock methods with move-only args so we forward it to ourself. void SetMutationUpdate( @@ -76,33 +92,15 @@ SetMutationUpdateRef(output_state.get()); } - MOCK_METHOD0(NotifyAnimationsPending, void()); - - void NotifyAnimationsReady() override { - NotifyAnimationsReadyRef(); - if (done_event_) { - done_event_->Signal(); - } - } - - MOCK_METHOD0(NotifyAnimationsReadyRef, void()); - - void SignalWhenComplete(base::WaitableEvent* done_event) { - done_event_ = done_event; - } - MOCK_METHOD1(SetMutationUpdateRef, void(cc::MutatorOutputState* output_state)); - - private: - base::WaitableEvent* done_event_; // not owned. }; class AnimationWorkletMutatorDispatcherImplTest : public ::testing::Test { public: void SetUp() override { - auto mutator = - std::make_unique<AnimationWorkletMutatorDispatcherImpl>(false); + auto mutator = std::make_unique<AnimationWorkletMutatorDispatcherImpl>( + /*main_thread_task_runner=*/true); mutator_ = mutator.get(); client_ = std::make_unique<::testing::StrictMock<MockCompositorMutatorClient>>( @@ -233,9 +231,7 @@ // Ensure mutator is not invoked after unregistration. EXPECT_CALL(*first_mutator, MutateRef(_)).Times(0); - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(0); EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0); - EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(0); mutator_->UnregisterAnimationWorkletMutator(first_mutator); mutator_->MutateSynchronously(CreateTestMutatorInput()); @@ -340,41 +336,49 @@ class AnimationWorkletMutatorDispatcherImplAsyncTest : public AnimationWorkletMutatorDispatcherImplTest { public: - void SetUp() override { - if (!Thread::CompositorThread()) { - Thread::CreateAndSetCompositorThread(); - } - AnimationWorkletMutatorDispatcherImplTest::SetUp(); + AnimationWorkletMutatorDispatcher::AsyncMutationCompleteCallback + CreateIntermediateResultCallback(MutateStatus expected_result) { + return ConvertToBaseCallback( + CrossThreadBind(&AnimationWorkletMutatorDispatcherImplAsyncTest :: + VerifyExpectedMutationResult, + CrossThreadUnretained(this), expected_result)); } - // Call this version of mutate and wait if expecting a mutate completion - // notification from the client. - void CallMutateAndWaitForClientCompletion( - MutateAsyncCallback mutate_callback) { - base::WaitableEvent done_event; - client_->SignalWhenComplete(&done_event); - PostCrossThreadTask(*Thread::CompositorThread()->GetTaskRunner(), FROM_HERE, - std::move(mutate_callback)); - done_event.Wait(); + AnimationWorkletMutatorDispatcher::AsyncMutationCompleteCallback + CreateNotReachedCallback() { + return ConvertToBaseCallback(CrossThreadBind([](MutateStatus unused) { + NOTREACHED() << "Mutate complete callback should not have been triggered"; + })); } - // Call this version of mutate and wait if there is no expectation of client - // notifications. There are no notificaitons if the mutate call is a no-op - // such as when there are no inputs. - void CallMutateAndWaitForCallbackCompletion( - MutateAsyncCallback mutate_callback) { - base::WaitableEvent done_event; - PostCrossThreadTask(*Thread::CompositorThread()->GetTaskRunner(), FROM_HERE, - CrossThreadBind( - [](MutateAsyncCallback mutate_callback, - base::WaitableEvent* done_event) { - mutate_callback.Run(); - done_event->Signal(); - }, - WTF::Passed(std::move(mutate_callback)), - WTF::CrossThreadUnretained(&done_event))); - done_event.Wait(); + AnimationWorkletMutatorDispatcher::AsyncMutationCompleteCallback + CreateTestCompleteCallback() { + return ConvertToBaseCallback( + CrossThreadBind(&AnimationWorkletMutatorDispatcherImplAsyncTest :: + VerifyCompletedMutationResultAndFinish, + CrossThreadUnretained(this))); } + + // Executes run loop until quit closure is called. + void WaitForTestCompletion() { run_loop_.Run(); } + + void VerifyExpectedMutationResult(MutateStatus expectation, + MutateStatus result) { + EXPECT_EQ(expectation, result); + IntermediateResultCallbackRef(); + } + + void VerifyCompletedMutationResultAndFinish(MutateStatus result) { + EXPECT_EQ(MutateStatus::kCompleted, result); + run_loop_.QuitClosure().Run(); + } + + // Verifying that intermediate result callbacks are invoked the correct number + // of times. + MOCK_METHOD0(IntermediateResultCallbackRef, void()); + + private: + base::RunLoop run_loop_; }; TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, @@ -384,30 +388,22 @@ MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); - // Call MutateAsynchronously from the compositor thread. - MutateAsyncCallback mutate_callback = CrossThreadBind( - [](std::unique_ptr<Thread> first_thread, - MockAnimationWorkletMutator* first_mutator, - AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) { - async_test->mutator_->RegisterAnimationWorkletMutator( - first_mutator, first_thread->GetTaskRunner()); - async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput()); - }, - WTF::Passed(std::move(first_thread)), - WrapCrossThreadWeakPersistent(first_mutator), - WTF::CrossThreadUnretained(this)); + mutator_->RegisterAnimationWorkletMutator(first_mutator, + first_thread->GetTaskRunner()); - Sequence s; EXPECT_CALL(*first_mutator, GetWorkletId()) .Times(AtLeast(1)) .WillRepeatedly(Return(11)); EXPECT_CALL(*first_mutator, MutateRef(_)) .Times(1) .WillOnce(Return(new AnimationWorkletOutput())); - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s); - EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1).InSequence(s); - EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s); - CallMutateAndWaitForClientCompletion(std::move(mutate_callback)); + EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1); + + EXPECT_TRUE(mutator_->MutateAsynchronously(CreateTestMutatorInput(), + MutateQueuingStrategy::kDrop, + CreateTestCompleteCallback())); + + WaitForTestCompletion(); } TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, @@ -417,52 +413,32 @@ MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); - // Call MutateAsynchronously from the compositor thread. - MutateAsyncCallback mutate_callback = CrossThreadBind( - [](std::unique_ptr<Thread> first_thread, - MockAnimationWorkletMutator* first_mutator, - AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) { - async_test->mutator_->RegisterAnimationWorkletMutator( - first_mutator, first_thread->GetTaskRunner()); + mutator_->RegisterAnimationWorkletMutator(first_mutator, + first_thread->GetTaskRunner()); - AnimationWorkletInput::AddAndUpdateState state2{ - {22, 2}, "test2", 5000, nullptr, 1}; + AnimationWorkletInput::AddAndUpdateState state2{ + {22, 2}, "test2", 5000, nullptr, 1}; - auto input = std::make_unique<AnimationWorkletDispatcherInput>(); - input->Add(std::move(state2)); + auto input = std::make_unique<AnimationWorkletDispatcherInput>(); + input->Add(std::move(state2)); - async_test->mutator_->MutateAsynchronously(std::move(input)); - }, - WTF::Passed(std::move(first_thread)), - WrapCrossThreadWeakPersistent(first_mutator), - WTF::CrossThreadUnretained(this)); - - // The start of the mutation process will be synchronous. If a pending - // notification is not received by the time the callback returns, it will not - // be triggered later. EXPECT_CALL(*first_mutator, GetWorkletId()) .Times(AtLeast(1)) .WillRepeatedly(Return(11)); - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(0); - CallMutateAndWaitForCallbackCompletion(std::move(mutate_callback)); + + EXPECT_FALSE(mutator_->MutateAsynchronously(std::move(input), + MutateQueuingStrategy::kDrop, + CreateNotReachedCallback())); } TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateIsNotInvokedWithNoRegisteredAnimators) { - // Call MutateAsynchronously from the compositor thread. - MutateAsyncCallback mutate_callback = CrossThreadBind( - [](AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) { - std::unique_ptr<AnimationWorkletDispatcherInput> input = - std::make_unique<AnimationWorkletDispatcherInput>(); - async_test->mutator_->MutateAsynchronously(std::move(input)); - }, - WTF::CrossThreadUnretained(this)); - - // The start of the mutation process will be synchronous. If a pending - // notification is not received by the time the callback returns, it will not - // be triggered later. - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(0); - CallMutateAndWaitForCallbackCompletion(std::move(mutate_callback)); + EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0); + std::unique_ptr<AnimationWorkletDispatcherInput> input = + std::make_unique<AnimationWorkletDispatcherInput>(); + EXPECT_FALSE(mutator_->MutateAsynchronously(std::move(input), + MutateQueuingStrategy::kDrop, + CreateNotReachedCallback())); } TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, @@ -473,28 +449,20 @@ MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); - // Call MutateAsynchronously from the compositor thread. - MutateAsyncCallback mutate_callback = CrossThreadBind( - [](std::unique_ptr<Thread> first_thread, - MockAnimationWorkletMutator* first_mutator, - AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) { - async_test->mutator_->RegisterAnimationWorkletMutator( - first_mutator, first_thread->GetTaskRunner()); - async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput()); - }, - WTF::Passed(std::move(first_thread)), - WrapCrossThreadWeakPersistent(first_mutator), - WTF::CrossThreadUnretained(this)); + mutator_->RegisterAnimationWorkletMutator(first_mutator, + first_thread->GetTaskRunner()); - Sequence s; EXPECT_CALL(*first_mutator, GetWorkletId()) .Times(AtLeast(1)) .WillRepeatedly(Return(11)); EXPECT_CALL(*first_mutator, MutateRef(_)).Times(1).WillOnce(Return(nullptr)); - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s); EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0); - EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s); - CallMutateAndWaitForClientCompletion(std::move(mutate_callback)); + + EXPECT_TRUE(mutator_->MutateAsynchronously(CreateTestMutatorInput(), + MutateQueuingStrategy::kDrop, + CreateTestCompleteCallback())); + + WaitForTestCompletion(); } TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, @@ -505,50 +473,32 @@ MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); - // Call MutateAsynchronously from the compositor thread. - MutateAsyncCallback mutate_callback = CrossThreadBind( - [](std::unique_ptr<Thread> first_thread, - MockAnimationWorkletMutator* first_mutator, - AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) { - async_test->mutator_->RegisterAnimationWorkletMutator( - first_mutator, first_thread->GetTaskRunner()); - async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput()); - }, - WTF::Passed(std::move(first_thread)), - WrapCrossThreadWeakPersistent(first_mutator), - WTF::CrossThreadUnretained(this)); + mutator_->RegisterAnimationWorkletMutator(first_mutator, + first_thread->GetTaskRunner()); - Sequence s; EXPECT_CALL(*first_mutator, GetWorkletId()) .Times(AtLeast(1)) .WillRepeatedly(Return(11)); EXPECT_CALL(*first_mutator, MutateRef(_)) .Times(1) .WillOnce(Return(new AnimationWorkletOutput())); - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s); - EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1).InSequence(s); - EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s); - CallMutateAndWaitForClientCompletion(std::move(mutate_callback)); + EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1); + + EXPECT_TRUE(mutator_->MutateAsynchronously(CreateTestMutatorInput(), + MutateQueuingStrategy::kDrop, + CreateTestCompleteCallback())); + + WaitForTestCompletion(); // Above call blocks until complete signal is received. Mock::VerifyAndClearExpectations(client_.get()); - // Call MutateAsynchronously from the compositor thread. - MutateAsyncCallback mutate_callback2 = CrossThreadBind( - [](MockAnimationWorkletMutator* first_mutator, - AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) { - // Ensure mutator is not invoked after unregistration. - async_test->mutator_->UnregisterAnimationWorkletMutator(first_mutator); - async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput()); - }, - WrapCrossThreadWeakPersistent(first_mutator), - WTF::CrossThreadUnretained(this)); + // Ensure mutator is not invoked after unregistration. + mutator_->UnregisterAnimationWorkletMutator(first_mutator); + EXPECT_FALSE(mutator_->MutateAsynchronously(CreateTestMutatorInput(), + MutateQueuingStrategy::kDrop, + CreateNotReachedCallback())); - // The start of the mutation process will be synchronous. If a pending - // notification is not received by the time the callback returns, it will not - // be triggered later. - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(0); - CallMutateAndWaitForCallbackCompletion(std::move(mutate_callback2)); Mock::VerifyAndClearExpectations(client_.get()); } @@ -562,24 +512,11 @@ MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); - // Call MutateAsynchronously from the compositor thread. - MutateAsyncCallback mutate_callback = CrossThreadBind( - [](std::unique_ptr<Thread> first_thread, - MockAnimationWorkletMutator* first_mutator, - MockAnimationWorkletMutator* second_mutator, - AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) { - async_test->mutator_->RegisterAnimationWorkletMutator( - first_mutator, first_thread->GetTaskRunner()); - async_test->mutator_->RegisterAnimationWorkletMutator( - second_mutator, first_thread->GetTaskRunner()); - async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput()); - }, - WTF::Passed(std::move(first_thread)), - WrapCrossThreadWeakPersistent(first_mutator), - WrapCrossThreadWeakPersistent(second_mutator), - WTF::CrossThreadUnretained(this)); + mutator_->RegisterAnimationWorkletMutator(first_mutator, + first_thread->GetTaskRunner()); + mutator_->RegisterAnimationWorkletMutator(second_mutator, + first_thread->GetTaskRunner()); - Sequence s; EXPECT_CALL(*first_mutator, GetWorkletId()) .Times(AtLeast(1)) .WillRepeatedly(Return(11)); @@ -592,10 +529,13 @@ EXPECT_CALL(*second_mutator, MutateRef(_)) .Times(1) .WillOnce(Return(new AnimationWorkletOutput())); - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s); - EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2).InSequence(s); - EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s); - CallMutateAndWaitForClientCompletion(std::move(mutate_callback)); + EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2); + + EXPECT_TRUE(mutator_->MutateAsynchronously(CreateTestMutatorInput(), + MutateQueuingStrategy::kDrop, + CreateTestCompleteCallback())); + + WaitForTestCompletion(); } TEST_F( @@ -611,26 +551,11 @@ MakeGarbageCollected<MockAnimationWorkletMutator>( second_thread->GetTaskRunner()); - // Call MutateAsynchronously from the compositor thread. - MutateAsyncCallback mutate_callback = CrossThreadBind( - [](std::unique_ptr<Thread> first_thread, - std::unique_ptr<Thread> second_thread, - MockAnimationWorkletMutator* first_mutator, - MockAnimationWorkletMutator* second_mutator, - AnimationWorkletMutatorDispatcherImplAsyncTest* async_test) { - async_test->mutator_->RegisterAnimationWorkletMutator( - first_mutator, first_thread->GetTaskRunner()); - async_test->mutator_->RegisterAnimationWorkletMutator( - second_mutator, second_thread->GetTaskRunner()); - async_test->mutator_->MutateAsynchronously(CreateTestMutatorInput()); - }, - WTF::Passed(std::move(first_thread)), - WTF::Passed(std::move(second_thread)), - WrapCrossThreadWeakPersistent(first_mutator), - WrapCrossThreadWeakPersistent(second_mutator), - WTF::CrossThreadUnretained(this)); + mutator_->RegisterAnimationWorkletMutator(first_mutator, + first_thread->GetTaskRunner()); + mutator_->RegisterAnimationWorkletMutator(second_mutator, + second_thread->GetTaskRunner()); - Sequence s; EXPECT_CALL(*first_mutator, GetWorkletId()) .Times(AtLeast(1)) .WillRepeatedly(Return(11)); @@ -643,10 +568,84 @@ EXPECT_CALL(*second_mutator, MutateRef(_)) .Times(1) .WillOnce(Return(new AnimationWorkletOutput())); - EXPECT_CALL(*client_, NotifyAnimationsPending()).Times(1).InSequence(s); - EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2).InSequence(s); - EXPECT_CALL(*client_, NotifyAnimationsReadyRef()).Times(1).InSequence(s); - CallMutateAndWaitForClientCompletion(std::move(mutate_callback)); + EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2); + + EXPECT_TRUE(mutator_->MutateAsynchronously(CreateTestMutatorInput(), + MutateQueuingStrategy::kDrop, + CreateTestCompleteCallback())); + + WaitForTestCompletion(); +} + +TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, + MutationUpdateDroppedWhenBusy) { + std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + MockAnimationWorkletMutator* first_mutator = + MakeGarbageCollected<MockAnimationWorkletMutator>( + first_thread->GetTaskRunner()); + mutator_->RegisterAnimationWorkletMutator(first_mutator, + first_thread->GetTaskRunner()); + + EXPECT_CALL(*first_mutator, GetWorkletId()) + .Times(AtLeast(1)) + .WillRepeatedly(Return(11)); + EXPECT_CALL(*first_mutator, MutateRef(_)) + .Times(1) + .WillOnce(Return(new AnimationWorkletOutput())); + EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1); + + // Block Responses until all requests have been queued. + first_mutator->BlockWorkletThread(); + // Response for first mutator call is blocked until after the second + // call is sent. + EXPECT_TRUE(mutator_->MutateAsynchronously(CreateTestMutatorInput(), + MutateQueuingStrategy::kDrop, + CreateTestCompleteCallback())); + // Second request dropped since busy processing first. + EXPECT_FALSE(mutator_->MutateAsynchronously(CreateTestMutatorInput(), + MutateQueuingStrategy::kDrop, + CreateNotReachedCallback())); + // Unblock first request. + first_mutator->UnblockWorkletThread(); + + WaitForTestCompletion(); +} + +TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, + MutationUpdateQueuedWhenBusy) { + std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + + MockAnimationWorkletMutator* first_mutator = + MakeGarbageCollected<MockAnimationWorkletMutator>( + first_thread->GetTaskRunner()); + mutator_->RegisterAnimationWorkletMutator(first_mutator, + first_thread->GetTaskRunner()); + + EXPECT_CALL(*first_mutator, GetWorkletId()) + .Times(AtLeast(2)) + .WillRepeatedly(Return(11)); + EXPECT_CALL(*first_mutator, MutateRef(_)) + .Times(2) + .WillOnce(Return(new AnimationWorkletOutput())) + .WillOnce(Return(new AnimationWorkletOutput())); + EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2); + EXPECT_CALL(*this, IntermediateResultCallbackRef()).Times(1); + + // Block Responses until all requests have been queued. + first_mutator->BlockWorkletThread(); + // Response for first mutator call is blocked until after the second + // call is sent. + EXPECT_TRUE(mutator_->MutateAsynchronously( + CreateTestMutatorInput(), MutateQueuingStrategy::kDrop, + CreateIntermediateResultCallback(MutateStatus::kCompleted))); + // First request still processing, queue request. + EXPECT_TRUE(mutator_->MutateAsynchronously( + CreateTestMutatorInput(), MutateQueuingStrategy::kQueueAndReplace, + CreateTestCompleteCallback())); + // Unblock first request. + first_mutator->UnblockWorkletThread(); + + WaitForTestCompletion(); } } // namespace
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutators_state.h b/third_party/blink/renderer/platform/graphics/animation_worklet_mutators_state.h index f559e973..0cabaa5 100644 --- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutators_state.h +++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutators_state.h
@@ -14,6 +14,8 @@ using AnimationWorkletDispatcherInput = cc::MutatorInputState; using AnimationWorkletDispatcherOutput = cc::MutatorOutputState; using WorkletAnimationId = cc::WorkletAnimationId; +using MutateQueuingStrategy = cc::MutateQueuingStrategy; +using MutateStatus = cc::MutateStatus; } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h index f0a99e9..7be2a33 100644 --- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h +++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
@@ -8,7 +8,7 @@ #include "base/optional.h" #include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h" #include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h" -#include "third_party/blink/renderer/platform/scroll/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h"
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h index 049abc1c..470b482 100644 --- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h +++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h
@@ -6,8 +6,8 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_GEOMETRY_MAPPER_CLIP_CACHE_H_ #include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h" +#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/scroll/scroll_types.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink {
diff --git a/third_party/blink/renderer/platform/graphics/scroll_types.h b/third_party/blink/renderer/platform/graphics/scroll_types.h new file mode 100644 index 0000000..1f00a31 --- /dev/null +++ b/third_party/blink/renderer/platform/graphics/scroll_types.h
@@ -0,0 +1,21 @@ +// Copyright 2019 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_PLATFORM_GRAPHICS_SCROLL_TYPES_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SCROLL_TYPES_H_ + +namespace blink { + +// Platform overlay scrollbars are controlled and painted by the operating +// system (e.g., OSX and Android). CSS overlay scrollbars are created by +// setting overflow:overlay, and they are painted by chromium. +enum OverlayScrollbarClipBehavior { + kIgnorePlatformOverlayScrollbarSize, + kIgnorePlatformAndCSSOverlayScrollbarSize, + kExcludeOverlayScrollbarSizeForHitTesting +}; + +} // namespace blink + +#endif
diff --git a/third_party/blink/renderer/platform/scroll/scroll_types.h b/third_party/blink/renderer/platform/scroll/scroll_types.h index 6be6f516..da6ee9a 100644 --- a/third_party/blink/renderer/platform/scroll/scroll_types.h +++ b/third_party/blink/renderer/platform/scroll/scroll_types.h
@@ -44,15 +44,6 @@ return ScrollOffset(p.X(), p.Y()); } -// Platform overlay scrollbars are controlled and painted by the operating -// system (e.g., OSX and Android). CSS overlay scrollbars are created by -// setting overflow:overlay, and they are painted by chromium. -enum OverlayScrollbarClipBehavior { - kIgnorePlatformOverlayScrollbarSize, - kIgnorePlatformAndCSSOverlayScrollbarSize, - kExcludeOverlayScrollbarSizeForHitTesting -}; - using ScrollDirection = WebScrollDirection; using ScrollGranularity = WebScrollGranularity; @@ -272,4 +263,4 @@ } // namespace blink -#endif +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_SCROLL_TYPES_H_
diff --git a/third_party/blink/renderer/platform/testing/run_all_tests.cc b/third_party/blink/renderer/platform/testing/run_all_tests.cc index 8b7ea4b..88ed726 100644 --- a/third_party/blink/renderer/platform/testing/run_all_tests.cc +++ b/third_party/blink/renderer/platform/testing/run_all_tests.cc
@@ -33,8 +33,10 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_io_thread.h" #include "base/test/test_suite.h" +#include "build/build_config.h" #include "mojo/core/embedder/embedder.h" #include "mojo/core/embedder/scoped_ipc_support.h" +#include "skia/ext/test_fonts.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" @@ -51,6 +53,14 @@ int main(int argc, char** argv) { blink::ScopedUnittestsEnvironmentSetup testEnvironmentSetup(argc, argv); int result = 0; + +#if defined(OS_FUCHSIA) + // Some unittests depend on specific fonts provided by the system (e.g. some + // tests load Arial). On Fuchsia the default font set contains only Roboto. + // Load //third_party/test_fonts to make these tests pass on Fuchsia. + skia::ConfigureTestFont(); +#endif + { base::TestSuite testSuite(argc, argv);
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc b/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc index e2ffef20..5aebe0ba 100644 --- a/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc +++ b/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc
@@ -56,6 +56,14 @@ return nullptr; } uintptr_t Id() const override { return internal_->id(); } + rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override { + return nullptr; + } + webrtc::DtlsTransportInformation DtlsTransportInformation() override { + static webrtc::DtlsTransportInformation dummy( + webrtc::DtlsTransportState::kNew); + return dummy; + } WebMediaStreamTrack Track() const override { return internal_->track(); } WebVector<WebString> StreamIds() const override { return std::vector<WebString>({WebString::FromUTF8("DummyStringId")}); @@ -109,6 +117,14 @@ return nullptr; } uintptr_t Id() const override { return id_; } + rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override { + return nullptr; + } + webrtc::DtlsTransportInformation DtlsTransportInformation() override { + static webrtc::DtlsTransportInformation dummy( + webrtc::DtlsTransportState::kNew); + return dummy; + } const WebMediaStreamTrack& Track() const override { return track_; } WebVector<WebString> StreamIds() const override { return WebVector<WebString>();
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index c28ee0c..41a925f0 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -88,14 +88,11 @@ crbug.com/450493 http/tests/devtools/profiler/ [ Slow ] crbug.com/420008 http/tests/devtools/tracing/ [ Slow ] crbug.com/420008 virtual/threaded/http/tests/devtools/tracing/ [ Slow ] -crbug.com/902685 http/tests/devtools/isolated-code-cache/same-origin-test.js [ Slow ] -crbug.com/902685 http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Slow ] +crbug.com/902685 http/tests/devtools/isolated-code-cache/ [ Slow ] +crbug.com/902685 virtual/site-isolated-code-cache/http/tests/devtools/isolated-code-cache/ [ Slow ] +crbug.com/902685 virtual/not-site-per-process/http/tests/devtools/isolated-code-cache/ [ Slow ] crbug.com/902685 http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Slow ] -crbug.com/902685 virtual/site-isolated-code-cache/http/tests/devtools/isolated-code-cache/same-origin-test.js [ Slow ] -crbug.com/902685 virtual/site-isolated-code-cache/http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Slow ] crbug.com/902685 virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Slow ] -crbug.com/902685 virtual/not-site-per-process/http/tests/devtools/isolated-code-cache/same-origin-test.js [ Slow ] -crbug.com/902685 virtual/not-site-per-process/http/tests/devtools/isolated-code-cache/cross-origin-test.js [ Slow ] # Misc DevTools tests that are slow crbug.com/246190 [ Release ] http/tests/devtools/indexeddb/ [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index c87e1ad..d897682 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3025,6 +3025,11 @@ crbug.com/918664 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-table-1a.html [ Failure Pass ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/reporting/disconnect.html [ Timeout ] +crbug.com/626703 external/wpt/reporting/generateTestReport.html [ Timeout ] +crbug.com/626703 external/wpt/reporting/bufferSize.html [ Timeout ] +crbug.com/626703 external/wpt/reporting/order.html [ Timeout ] +crbug.com/626703 external/wpt/reporting/nestedReport.html [ Timeout ] crbug.com/626703 [ Retina ] virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/navigation-preload/empty-preload-response-body.https.html [ Timeout ] crbug.com/626703 [ Retina ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/idlharness.https.window.html [ Timeout ] crbug.com/626703 [ Retina ] virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/oninstall-script-error.https.html [ Timeout ] @@ -3109,14 +3114,6 @@ crbug.com/626703 external/wpt/svg/interact/manual/event-attribute-001-manual.svg [ Skip ] crbug.com/626703 [ Retina ] virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/async_005.htm [ Timeout ] crbug.com/626703 external/wpt/css/css-text/tab-size/tab-size-spacing-001.html [ Failure ] -crbug.com/626703 external/wpt/referrer-policy/generic/iframe-inheritance.html [ Timeout ] -crbug.com/626703 virtual/outofblink-cors/external/wpt/referrer-policy/generic/iframe-inheritance.html [ Timeout ] -crbug.com/626703 virtual/omt-worker-fetch/external/wpt/referrer-policy/generic/iframe-inheritance.html [ Timeout ] -crbug.com/626703 virtual/omt-worker-fetch/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html [ Timeout ] -crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/referrer-policy/generic/iframe-inheritance.html [ Timeout ] -crbug.com/626703 virtual/outofblink-cors/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html [ Timeout ] -crbug.com/626703 external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html [ Timeout ] -crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html [ Timeout ] crbug.com/626703 external/wpt/css/css-values/vh-support-atviewport.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/boundary-shaping/boundary-shaping-005.html [ Failure ] crbug.com/626703 external/wpt/css/CSS2/text/white-space-nowrap-attribute-001.xht [ Failure ]
diff --git a/third_party/blink/web_tests/accessibility/contenteditable-caret-position.html b/third_party/blink/web_tests/accessibility/contenteditable-caret-position.html index 5a2d6b40..4d4ba8c 100644 --- a/third_party/blink/web_tests/accessibility/contenteditable-caret-position.html +++ b/third_party/blink/web_tests/accessibility/contenteditable-caret-position.html
@@ -18,188 +18,203 @@ </div> <script> - test(function() + test(() => { - var mainAccessible = accessibilityController.accessibleElementById("main"); + let mainAccessible = accessibilityController.accessibleElementById("main"); - assert_equals(mainAccessible.selectionStart, 0); - assert_equals(mainAccessible.selectionEnd, 0); + assert_equals(mainAccessible.selectionAnchorObject, null); + assert_equals(mainAccessible.selectionAnchorOffset, -1); + assert_equals(mainAccessible.selectionFocusObject, null); + assert_equals(mainAccessible.selectionFocusOffset, -1); }, "Initially there should be no selection under the main object."); -</script> -<script> - test(function() + test(() => { - var rootAccessible = accessibilityController.rootElement; + let rootAccessible = accessibilityController.rootElement; assert_equals(rootAccessible.selectionAnchorObject, null); assert_equals(rootAccessible.selectionAnchorOffset, -1); assert_equals(rootAccessible.selectionFocusObject, null); assert_equals(rootAccessible.selectionFocusOffset, -1); }, "Initially there should be no selection on the root object."); -</script> -<script> - test(function() + test(() => { - var textbox = document.getElementById("contenteditable-textbox"); + let textbox = document.getElementById("contenteditable-textbox"); textbox.focus(); - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - assert_equals(textboxAccessible.selectionStart, 0); - assert_equals(textboxAccessible.selectionEnd, 0); + assert_equals(textboxAccessible.selectionAnchorOffset, 0); + assert_equals(textboxAccessible.selectionFocusOffset, 0); }, "Moving the focus to an ARIA textbox should place the caret at its beginning."); -</script> -<script> - test(function() + test(() => { - var selection = window.getSelection(); - var selectionRange = document.createRange(); - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; - var line1 = document.getElementById("contenteditable-line1"); - var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); - var line1TextAccessible = line1Accessible.childAtIndex(0); + let selection = window.getSelection(); + let selectionRange = document.createRange(); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; + let line1 = document.getElementById("contenteditable-line1"); + let line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); + let line1TextAccessible = line1Accessible.childAtIndex(0); selectionRange.setStart(line1.firstChild, 1); selectionRange.setEnd(line1.firstChild, 1); selection.removeAllRanges(); selection.addRange(selectionRange); - assert_equals(textboxAccessible.selectionStart, 1); - assert_equals(textboxAccessible.selectionEnd, 1); + assert_equals(textboxAccessible.selectionAnchorObject, line1TextAccessible); + assert_equals(textboxAccessible.selectionAnchorOffset, 1); + assert_equals(textboxAccessible.selectionFocusObject, line1TextAccessible); + assert_equals(textboxAccessible.selectionFocusOffset, 1); - assert_equals(mainAccessible.selectionStart, 1); - assert_equals(mainAccessible.selectionEnd, 1); + assert_equals(mainAccessible.selectionAnchorObject, line1TextAccessible); + assert_equals(mainAccessible.selectionAnchorOffset, 1); + assert_equals(mainAccessible.selectionFocusObject, line1TextAccessible); + assert_equals(mainAccessible.selectionFocusOffset, 1); assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible); assert_equals(rootAccessible.selectionAnchorOffset, 1); assert_equals(rootAccessible.selectionFocusObject, line1TextAccessible); assert_equals(rootAccessible.selectionFocusOffset, 1); }, "Setting a new caret position in the ARIA textbox should be reflected in the accessibility APIs."); -</script> -<script> - test(function() + test(() => { - var selection = window.getSelection(); - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; + let selection = window.getSelection(); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; selection.removeAllRanges(); - assert_equals(textboxAccessible.selectionStart, 0); - assert_equals(textboxAccessible.selectionEnd, 0); + assert_equals(textboxAccessible.selectionAnchorObject, null); + assert_equals(textboxAccessible.selectionAnchorOffset, -1); + assert_equals(textboxAccessible.selectionFocusObject, null); + assert_equals(textboxAccessible.selectionFocusOffset, -1); - assert_equals(mainAccessible.selectionStart, 0); - assert_equals(mainAccessible.selectionEnd, 0); + assert_equals(mainAccessible.selectionAnchorObject, null); + assert_equals(mainAccessible.selectionAnchorOffset, -1); + assert_equals(mainAccessible.selectionFocusObject, null); + assert_equals(mainAccessible.selectionFocusOffset, -1); assert_equals(rootAccessible.selectionAnchorObject, null); assert_equals(rootAccessible.selectionAnchorOffset, -1); assert_equals(rootAccessible.selectionFocusObject, null); assert_equals(rootAccessible.selectionFocusOffset, -1); }, "Removing the selection should remove the caret completely."); -</script> -<script> - test(function() + test(() => { - var selection = window.getSelection(); - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; - var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); - var line1TextAccessible = line1Accessible.childAtIndex(0); + let selection = window.getSelection(); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; + let line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); + let line1TextAccessible = line1Accessible.childAtIndex(0); line1TextAccessible.setSelectedTextRange(2, 0); - assert_equals(textboxAccessible.selectionStart, 2); - assert_equals(textboxAccessible.selectionEnd, 2); + assert_equals(textboxAccessible.selectionAnchorObject, line1TextAccessible); + assert_equals(textboxAccessible.selectionAnchorOffset, 2); + assert_equals(textboxAccessible.selectionFocusObject, line1TextAccessible); + assert_equals(textboxAccessible.selectionFocusOffset, 2); - assert_equals(mainAccessible.selectionStart, 2); - assert_equals(mainAccessible.selectionEnd, 2); + assert_equals(mainAccessible.selectionAnchorObject, line1TextAccessible); + assert_equals(mainAccessible.selectionAnchorOffset, 2); + assert_equals(mainAccessible.selectionFocusObject, line1TextAccessible); + assert_equals(mainAccessible.selectionFocusOffset, 2); assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible); assert_equals(rootAccessible.selectionAnchorOffset, 2); assert_equals(rootAccessible.selectionFocusObject, line1TextAccessible); assert_equals(rootAccessible.selectionFocusOffset, 2); }, "Positioning the caret using the accessibility API instead of the DOM should work."); -</script> -<script> - test(function() + test(() => { - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var line2 = document.getElementById("contenteditable-line2"); + let line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let line2 = document.getElementById("contenteditable-line2"); line2.focus(); - assert_equals(textboxAccessible.selectionStart, 0); - assert_equals(textboxAccessible.selectionEnd, 0); + assert_equals(line2Accessible.selectionAnchorObject, line2Accessible); + assert_equals(line2Accessible.selectionAnchorOffset, 0); + assert_equals(line2Accessible.selectionFocusObject, line2Accessible); + assert_equals(line2Accessible.selectionFocusOffset, 0); - assert_equals(mainAccessible.selectionStart, 0); - assert_equals(mainAccessible.selectionEnd, 0); + assert_equals(textboxAccessible.selectionAnchorObject, line2Accessible); + assert_equals(textboxAccessible.selectionAnchorOffset, 0); + assert_equals(textboxAccessible.selectionFocusObject, line2Accessible); + assert_equals(textboxAccessible.selectionFocusOffset, 0); + + assert_equals(mainAccessible.selectionAnchorObject, line2Accessible); + assert_equals(mainAccessible.selectionAnchorOffset, 0); + assert_equals(mainAccessible.selectionFocusObject, line2Accessible); + assert_equals(mainAccessible.selectionFocusOffset, 0); }, "Moving the focus into a textarea should remove the caret from the ARIA textbox."); -</script> -<script> - test(function() + test(() => { - var rootAccessible = accessibilityController.rootElement; - var line2Accessible = accessibilityController.focusedElement; + document.getElementById("contenteditable-line2").focus(); + let rootAccessible = accessibilityController.rootElement; + let line2Accessible = accessibilityController.focusedElement; assert_equals(rootAccessible.selectionAnchorObject, line2Accessible); assert_equals(rootAccessible.selectionAnchorOffset, 0); assert_equals(rootAccessible.selectionFocusObject, line2Accessible); assert_equals(rootAccessible.selectionFocusOffset, 0); - assert_equals(line2Accessible.selectionStart, 0); - assert_equals(line2Accessible.selectionEnd, 0); + assert_equals(line2Accessible.selectionAnchorObject, line2Accessible); + assert_equals(line2Accessible.selectionAnchorOffset, 0); + assert_equals(line2Accessible.selectionFocusObject, line2Accessible); + assert_equals(line2Accessible.selectionFocusOffset, 0); }, "Standard text fields start with the caret at the beginning of their contents."); -</script> -<script> - test(function() + test(() => { - var line2 = document.getElementById("contenteditable-line2"); - var line2Accessible = accessibilityController.focusedElement; + let line2 = document.getElementById("contenteditable-line2"); + line2.focus(); + let line2Accessible = accessibilityController.focusedElement; line2.setSelectionRange(3, 3); - assert_equals(line2Accessible.selectionStart, 3); - assert_equals(line2Accessible.selectionEnd, 3); + assert_equals(line2Accessible.selectionAnchorObject, line2Accessible); + assert_equals(line2Accessible.selectionAnchorOffset, 3); + assert_equals(line2Accessible.selectionFocusObject, line2Accessible); + assert_equals(line2Accessible.selectionFocusOffset, 3); }, "Setting a new caret position in the textarea should be exposed in the accessibility APIs."); -</script> -<script> - test(function() + test(() => { - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; - var line2Accessible = accessibilityController.focusedElement; + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; + document.getElementById("contenteditable-line2").focus(); + let line2Accessible = accessibilityController.focusedElement; - assert_equals(textboxAccessible.selectionStart, 3); - assert_equals(textboxAccessible.selectionEnd, 3); + assert_equals(textboxAccessible.selectionAnchorObject, line2Accessible); + assert_equals(textboxAccessible.selectionAnchorOffset, 3); + assert_equals(textboxAccessible.selectionFocusObject, line2Accessible); + assert_equals(textboxAccessible.selectionFocusOffset, 3); - assert_equals(mainAccessible.selectionStart, 3); - assert_equals(mainAccessible.selectionEnd, 3); + assert_equals(mainAccessible.selectionAnchorObject, line2Accessible); + assert_equals(mainAccessible.selectionAnchorOffset, 3); + assert_equals(mainAccessible.selectionFocusObject, line2Accessible); + assert_equals(mainAccessible.selectionFocusOffset, 3); assert_equals(rootAccessible.selectionAnchorObject, line2Accessible); assert_equals(rootAccessible.selectionAnchorOffset, 3); assert_equals(rootAccessible.selectionFocusObject, line2Accessible); assert_equals(rootAccessible.selectionFocusOffset, 3); }, "Offsets in text fields should be reported from the beginning of the field and not from the top of the container."); -</script> -<script> - test(function() + test(() => { - var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); - var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); + let line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); + let line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); assert_equals(line1Accessible.selectionAnchorObject, line2Accessible); assert_equals(line1Accessible.selectionAnchorOffset, 3); @@ -210,73 +225,61 @@ assert_equals(line2Accessible.selectionFocusObject, line2Accessible); assert_equals(line2Accessible.selectionFocusOffset, 3); }, "The caret position should be retrievable from any object."); -</script> -<script> - test(function() + test(() => { - var selection = window.getSelection(); - var selectionRange = document.createRange(); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; + let selection = window.getSelection(); + let selectionRange = document.createRange(); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; - var contenteditable = document.getElementById("contenteditable-div"); + let contenteditable = document.getElementById("contenteditable-div"); contenteditable.focus(); - // The offset from the beginning of the main div to the first character of - // contenteditable-div. - var mainOffset = 9; // The offset from the newline character between the two lines of the // first paragraph to the first character of its second line. // (Needed for skipping wide space.) - var line2Offset = 13; + let line2Offset = 13; - var line1 = document.getElementById("paragraph1").firstChild; - var line2 = document.getElementById("paragraph1").lastChild; - var line3 = document.getElementById("paragraph2").firstChild; - var contenteditableLines = [ line1, line2, line3 ]; - var contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div"); + let line1 = document.getElementById("paragraph1").firstChild; + let line2 = document.getElementById("paragraph1").lastChild; + let line3 = document.getElementById("paragraph2").firstChild; + let contenteditableLines = [ line1, line2, line3 ]; + let contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div"); - for (var lineNumber = 0; lineNumber < 3; ++lineNumber) { - var lineOffset = lineNumber * 7; + for (let lineNumber = 0; lineNumber < 3; ++lineNumber) { + let lineOffset = lineNumber * 7; // Paragraphs should be separated by an empty line. if (lineNumber == 2) ++lineOffset; - for (var characterOffset = 0; characterOffset < 7; ++characterOffset) { + for (let characterOffset = 0; characterOffset < 7; ++characterOffset) { // Any widespace in the DOM should be stripped out. - var selectionOffset = characterOffset; + let selectionOffset = characterOffset; if (lineNumber == 1) selectionOffset += line2Offset; - var caretPosition = lineOffset + characterOffset; selectionRange.setStart(contenteditableLines[lineNumber], selectionOffset); selectionRange.setEnd(contenteditableLines[lineNumber], selectionOffset); selection.removeAllRanges(); selection.addRange(selectionRange); - assert_equals(contenteditableAccessible.selectionStart, caretPosition); - assert_equals(contenteditableAccessible.selectionEnd, caretPosition); + assert_equals(contenteditableAccessible.selectionAnchorOffset, characterOffset); + assert_equals(contenteditableAccessible.selectionFocusOffset, characterOffset); - assert_equals(mainAccessible.selectionStart, - mainOffset + caretPosition); - assert_equals(mainAccessible.selectionEnd, - mainOffset + caretPosition); + assert_equals(mainAccessible.selectionAnchorOffset, characterOffset); + assert_equals(mainAccessible.selectionFocusOffset, characterOffset); assert_equals(rootAccessible.selectionAnchorObject.name, contenteditableLines[lineNumber].textContent.trim()); - assert_equals(rootAccessible.selectionAnchorOffset, - characterOffset); + assert_equals(rootAccessible.selectionAnchorOffset, characterOffset); assert_equals(rootAccessible.selectionFocusObject.name, contenteditableLines[lineNumber].textContent.trim()); - assert_equals(rootAccessible.selectionFocusOffset, - characterOffset); + assert_equals(rootAccessible.selectionFocusOffset, characterOffset); } } }, "Test moving the caret across two paragraphs."); -</script> -<script> if (window.testRunner) document.getElementById("main").style.display = "none"; </script>
diff --git a/third_party/blink/web_tests/accessibility/contenteditable-selection.html b/third_party/blink/web_tests/accessibility/contenteditable-selection.html index fd740f2..5cb78c0 100644 --- a/third_party/blink/web_tests/accessibility/contenteditable-selection.html +++ b/third_party/blink/web_tests/accessibility/contenteditable-selection.html
@@ -17,17 +17,17 @@ </div> <script> - test(function() + test(() => { - var selection = window.getSelection(); - var selectionRange = document.createRange(); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; + let selection = window.getSelection(); + let selectionRange = document.createRange(); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; - var textbox = document.getElementById("contenteditable-textbox"); - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); - var line1TextAccessible = line1Accessible.childAtIndex(0); + let textbox = document.getElementById("contenteditable-textbox"); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); + let line1TextAccessible = line1Accessible.childAtIndex(0); // Select the entire contents of the outer ARIA textbox. // These include another ARIA textbox and a textarea node @@ -37,34 +37,34 @@ selection.removeAllRanges(); selection.addRange(selectionRange); - assert_equals(textboxAccessible.selectionStart, 0); + assert_equals(textboxAccessible.selectionAnchorOffset, 0); // 7 for the "Line 1" text div + 1 for the textarea node. // (The textarea node should be treated as a single unit.) - assert_equals(textboxAccessible.selectionEnd, 8); + assert_equals(textboxAccessible.selectionFocusOffset, 8); // Selection offsets should be the same when retrieved from the parent object. - assert_equals(mainAccessible.selectionStart, 0); - assert_equals(mainAccessible.selectionEnd, 8); + assert_equals(mainAccessible.selectionAnchorObject, line1TextAccessible); + assert_equals(mainAccessible.selectionAnchorOffset, 0); + assert_equals(mainAccessible.selectionAnchorObject, line1TextAccessible); + assert_equals(mainAccessible.selectionFocusOffset, 8); assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible); assert_equals(rootAccessible.selectionAnchorOffset, 0); assert_equals(rootAccessible.selectionFocusObject, textboxAccessible); assert_equals(rootAccessible.selectionFocusOffset, 8); }, "Test selectNodeContents on an ARIA textbox."); -</script> -<script> - test(function() + test(() => { - var selection = window.getSelection(); - var selectionRange = document.createRange(); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; + let selection = window.getSelection(); + let selectionRange = document.createRange(); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; - var contenteditable = document.getElementById("contenteditable-div"); - var line1 = document.getElementById("paragraph1").firstChild; - var line3 = document.getElementById("paragraph2").firstChild; - var contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div"); + let contenteditable = document.getElementById("contenteditable-div"); + let line1 = document.getElementById("paragraph1").firstChild; + let line3 = document.getElementById("paragraph2").firstChild; + let contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div"); // Select the entire contents of the second content editable. contenteditable.focus(); @@ -72,12 +72,11 @@ selection.removeAllRanges(); selection.addRange(selectionRange); - assert_equals(contenteditableAccessible.selectionStart, 0); - assert_equals(contenteditableAccessible.selectionEnd, 21); + assert_equals(contenteditableAccessible.selectionAnchorOffset, 0); + assert_equals(contenteditableAccessible.selectionFocusOffset, 6); - // 7 for line1 + 1 for the textarea + 1 for the blank line. - assert_equals(mainAccessible.selectionStart, 9); - assert_equals(mainAccessible.selectionEnd, 30); + assert_equals(mainAccessible.selectionAnchorOffset, 0); + assert_equals(mainAccessible.selectionFocusOffset, 6); assert_equals(rootAccessible.selectionAnchorObject.name, line1.textContent); @@ -86,19 +85,17 @@ line3.textContent); assert_equals(rootAccessible.selectionFocusOffset, 6); }, "Test selectNodeContents on a contenteditable."); -</script> -<script> - test(function() + test(() => { - var selection = window.getSelection(); - var selectionRange = document.createRange(); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var line1 = document.getElementById("contenteditable-line1"); - var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); - var line1TextAccessible = line1Accessible.childAtIndex(0); + let selection = window.getSelection(); + let selectionRange = document.createRange(); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let line1 = document.getElementById("contenteditable-line1"); + let line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); + let line1TextAccessible = line1Accessible.childAtIndex(0); // Select only the first line of the ARIA textbox. selectionRange.setStart(line1.firstChild, 0); @@ -106,135 +103,133 @@ selection.removeAllRanges(); selection.addRange(selectionRange); - assert_equals(textboxAccessible.selectionStart, 0); - assert_equals(textboxAccessible.selectionEnd, 6); + assert_equals(textboxAccessible.selectionAnchorObject, line1TextAccessible); + assert_equals(textboxAccessible.selectionAnchorOffset, 0); + assert_equals(textboxAccessible.selectionFocusObject, line1TextAccessible); + assert_equals(textboxAccessible.selectionFocusOffset, 6); - assert_equals(mainAccessible.selectionStart, 0); - assert_equals(mainAccessible.selectionEnd, 6); + assert_equals(mainAccessible.selectionAnchorObject, line1TextAccessible); + assert_equals(mainAccessible.selectionAnchorOffset, 0); + assert_equals(mainAccessible.selectionFocusObject, line1TextAccessible); + assert_equals(mainAccessible.selectionFocusOffset, 6); assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible); assert_equals(rootAccessible.selectionAnchorOffset, 0); assert_equals(rootAccessible.selectionFocusObject, line1TextAccessible); assert_equals(rootAccessible.selectionFocusOffset, 6); }, "The effects of the setStart and setEnd methods should be reflected in the accessibility API."); -</script> -<script> - test(function() + test(() => { - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var rootAccessible = accessibilityController.rootElement; - var line2 = document.getElementById("contenteditable-line2"); - var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let rootAccessible = accessibilityController.rootElement; + let line2 = document.getElementById("contenteditable-line2"); + let line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); line2.focus(); // The selection should have been removed from the line1 div // due to the focus being moved. - assert_equals(textboxAccessible.selectionStart, 0); - assert_equals(textboxAccessible.selectionEnd, 0); + assert_equals(textboxAccessible.selectionAnchorObject, line2Accessible); + assert_equals(textboxAccessible.selectionAnchorOffset, 0); + assert_equals(textboxAccessible.selectionFocusObject, line2Accessible); + assert_equals(textboxAccessible.selectionFocusOffset, 0); + assert_equals(rootAccessible.selectionAnchorObject, line2Accessible); assert_equals(rootAccessible.selectionAnchorOffset, 0); assert_equals(rootAccessible.selectionFocusObject, line2Accessible); assert_equals(rootAccessible.selectionFocusOffset, 0); }, "Verify that changing the focus removes the selection."); -</script> -<script> - test(function() + test(() => { - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; - var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); - var line2 = document.getElementById("contenteditable-line2"); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; + let line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); + let line2 = document.getElementById("contenteditable-line2"); // Select only the second line of the ARIA textbox, that is, // the one found in the textarea. line2.setSelectionRange(0, line2.textLength); - assert_equals(line2Accessible.selectionStart, 0); - assert_equals(line2Accessible.selectionEnd, line2.textLength); + assert_equals(line2Accessible.selectionAnchorOffset, 0); + assert_equals(line2Accessible.selectionFocusOffset, line2.textLength); - // Unlike for other elements, offsets in text fields should be - // reported from the beginning of the field and not from the top of the - // container on which the API was called. - assert_equals(textboxAccessible.selectionStart, 0); - assert_equals(textboxAccessible.selectionEnd, line2.textLength); + assert_equals(textboxAccessible.selectionAnchorObject, line2Accessible); + assert_equals(textboxAccessible.selectionAnchorOffset, 0); + assert_equals(textboxAccessible.selectionFocusObject, line2Accessible); + assert_equals(textboxAccessible.selectionFocusOffset, line2.textLength); - assert_equals(mainAccessible.selectionStart, 0); - assert_equals(mainAccessible.selectionEnd, line2.textLength); + assert_equals(mainAccessible.selectionAnchorObject, line2Accessible); + assert_equals(mainAccessible.selectionAnchorOffset, 0); + assert_equals(mainAccessible.selectionFocusObject, line2Accessible); + assert_equals(mainAccessible.selectionFocusOffset, line2.textLength); assert_equals(rootAccessible.selectionAnchorObject, line2Accessible); assert_equals(rootAccessible.selectionAnchorOffset, 0); assert_equals(rootAccessible.selectionFocusObject, line2Accessible); assert_equals(rootAccessible.selectionFocusOffset, line2.textLength); }, "The effects of the textarea.setSelectionRange method should be reflected in the accessibility API."); -</script> -<script> - test(function() + test(() => { - var textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; - var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); + let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; + let line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); // Selection can also be set via the accessibility API. line2Accessible.setSelectedTextRange(2, 3); - assert_equals(line2Accessible.selectionStart, 2); - assert_equals(line2Accessible.selectionEnd, 5); + assert_equals(line2Accessible.selectionAnchorObject, line2Accessible); + assert_equals(line2Accessible.selectionAnchorOffset, 2); + assert_equals(line2Accessible.selectionFocusObject, line2Accessible); + assert_equals(line2Accessible.selectionFocusOffset, 5); - assert_equals(textboxAccessible.selectionStart, 2); - assert_equals(textboxAccessible.selectionEnd, 5); + assert_equals(textboxAccessible.selectionAnchorObject, line2Accessible); + assert_equals(textboxAccessible.selectionAnchorOffset, 2); + assert_equals(textboxAccessible.selectionFocusObject, line2Accessible); + assert_equals(textboxAccessible.selectionFocusOffset, 5); - assert_equals(mainAccessible.selectionStart, 2); - assert_equals(mainAccessible.selectionEnd, 5); + assert_equals(mainAccessible.selectionAnchorObject, line2Accessible); + assert_equals(mainAccessible.selectionAnchorOffset, 2); + assert_equals(mainAccessible.selectionFocusObject, line2Accessible); + assert_equals(mainAccessible.selectionFocusOffset, 5); assert_equals(rootAccessible.selectionAnchorObject, line2Accessible); assert_equals(rootAccessible.selectionAnchorOffset, 2); assert_equals(rootAccessible.selectionFocusObject, line2Accessible); assert_equals(rootAccessible.selectionFocusOffset, 5); }, "Test the setSelectedTextRange accessibility API function."); -</script> -<script> - test(function() + test(() => { - var selection = window.getSelection(); - var selectionRange = document.createRange(); - var mainAccessible = accessibilityController.accessibleElementById("main"); - var rootAccessible = accessibilityController.rootElement; + let selection = window.getSelection(); + let selectionRange = document.createRange(); + let mainAccessible = accessibilityController.accessibleElementById("main"); + let rootAccessible = accessibilityController.rootElement; - var contenteditable = document.getElementById("contenteditable-div"); - var line1 = document.getElementById("paragraph1").firstChild; - var line2 = document.getElementById("paragraph1").lastChild; - var line3 = document.getElementById("paragraph2").firstChild; - var contenteditableLines = [ line1, line2, line3 ]; - var contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div"); + let contenteditable = document.getElementById("contenteditable-div"); + let line1 = document.getElementById("paragraph1").firstChild; + let line2 = document.getElementById("paragraph1").lastChild; + let line3 = document.getElementById("paragraph2").firstChild; + let contenteditableLines = [ line1, line2, line3 ]; + let contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div"); // Select entire lines in the second content editable. - for (var testCase = 0; testCase < 2; ++testCase) { + for (let testCase = 0; testCase < 2; ++testCase) { - for (var i = 0; i < contenteditableLines.length; ++i) { - var start = i * 7; - var end = i * 7 + 6; - if (i == 2) { - // Paragraphs have a blank line between them. - ++start; - ++end; - } - + for (let i = 0; i < contenteditableLines.length; ++i) { selectionRange.selectNode(contenteditableLines[i]); selection.removeAllRanges(); selection.addRange(selectionRange); - assert_equals(contenteditableAccessible.selectionStart, start); - assert_equals(contenteditableAccessible.selectionEnd, end); + assert_equals(contenteditableAccessible.selectionAnchorOffset, 0); + assert_equals(contenteditableAccessible.selectionFocusOffset, 6); - assert_equals(mainAccessible.selectionStart, start + 9); - assert_equals(mainAccessible.selectionEnd, end + 9); + assert_equals(mainAccessible.selectionAnchorOffset, 0); + assert_equals(mainAccessible.selectionFocusOffset, 6); assert_equals(rootAccessible.selectionAnchorObject.name, contenteditableLines[i].textContent); @@ -249,9 +244,7 @@ } }, "The effects of the selectNode method should be reflected in the accessibility API."); -</script> -<script> if (window.testRunner) document.getElementById("main").style.display = "none";; </script>
diff --git a/third_party/blink/web_tests/accessibility/input-type-password-value-and-selection-expected.txt b/third_party/blink/web_tests/accessibility/input-type-password-value-and-selection-expected.txt index e8c7ce1..100de3f 100644 --- a/third_party/blink/web_tests/accessibility/input-type-password-value-and-selection-expected.txt +++ b/third_party/blink/web_tests/accessibility/input-type-password-value-and-selection-expected.txt
@@ -2,99 +2,99 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS axPassword.selectionStart is 0 -PASS axPassword.selectionEnd is 0 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 0 +PASS axPassword.selectionFocusOffset is 0 PASS axPassword.stringValue is "AXValue: ••••••" -PASS axPassword.selectionStart is 0 -PASS axPassword.selectionEnd is 0 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 0 -PASS axPassword.selectionEnd is 1 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 0 -PASS axPassword.selectionEnd is 2 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 0 -PASS axPassword.selectionEnd is 3 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 0 -PASS axPassword.selectionEnd is 4 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 0 -PASS axPassword.selectionEnd is 5 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 1 -PASS axPassword.selectionEnd is 1 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 1 -PASS axPassword.selectionEnd is 2 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 1 -PASS axPassword.selectionEnd is 3 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 1 -PASS axPassword.selectionEnd is 4 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 1 -PASS axPassword.selectionEnd is 5 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 2 -PASS axPassword.selectionEnd is 2 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 2 -PASS axPassword.selectionEnd is 3 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 2 -PASS axPassword.selectionEnd is 4 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 2 -PASS axPassword.selectionEnd is 5 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 3 -PASS axPassword.selectionEnd is 3 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 3 -PASS axPassword.selectionEnd is 4 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 3 -PASS axPassword.selectionEnd is 5 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 4 -PASS axPassword.selectionEnd is 4 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 4 -PASS axPassword.selectionEnd is 5 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 5 -PASS axPassword.selectionEnd is 5 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 -PASS axPassword.selectionStart is 0 -PASS axPassword.selectionEnd is 0 -PASS axPassword.selectionStartLineNumber is 0 -PASS axPassword.selectionEndLineNumber is 0 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 0 +PASS axPassword.selectionFocusOffset is 0 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 0 +PASS axPassword.selectionFocusOffset is 1 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 0 +PASS axPassword.selectionFocusOffset is 2 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 0 +PASS axPassword.selectionFocusOffset is 3 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 0 +PASS axPassword.selectionFocusOffset is 4 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 0 +PASS axPassword.selectionFocusOffset is 5 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 1 +PASS axPassword.selectionFocusOffset is 1 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 1 +PASS axPassword.selectionFocusOffset is 2 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 1 +PASS axPassword.selectionFocusOffset is 3 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 1 +PASS axPassword.selectionFocusOffset is 4 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 1 +PASS axPassword.selectionFocusOffset is 5 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 2 +PASS axPassword.selectionFocusOffset is 2 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 2 +PASS axPassword.selectionFocusOffset is 3 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 2 +PASS axPassword.selectionFocusOffset is 4 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 2 +PASS axPassword.selectionFocusOffset is 5 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 3 +PASS axPassword.selectionFocusOffset is 3 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 3 +PASS axPassword.selectionFocusOffset is 4 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 3 +PASS axPassword.selectionFocusOffset is 5 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 4 +PASS axPassword.selectionFocusOffset is 4 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 4 +PASS axPassword.selectionFocusOffset is 5 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 5 +PASS axPassword.selectionFocusOffset is 5 +PASS axPassword is axPassword.selectionAnchorObject +PASS axPassword is axPassword.selectionFocusObject +PASS axPassword.selectionAnchorOffset is 0 +PASS axPassword.selectionFocusOffset is 0 PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/accessibility/input-type-password-value-and-selection.html b/third_party/blink/web_tests/accessibility/input-type-password-value-and-selection.html index 85f4f27..7756ddc 100644 --- a/third_party/blink/web_tests/accessibility/input-type-password-value-and-selection.html +++ b/third_party/blink/web_tests/accessibility/input-type-password-value-and-selection.html
@@ -7,47 +7,43 @@ <input id="password" type="password" value="Secret"> - <p id="description"></p> - <div id="console"></div> - <script> description("This tests that AXValue, caret position and text selection are reported correctly for password fields."); if (window.accessibilityController) { - var password = document.getElementById("password"); - var textLength = password.value.length; + let password = document.getElementById("password"); + let textLength = password.value.length; password.focus(); - var axPassword = accessibilityController.accessibleElementById("password"); + window.axPassword = accessibilityController.accessibleElementById("password"); // Initially the caret should be at the beginning of the field. - shouldBeZero("axPassword.selectionStart"); - shouldBeZero("axPassword.selectionEnd"); - shouldBeZero("axPassword.selectionStartLineNumber"); - shouldBeZero("axPassword.selectionEndLineNumber"); + shouldBe("axPassword", "axPassword.selectionAnchorObject"); + shouldBe("axPassword", "axPassword.selectionFocusObject"); + shouldBeZero("axPassword.selectionAnchorOffset"); + shouldBeZero("axPassword.selectionFocusOffset"); // The password field should contain 6 bullets. // (Bullet is the default mask character, not star.) - var axValue = "AXValue: " + new Array(textLength + 1).join( + let axValue = "AXValue: " + new Array(textLength + 1).join( String.fromCharCode(8226 /* Bullet symbol. */)); shouldBeEqualToString("axPassword.stringValue", axValue); - for (var start = 0; start < textLength; ++start) { - for (var end = start; end < textLength; ++end) { + for (let start = 0; start < textLength; ++start) { + for (let end = start; end < textLength; ++end) { password.setSelectionRange(start, end); - shouldBeEqualToNumber("axPassword.selectionStart", start); - shouldBeEqualToNumber("axPassword.selectionEnd", end); - shouldBeZero("axPassword.selectionStartLineNumber"); - shouldBeZero("axPassword.selectionEndLineNumber"); + shouldBe("axPassword", "axPassword.selectionAnchorObject"); + shouldBe("axPassword", "axPassword.selectionFocusObject"); + shouldBeEqualToNumber("axPassword.selectionAnchorOffset", start); + shouldBeEqualToNumber("axPassword.selectionFocusOffset", end); } } // Invalid range. password.setSelectionRange(7, 0); - shouldBeZero("axPassword.selectionStart"); - shouldBeZero("axPassword.selectionEnd"); - shouldBeZero("axPassword.selectionStartLineNumber"); - shouldBeZero("axPassword.selectionEndLineNumber"); - + shouldBe("axPassword", "axPassword.selectionAnchorObject"); + shouldBe("axPassword", "axPassword.selectionFocusObject"); + shouldBeZero("axPassword.selectionAnchorOffset"); + shouldBeZero("axPassword.selectionFocusOffset"); } </script> </body>
diff --git a/third_party/blink/web_tests/accessibility/input-type-text-caret-position-expected.txt b/third_party/blink/web_tests/accessibility/input-type-text-caret-position-expected.txt index bc914f2c..cd06e56 100644 --- a/third_party/blink/web_tests/accessibility/input-type-text-caret-position-expected.txt +++ b/third_party/blink/web_tests/accessibility/input-type-text-caret-position-expected.txt
@@ -2,20 +2,34 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS inputAccessible.selectionStart is 0 -PASS inputAccessible.selectionEnd is 0 -PASS inputAccessible.selectionStart is 1 -PASS inputAccessible.selectionEnd is 1 -PASS inputAccessible.selectionStart is 2 -PASS inputAccessible.selectionEnd is 2 -PASS inputAccessible.selectionStart is 3 -PASS inputAccessible.selectionEnd is 3 -PASS inputAccessible.selectionStart is 4 -PASS inputAccessible.selectionEnd is 4 -PASS inputAccessible.selectionStart is 5 -PASS inputAccessible.selectionEnd is 5 -PASS inputAccessible.selectionStart is 6 -PASS inputAccessible.selectionEnd is 6 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 0 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 0 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 1 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 1 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 2 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 2 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 3 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 3 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 4 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 4 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 5 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 5 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 6 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 6 PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/accessibility/input-type-text-caret-position.html b/third_party/blink/web_tests/accessibility/input-type-text-caret-position.html index b95faeb5..d2f546f 100644 --- a/third_party/blink/web_tests/accessibility/input-type-text-caret-position.html +++ b/third_party/blink/web_tests/accessibility/input-type-text-caret-position.html
@@ -12,16 +12,18 @@ if (window.accessibilityController) { - var input = document.getElementById('input'); + let input = document.getElementById('input'); input.focus(); - var inputAccessible = + window.inputAccessible = accessibilityController.accessibleElementById('input'); - for (var characterIndex = 0; characterIndex < 7; ++characterIndex) { + for (let characterIndex = 0; characterIndex < 7; ++characterIndex) { input.setSelectionRange(characterIndex, characterIndex); - shouldBeEqualToNumber("inputAccessible.selectionStart", + shouldBe("inputAccessible", "inputAccessible.selectionAnchorObject"); + shouldBeEqualToNumber("inputAccessible.selectionAnchorOffset", characterIndex); - shouldBeEqualToNumber("inputAccessible.selectionEnd", + shouldBe("inputAccessible", "inputAccessible.selectionFocusObject"); + shouldBeEqualToNumber("inputAccessible.selectionFocusOffset", characterIndex); }
diff --git a/third_party/blink/web_tests/accessibility/input-type-text-selection-expected.txt b/third_party/blink/web_tests/accessibility/input-type-text-selection-expected.txt index eed2b83..cf6bc5f 100644 --- a/third_party/blink/web_tests/accessibility/input-type-text-selection-expected.txt +++ b/third_party/blink/web_tests/accessibility/input-type-text-selection-expected.txt
@@ -2,94 +2,94 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS inputAccessible.selectionStart is 0 -PASS inputAccessible.selectionEnd is 6 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 0 -PASS inputAccessible.selectionEnd is 1 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 0 -PASS inputAccessible.selectionEnd is 2 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 0 -PASS inputAccessible.selectionEnd is 3 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 0 -PASS inputAccessible.selectionEnd is 4 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 0 -PASS inputAccessible.selectionEnd is 5 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 0 -PASS inputAccessible.selectionEnd is 6 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 1 -PASS inputAccessible.selectionEnd is 2 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 1 -PASS inputAccessible.selectionEnd is 3 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 1 -PASS inputAccessible.selectionEnd is 4 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 1 -PASS inputAccessible.selectionEnd is 5 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 1 -PASS inputAccessible.selectionEnd is 6 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 2 -PASS inputAccessible.selectionEnd is 3 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 2 -PASS inputAccessible.selectionEnd is 4 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 2 -PASS inputAccessible.selectionEnd is 5 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 2 -PASS inputAccessible.selectionEnd is 6 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 3 -PASS inputAccessible.selectionEnd is 4 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 3 -PASS inputAccessible.selectionEnd is 5 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 3 -PASS inputAccessible.selectionEnd is 6 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 4 -PASS inputAccessible.selectionEnd is 5 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 4 -PASS inputAccessible.selectionEnd is 6 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 -PASS inputAccessible.selectionStart is 5 -PASS inputAccessible.selectionEnd is 6 -PASS inputAccessible.selectionStartLineNumber is 0 -PASS inputAccessible.selectionEndLineNumber is 0 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 0 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 6 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 0 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 1 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 0 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 2 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 0 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 3 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 0 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 4 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 0 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 5 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 0 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 6 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 1 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 2 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 1 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 3 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 1 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 4 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 1 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 5 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 1 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 6 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 2 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 3 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 2 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 4 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 2 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 5 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 2 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 6 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 3 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 4 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 3 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 5 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 3 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 6 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 4 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 5 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 4 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 6 +PASS inputAccessible is inputAccessible.selectionAnchorObject +PASS inputAccessible.selectionAnchorOffset is 5 +PASS inputAccessible is inputAccessible.selectionFocusObject +PASS inputAccessible.selectionFocusOffset is 6 PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/accessibility/input-type-text-selection.html b/third_party/blink/web_tests/accessibility/input-type-text-selection.html index 3ac4fa6..63ac034 100644 --- a/third_party/blink/web_tests/accessibility/input-type-text-selection.html +++ b/third_party/blink/web_tests/accessibility/input-type-text-selection.html
@@ -12,26 +12,26 @@ if (window.accessibilityController) { - var input = document.getElementById('input'); + let input = document.getElementById('input'); input.focus(); - var inputAccessible = + window.inputAccessible = accessibilityController.accessibleElementById('input'); // Select the entire contents. input.select(); - shouldBeZero("inputAccessible.selectionStart"); - shouldBeEqualToNumber("inputAccessible.selectionEnd", 6); - shouldBeEqualToNumber("inputAccessible.selectionStartLineNumber", 0); - shouldBeEqualToNumber("inputAccessible.selectionEndLineNumber", 0); + shouldBe("inputAccessible", "inputAccessible.selectionAnchorObject"); + shouldBeZero("inputAccessible.selectionAnchorOffset"); + shouldBe("inputAccessible", "inputAccessible.selectionFocusObject"); + shouldBeEqualToNumber("inputAccessible.selectionFocusOffset", 6); // Select all possible text ranges. - for (var start = 0; start < 7; ++start) { - for (var end = start + 1; end < 7; ++end) { + for (let start = 0; start < 7; ++start) { + for (let end = start + 1; end < 7; ++end) { input.setSelectionRange(start, end); - shouldBeEqualToNumber("inputAccessible.selectionStart", start); - shouldBeEqualToNumber("inputAccessible.selectionEnd", end); - shouldBeZero("inputAccessible.selectionStartLineNumber"); - shouldBeZero("inputAccessible.selectionEndLineNumber"); + shouldBe("inputAccessible", "inputAccessible.selectionAnchorObject"); + shouldBeEqualToNumber("inputAccessible.selectionAnchorOffset", start); + shouldBe("inputAccessible", "inputAccessible.selectionFocusObject"); + shouldBeEqualToNumber("inputAccessible.selectionFocusOffset", end); } }
diff --git a/third_party/blink/web_tests/accessibility/list-with-selection.html b/third_party/blink/web_tests/accessibility/list-with-selection.html index e9774dc..0fd688ec 100644 --- a/third_party/blink/web_tests/accessibility/list-with-selection.html +++ b/third_party/blink/web_tests/accessibility/list-with-selection.html
@@ -34,10 +34,9 @@ // Select both items in the list. axList.setSelectedTextRange(0, 2); - // |selectionStart| and |selectionEnd| are character-based. let selectionText = 'Item1\nItem2'; - assert_equals(axList.selectionStart, 0, id); - assert_equals(axList.selectionEnd, selectionText.length, id); + assert_equals(axList.selectionAnchorOffset, 0, id); + assert_equals(axList.selectionFocusOffset, 5, id); let selection = window.getSelection(); assert_equals(selection.toString(), selectionText, id);
diff --git a/third_party/blink/web_tests/accessibility/textarea-caret-position-expected.txt b/third_party/blink/web_tests/accessibility/textarea-caret-position-expected.txt index 42d20a8..ef877e2 100644 --- a/third_party/blink/web_tests/accessibility/textarea-caret-position-expected.txt +++ b/third_party/blink/web_tests/accessibility/textarea-caret-position-expected.txt
@@ -2,96 +2,100 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS textareaAccessible.selectionStart is 0 -PASS textareaAccessible.selectionEnd is 0 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 0 -PASS textareaAccessible.selectionStart is 1 -PASS textareaAccessible.selectionEnd is 1 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 0 -PASS textareaAccessible.selectionStart is 2 -PASS textareaAccessible.selectionEnd is 2 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 0 -PASS textareaAccessible.selectionStart is 3 -PASS textareaAccessible.selectionEnd is 3 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 0 -PASS textareaAccessible.selectionStart is 4 -PASS textareaAccessible.selectionEnd is 4 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 0 -PASS textareaAccessible.selectionStart is 5 -PASS textareaAccessible.selectionEnd is 5 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 0 -PASS textareaAccessible.selectionStart is 6 -PASS textareaAccessible.selectionEnd is 6 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 0 -PASS textareaAccessible.selectionStart is 7 -PASS textareaAccessible.selectionEnd is 7 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 8 -PASS textareaAccessible.selectionEnd is 8 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 9 -PASS textareaAccessible.selectionEnd is 9 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 10 -PASS textareaAccessible.selectionEnd is 10 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 11 -PASS textareaAccessible.selectionEnd is 11 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 12 -PASS textareaAccessible.selectionEnd is 12 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 13 -PASS textareaAccessible.selectionEnd is 13 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 14 -PASS textareaAccessible.selectionEnd is 14 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 15 -PASS textareaAccessible.selectionEnd is 15 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 16 -PASS textareaAccessible.selectionEnd is 16 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 17 -PASS textareaAccessible.selectionEnd is 17 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 18 -PASS textareaAccessible.selectionEnd is 18 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 19 -PASS textareaAccessible.selectionEnd is 19 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 20 -PASS textareaAccessible.selectionEnd is 20 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 20 -PASS textareaAccessible.selectionEnd is 20 -PASS emptyTextareaAccessible.selectionStart is 0 -PASS emptyTextareaAccessible.selectionEnd is 0 -PASS emptyTextareaAccessible.selectionStart is 0 -PASS emptyTextareaAccessible.selectionEnd is 0 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 0 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 0 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 1 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 1 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 2 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 2 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 3 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 3 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 4 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 4 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 5 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 5 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 6 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 6 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 7 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 7 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 8 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 8 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 9 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 9 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 10 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 10 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 11 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 11 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 12 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 12 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 13 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 13 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 14 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 14 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 15 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 15 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 16 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 16 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 17 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 17 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 18 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 18 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 19 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 19 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 20 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 20 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 20 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 20 +PASS emptyTextareaAccessible is emptyTextareaAccessible.selectionAnchorObject +PASS emptyTextareaAccessible.selectionAnchorOffset is 0 +PASS emptyTextareaAccessible is emptyTextareaAccessible.selectionFocusObject +PASS emptyTextareaAccessible.selectionFocusOffset is 0 +PASS emptyTextareaAccessible.selectionAnchorOffset is 0 +PASS emptyTextareaAccessible.selectionFocusOffset is 0 PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/accessibility/textarea-caret-position.html b/third_party/blink/web_tests/accessibility/textarea-caret-position.html index c8cea3d2..b1f72e6 100644 --- a/third_party/blink/web_tests/accessibility/textarea-caret-position.html +++ b/third_party/blink/web_tests/accessibility/textarea-caret-position.html
@@ -18,40 +18,44 @@ if (window.accessibilityController) { - var textarea = document.getElementById('textarea'); + let textarea = document.getElementById('textarea'); textarea.focus(); - var textareaAccessible = + window.textareaAccessible = accessibilityController.accessibleElementById('textarea'); - for (var i = 0; i < 3; ++i) { - for (var j = 0; j < 7; ++j) { - var caretPosition = i * 7 + j; + for (let i = 0; i < 3; ++i) { + for (let j = 0; j < 7; ++j) { + let caretPosition = i * 7 + j; textarea.selectionStart = caretPosition; textarea.selectionEnd = caretPosition; - shouldBeEqualToNumber("textareaAccessible.selectionStart", + shouldBe("textareaAccessible", "textareaAccessible.selectionAnchorObject"); + shouldBeEqualToNumber("textareaAccessible.selectionAnchorOffset", caretPosition); - shouldBeEqualToNumber("textareaAccessible.selectionEnd", + shouldBe("textareaAccessible", "textareaAccessible.selectionFocusObject"); + shouldBeEqualToNumber("textareaAccessible.selectionFocusOffset", caretPosition); - shouldBeEqualToNumber("textareaAccessible.selectionStartLineNumber", i); - shouldBeEqualToNumber("textareaAccessible.selectionEndLineNumber", i); } } - var emptyTextarea = document.getElementById('textarea-empty'); + let emptyTextarea = document.getElementById('textarea-empty'); emptyTextarea.focus(); // Each textarea has its own independent caret. - shouldBeEqualToNumber("textareaAccessible.selectionStart", 20); - shouldBeEqualToNumber("textareaAccessible.selectionEnd", 20); + shouldBe("textareaAccessible", "textareaAccessible.selectionAnchorObject"); + shouldBeEqualToNumber("textareaAccessible.selectionAnchorOffset", 20); + shouldBe("textareaAccessible", "textareaAccessible.selectionFocusObject"); + shouldBeEqualToNumber("textareaAccessible.selectionFocusOffset", 20); - var emptyTextareaAccessible = + window.emptyTextareaAccessible = accessibilityController.accessibleElementById('textarea-empty'); - shouldBeZero("emptyTextareaAccessible.selectionStart"); - shouldBeZero("emptyTextareaAccessible.selectionEnd"); + shouldBe("emptyTextareaAccessible", "emptyTextareaAccessible.selectionAnchorObject"); + shouldBeZero("emptyTextareaAccessible.selectionAnchorOffset"); + shouldBe("emptyTextareaAccessible", "emptyTextareaAccessible.selectionFocusObject"); + shouldBeZero("emptyTextareaAccessible.selectionFocusOffset"); // Setting the caret at an invalid offset should not move it. emptyTextarea.setSelectionRange(1, 1); - shouldBeZero("emptyTextareaAccessible.selectionStart"); - shouldBeZero("emptyTextareaAccessible.selectionEnd"); + shouldBeZero("emptyTextareaAccessible.selectionAnchorOffset"); + shouldBeZero("emptyTextareaAccessible.selectionFocusOffset"); } </script>
diff --git a/third_party/blink/web_tests/accessibility/textarea-selection-expected.txt b/third_party/blink/web_tests/accessibility/textarea-selection-expected.txt index eda2e9ce..9c6f6ac 100644 --- a/third_party/blink/web_tests/accessibility/textarea-selection-expected.txt +++ b/third_party/blink/web_tests/accessibility/textarea-selection-expected.txt
@@ -2,46 +2,44 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS textareaAccessible.selectionStart is 0 -PASS textareaAccessible.selectionEnd is 25 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 3 -PASS textareaAccessible.selectionStart is 0 -PASS textareaAccessible.selectionEnd is 7 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 0 -PASS textareaAccessible.selectionEnd is 7 -PASS textareaAccessible.selectionStartLineNumber is 0 -PASS textareaAccessible.selectionEndLineNumber is 1 -PASS textareaAccessible.selectionStart is 7 -PASS textareaAccessible.selectionEnd is 14 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 7 -PASS textareaAccessible.selectionEnd is 14 -PASS textareaAccessible.selectionStartLineNumber is 1 -PASS textareaAccessible.selectionEndLineNumber is 2 -PASS textareaAccessible.selectionStart is 14 -PASS textareaAccessible.selectionEnd is 21 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 3 -PASS textareaAccessible.selectionStart is 14 -PASS textareaAccessible.selectionEnd is 21 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 3 -PASS textareaAccessible.selectionStart is 14 -PASS textareaAccessible.selectionEnd is 21 -PASS textareaAccessible.selectionStartLineNumber is 2 -PASS textareaAccessible.selectionEndLineNumber is 3 -PASS emptyTextareaAccessible.selectionStart is 0 -PASS emptyTextareaAccessible.selectionEnd is 0 -PASS emptyTextareaAccessible.selectionStartLineNumber is 0 -PASS emptyTextareaAccessible.selectionEndLineNumber is 0 -PASS emptyTextareaAccessible.selectionStart is 0 -PASS emptyTextareaAccessible.selectionEnd is 0 -PASS emptyTextareaAccessible.selectionStartLineNumber is 0 -PASS emptyTextareaAccessible.selectionEndLineNumber is 0 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 0 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 25 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 0 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 7 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 0 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 7 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 7 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 14 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 7 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 14 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 14 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 21 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 14 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 21 +PASS textareaAccessible is textareaAccessible.selectionAnchorObject +PASS textareaAccessible.selectionAnchorOffset is 14 +PASS textareaAccessible is textareaAccessible.selectionFocusObject +PASS textareaAccessible.selectionFocusOffset is 21 +PASS emptyTextareaAccessible is emptyTextareaAccessible.selectionAnchorObject +PASS emptyTextareaAccessible.selectionAnchorOffset is 0 +PASS emptyTextareaAccessible is emptyTextareaAccessible.selectionFocusObject +PASS emptyTextareaAccessible.selectionFocusOffset is 0 +PASS emptyTextareaAccessible.selectionAnchorOffset is 0 +PASS emptyTextareaAccessible.selectionFocusOffset is 0 PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/accessibility/textarea-selection.html b/third_party/blink/web_tests/accessibility/textarea-selection.html index 6067e3f..e90d515 100644 --- a/third_party/blink/web_tests/accessibility/textarea-selection.html +++ b/third_party/blink/web_tests/accessibility/textarea-selection.html
@@ -18,69 +18,59 @@ if (window.accessibilityController) { - var textarea = document.getElementById('textarea'); + let textarea = document.getElementById('textarea'); textarea.focus(); - var textareaAccessible = + window.textareaAccessible = accessibilityController.accessibleElementById('textarea'); // Select the entire contents. textarea.select(); - shouldBeZero("textareaAccessible.selectionStart"); - shouldBeEqualToNumber("textareaAccessible.selectionEnd", + shouldBe("textareaAccessible", "textareaAccessible.selectionAnchorObject"); + shouldBeZero("textareaAccessible.selectionAnchorOffset"); + shouldBe("textareaAccessible", "textareaAccessible.selectionFocusObject"); + shouldBeEqualToNumber("textareaAccessible.selectionFocusOffset", textarea.textLength); - shouldBeZero("textareaAccessible.selectionStartLineNumber"); - shouldBeEqualToNumber( - "textareaAccessible.selectionEndLineNumber", - 3); - + // Select entire lines. - for (var lineNumber = 0; lineNumber < 3; ++lineNumber) { - for (var directionIndex = 0; directionIndex < 2; + for (let lineNumber = 0; lineNumber < 3; ++lineNumber) { + for (let directionIndex = 0; directionIndex < 2; ++directionIndex) { - var selectionStart = lineNumber * 7; - var selectionEnd = (lineNumber + 1) * 7; - var direction = 'forward'; + let selectionAnchorOffset = lineNumber * 7; + let selectionFocusOffset = (lineNumber + 1) * 7; + let direction = 'forward'; if (directionIndex) direction = 'backward'; - textarea.setSelectionRange(selectionStart, selectionEnd, + textarea.setSelectionRange(selectionAnchorOffset, selectionFocusOffset, direction); - shouldBeEqualToNumber("textareaAccessible.selectionStart", - selectionStart); - shouldBeEqualToNumber("textareaAccessible.selectionEnd", - selectionEnd); - shouldBeEqualToNumber( - "textareaAccessible.selectionStartLineNumber", - lineNumber); - shouldBeEqualToNumber( - "textareaAccessible.selectionEndLineNumber", - lineNumber + 1); + shouldBe("textareaAccessible", "textareaAccessible.selectionAnchorObject"); + shouldBeEqualToNumber("textareaAccessible.selectionAnchorOffset", + selectionAnchorOffset); + shouldBe("textareaAccessible", "textareaAccessible.selectionFocusObject"); + shouldBeEqualToNumber("textareaAccessible.selectionFocusOffset", + selectionFocusOffset); } } - var emptyTextarea = document.getElementById('textarea-empty'); + let emptyTextarea = document.getElementById('textarea-empty'); emptyTextarea.focus(); // Each textarea has its own independent selection. - shouldBeEqualToNumber("textareaAccessible.selectionStart", 14); - shouldBeEqualToNumber("textareaAccessible.selectionEnd", 21); - shouldBeEqualToNumber( - "textareaAccessible.selectionStartLineNumber", 2); - shouldBeEqualToNumber( - "textareaAccessible.selectionEndLineNumber", 3); - - var emptyTextareaAccessible = + shouldBe("textareaAccessible", "textareaAccessible.selectionAnchorObject"); + shouldBeEqualToNumber("textareaAccessible.selectionAnchorOffset", 14); + shouldBe("textareaAccessible", "textareaAccessible.selectionFocusObject"); + shouldBeEqualToNumber("textareaAccessible.selectionFocusOffset", 21); + + window.emptyTextareaAccessible = accessibilityController.accessibleElementById('textarea-empty'); - shouldBeZero("emptyTextareaAccessible.selectionStart"); - shouldBeZero("emptyTextareaAccessible.selectionEnd"); - shouldBeZero("emptyTextareaAccessible.selectionStartLineNumber"); - shouldBeZero("emptyTextareaAccessible.selectionEndLineNumber"); - + shouldBe("emptyTextareaAccessible", "emptyTextareaAccessible.selectionAnchorObject"); + shouldBeZero("emptyTextareaAccessible.selectionAnchorOffset"); + shouldBe("emptyTextareaAccessible", "emptyTextareaAccessible.selectionFocusObject"); + shouldBeZero("emptyTextareaAccessible.selectionFocusOffset"); + // Setting an invalid selection should not be visible. emptyTextarea.setSelectionRange(1, 1); - shouldBeZero("emptyTextareaAccessible.selectionStart"); - shouldBeZero("emptyTextareaAccessible.selectionEnd"); - shouldBeZero("emptyTextareaAccessible.selectionStartLineNumber"); - shouldBeZero("emptyTextareaAccessible.selectionEndLineNumber"); + shouldBeZero("emptyTextareaAccessible.selectionAnchorOffset"); + shouldBeZero("emptyTextareaAccessible.selectionFocusOffset"); } </script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index f660c91..5190611 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -117418,11 +117418,21 @@ {} ] ], + "client-hints/resources/sec-ch-ua.py": [ + [ + {} + ] + ], "client-hints/resources/square.png": [ [ {} ] ], + "client-hints/sec-ch-ua.https-expected.txt": [ + [ + {} + ] + ], "clipboard-apis/META.yml": [ [ {} @@ -205181,6 +205191,18 @@ {} ] ], + "client-hints/sec-ch-ua.http.html": [ + [ + "/client-hints/sec-ch-ua.http.html", + {} + ] + ], + "client-hints/sec-ch-ua.https.html": [ + [ + "/client-hints/sec-ch-ua.https.html", + {} + ] + ], "clipboard-apis/async-interfaces.https.html": [ [ "/clipboard-apis/async-interfaces.https.html", @@ -277053,12 +277075,52 @@ {} ] ], + "reporting/bufferSize.html": [ + [ + "/reporting/bufferSize.html", + { + "testdriver": true + } + ] + ], + "reporting/disconnect.html": [ + [ + "/reporting/disconnect.html", + { + "testdriver": true + } + ] + ], + "reporting/generateTestReport.html": [ + [ + "/reporting/generateTestReport.html", + { + "testdriver": true + } + ] + ], "reporting/idlharness.window.js": [ [ "/reporting/idlharness.window.html", {} ] ], + "reporting/nestedReport.html": [ + [ + "/reporting/nestedReport.html", + { + "testdriver": true + } + ] + ], + "reporting/order.html": [ + [ + "/reporting/order.html", + { + "testdriver": true + } + ] + ], "requestidlecallback/basic.html": [ [ "/requestidlecallback/basic.html", @@ -310346,10 +310408,26 @@ "2dd18068427ccec7f75ecbdc7fa4e19c339f53a7", "support" ], + "client-hints/resources/sec-ch-ua.py": [ + "a14a27dadf9e333784a5c636c821634b387e475f", + "support" + ], "client-hints/resources/square.png": [ "01c9666a8de9d5535615aff830810e5df4b2156f", "support" ], + "client-hints/sec-ch-ua.http.html": [ + "e333c605301e621133ee5e6f3d01e2525d5c058a", + "testharness" + ], + "client-hints/sec-ch-ua.https-expected.txt": [ + "0bed3d3b8ad9e7882b8f420cd09684208bf31042", + "support" + ], + "client-hints/sec-ch-ua.https.html": [ + "b293745365a611475697aaa7b66a8a809cad7b3c", + "testharness" + ], "clipboard-apis/META.yml": [ "ecbac54806cb0d3a915c551f0a684fdc84acdd5e", "support" @@ -446126,6 +446204,18 @@ "980823f59f7e3ac4f35a31ab6df37ce16e538f54", "support" ], + "reporting/bufferSize.html": [ + "b3512b3bc93b322e2015e71d70f01bc5986bc24d", + "testharness" + ], + "reporting/disconnect.html": [ + "2dc5e8fd2de724e41bc0c003b4e7036d1d954371", + "testharness" + ], + "reporting/generateTestReport.html": [ + "e3c2735686a05eefc9bbcfb107f76ec7275b8948", + "testharness" + ], "reporting/idlharness.window-expected.txt": [ "99905f17a3c270638d312766a9cf5574dae976f5", "support" @@ -446134,6 +446224,14 @@ "17cef8183596ae1d0b307fb8ddccc7455b955966", "testharness" ], + "reporting/nestedReport.html": [ + "156338ee74653bfdc843e6acceda073c02ca635b", + "testharness" + ], + "reporting/order.html": [ + "c43964220c981f4b91c7c5e7eac7fc67377b367b", + "testharness" + ], "requestidlecallback/META.yml": [ "9c829d3c8885bb9b594e7096a878166e07f3e278", "support" @@ -446867,7 +446965,7 @@ "support" ], "resources/testdriver.js": [ - "e328302e4f345114654eda323dbd09a5f650d419", + "031be1b7e5501658d412aecc6f0cba56b3444601", "support" ], "resources/testdriver.js.headers": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/dynamic-available-size-iframe.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/dynamic-available-size-iframe.html new file mode 100644 index 0000000..fc265d4d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/dynamic-available-size-iframe.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<meta name="assert" content="Checks that an absolute positioned element is positioned correctly, when the available size of its parent changes due to document resize." /> +<link rel="help" href="https://crbug.com/928672"> +<link rel="match" href="../reference/ref-filled-green-100px-square-only.html"> +<script src="/common/reftest-wait.js"></script> +<p>Test passes if there is a filled green square.</p> +<iframe id="target" height="100" width="200" src="support/dynamic-available-size-iframe.html" style="border: none;"></iframe> +<script> +onload = () => { + requestAnimationFrame(() => requestAnimationFrame(() => { + target.width = '100'; + takeScreenshot(); + })); +}; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/support/dynamic-available-size-iframe.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/support/dynamic-available-size-iframe.html new file mode 100644 index 0000000..8b61c87 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/support/dynamic-available-size-iframe.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<style> +body { margin: 0; } +.parent { + position: relative; + display: flex; + width: 100%; + height: 100px; + background: red; +} + +.content { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; + width: 100px; + height: 100px; + background: green; +} + +svg { + width: 50px; + height: 50px; +} +</style> +<div class="parent"> + <div class="content"> + <svg xmlns="http://www.w3.org/2000/svg"></svg> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/AnimationEffect-getComputedTiming.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-transitions/AnimationEffect-getComputedTiming.tentative-expected.txt deleted file mode 100644 index 9c3a46bd..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/AnimationEffect-getComputedTiming.tentative-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -This is a testharness.js-based test. -PASS delay of a new tranisition -FAIL Positive delay of a new transition assert_equals: Initial value of delay expected 10000 but got 0 -PASS Negative delay of a new transition -PASS endDelay of a new transition -FAIL fill of a new transition assert_equals: Fill backwards expected "backwards" but got "none" -PASS iterationStart of a new transition -PASS iterations of a new transition -PASS duration of a new transition -PASS direction of a new transition -PASS easing of a new transition -PASS endTime of a new transition -PASS activeDuration of a new transition -PASS localTime of a new transition -PASS localTime is always equal to currentTime -PASS localTime reflects playbackRate immediately -PASS progress of a new transition -PASS progress of a new transition with positive delay in before phase -PASS progress of a finished transition -PASS currentIteration of a new transition -PASS currentIteration of a new transition with positive delay in before phase -PASS currentIteration of a finished transition -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/CSSTransition-startTime.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-transitions/CSSTransition-startTime.tentative-expected.txt deleted file mode 100644 index d90daa4..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/CSSTransition-startTime.tentative-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -This is a testharness.js-based test. -PASS The start time of a newly-created transition is unresolved -PASS The start time of transitions is based on when they are generated -PASS The start time of a transition can be set -PASS The start time can be set to seek a transition -FAIL Seeking a transition using start time dispatches transition events promise_test: Unhandled rejection with value: object "Error: Timed out waiting for Promise to resolve: transitionstart" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/img.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/img.tentative.https.sub.html index 252b220..befc7a9 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/img.tentative.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/img.tentative.https.sub.html
@@ -7,16 +7,18 @@ <script> // These tests reuse the `referrer-policy` infrastructure to load images that // encode their request headers in their pixels. Fun stuff! - async_test(t => { + promise_test(() => loadImageInWindow( "https://{{host}}:{{ports[https][0]}}/referrer-policy/generic/subresource/image.py", - t.step_func_done(img => { + [], + window) + .then(img => { headers = decodeImageData(extractImageData(img)).headers; got = { - "dest": headers["sec-fetch-dest"], - "mode": headers["sec-fetch-mode"], - "site": headers["sec-fetch-site"], - "user": headers["sec-fetch-user"] + "dest": headers["sec-fetch-dest"], + "mode": headers["sec-fetch-mode"], + "site": headers["sec-fetch-site"], + "user": headers["sec-fetch-user"] }; assert_header_equals(got, { "dest": "image", @@ -25,20 +27,20 @@ "mode": "cors", // Because `loadImageInWindow` tacks on `crossorigin` }); }), - [], - window); - }, "Same-origin image"); + "Same-origin image"); - async_test(t => { + promise_test(() => loadImageInWindow( "https://{{hosts[][www]}}:{{ports[https][0]}}/referrer-policy/generic/subresource/image.py", - t.step_func_done(img => { + [], + window) + .then(img => { headers = decodeImageData(extractImageData(img)).headers; got = { - "dest": headers["sec-fetch-dest"], - "mode": headers["sec-fetch-mode"], - "site": headers["sec-fetch-site"], - "user": headers["sec-fetch-user"] + "dest": headers["sec-fetch-dest"], + "mode": headers["sec-fetch-mode"], + "site": headers["sec-fetch-site"], + "user": headers["sec-fetch-user"] }; assert_header_equals(got, { "dest": "image", @@ -47,20 +49,20 @@ "mode": "cors", // Because `loadImageInWindow` tacks on `crossorigin` }); }), - [], - window); - }, "Same-site image"); + "Same-site image"); - async_test(t => { + promise_test(() => loadImageInWindow( "https://{{hosts[alt][www]}}:{{ports[https][0]}}/referrer-policy/generic/subresource/image.py", - t.step_func_done(img => { + [], + window) + .then(img => { headers = decodeImageData(extractImageData(img)).headers; got = { - "dest": headers["sec-fetch-dest"], - "mode": headers["sec-fetch-mode"], - "site": headers["sec-fetch-site"], - "user": headers["sec-fetch-user"] + "dest": headers["sec-fetch-dest"], + "mode": headers["sec-fetch-mode"], + "site": headers["sec-fetch-site"], + "user": headers["sec-fetch-user"] }; assert_header_equals(got, { "dest": "image", @@ -69,7 +71,5 @@ "mode": "cors", // Because `loadImageInWindow` tacks on `crossorigin` }); }), - [], - window); - }, "Cross-site image"); + "Cross-site image"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/mixed-content/generic/common.js b/third_party/blink/web_tests/external/wpt/mixed-content/generic/common.js index 63383f8..f1574e9 100644 --- a/third_party/blink/web_tests/external/wpt/mixed-content/generic/common.js +++ b/third_party/blink/web_tests/external/wpt/mixed-content/generic/common.js
@@ -5,6 +5,20 @@ * method's JSDoc. */ +// The same content is placed as +// - wpt/referrer-policy/generic/common.js and +// - wpt/mixed-content/generic/common.js. +// If you modify either one, please also update the other one. +// +// TODO(https://crbug.com/906850): These two files are going to be merged. +// Currently they are duplicated only to avoid frequent mass modification +// for each step of refactoring, as these file names are hard-coded in +// a large number of generated test files. + +function timeoutPromise(t, ms) { + return new Promise(resolve => { t.step_timeout(resolve, ms); }); +} + /** * Normalizes the target port for use in a URL. For default ports, this is the * empty string (omitted port), otherwise it's a colon followed by the port @@ -70,27 +84,66 @@ el.setAttribute(attr, attrs[attr]); } - /** * Binds to success and error events of an object wrapping them into a promise * available through {@code element.eventPromise}. The success event * resolves and error event rejects. + * This method adds event listeners, and then removes all the added listeners + * when one of listened event is fired. * @param {object} element An object supporting events on which to bind the * promise. * @param {string} resolveEventName [="load"] The event name to bind resolve to. * @param {string} rejectEventName [="error"] The event name to bind reject to. */ function bindEvents(element, resolveEventName, rejectEventName) { - element.eventPromise = new Promise(function(resolve, reject) { - element.addEventListener(resolveEventName || "load", function (e) { - resolve(e); - }); - element.addEventListener(rejectEventName || "error", function(e) { + element.eventPromise = + bindEvents2(element, resolveEventName, element, rejectEventName); +} + +// Returns a promise wrapping success and error events of objects. +// This is a variant of bindEvents that can accept separate objects for each +// events and two events to reject, and doesn't set `eventPromise`. +// +// When `resolveObject`'s `resolveEventName` event (default: "load") is +// fired, the promise is resolved with the event. +// +// When `rejectObject`'s `rejectEventName` event (default: "error") or +// `rejectObject2`'s `rejectEventName2` event (default: "error") is +// fired, the promise is rejected. +// +// `rejectObject2` is optional. +function bindEvents2(resolveObject, resolveEventName, rejectObject, rejectEventName, rejectObject2, rejectEventName2) { + return new Promise(function(resolve, reject) { + const actualResolveEventName = resolveEventName || "load"; + const actualRejectEventName = rejectEventName || "error"; + const actualRejectEventName2 = rejectEventName2 || "error"; + + const resolveHandler = function(event) { + cleanup(); + resolve(event); + }; + + const rejectHandler = function(event) { // Chromium starts propagating errors from worker.onerror to // window.onerror. This handles the uncaught exceptions in tests. - e.preventDefault(); - reject(e); - }); + event.preventDefault(); + cleanup(); + reject(event); + }; + + const cleanup = function() { + resolveObject.removeEventListener(actualResolveEventName, resolveHandler); + rejectObject.removeEventListener(actualRejectEventName, rejectHandler); + if (rejectObject2) { + rejectObject2.removeEventListener(actualRejectEventName2, rejectHandler); + } + }; + + resolveObject.addEventListener(actualResolveEventName, resolveHandler); + rejectObject.addEventListener(actualRejectEventName, rejectHandler); + if (rejectObject2) { + rejectObject2.addEventListener(actualRejectEventName2, rejectHandler); + } }); } @@ -150,13 +203,34 @@ } /** + * requestVia*() functions return promises that are resolved on successful + * requests with objects of the same "type", i.e. objects that contains + * the same sets of keys that are fixed within one category of tests (e.g. + * within wpt/referrer-policy tests). + * wrapResult() (that should be defined outside this file) is used to convert + * the response bodies of subresources into the expected result objects in some + * cases, and in other cases the result objects are constructed more directly. + * TODO(https://crbug.com/906850): Clean up the semantics around this, e.g. + * use (or not use) wrapResult() consistently, unify the arguments, etc. + */ + +/** * Creates a new iframe, binds load and error events, sets the src attribute and * appends it to {@code document.body} . * @param {string} url The src for the iframe. * @return {Promise} The promise for success/error events. */ -function requestViaIframe(url) { - return createRequestViaElement("iframe", {"src": url}, document.body); +function requestViaIframe(url, additionalAttributes) { + const iframe = createElement( + "iframe", + Object.assign({"src": url}, additionalAttributes), + document.body, + false); + return bindEvents2(window, "message", iframe, "error", window, "error") + .then(event => { + assert_equals(event.source, iframe.contentWindow); + return event.data; + }); } /** @@ -169,13 +243,122 @@ return createRequestViaElement("img", {"src": url}, document.body); } +// Helpers for requestViaImageForReferrerPolicy(). +function loadImageInWindow(src, attributes, w) { + return new Promise((resolve, reject) => { + var image = new w.Image(); + image.crossOrigin = "Anonymous"; + image.onload = function() { + resolve(image); + }; + + // Extend element with attributes. (E.g. "referrerPolicy" or "rel") + if (attributes) { + for (var attr in attributes) { + image[attr] = attributes[attr]; + } + } + + image.src = src; + w.document.body.appendChild(image) + }); +} + +function extractImageData(img) { + var canvas = document.createElement("canvas"); + var context = canvas.getContext('2d'); + context.drawImage(img, 0, 0); + var imgData = context.getImageData(0, 0, img.clientWidth, img.clientHeight); + return imgData.data; +} + +function decodeImageData(rgba) { + var rgb = new Uint8ClampedArray(rgba.length); + + // RGBA -> RGB. + var rgb_length = 0; + for (var i = 0; i < rgba.length; ++i) { + // Skip alpha component. + if (i % 4 == 3) + continue; + + // Zero is the string terminator. + if (rgba[i] == 0) + break; + + rgb[rgb_length++] = rgba[i]; + } + + // Remove trailing nulls from data. + rgb = rgb.subarray(0, rgb_length); + var string_data = (new TextDecoder("ascii")).decode(rgb); + + return JSON.parse(string_data); +} + +// A variant of requestViaImage for referrer policy tests. +// This tests many patterns of <iframe>s to test referrer policy inheritance. +// TODO(https://crbug.com/906850): Merge this into requestViaImage(). +// <iframe>-related code should be moved outside requestViaImage*(). +function requestViaImageForReferrerPolicy(url, attributes, referrerPolicy) { + // For images, we'll test: + // - images in a `srcdoc` frame to ensure that it uses the referrer + // policy of its parent, + // - images in a top-level document, + // - and images in a `srcdoc` frame with its own referrer policy to + // override its parent. + + var iframeWithoutOwnPolicy = document.createElement('iframe'); + var noSrcDocPolicy = new Promise((resolve, reject) => { + iframeWithoutOwnPolicy.srcdoc = "Hello, world."; + iframeWithoutOwnPolicy.onload = resolve; + document.body.appendChild(iframeWithoutOwnPolicy); + }) + .then(() => { + var nextUrl = url + "&cache_destroyer2=" + (new Date()).getTime(); + return loadImageInWindow(nextUrl, attributes, + iframeWithoutOwnPolicy.contentWindow); + }) + .then(function (img) { + return decodeImageData(extractImageData(img)); + }); + + // Give a srcdoc iframe a referrer policy different from the top-level page's policy. + var iframePolicy = (referrerPolicy === "no-referrer") ? "unsafe-url" : "no-referrer"; + var iframeWithOwnPolicy = document.createElement('iframe'); + var srcDocPolicy = new Promise((resolve, reject) => { + iframeWithOwnPolicy.srcdoc = "<meta name='referrer' content='" + iframePolicy + "'>Hello world."; + iframeWithOwnPolicy.onload = resolve; + document.body.appendChild(iframeWithOwnPolicy); + }) + .then(() => { + var nextUrl = url + "&cache_destroyer3=" + (new Date()).getTime(); + return loadImageInWindow(nextUrl, null, + iframeWithOwnPolicy.contentWindow); + }) + .then(function (img) { + return decodeImageData(extractImageData(img)); + }); + + var pagePolicy = loadImageInWindow(url, attributes, window) + .then(function (img) { + return decodeImageData(extractImageData(img)); + }); + + return Promise.all([noSrcDocPolicy, srcDocPolicy, pagePolicy]).then(values => { + assert_equals(values[0].headers.referer, values[2].headers.referer, "Referrer inside 'srcdoc' without its own policy should be the same as embedder's referrer."); + assert_equals((iframePolicy === "no-referrer" ? undefined : document.location.href), values[1].headers.referer, "Referrer inside 'srcdoc' should use the iframe's policy if it has one"); + return wrapResult(values[2]); + }); +} + /** * Initiates a new XHR GET request to provided URL. * @param {string} url The endpoint URL for the XHR. * @return {Promise} The promise for success/error events. */ function requestViaXhr(url) { - return xhrRequest(url); + return xhrRequest(url).then(result => wrapResult(result)); } /** @@ -184,7 +367,9 @@ * @return {Promise} The promise for success/error events. */ function requestViaFetch(url) { - return fetch(url); + return fetch(url) + .then(res => res.json()) + .then(j => wrapResult(j)); } function dedicatedWorkerUrlThatFetches(url) { @@ -213,10 +398,22 @@ } catch (e) { return Promise.reject(e); } - bindEvents(worker, "message", "error"); worker.postMessage(''); + return bindEvents2(worker, "message", worker, "error") + .then(event => wrapResult(event.data)); +} - return worker.eventPromise; +function requestViaSharedWorker(url) { + var worker; + try { + worker = new SharedWorker(url); + } catch(e) { + return Promise.reject(e); + } + const promise = bindEvents2(worker.port, "message", worker, "error") + .then(event => wrapResult(event.data)); + worker.port.start(); + return promise; } // Returns a reference to a worklet object corresponding to a given type. @@ -251,13 +448,19 @@ * @return {Promise} The promise for success/error events. */ function requestViaNavigable(navigableElement, url) { - var iframe = createHelperIframe(guid(), true); + var iframe = createHelperIframe(guid(), false); setAttributes(navigableElement, {"href": url, "target": iframe.name}); - navigableElement.click(); - return iframe.eventPromise; + const promise = + bindEvents2(window, "message", iframe, "error", window, "error") + .then(event => { + assert_equals(event.source, iframe.contentWindow, "event.source"); + return event.data; + }); + navigableElement.click(); + return promise; } /** @@ -266,8 +469,11 @@ * @param {string} url The URL to navigate to. * @return {Promise} The promise for success/error events. */ -function requestViaAnchor(url) { - var a = createElement("a", {"innerHTML": "Link to resource"}, document.body); +function requestViaAnchor(url, additionalAttributes) { + var a = createElement( + "a", + Object.assign({"innerHTML": "Link to resource"}, additionalAttributes), + document.body); return requestViaNavigable(a, url); } @@ -278,9 +484,13 @@ * @param {string} url The URL to navigate to. * @return {Promise} The promise for success/error events. */ -function requestViaArea(url) { - var area = createElement("area", {}, document.body); +function requestViaArea(url, additionalAttributes) { + var area = createElement( + "area", + Object.assign({}, additionalAttributes), + document.body); + // TODO(kristijanburnik): Append to map and add image. return requestViaNavigable(area, url); } @@ -290,8 +500,15 @@ * @param {string} url The src URL. * @return {Promise} The promise for success/error events. */ -function requestViaScript(url) { - return createRequestViaElement("script", {"src": url}, document.body); +function requestViaScript(url, additionalAttributes) { + const script = createElement( + "script", + Object.assign({"src": url}, additionalAttributes), + document.body, + false); + + return bindEvents2(window, "message", script, "error", window, "error") + .then(event => wrapResult(event.data)); } /** @@ -458,7 +675,7 @@ var websocket = new WebSocket(url); websocket.addEventListener("message", function(e) { - resolve(JSON.parse(e.data)); + resolve(e.data); }); websocket.addEventListener("open", function(e) { @@ -468,7 +685,10 @@ websocket.addEventListener("error", function(e) { reject(e) }); - }); + }) + .then(data => { + return JSON.parse(data); + }); } // SanityChecker does nothing in release mode. See sanity-checker.js for debug @@ -476,3 +696,4 @@ function SanityChecker() {} SanityChecker.prototype.checkScenario = function() {}; SanityChecker.prototype.setFailTimeout = function(test, timeout) {}; +SanityChecker.prototype.checkSubresourceResult = function() {};
diff --git a/third_party/blink/web_tests/external/wpt/mixed-content/generic/expect.py b/third_party/blink/web_tests/external/wpt/mixed-content/generic/expect.py index 672a54c3..2c360c1d 100644 --- a/third_party/blink/web_tests/external/wpt/mixed-content/generic/expect.py +++ b/third_party/blink/web_tests/external/wpt/mixed-content/generic/expect.py
@@ -83,6 +83,11 @@ "mixed-content", "generic", "worker.js"), "rb").read() + elif content_type == "text/javascript": + response_data = open(os.path.join(request.doc_root, + "mixed-content", + "generic", + "script.js"), "rb").read() else: response_data = "/* purged */" elif action == "take":
diff --git a/third_party/blink/web_tests/external/wpt/mixed-content/generic/mixed-content-test-case.js b/third_party/blink/web_tests/external/wpt/mixed-content/generic/mixed-content-test-case.js index 8708f5a9..b2c0bcde 100644 --- a/third_party/blink/web_tests/external/wpt/mixed-content/generic/mixed-content-test-case.js +++ b/third_party/blink/web_tests/external/wpt/mixed-content/generic/mixed-content-test-case.js
@@ -3,6 +3,11 @@ * @author burnik@google.com (Kristijan Burnik) */ +function wrapResult(server_data) { + // Currently the returned value is not used in mixed-content tests. + return null; +} + /** * MixedContentTestCase exercises all the tests for checking browser behavior * when resources regarded as mixed-content are requested. A single run covers
diff --git a/third_party/blink/web_tests/external/wpt/mixed-content/generic/script.js b/third_party/blink/web_tests/external/wpt/mixed-content/generic/script.js new file mode 100644 index 0000000..2d1cdf0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mixed-content/generic/script.js
@@ -0,0 +1 @@ +postMessage("", "*");
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/external-import-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/external-import-stylesheet.html index 40f4234..6be475e 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/external-import-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/external-import-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body> @@ -16,7 +17,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { let id = token(); let url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port; let css_url = url_prefix + @@ -25,19 +26,19 @@ let check_url = url_prefix + "/referrer-policy/generic/subresource/stylesheet.py" + "?id=" + id + "&report-headers"; - let link = document.createElement("link"); - link.href = css_url; - link.rel = "stylesheet"; - link.onload = function() { - css_test.step_timeout(function() { - queryXhr(check_url, function(message) { - assert_own_property(message, "headers"); - assert_equals(message.referrer, undefined); - css_test.done(); - }, null, null, css_test); - }, 1000); - }; - document.head.appendChild(link); + return new Promise(resolve => { + let link = document.createElement("link"); + link.href = css_url; + link.rel = "stylesheet"; + link.onload = resolve; + document.head.appendChild(link); + }) + .then(() => timeoutPromise(css_test, 1000)) + .then(() => requestViaXhr(check_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_equals(message.referrer, undefined); + }); }, "Child css from external stylesheet."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet.html index 30c5ea29..37370fdd 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="never"> </head> <body> @@ -16,7 +17,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { let id = token(); let url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port; let css_url = url_prefix + "/referrer-policy/generic/subresource/stylesheet.py?id=" + id + "&import-rule"; @@ -27,14 +28,13 @@ style.type = 'text/css'; style.appendChild(document.createTextNode("@import url('" + css_url + "');")); document.head.appendChild(style); - css_test.step_timeout(function() { - queryXhr(check_url, function(message) { + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(check_url)) + .then(function(message) { assert_own_property(message, "headers"); assert_own_property(message, "referrer"); assert_equals(message.referrer, css_url); - css_test.done(); - }, null, null, css_test); - }, 1000); + }); }, "Child css from internal stylesheet."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/processing-instruction.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/processing-instruction.html index 52a0ded4..5362234 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/processing-instruction.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/processing-instruction.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body> @@ -15,7 +16,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { let id = token(); let url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port + @@ -28,15 +29,14 @@ let processingInstruction = document.createProcessingInstruction( "xml-stylesheet", "href=\"" +css_url + "\" type=\"text/css\""); - css_test.step_timeout(function() { - queryXhr(check_url, function(message) { + document.insertBefore(processingInstruction, document.firstChild); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(check_url)) + .then(function(message) { assert_own_property(message, "headers"); assert_own_property(message, "referrer"); assert_equals(message.referrer, expected); - css_test.done(); - }, null, null, css_test); - }, 1000); - document.insertBefore(processingInstruction, document.firstChild); + }); }, "Child css via a ProcessingInstruction."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/css-test-helper.js b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/css-test-helper.js index 788df16a..0afa9e1 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/css-test-helper.js +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/css-test-helper.js
@@ -14,41 +14,34 @@ 'mask-image', ]; -// Schedules async_test's for each of the test properties // Parameters: // testProperties: An array of test properties. // testDescription: A test description // testFunction: A function call which sets up the expect result and runs // the actual test function runSvgTests(testProperties, testDescription, testFunction) { - let runNextTest = function () { - let property = testProperties.shift(); - if (property === undefined) { - return; - } - + for (const property of testProperties) { let current = { - test: async_test(testDescription + " " + property), id: token(), property: property, }; - current.test.step(function() { testFunction(current) }); - - let check_url = url_prefix + "svg.py" + "?id=" + current.id + - "&report-headers"; - current.test.step_timeout(function() { - queryXhr(check_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, current.expected); - current.test.done(); - }, null, null, current.test); - }, 800); - }; - - add_result_callback(runNextTest); - runNextTest(); + promise_test(t => { + testFunction(current); + return timeoutPromise(t, 800) + .then(() => { + let check_url = url_prefix + "svg.py" + "?id=" + current.id + + "&report-headers"; + return requestViaFetch(check_url); + }) + .then(message => { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, current.expected); + }); + }, + testDescription + " " + property); + } } function createSvg() {
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/external-import-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/external-import-stylesheet.html index 80e3587..300960d2 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/external-import-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/external-import-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="never"> </head> <body> @@ -17,7 +18,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { let id = token(); let css_url = location.protocol + "//www1." + location.hostname + ":" + location.port + @@ -29,20 +30,20 @@ let font_url = url_prefix + "/referrer-policy/generic/subresource/font.py" + "?id=" + id + "&report-headers" + "&type=font"; - let link = document.createElement("link"); - link.href = css_url; - link.rel = "stylesheet"; - link.onload = function() { - css_test.step_timeout(function() { - queryXhr(font_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, css_referrer); - css_test.done(); - }, null, null, css_test); - }, 1000); - }; - document.head.appendChild(link); + return new Promise(resolve => { + let link = document.createElement("link"); + link.href = css_url; + link.rel = "stylesheet"; + link.onload = resolve; + document.head.appendChild(link); + }) + .then(() => timeoutPromise(css_test, 1000)) + .then(() => requestViaXhr(font_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, css_referrer); + }); }, "Font from imported stylesheet (external)."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/external-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/external-stylesheet.html index a91eb3f..45da018 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/external-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/external-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="never"> </head> <body> @@ -16,27 +17,27 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { let id = token(); let url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port; let css_url = url_prefix + "/referrer-policy/generic/subresource/stylesheet.py?id=" + id + "&type=font"; let font_url = url_prefix + "/referrer-policy/generic/subresource/font.py" + "?id=" + id + "&report-headers"; - let link = document.createElement("link"); - link.href = css_url; - link.rel = "stylesheet"; - link.onload = function() { - css_test.step_timeout(function() { - queryXhr(font_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, css_url); - css_test.done(); - }, null, null, css_test); - }, 1000); - }; - document.head.appendChild(link); + return new Promise(resolve => { + let link = document.createElement("link"); + link.href = css_url; + link.rel = "stylesheet"; + link.onload = resolve; + document.head.appendChild(link); + }) + .then(() => timeoutPromise(css_test, 1000)) + .then(() => requestViaXhr(font_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, css_url); + }); }, "Font from external stylesheet."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/internal-import-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/internal-import-stylesheet.html index a637082..dd06b7d7 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/internal-import-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/internal-import-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body> @@ -17,7 +18,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { let id = token(); let url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port + "/referrer-policy/generic/subresource/"; @@ -27,14 +28,13 @@ let style = document.createElement("style"); style.textContent = "@import url('" + css_url + "');"; document.head.appendChild(style); - css_test.step_timeout(function() { - queryXhr(font_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, css_url); - css_test.done(); - }, null, null, css_test); - }, 1000); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(font_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, css_url); + }); }, "Font from imported stylesheet (internal)."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/internal-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/internal-stylesheet.html index eebd864b..a0a9067 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/internal-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/internal-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body> @@ -16,7 +17,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { let id = token(); let css_url = location.protocol + "//www1." + location.hostname + ":" + location.port + @@ -27,14 +28,13 @@ let style = document.createElement("style"); style.textContent = "@font-face { font-family: 'wpt'; font-style: normal; font-weight: normal; src: url(" + css_url + "); format('truetype'); } body { font-family: 'wpt';}"; document.head.appendChild(style); - css_test.step_timeout(function() { - queryXhr(font_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, location.origin + "/"); - css_test.done(); - }, null, null, css_test); - }, 1000); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(font_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, location.origin + "/"); + }); }, "Font from internal stylesheet."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/processing-instruction.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/processing-instruction.html index bfc42d9..a9d79a3 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/processing-instruction.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/font-face/processing-instruction.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="never"> </head> <body> @@ -17,7 +18,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { let id = token(); let url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port; let css_url = url_prefix + @@ -32,15 +33,14 @@ let processingInstruction = document.createProcessingInstruction( "xml-stylesheet", "href=\"" + css_url + "\" type=\"text/css\""); - css_test.step_timeout(function() { - queryXhr(font_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, expected); - css_test.done(); - }, null, null, css_test); - }, 1000); document.insertBefore(processingInstruction, document.firstChild); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(font_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, expected); + }); }, "Font from external stylesheet (from ProcessingInstruction)."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/external-import-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/external-import-stylesheet.html index 80c71b0..2a7ac43 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/external-import-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/external-import-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="never"> </head> <body> @@ -17,7 +18,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { var id = token(); var css_url = location.protocol + "//www1." + location.hostname + ":" + location.port + "/referrer-policy/generic/subresource/stylesheet.py?id=" + id + @@ -29,20 +30,20 @@ var img_url = url_prefix + "/referrer-policy/generic/subresource/image.py" + "?id=" + id + "&report-headers"; - var link = document.createElement("link"); - link.href = css_url; - link.rel = "stylesheet"; - link.onload = function() { - css_test.step_timeout(function() { - queryXhr(img_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, css_referrer); - css_test.done(); - }, null, null, css_test); - }, 1000); - }; - document.head.appendChild(link); + return new Promise(resolve => { + var link = document.createElement("link"); + link.href = css_url; + link.rel = "stylesheet"; + link.onload = resolve; + document.head.appendChild(link); + }) + .then(() => timeoutPromise(css_test, 1000)) + .then(() => requestViaXhr(img_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, css_referrer); + }); }, "Image from imported stylesheet (external)."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/external-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/external-stylesheet.html index ba7497b..c763ecb 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/external-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/external-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="never"> </head> <body> @@ -16,27 +17,27 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { var id = token(); var url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port; var css_url = url_prefix + "/referrer-policy/generic/subresource/stylesheet.py?id=" + id; var img_url = url_prefix + "/referrer-policy/generic/subresource/image.py" + "?id=" + id + "&report-headers"; - var link = document.createElement("link"); - link.href = css_url; - link.rel = "stylesheet"; - link.onload = css_test.step_func(function() { - css_test.step_timeout(function() { - queryXhr(img_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, css_url); - css_test.done(); - }, null, null, css_test); - }, 1000); - }); - document.head.appendChild(link); + return new Promise(resolve => { + var link = document.createElement("link"); + link.href = css_url; + link.rel = "stylesheet"; + link.onload = resolve; + document.head.appendChild(link); + }) + .then(() => timeoutPromise(css_test, 1000)) + .then(() => requestViaXhr(img_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, css_url); + }); }, "Image from external stylesheet."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/inline-style.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/inline-style.html index 758b6d9..da571af 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/inline-style.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/inline-style.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body> @@ -16,21 +17,20 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { var id = token(); var css_url = location.protocol + "//www1." + location.hostname + ":" + location.port + "/referrer-policy/generic/subresource/image.py" + "?id=" + id; var img_url = css_url + "&report-headers"; var div = document.querySelector("div.styled"); div.style = "content:url(" + css_url + ")"; - css_test.step_timeout(function() { - queryXhr(img_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, location.origin + "/"); - css_test.done(); - }, null, null, css_test); - }, 1000); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(img_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, location.origin + "/"); + }); }, "Image from inline styles."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/internal-import-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/internal-import-stylesheet.html index 24aa1858..e320e063 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/internal-import-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/internal-import-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body> @@ -17,7 +18,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { var id = token(); var url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port + "/referrer-policy/generic/subresource/"; var css_url = url_prefix + "stylesheet.py?id=" + id; @@ -27,14 +28,13 @@ style.type = 'text/css'; style.appendChild(document.createTextNode("@import url('" + css_url + "');")); document.head.appendChild(style); - css_test.step_timeout(function() { - queryXhr(img_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, css_url); - css_test.done(); - }, null, null, css_test); - }, 1000); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(img_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, css_url); + }); }, "Image from imported stylesheet (internal)."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/internal-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/internal-stylesheet.html index f456788..3e2fc10 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/internal-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/internal-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body> @@ -16,7 +17,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { var id = token(); var css_url = location.protocol + "//www1." + location.hostname + ":" + location.port + "/referrer-policy/generic/subresource/image.py" + "?id=" + id; var img_url = css_url + "&report-headers"; @@ -25,14 +26,13 @@ style.type = 'text/css'; style.appendChild(document.createTextNode("div.styled::before { content:url(" + css_url + ")}")); document.head.appendChild(style); - css_test.step_timeout(function() { - queryXhr(img_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, location.origin + "/"); - css_test.done(); - }, null, null, css_test); - }, 1000); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(img_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, location.origin + "/"); + }); }, "Image from internal stylesheet."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/presentation-attribute.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/presentation-attribute.html index d0a4d96f..e810df54 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/presentation-attribute.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/presentation-attribute.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body> @@ -14,20 +15,19 @@ the referrer and referrer policy from the document.</p> <script> - async_test(function(css_test) { + promise_test(function(css_test) { var id = token(); var css_url = location.protocol + "//www1." + location.hostname + ":" + location.port + "/referrer-policy/generic/subresource/image.py" + "?id=" + id; var img_url = css_url + "&report-headers"; document.body.background = css_url; - css_test.step_timeout(function() { - queryXhr(img_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, location.origin + "/"); - css_test.done(); - }, null, null, css_test); - }, 1000); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(img_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, location.origin + "/"); + }); }, "Image from presentation attributes."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/processing-instruction.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/processing-instruction.html index 926147b..e5a1e20a 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/processing-instruction.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/image/processing-instruction.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="never"> </head> <body> @@ -17,7 +18,7 @@ <div class="styled"></div> <script> - async_test(function(css_test) { + promise_test(function(css_test) { var id = token(); var url_prefix = location.protocol + "//www1." + location.hostname + ":" + location.port; var css_url = url_prefix + "/referrer-policy/generic/subresource/stylesheet.py?id=" + id; @@ -25,15 +26,14 @@ "?id=" + id + "&report-headers"; var processingInstruction = document.createProcessingInstruction("xml-stylesheet", "href=\"" + css_url + "\" type=\"text/css\""); - css_test.step_timeout(function() { - queryXhr(img_url, function(message) { - assert_own_property(message, "headers"); - assert_own_property(message, "referrer"); - assert_equals(message.referrer, css_url); - css_test.done(); - }, null, null, css_test); - }, 1000); document.insertBefore(processingInstruction, document.firstChild); + return timeoutPromise(css_test, 1000) + .then(() => requestViaXhr(img_url)) + .then(function(message) { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, css_url); + }); }, "Image from external stylesheet (from ProcessingInstruction)."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/external-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/external-stylesheet.html index 148584a..dfa6fd0 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/external-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/external-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <!-- Helper functions for referrer-policy css tests. --> <script src="/referrer-policy/css-integration/css-test-helper.js"></script> <meta name="referrer" content="never">
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/inline-style.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/inline-style.html index 1f46acb..fd6e4ba 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/inline-style.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/inline-style.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <!-- Helper functions for referrer-policy css tests. --> <script src="/referrer-policy/css-integration/css-test-helper.js"></script> <meta name="referrer" content="origin">
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/internal-stylesheet.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/internal-stylesheet.html index 08be4ef..228de6d 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/internal-stylesheet.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/internal-stylesheet.html
@@ -7,6 +7,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <!-- Helper functions for referrer-policy css tests. --> <script src="/referrer-policy/css-integration/css-test-helper.js"></script> <meta name="referrer" content="origin">
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/presentation-attribute.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/presentation-attribute.html index edeceb1..65bb642f 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/presentation-attribute.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/presentation-attribute.html
@@ -8,6 +8,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <!-- Helper functions for referrer-policy css tests. --> <script src="/referrer-policy/css-integration/css-test-helper.js"></script> <meta name="referrer" content="origin">
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/processing-instruction.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/processing-instruction.html index ba0e6673..c0e8d4b 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/processing-instruction.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/svg/processing-instruction.html
@@ -8,6 +8,7 @@ <script src="/common/utils.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <!-- Helper functions for referrer-policy css tests. --> <script src="/referrer-policy/css-integration/css-test-helper.js"></script> <meta name="referrer" content="origin">
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/common.js b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/common.js index a16691b..f1574e9 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/common.js +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/common.js
@@ -1,54 +1,267 @@ -// NOTE: This method only strips the fragment and is not in accordance to the -// recommended draft specification: -// https://w3c.github.io/webappsec/specs/referrer-policy/#null -// TODO(kristijanburnik): Implement this helper as defined by spec once added -// scenarios for URLs containing username/password/etc. -function stripUrlForUseAsReferrer(url) { - return url.replace(/#.*$/, ""); +/** + * @fileoverview Utilities for mixed-content in Web Platform Tests. + * @author burnik@google.com (Kristijan Burnik) + * Disclaimer: Some methods of other authors are annotated in the corresponding + * method's JSDoc. + */ + +// The same content is placed as +// - wpt/referrer-policy/generic/common.js and +// - wpt/mixed-content/generic/common.js. +// If you modify either one, please also update the other one. +// +// TODO(https://crbug.com/906850): These two files are going to be merged. +// Currently they are duplicated only to avoid frequent mass modification +// for each step of refactoring, as these file names are hard-coded in +// a large number of generated test files. + +function timeoutPromise(t, ms) { + return new Promise(resolve => { t.step_timeout(resolve, ms); }); } -function parseUrlQueryString(queryString) { - var queries = queryString.replace(/^\?/, "").split("&"); - var params = {}; - - for (var i in queries) { - var kvp = queries[i].split("="); - params[kvp[0]] = kvp[1]; - } - - return params; -}; - -function appendIframeToBody(url, attributes) { - var iframe = document.createElement("iframe"); - iframe.src = url; - // Extend element with attributes. (E.g. "referrerPolicy" or "rel") - if (attributes) { - for (var attr in attributes) { - iframe[attr] = attributes[attr]; - } - } - document.body.appendChild(iframe); - - return iframe; +/** + * Normalizes the target port for use in a URL. For default ports, this is the + * empty string (omitted port), otherwise it's a colon followed by the port + * number. Ports 80, 443 and an empty string are regarded as default ports. + * @param {number} targetPort The port to use + * @return {string} The port portion for using as part of a URL. + */ +function getNormalizedPort(targetPort) { + return ([80, 443, ""].indexOf(targetPort) >= 0) ? "" : ":" + targetPort; } -function loadImageInWindow(src, callback, attributes, w) { - var image = new w.Image(); - image.crossOrigin = "Anonymous"; - image.onload = function() { - callback(image); - } +/** + * Creates a GUID. + * See: https://en.wikipedia.org/wiki/Globally_unique_identifier + * Original author: broofa (http://www.broofa.com/) + * Sourced from: http://stackoverflow.com/a/2117523/4949715 + * @return {string} A pseudo-random GUID. + */ +function guid() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} - // Extend element with attributes. (E.g. "referrerPolicy" or "rel") - if (attributes) { - for (var attr in attributes) { - image[attr] = attributes[attr]; +/** + * Initiates a new XHR via GET. + * @param {string} url The endpoint URL for the XHR. + * @param {string} responseType Optional - how should the response be parsed. + * Default is "json". + * See: https://xhr.spec.whatwg.org/#dom-xmlhttprequest-responsetype + * @return {Promise} A promise wrapping the success and error events. + */ +function xhrRequest(url, responseType) { + return new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = responseType || "json"; + + xhr.addEventListener("error", function() { + reject(Error("Network Error")); + }); + + xhr.addEventListener("load", function() { + if (xhr.status != 200) + reject(Error(xhr.statusText)); + else + resolve(xhr.response); + }); + + xhr.send(); + }); +} + +/** + * Sets attributes on a given DOM element. + * @param {DOMElement} element The element on which to set the attributes. + * @param {object} An object with keys (serving as attribute names) and values. + */ +function setAttributes(el, attrs) { + attrs = attrs || {} + for (var attr in attrs) + el.setAttribute(attr, attrs[attr]); +} + +/** + * Binds to success and error events of an object wrapping them into a promise + * available through {@code element.eventPromise}. The success event + * resolves and error event rejects. + * This method adds event listeners, and then removes all the added listeners + * when one of listened event is fired. + * @param {object} element An object supporting events on which to bind the + * promise. + * @param {string} resolveEventName [="load"] The event name to bind resolve to. + * @param {string} rejectEventName [="error"] The event name to bind reject to. + */ +function bindEvents(element, resolveEventName, rejectEventName) { + element.eventPromise = + bindEvents2(element, resolveEventName, element, rejectEventName); +} + +// Returns a promise wrapping success and error events of objects. +// This is a variant of bindEvents that can accept separate objects for each +// events and two events to reject, and doesn't set `eventPromise`. +// +// When `resolveObject`'s `resolveEventName` event (default: "load") is +// fired, the promise is resolved with the event. +// +// When `rejectObject`'s `rejectEventName` event (default: "error") or +// `rejectObject2`'s `rejectEventName2` event (default: "error") is +// fired, the promise is rejected. +// +// `rejectObject2` is optional. +function bindEvents2(resolveObject, resolveEventName, rejectObject, rejectEventName, rejectObject2, rejectEventName2) { + return new Promise(function(resolve, reject) { + const actualResolveEventName = resolveEventName || "load"; + const actualRejectEventName = rejectEventName || "error"; + const actualRejectEventName2 = rejectEventName2 || "error"; + + const resolveHandler = function(event) { + cleanup(); + resolve(event); + }; + + const rejectHandler = function(event) { + // Chromium starts propagating errors from worker.onerror to + // window.onerror. This handles the uncaught exceptions in tests. + event.preventDefault(); + cleanup(); + reject(event); + }; + + const cleanup = function() { + resolveObject.removeEventListener(actualResolveEventName, resolveHandler); + rejectObject.removeEventListener(actualRejectEventName, rejectHandler); + if (rejectObject2) { + rejectObject2.removeEventListener(actualRejectEventName2, rejectHandler); + } + }; + + resolveObject.addEventListener(actualResolveEventName, resolveHandler); + rejectObject.addEventListener(actualRejectEventName, rejectHandler); + if (rejectObject2) { + rejectObject2.addEventListener(actualRejectEventName2, rejectHandler); } - } + }); +} - image.src = src; - w.document.body.appendChild(image) +/** + * Creates a new DOM element. + * @param {string} tagName The type of the DOM element. + * @param {object} attrs A JSON with attributes to apply to the element. + * @param {DOMElement} parent Optional - an existing DOM element to append to + * If not provided, the returned element will remain orphaned. + * @param {boolean} doBindEvents Optional - Whether to bind to load and error + * events and provide the promise wrapping the events via the element's + * {@code eventPromise} property. Default value evaluates to false. + * @return {DOMElement} The newly created DOM element. + */ +function createElement(tagName, attrs, parentNode, doBindEvents) { + var element = document.createElement(tagName); + + if (doBindEvents) + bindEvents(element); + + // We set the attributes after binding to events to catch any + // event-triggering attribute changes. E.g. form submission. + // + // But be careful with images: unlike other elements they will start the load + // as soon as the attr is set, even if not in the document yet, and sometimes + // complete it synchronously, so the append doesn't have the effect we want. + // So for images, we want to set the attrs after appending, whereas for other + // elements we want to do it before appending. + var isImg = (tagName == "img"); + if (!isImg) + setAttributes(element, attrs); + + if (parentNode) + parentNode.appendChild(element); + + if (isImg) + setAttributes(element, attrs); + + return element; +} + +function createRequestViaElement(tagName, attrs, parentNode) { + return createElement(tagName, attrs, parentNode, true).eventPromise; +} + +/** + * Creates a new empty iframe and appends it to {@code document.body} . + * @param {string} name The name and ID of the new iframe. + * @param {boolean} doBindEvents Whether to bind load and error events. + * @return {DOMElement} The newly created iframe. + */ +function createHelperIframe(name, doBindEvents) { + return createElement("iframe", + {"name": name, "id": name}, + document.body, + doBindEvents); +} + +/** + * requestVia*() functions return promises that are resolved on successful + * requests with objects of the same "type", i.e. objects that contains + * the same sets of keys that are fixed within one category of tests (e.g. + * within wpt/referrer-policy tests). + * wrapResult() (that should be defined outside this file) is used to convert + * the response bodies of subresources into the expected result objects in some + * cases, and in other cases the result objects are constructed more directly. + * TODO(https://crbug.com/906850): Clean up the semantics around this, e.g. + * use (or not use) wrapResult() consistently, unify the arguments, etc. + */ + +/** + * Creates a new iframe, binds load and error events, sets the src attribute and + * appends it to {@code document.body} . + * @param {string} url The src for the iframe. + * @return {Promise} The promise for success/error events. + */ +function requestViaIframe(url, additionalAttributes) { + const iframe = createElement( + "iframe", + Object.assign({"src": url}, additionalAttributes), + document.body, + false); + return bindEvents2(window, "message", iframe, "error", window, "error") + .then(event => { + assert_equals(event.source, iframe.contentWindow); + return event.data; + }); +} + +/** + * Creates a new image, binds load and error events, sets the src attribute and + * appends it to {@code document.body} . + * @param {string} url The src for the image. + * @return {Promise} The promise for success/error events. + */ +function requestViaImage(url) { + return createRequestViaElement("img", {"src": url}, document.body); +} + +// Helpers for requestViaImageForReferrerPolicy(). +function loadImageInWindow(src, attributes, w) { + return new Promise((resolve, reject) => { + var image = new w.Image(); + image.crossOrigin = "Anonymous"; + image.onload = function() { + resolve(image); + }; + + // Extend element with attributes. (E.g. "referrerPolicy" or "rel") + if (attributes) { + for (var attr in attributes) { + image[attr] = attributes[attr]; + } + } + + image.src = src; + w.document.body.appendChild(image) + }); } function extractImageData(img) { @@ -83,35 +296,11 @@ return JSON.parse(string_data); } -function normalizePort(targetPort) { - var defaultPorts = [80, 443]; - var isDefaultPortForProtocol = (defaultPorts.indexOf(targetPort) >= 0); - - return (targetPort == "" || isDefaultPortForProtocol) ? - "" : ":" + targetPort; -} - -function wrapResult(url, server_data) { - return { - location: url, - referrer: server_data.headers.referer, - headers: server_data.headers - } -} - -function queryIframe(url, callback, attributes, referrer_policy, test) { - var iframe = appendIframeToBody(url, attributes); - var listener = test.step_func(function(event) { - if (event.source != iframe.contentWindow) - return; - - callback(event.data, url); - window.removeEventListener("message", listener); - }); - window.addEventListener("message", listener); -} - -function queryImage(url, callback, attributes, referrerPolicy, test) { +// A variant of requestViaImage for referrer policy tests. +// This tests many patterns of <iframe>s to test referrer policy inheritance. +// TODO(https://crbug.com/906850): Merge this into requestViaImage(). +// <iframe>-related code should be moved outside requestViaImage*(). +function requestViaImageForReferrerPolicy(url, attributes, referrerPolicy) { // For images, we'll test: // - images in a `srcdoc` frame to ensure that it uses the referrer // policy of its parent, @@ -119,148 +308,392 @@ // - and images in a `srcdoc` frame with its own referrer policy to // override its parent. + var iframeWithoutOwnPolicy = document.createElement('iframe'); var noSrcDocPolicy = new Promise((resolve, reject) => { - var iframeWithoutOwnPolicy = document.createElement('iframe'); - iframeWithoutOwnPolicy.srcdoc = "Hello, world."; - iframeWithoutOwnPolicy.onload = test.step_func(function () { - var nextUrl = url + "&cache_destroyer2=" + (new Date()).getTime(); - loadImageInWindow(nextUrl, test.step_func(function (img) { - resolve(decodeImageData(extractImageData(img))); - }), attributes, iframeWithoutOwnPolicy.contentWindow); - }); - document.body.appendChild(iframeWithoutOwnPolicy); - }); + iframeWithoutOwnPolicy.srcdoc = "Hello, world."; + iframeWithoutOwnPolicy.onload = resolve; + document.body.appendChild(iframeWithoutOwnPolicy); + }) + .then(() => { + var nextUrl = url + "&cache_destroyer2=" + (new Date()).getTime(); + return loadImageInWindow(nextUrl, attributes, + iframeWithoutOwnPolicy.contentWindow); + }) + .then(function (img) { + return decodeImageData(extractImageData(img)); + }); // Give a srcdoc iframe a referrer policy different from the top-level page's policy. var iframePolicy = (referrerPolicy === "no-referrer") ? "unsafe-url" : "no-referrer"; + var iframeWithOwnPolicy = document.createElement('iframe'); var srcDocPolicy = new Promise((resolve, reject) => { - var iframeWithOwnPolicy = document.createElement('iframe'); - iframeWithOwnPolicy.srcdoc = "<meta name='referrer' content='" + iframePolicy + "'>Hello world."; + iframeWithOwnPolicy.srcdoc = "<meta name='referrer' content='" + iframePolicy + "'>Hello world."; + iframeWithOwnPolicy.onload = resolve; + document.body.appendChild(iframeWithOwnPolicy); + }) + .then(() => { + var nextUrl = url + "&cache_destroyer3=" + (new Date()).getTime(); + return loadImageInWindow(nextUrl, null, + iframeWithOwnPolicy.contentWindow); + }) + .then(function (img) { + return decodeImageData(extractImageData(img)); + }); - iframeWithOwnPolicy.onload = test.step_func(function () { - var nextUrl = url + "&cache_destroyer3=" + (new Date()).getTime(); - loadImageInWindow(nextUrl, test.step_func(function (img) { - resolve(decodeImageData(extractImageData(img))); - }), null, iframeWithOwnPolicy.contentWindow); - }); - document.body.appendChild(iframeWithOwnPolicy); - }); + var pagePolicy = loadImageInWindow(url, attributes, window) + .then(function (img) { + return decodeImageData(extractImageData(img)); + }); - var pagePolicy = new Promise((resolve, reject) => { - loadImageInWindow(url, test.step_func(function (img) { - resolve(decodeImageData(extractImageData(img))); - }), attributes, window); - }); - - Promise.all([noSrcDocPolicy, srcDocPolicy, pagePolicy]).then(test.step_func(values => { + return Promise.all([noSrcDocPolicy, srcDocPolicy, pagePolicy]).then(values => { assert_equals(values[0].headers.referer, values[2].headers.referer, "Referrer inside 'srcdoc' without its own policy should be the same as embedder's referrer."); assert_equals((iframePolicy === "no-referrer" ? undefined : document.location.href), values[1].headers.referer, "Referrer inside 'srcdoc' should use the iframe's policy if it has one"); - callback(wrapResult(url, values[2]), url); - })); -} - -function queryXhr(url, callback, attributes, referrer_policy, test) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, true); - xhr.onreadystatechange = test.step_func(function(e) { - if (xhr.readyState == 4 && xhr.status == 200) { - var server_data = JSON.parse(xhr.responseText); - callback(wrapResult(url, server_data), url); - } - }); - xhr.send(); -} - -function queryWorker(url, callback, attributes, referrer_policy, test) { - var worker = new Worker(url); - worker.onmessage = test.step_func(function(event) { - var server_data = event.data; - callback(wrapResult(url, server_data), url); + return wrapResult(values[2]); }); } -function queryModuleWorkerTopLevel(url, callback, attributes, referrer_policy, test) { - var worker = new Worker(url, {type: "module"}); - worker.onmessage = test.step_func(function(event) { - var server_data = event.data; - callback(wrapResult(url, server_data), url); - }); +/** + * Initiates a new XHR GET request to provided URL. + * @param {string} url The endpoint URL for the XHR. + * @return {Promise} The promise for success/error events. + */ +function requestViaXhr(url) { + return xhrRequest(url).then(result => wrapResult(result)); } -function querySharedWorker(url, callback, attributes, referrer_policy, test) { - var worker = new SharedWorker(url); - worker.port.onmessage = test.step_func(function(event) { - var server_data = event.data; - callback(wrapResult(url, server_data), url); - }); +/** + * Initiates a new GET request to provided URL via the Fetch API. + * @param {string} url The endpoint URL for the Fetch. + * @return {Promise} The promise for success/error events. + */ +function requestViaFetch(url) { + return fetch(url) + .then(res => res.json()) + .then(j => wrapResult(j)); } -function queryFetch(url, callback, attributes, referrer_policy, test) { - fetch(url).then(test.step_func(function(response) { - response.json().then(test.step_func(function(server_data) { - callback(wrapResult(url, server_data), url); - })); - }) - ); +function dedicatedWorkerUrlThatFetches(url) { + return `data:text/javascript, + fetch('${url}') + .then(() => postMessage(''), + () => postMessage(''));`; } -function queryNavigable(element, url, callback, attributes, test) { - var navigable = element - navigable.href = url; - navigable.target = "helper-iframe"; +function workerUrlThatImports(url) { + return `data:text/javascript,import '${url}';`; +} - var helperIframe = document.createElement("iframe") - helperIframe.name = "helper-iframe" - document.body.appendChild(helperIframe) - - // Extend element with attributes. (E.g. "referrer_policy" or "rel") - if (attributes) { - for (var attr in attributes) { - navigable[attr] = attributes[attr]; - } +/** + * Creates a new Worker, binds message and error events wrapping them into. + * {@code worker.eventPromise} and posts an empty string message to start + * the worker. + * @param {string} url The endpoint URL for the worker script. + * @param {object} options The options for Worker constructor. + * @return {Promise} The promise for success/error events. + */ +function requestViaDedicatedWorker(url, options) { + var worker; + try { + worker = new Worker(url, options); + } catch (e) { + return Promise.reject(e); } - - var listener = test.step_func(function(event) { - if (event.source != helperIframe.contentWindow) - return; - callback(event.data, url); - window.removeEventListener("message", listener); - }); - window.addEventListener("message", listener); - - navigable.click(); + worker.postMessage(''); + return bindEvents2(worker, "message", worker, "error") + .then(event => wrapResult(event.data)); } -function queryLink(url, callback, attributes, referrer_policy, test) { - var a = document.createElement("a"); - a.innerHTML = "Link to subresource"; - document.body.appendChild(a); - queryNavigable(a, url, callback, attributes, test) +function requestViaSharedWorker(url) { + var worker; + try { + worker = new SharedWorker(url); + } catch(e) { + return Promise.reject(e); + } + const promise = bindEvents2(worker.port, "message", worker, "error") + .then(event => wrapResult(event.data)); + worker.port.start(); + return promise; } -function queryAreaLink(url, callback, attributes, referrer_policy, test) { - var area = document.createElement("area"); +// Returns a reference to a worklet object corresponding to a given type. +function get_worklet(type) { + if (type == 'animation') + return CSS.animationWorklet; + if (type == 'layout') + return CSS.layoutWorklet; + if (type == 'paint') + return CSS.paintWorklet; + if (type == 'audio') + return new OfflineAudioContext(2,44100*40,44100).audioWorklet; + + assert_unreached('unknown worklet type is passed.'); + return undefined; +} + +function requestViaWorklet(type, url) { + try { + return get_worklet(type).addModule(url); + } catch (e) { + return Promise.reject(e); + } +} + +/** + * Sets the href attribute on a navigable DOM element and performs a navigation + * by clicking it. To avoid navigating away from the current execution + * context, a target attribute is set to point to a new helper iframe. + * @param {DOMElement} navigableElement The navigable DOMElement + * @param {string} url The href for the navigable element. + * @return {Promise} The promise for success/error events. + */ +function requestViaNavigable(navigableElement, url) { + var iframe = createHelperIframe(guid(), false); + setAttributes(navigableElement, + {"href": url, + "target": iframe.name}); + + const promise = + bindEvents2(window, "message", iframe, "error", window, "error") + .then(event => { + assert_equals(event.source, iframe.contentWindow, "event.source"); + return event.data; + }); + navigableElement.click(); + return promise; +} + +/** + * Creates a new anchor element, appends it to {@code document.body} and + * performs the navigation. + * @param {string} url The URL to navigate to. + * @return {Promise} The promise for success/error events. + */ +function requestViaAnchor(url, additionalAttributes) { + var a = createElement( + "a", + Object.assign({"innerHTML": "Link to resource"}, additionalAttributes), + document.body); + + return requestViaNavigable(a, url); +} + +/** + * Creates a new area element, appends it to {@code document.body} and performs + * the navigation. + * @param {string} url The URL to navigate to. + * @return {Promise} The promise for success/error events. + */ +function requestViaArea(url, additionalAttributes) { + var area = createElement( + "area", + Object.assign({}, additionalAttributes), + document.body); + // TODO(kristijanburnik): Append to map and add image. - document.body.appendChild(area); - queryNavigable(area, url, callback, attributes, test) + return requestViaNavigable(area, url); } -function queryScript(url, callback, attributes, referrer_policy, test) { - var script = document.createElement("script"); - script.src = url; - script.referrerPolicy = referrer_policy; +/** + * Creates a new script element, sets the src to url, and appends it to + * {@code document.body}. + * @param {string} url The src URL. + * @return {Promise} The promise for success/error events. + */ +function requestViaScript(url, additionalAttributes) { + const script = createElement( + "script", + Object.assign({"src": url}, additionalAttributes), + document.body, + false); - var listener = test.step_func(function(event) { - var server_data = event.data; - callback(wrapResult(url, server_data), url); - window.removeEventListener("message", listener); + return bindEvents2(window, "message", script, "error", window, "error") + .then(event => wrapResult(event.data)); +} + +/** + * Creates a new form element, sets attributes, appends it to + * {@code document.body} and submits the form. + * @param {string} url The URL to submit to. + * @return {Promise} The promise for success/error events. + */ +function requestViaForm(url) { + var iframe = createHelperIframe(guid()); + var form = createElement("form", + {"action": url, + "method": "POST", + "target": iframe.name}, + document.body); + bindEvents(iframe); + form.submit(); + + return iframe.eventPromise; +} + +/** + * Creates a new link element for a stylesheet, binds load and error events, + * sets the href to url and appends it to {@code document.head}. + * @param {string} url The URL for a stylesheet. + * @return {Promise} The promise for success/error events. + */ +function requestViaLinkStylesheet(url) { + return createRequestViaElement("link", + {"rel": "stylesheet", "href": url}, + document.head); +} + +/** + * Creates a new link element for a prefetch, binds load and error events, sets + * the href to url and appends it to {@code document.head}. + * @param {string} url The URL of a resource to prefetch. + * @return {Promise} The promise for success/error events. + */ +function requestViaLinkPrefetch(url) { + var link = document.createElement('link'); + if (link.relList && link.relList.supports && link.relList.supports("prefetch")) { + return createRequestViaElement("link", + {"rel": "prefetch", "href": url}, + document.head); + } else { + return Promise.reject("This browser does not support 'prefetch'."); + } +} + +/** + * Initiates a new beacon request. + * @param {string} url The URL of a resource to prefetch. + * @return {Promise} The promise for success/error events. + */ +async function requestViaSendBeacon(url) { + function wait(ms) { + return new Promise(resolve => step_timeout(resolve, ms)); + } + if (!navigator.sendBeacon(url)) { + // If mixed-content check fails, it should return false. + throw new Error('sendBeacon() fails.'); + } + // We don't have a means to see the result of sendBeacon() request + // for sure. Let's wait for a while and let the generic test function + // ask the server for the result. + await wait(500); + return 'allowed'; +} + +/** + * Creates a new media element with a child source element, binds loadeddata and + * error events, sets attributes and appends to document.body. + * @param {string} type The type of the media element (audio/video/picture). + * @param {object} media_attrs The attributes for the media element. + * @param {object} source_attrs The attributes for the child source element. + * @return {DOMElement} The newly created media element. + */ +function createMediaElement(type, media_attrs, source_attrs) { + var mediaElement = createElement(type, {}); + + var sourceElement = createElement("source", {}); + + mediaElement.eventPromise = new Promise(function(resolve, reject) { + mediaElement.addEventListener("loadeddata", function (e) { + resolve(e); + }); + + // Safari doesn't fire an `error` event when blocking mixed content. + mediaElement.addEventListener("stalled", function(e) { + reject(e); + }); + + sourceElement.addEventListener("error", function(e) { + reject(e); + }); }); - window.addEventListener("message", listener); - document.body.appendChild(script); + setAttributes(mediaElement, media_attrs); + setAttributes(sourceElement, source_attrs); + + mediaElement.appendChild(sourceElement); + document.body.appendChild(mediaElement); + + return mediaElement; } - // SanityChecker does nothing in release mode. +/** + * Creates a new video element, binds loadeddata and error events, sets + * attributes and source URL and appends to {@code document.body}. + * @param {string} url The URL of the video. + * @return {Promise} The promise for success/error events. + */ +function requestViaVideo(url) { + return createMediaElement("video", + {}, + {"src": url}).eventPromise; +} + +/** + * Creates a new audio element, binds loadeddata and error events, sets + * attributes and source URL and appends to {@code document.body}. + * @param {string} url The URL of the audio. + * @return {Promise} The promise for success/error events. + */ +function requestViaAudio(url) { + return createMediaElement("audio", + {}, + {"type": "audio/wav", "src": url}).eventPromise; +} + +/** + * Creates a new picture element, binds loadeddata and error events, sets + * attributes and source URL and appends to {@code document.body}. Also + * creates new image element appending it to the picture + * @param {string} url The URL of the image for the source and image elements. + * @return {Promise} The promise for success/error events. + */ +function requestViaPicture(url) { + var picture = createMediaElement("picture", {}, {"srcset": url, + "type": "image/png"}); + return createRequestViaElement("img", {"src": url}, picture); +} + +/** + * Creates a new object element, binds load and error events, sets the data to + * url, and appends it to {@code document.body}. + * @param {string} url The data URL. + * @return {Promise} The promise for success/error events. + */ +function requestViaObject(url) { + return createRequestViaElement("object", {"data": url, "type": "text/html"}, document.body); +} + +/** + * Creates a new WebSocket pointing to {@code url} and sends a message string + * "echo". The {@code message} and {@code error} events are triggering the + * returned promise resolve/reject events. + * @param {string} url The URL for WebSocket to connect to. + * @return {Promise} The promise for success/error events. + */ +function requestViaWebSocket(url) { + return new Promise(function(resolve, reject) { + var websocket = new WebSocket(url); + + websocket.addEventListener("message", function(e) { + resolve(e.data); + }); + + websocket.addEventListener("open", function(e) { + websocket.send("echo"); + }); + + websocket.addEventListener("error", function(e) { + reject(e) + }); + }) + .then(data => { + return JSON.parse(data); + }); +} + +// SanityChecker does nothing in release mode. See sanity-checker.js for debug +// mode. function SanityChecker() {} SanityChecker.prototype.checkScenario = function() {}; +SanityChecker.prototype.setFailTimeout = function(test, timeout) {}; SanityChecker.prototype.checkSubresourceResult = function() {};
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/iframe-inheritance.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/iframe-inheritance.html index 478a7ce..6c54c43 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/iframe-inheritance.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/iframe-inheritance.html
@@ -8,6 +8,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> <meta name="referrer" content="origin"> </head> <body onload="runTest()"> @@ -25,11 +26,15 @@ document.body.appendChild(iframe); iframe.contentDocument.write(` <script src = "/referrer-policy/generic/common.js"></` + `script> + <script src = "/referrer-policy/generic/referrer-policy-test-case.js"></` + `script> <script> var urlPath = "/referrer-policy/generic/subresource/xhr.py"; var url = "${location.protocol}//www1.${location.hostname}:${location.port}" + urlPath; - queryXhr(url, (msg) => { - parent.postMessage({referrer: msg.referrer}, "*")}); + requestViaXhr(url).then((msg) => { + parent.postMessage({referrer: msg.referrer}, "*")}) + .catch((e) => { + parent.postMessage({referrer: "FAILURE"}, "*"); + }); </` + "script>"); } </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/link-rel-prefetch.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/link-rel-prefetch.html index 5496314..16452b1d 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/link-rel-prefetch.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/link-rel-prefetch.html
@@ -14,18 +14,14 @@ and referrer policy from the document.</p> <script> - var prefetch_test = async_test("Prefetched image."); - var img_url = "/referrer-policy/generic/subresource/image.py"; - prefetch_test.step_timeout( - function() { - loadImageInWindow(img_url, function (img) { - var message = decodeImageData(extractImageData(img)); - prefetch_test.step(function() { assert_equals(message.headers.referer, document.location.origin + "/")}); - prefetch_test.done(); - }, null, window); - }, - 1000); + promise_test((t) => timeoutPromise(t, 1000) + .then(() => loadImageInWindow(img_url, null, window)) + .then(function (img) { + var message = decodeImageData(extractImageData(img)); + assert_equals(message.headers.referer, document.location.origin + "/"); + }), + "Prefetched image."); </script> <div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html index 682199b9..ccbc02be 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html
@@ -6,6 +6,7 @@ <script src="/resources/testharnessreport.js"></script> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Referrer Policy: multiple Referrer-Policy header and header values are allowed</h1> @@ -14,14 +15,15 @@ <pre id="received_message">Running...</pre> <script> - var test = async_test("Image uses the last recognized Referrer-Policy header value"); - var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); - var url = location.protocol + "//www1." + location.hostname + ":" + location.port + - urlPath; - queryImage(url, test.step_func(function(message) { - assert_equals(message.referrer, document.location.origin + "/"); - test.done(); - }), null, 'no-referrer', test); + promise_test(() => { + var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImageForReferrerPolicy(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.origin + "/"); + }); + }, "Image uses the last recognized Referrer-Policy header value"); </script> <div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-combined.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-combined.html index ad02ae84..7def76b9 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-combined.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-combined.html
@@ -6,6 +6,7 @@ <script src="/resources/testharnessreport.js"></script> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Referrer Policy: multiple Referrer-Policy header values are allowed</h1> @@ -14,14 +15,15 @@ <pre id="received_message">Running...</pre> <script> - var test = async_test("Image uses the last recognized Referrer-Policy header value"); - var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); - var url = location.protocol + "//www1." + location.hostname + ":" + location.port + - urlPath; - queryImage(url, test.step_func(function(message) { - assert_equals(message.referrer, document.location.origin + "/"); - test.done(); - }), null, 'no-referrer', test); + promise_test(() => { + var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImageForReferrerPolicy(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.origin + "/"); + }); + }, "Image uses the last recognized Referrer-Policy header value"); </script> <div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html index b1384b1..eb6c217 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html
@@ -6,6 +6,7 @@ <script src="/resources/testharnessreport.js"></script> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Referrer Policy: multiple Referrer-Policy headers with one invalid</h1> @@ -14,14 +15,15 @@ <pre id="received_message">Running...</pre> <script> - var test = async_test("Referrer policy header parsing fails if one header is invalid"); - var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); - var url = location.protocol + "//www1." + location.hostname + ":" + location.port + - urlPath; - queryImage(url, test.step_func(function(message) { - assert_equals(message.referrer, document.location.href); - test.done(); - }), null, 'no-referrer', test); + promise_test(() => { + var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImageForReferrerPolicy(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.href); + }); + }, "Referrer policy header parsing fails if one header is invalid"); </script> <div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html index 3273c0d..91e216b2 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html
@@ -6,6 +6,7 @@ <script src="/resources/testharnessreport.js"></script> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Referrer Policy: multiple Referrer-Policy headers with one invalid</h1> @@ -14,14 +15,15 @@ <pre id="received_message">Running...</pre> <script> - var test = async_test("Image uses last recognized referrer policy token from Referrer-Policy headers"); - var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); - var url = location.protocol + "//www1." + location.hostname + ":" + location.port + - urlPath; - queryImage(url, test.step_func(function(message) { - assert_equals(message.referrer, document.location.origin + "/"); - test.done(); - }), null, 'no-referrer', test); + promise_test(() => { + var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImageForReferrerPolicy(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.origin + "/"); + }); + }, "Image uses last recognized referrer policy token from Referrer-Policy headers"); </script> <div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers.html index 5f6a749..a74cf60 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/multiple-headers.html
@@ -6,6 +6,7 @@ <script src="/resources/testharnessreport.js"></script> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Referrer Policy: multiple Referrer-Policy headers are allowed</h1> @@ -14,14 +15,15 @@ <pre id="received_message">Running...</pre> <script> - var test = async_test("Image uses the last recognized Referrer-Policy header"); - var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); - var url = location.protocol + "//www1." + location.hostname + ":" + location.port + - urlPath; - queryImage(url, test.step_func(function(message) { - assert_equals(message.referrer, document.location.origin + "/"); - test.done(); - }), null, 'no-referrer', test); + promise_test(() => { + var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImageForReferrerPolicy(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.origin + "/"); + }); + }, "Image uses the last recognized Referrer-Policy header"); </script> <div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/referrer-policy-test-case.js b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/referrer-policy-test-case.js index 2385cc2a1..2c5c8eb 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/referrer-policy-test-case.js +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/referrer-policy-test-case.js
@@ -1,3 +1,27 @@ +function wrapResult(server_data) { + return { + referrer: server_data.headers.referer, + headers: server_data.headers + } +} + +// NOTE: This method only strips the fragment and is not in accordance to the +// recommended draft specification: +// https://w3c.github.io/webappsec/specs/referrer-policy/#null +// TODO(kristijanburnik): Implement this helper as defined by spec once added +// scenarios for URLs containing username/password/etc. +function stripUrlForUseAsReferrer(url) { + return url.replace(/#.*$/, ""); +} + +function normalizePort(targetPort) { + var defaultPorts = [80, 443]; + var isDefaultPortForProtocol = (defaultPorts.indexOf(targetPort) >= 0); + + return (targetPort == "" || isDefaultPortForProtocol) ? + "" : ":" + targetPort; +} + function ReferrerPolicyTestCase(scenario, testDescription, sanityChecker) { // Pass and skip rest of the test if browser does not support fetch. if (scenario.subresource == "fetch-request" && !window.fetch) { @@ -14,16 +38,16 @@ sanityChecker.checkScenario(scenario); var subresourceInvoker = { - "a-tag": queryLink, - "area-tag": queryAreaLink, - "fetch-request": queryFetch, - "iframe-tag": queryIframe, - "img-tag": queryImage, - "script-tag": queryScript, - "worker-request": queryWorker, - "module-worker": queryModuleWorkerTopLevel, - "shared-worker": querySharedWorker, - "xhr-request": queryXhr + "a-tag": requestViaAnchor, + "area-tag": requestViaArea, + "fetch-request": requestViaFetch, + "iframe-tag": requestViaIframe, + "img-tag": requestViaImageForReferrerPolicy, + "script-tag": requestViaScript, + "worker-request": url => requestViaDedicatedWorker(url, {}), + "module-worker": url => requestViaDedicatedWorker(url, {type: "module"}), + "shared-worker": requestViaSharedWorker, + "xhr-request": requestViaXhr }; var referrerUrlResolver = { @@ -41,8 +65,6 @@ var t = { _scenario: scenario, _testDescription: testDescription, - _subresourceUrl: null, - _expectedReferrerUrl: null, _constructSubresourceUrl: function() { // TODO(kristijanburnik): We should assert that these two domains are // different. E.g. If someone runs the tets over www, this would fail. @@ -60,19 +82,20 @@ var targetPort = portForProtocol[t._scenario.target_protocol]; - t._subresourceUrl = t._scenario.target_protocol + "://" + - domainForOrigin[t._scenario.origin] + - normalizePort(targetPort) + - t._scenario["subresource_path"] + - "?redirection=" + t._scenario["redirection"] + - "&cache_destroyer=" + (new Date()).getTime(); + return t._scenario.target_protocol + "://" + + domainForOrigin[t._scenario.origin] + + normalizePort(targetPort) + + t._scenario["subresource_path"] + + "?redirection=" + t._scenario["redirection"] + + "&cache_destroyer=" + (new Date()).getTime(); }, _constructExpectedReferrerUrl: function() { - t._expectedReferrerUrl = referrerUrlResolver[t._scenario.referrer_url](); + return referrerUrlResolver[t._scenario.referrer_url](); }, - _invokeSubresource: function(callback, test) { + // Returns a promise. + _invokeSubresource: function(resourceRequestUrl) { var invoker = subresourceInvoker[t._scenario.subresource]; // Depending on the delivery method, extend the subresource element with // these attributes. @@ -84,43 +107,35 @@ var delivery_method = t._scenario.delivery_method; if (delivery_method in elementAttributesForDeliveryMethod) { - invoker(t._subresourceUrl, - callback, - elementAttributesForDeliveryMethod[delivery_method], - t._scenario.referrer_policy, - test); + return invoker(resourceRequestUrl, + elementAttributesForDeliveryMethod[delivery_method], + t._scenario.referrer_policy); } else { - invoker(t._subresourceUrl, callback, null, t._scenario.referrer_policy, test); + return invoker(resourceRequestUrl, {}, t._scenario.referrer_policy); } - }, start: function() { - async_test(function(test) { + promise_test(test => { + const resourceRequestUrl = t._constructSubresourceUrl(); + const expectedReferrerUrl = t._constructExpectedReferrerUrl(); + return t._invokeSubresource(resourceRequestUrl) + .then(result => { + // Check if the result is in valid format. NOOP in release. + sanityChecker.checkSubresourceResult( + test, t._scenario, resourceRequestUrl, result); - t._constructSubresourceUrl(); - t._constructExpectedReferrerUrl(); - - t._invokeSubresource(test.step_func(function(result) { - // Check if the result is in valid format. NOOP in release. - sanityChecker.checkSubresourceResult( - test, t._scenario, t._subresourceUrl, result); - - // Check the reported URL. - test.step(function() { - assert_equals(result.referrer, - t._expectedReferrerUrl, - "Reported Referrer URL is '" + - t._scenario.referrer_url + "'."); - assert_equals(result.headers.referer, - t._expectedReferrerUrl, - "Reported Referrer URL from HTTP header is '" + - t._expectedReferrerUrl + "'"); - }, "Reported Referrer URL is as expected: " + t._scenario.referrer_url); - - test.done(); - }), test); - }, t._testDescription); + // Check the reported URL. + assert_equals(result.referrer, + expectedReferrerUrl, + "Reported Referrer URL is '" + + t._scenario.referrer_url + "'."); + assert_equals(result.headers.referer, + expectedReferrerUrl, + "Reported Referrer URL from HTTP header is '" + + expectedReferrerUrl + "'"); + }); + }, t._testDescription); } }
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html index 1b2b12b..73b48f1 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html
@@ -8,6 +8,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Referrer Policy: A document with an opaque origin doesn't send referrers</h1> @@ -26,12 +27,16 @@ iframe.srcdoc = ` <meta name = "referrer" content = "always"> <script src = "/referrer-policy/generic/common.js"></` + `script> + <script src = "/referrer-policy/generic/referrer-policy-test-case.js"></` + `script> <script> var urlPath = "/referrer-policy/generic/subresource/xhr.py"; var url = "${location.protocol}//www1.${location.hostname}:${location.port}" + urlPath; - queryXhr(url, (msg) => { + requestViaXhr(url).then((msg) => { parent.postMessage({referrer: msg.referrer, description: "${description}"}, "*") - }, null, null, test); + }) + .catch((e) => { + parent.postMessage({referrer: "FAILURE", description: "${description}"}, "*") + }); </` + "script>"; document.body.appendChild(iframe); }, description);
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/area-navigate.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/area-navigate.html index 3eb82452..c601c24 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/area-navigate.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/area-navigate.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Area Link messaging - cross-origin Area Link navigation</h1> @@ -16,21 +17,22 @@ <pre id="received_message">Running...</pre> <script> - async_test(function(messaging_test) { - var urlPath = '/referrer-policy/generic/subresource/document.py'; - var url = location.protocol + "//www1." + location.hostname + ":" + location.port + - urlPath; - queryAreaLink(url, function(message) { - var pre = document.getElementById('received_message') - var headers = message.headers; - pre.innerHTML = ""; - pre.innerHTML += url + ":\n\n"; - pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" - assert_own_property(headers, "host") - assert_own_property(headers, "connection") - messaging_test.done(); - }, null, null, messaging_test); - }, "Area is responding with HTTP headers"); + promise_test(function() { + var urlPath = '/referrer-policy/generic/subresource/document.py'; + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaArea(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, + "Area is responding with HTTP headers"); </script> <div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/fetch-messaging.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/fetch-messaging.html index edb159d..4d40245 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/fetch-messaging.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/fetch-messaging.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Fetch messaging - same-origin Fetch request</h1> @@ -20,26 +21,21 @@ assert_true(!!window.fetch, "Fetch is not supported by this browser."); }, "Fetch is supported by the browser."); - (function() { - if (!window.fetch) - return; - - async_test(function(fetch_test) { + promise_test(function() { var urlPath = '/referrer-policy/generic/subresource/xhr.py'; var url = location.protocol + "//" + location.hostname + ":" + location.port + urlPath; - queryFetch(url, function(message) { - var pre = document.getElementById('received_message') - var headers = message.headers; - pre.innerHTML = ""; - pre.innerHTML += url + ":\n\n"; - pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"; - assert_own_property(headers, "host") - assert_own_property(headers, "connection") - fetch_test.done(); - }, null, null, fetch_test); - }, "Fetch is responding with HTTP headers"); - })(); + return requestViaFetch(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"; + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, "Fetch is responding with HTTP headers"); </script> <div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/iframe-messaging.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/iframe-messaging.html index 606e18b..3072436b 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/iframe-messaging.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/iframe-messaging.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Iframe messaging - cross-origin iframe request</h1> @@ -16,20 +17,20 @@ <pre id="received_message">Running...</pre> <script> - async_test(function(messaging_test) { + promise_test(function() { var urlPath = '/referrer-policy/generic/subresource/document.py'; var url = location.protocol + "//www1." + location.hostname + ":" + location.port + urlPath; - queryIframe(url, function(message) { - var pre = document.getElementById('received_message') - var headers = message.headers; - pre.innerHTML = ""; - pre.innerHTML += url + ":\n\n"; - pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" - assert_own_property(headers, "host") - assert_own_property(headers, "connection") - messaging_test.done(); - }, null, null, messaging_test); + return requestViaIframe(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); }, "Iframe is responding with HTTP headers"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/image-decoding.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/image-decoding.html index 9c50ea6..b132c06 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/image-decoding.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/image-decoding.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Image decoding - cross-origin image request</h1> @@ -16,20 +17,20 @@ <pre id="received_message">Running...</pre> <script> - async_test(function(messaging_test) { + promise_test(function() { var urlPath = '/referrer-policy/generic/subresource/image.py'; var url = location.protocol + "//www1." + location.hostname + ":" + location.port + urlPath + "?cache_destroyer=" + (new Date()).getTime(); - queryImage(url, function(message) { - var pre = document.getElementById('received_message') - var headers = message.headers; - pre.innerHTML = ""; - pre.innerHTML += url + ":\n\n"; - pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" - assert_own_property(headers, "host") - assert_own_property(headers, "connection") - messaging_test.done(); - }, null, "always", messaging_test); + return requestViaImageForReferrerPolicy(url, undefined, "always") + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); }, "Image is encoding headers as JSON."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/link-navigate.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/link-navigate.html index 95582f6..583458b5 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/link-navigate.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/link-navigate.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Link messaging - cross-origin Link navigation</h1> @@ -16,20 +17,20 @@ <pre id="received_message">Running...</pre> <script> - async_test(function(messaging_test) { + promise_test(function() { var urlPath = '/referrer-policy/generic/subresource/document.py'; var url = location.protocol + "//www1." + location.hostname + ":" + location.port + urlPath; - queryLink(url, function(message) { - var pre = document.getElementById('received_message') - var headers = message.headers; - pre.innerHTML = ""; - pre.innerHTML += url + ":\n\n"; - pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" - assert_own_property(headers, "host") - assert_own_property(headers, "connection") - messaging_test.done(); - }, null, null, messaging_test); + return requestViaAnchor(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); }, "Link is responding with HTTP headers"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/script-messaging.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/script-messaging.html index f73f440..7bc36dc 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/script-messaging.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/script-messaging.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Script messaging - cross-origin Script request</h1> @@ -16,20 +17,20 @@ <pre id="received_message">Running...</pre> <script> - async_test(function(messaging_test) { + promise_test(function() { var urlPath = '/referrer-policy/generic/subresource/script.py'; var url = location.protocol + "//www1." + location.hostname + ":" + location.port + urlPath; - queryScript(url, function(message) { - var pre = document.getElementById('received_message') - var headers = message.headers; - pre.innerHTML = ""; - pre.innerHTML += url + ":\n\n"; - pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" - assert_own_property(headers, "host") - assert_own_property(headers, "connection") - messaging_test.done(); - }, null, null, messaging_test); + return requestViaScript(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); }, "Script is responding with HTTP headers"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/worker-messaging.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/worker-messaging.html index fd75918..9daf6d5 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/worker-messaging.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/worker-messaging.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Worker messaging - same-origin Worker request</h1> @@ -16,20 +17,20 @@ <pre id="received_message">Running...</pre> <script> - async_test(function(messaging_test) { + promise_test(function() { var urlPath = '/referrer-policy/generic/subresource/worker.py'; var url = location.protocol + "//" + location.hostname + ":" + location.port + urlPath; - queryWorker(url, function(message) { - var pre = document.getElementById('received_message') - var headers = message.headers; - pre.innerHTML = ""; - pre.innerHTML += url + ":\n\n"; - pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" - assert_own_property(headers, "host") - assert_own_property(headers, "connection") - messaging_test.done(); - }, null, null, messaging_test); + return requestViaDedicatedWorker(url, {}) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); }, "Worker is responding with HTTP headers"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/xhr-messaging.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/xhr-messaging.html index 6ef4a9cf..a020805 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/xhr-messaging.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/subresource-test/xhr-messaging.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>XHR messaging - cross-origin XHR request</h1> @@ -16,20 +17,20 @@ <pre id="received_message">Running...</pre> <script> - async_test(function(messaging_test) { + promise_test(function() { var urlPath = '/referrer-policy/generic/subresource/xhr.py'; var url = location.protocol + "//www1." + location.hostname + ":" + location.port + urlPath; - queryXhr(url, function(message) { - var pre = document.getElementById('received_message') - var headers = message.headers; - pre.innerHTML = ""; - pre.innerHTML += url + ":\n\n"; - pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" - assert_own_property(headers, "host") - assert_own_property(headers, "connection") - messaging_test.done(); - }, null, null, messaging_test); + return requestViaXhr(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); }, "XHR is responding with HTTP headers"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/unsupported-csp-referrer-directive.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/unsupported-csp-referrer-directive.html index 475efa5..40942a8 100644 --- a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/unsupported-csp-referrer-directive.html +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/unsupported-csp-referrer-directive.html
@@ -7,6 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <!-- Common global functions for referrer-policy tests. --> <script src="/referrer-policy/generic/common.js"></script> + <script src="/referrer-policy/generic/referrer-policy-test-case.js"></script> </head> <body> <h1>Referrer Policy: CSP 'referrer' directive should not be supported</h1> @@ -15,14 +16,14 @@ <pre id="received_message">Running...</pre> <script> - async_test(function(test) { + promise_test(function() { var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); var url = location.protocol + "//www1." + location.hostname + ":" + location.port + urlPath; - queryImage(url, function(message) { - assert_equals(message.referrer, document.location.href); - test.done(); - }, null, 'always', test); + return requestViaImageForReferrerPolicy(url, null, 'always') + .then(function(message) { + assert_equals(message.referrer, document.location.href); + }); }, "Image has a referrer despite CSP 'referrer' directive"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/reporting/bufferSize.html b/third_party/blink/web_tests/external/wpt/reporting/bufferSize.html new file mode 100644 index 0000000..b3512b3b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/reporting/bufferSize.html
@@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Reporting: Buffer size</title> +<link rel="author" title="Paul Meyer" href="paulmeyer@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> + // Test the buffer size (100) of ReportingObserver. + async_test(async function(test) { + for (i = 0; i != 110; ++i) + await test_driver.generate_test_report("" + i); + + var observer = new ReportingObserver(function(reports) { + test.step(function() { + // Only (the most recent) 100 reports should be observed, even though + // 110 were buffered. + assert_equals(reports.length, 100); + for(i = 0; i != 100; ++i) { + assert_equals(reports[i].body.message, "" + (i + 10)); + } + }); + + test.done(); + }, {buffered: true}); + observer.observe(); + }, "Buffer size"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/reporting/disconnect.html b/third_party/blink/web_tests/external/wpt/reporting/disconnect.html new file mode 100644 index 0000000..2dc5e8f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/reporting/disconnect.html
@@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Reporting: Disconnect</title> +<link rel="author" title="Paul Meyer" href="paulmeyer@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> + async_test(async function(test) { + var observer = new ReportingObserver(function(reports, observer) { + test.step(function() { + assert_equals(reports.length, 1); + assert_equals(reports[0].body.message, "Test message."); + }); + test.done(); + }); + observer.observe(); + + // The observer should still receive this report even though disconnect() + // is called immediately afterwards. + await test_driver.generate_test_report("Test message."); + observer.disconnect(); + }, "Disconnect"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/reporting/generateTestReport.html b/third_party/blink/web_tests/external/wpt/reporting/generateTestReport.html new file mode 100644 index 0000000..e3c2735 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/reporting/generateTestReport.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>Reporting: Generate Test Report</title> +<link rel="author" title="Paul Meyer" href="paulmeyer@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> + // Test that the "generate_test_report" API works. + async_test(function(test) { + var observer = new ReportingObserver(function(reports) { + test.step(function() { + assert_equals(reports.length, 1); + // Ensure that the contents of the report are valid. + assert_equals(reports[0].type, "test"); + assert_true(reports[0].url.endsWith("reporting/generateTestReport.html")); + assert_equals(reports[0].body.message, "Test message."); + }); + test.done(); + }); + observer.observe(); + + // This should result in a "test" type report being generated and observed. + test_driver.generate_test_report("Test message."); + }, "Generate Test Report"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/reporting/nestedReport.html b/third_party/blink/web_tests/external/wpt/reporting/nestedReport.html new file mode 100644 index 0000000..156338e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/reporting/nestedReport.html
@@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Reporting: Nested report</title> +<link rel="author" title="Paul Meyer" href="paulmeyer@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> + // Test that reports can be generated within a ReportingObserver + // callback. These reports should be received by the same observer. + async_test(function(test) { + var step = 0; + var observer = new ReportingObserver(async function(reports, observer) { + test.step(function() { + assert_equals(reports.length, 1); + assert_equals(reports[0].body.message, "" + step); + }); + + ++step; + if (step == 3) + test.done(); + + test_driver.generate_test_report("" + step); + }); + observer.observe(); + + test_driver.generate_test_report("0"); + }, "Nested report"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/reporting/order.html b/third_party/blink/web_tests/external/wpt/reporting/order.html new file mode 100644 index 0000000..c439642 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/reporting/order.html
@@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Reporting: Order</title> +<link rel="author" title="Paul Meyer" href="paulmeyer@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<p id="error">No error</p> +<script> + var count = 0; + async_test(function(test) { + var observer = new ReportingObserver(function(reports) { + test.step(function() { + // Reports should be received in the same order that they were + // generated. + for(i in reports) { + assert_equals(reports[i].body.message, "" + count++); + } + }); + + if (count == 10) + test.done(); + }); + observer.observe(); + + for (i = 0; i != 10; ++i) + test_driver.generate_test_report("" + i); + }, "Order"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resources/testdriver.js b/third_party/blink/web_tests/external/wpt/resources/testdriver.js index e328302e..031be1b 100644 --- a/third_party/blink/web_tests/external/wpt/resources/testdriver.js +++ b/third_party/blink/web_tests/external/wpt/resources/testdriver.js
@@ -194,6 +194,20 @@ */ action_sequence: function(actions) { return window.test_driver_internal.action_sequence(actions); + }, + + /** + * Generates a test report on the current page + * + * The generate_test_report function generates a report (to be observed + * by ReportingObserver) for testing purposes, as described in + * {@link https://w3c.github.io/reporting/#generate-test-report-command} + * + * @returns {Promise} fulfilled after the report is generated, or + * rejected if the report generation fails + */ + generate_test_report: function(message) { + return window.test_driver_internal.generate_test_report(message); } }; @@ -281,6 +295,17 @@ */ action_sequence: function(actions) { return Promise.reject(new Error("unimplemented")); + }, + + /** + * Generates a test report on the current page + * + * @param {String} message - the message to be contained in the report + * @returns {Promise} fulfilled after the report is generated, or + * rejected if the report generation fails + */ + generate_test_report: function(message) { + return Promise.reject(new Error("unimplemented")); } }; })();
diff --git a/third_party/blink/web_tests/external/wpt/upgrade-insecure-requests/support/testharness-helper.sub.js b/third_party/blink/web_tests/external/wpt/upgrade-insecure-requests/support/testharness-helper.sub.js index 8b58eb9..d7be710 100644 --- a/third_party/blink/web_tests/external/wpt/upgrade-insecure-requests/support/testharness-helper.sub.js +++ b/third_party/blink/web_tests/external/wpt/upgrade-insecure-requests/support/testharness-helper.sub.js
@@ -1,3 +1,9 @@ +// Used by /mixed-content/generic/common.js. +function wrapResult(server_data) { + // Currently the returned value is not used in mixed-content tests. + return null; +} + const Host = { SAME_ORIGIN: "same-origin", CROSS_ORIGIN: "cross-origin",
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/constructor/instantiate.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/constructor/instantiate.any-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/constructor/instantiate.any-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/constructor/instantiate.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/constructor/instantiate.any.worker-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/constructor/instantiate.any.worker-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/instance/constructor.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/instance/constructor.any-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/instance/constructor.any-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/instance/constructor.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/instance/constructor.any.worker-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/instance/constructor.any.worker-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/exports.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/exports.any-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/exports.any-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/exports.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/exports.any.worker-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/exports.any.worker-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/get-set.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/get-set.any-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/get-set.any-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/get-set.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/get-set.any.worker-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/get-set.any.worker-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.serviceworker-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.serviceworker-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.sharedworker-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.sharedworker-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.worker-expected.txt deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/webapi/instantiateStreaming.any.worker-expected.txt +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-transport.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-transport.https.html index c687911..fb8aaaf 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-transport.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-transport.https.html
@@ -69,10 +69,14 @@ } await callee.setRemoteDescription(offer); const [callee_transceiver1, callee_transceiver2] = callee.getTransceivers(); - assert_not_equals(callee_transceiver1.receiver.transport, null); - assert_not_equals(callee_transceiver2.receiver.transport, null); + // According to spec, setRemoteDescription only updates the transports + // if the remote description is an answer. + assert_equals(callee_transceiver1.receiver.transport, null); + assert_equals(callee_transceiver2.receiver.transport, null); const answer = await callee.createAnswer(); await callee.setLocalDescription(answer); + assert_not_equals(callee_transceiver1.receiver.transport, null); + assert_not_equals(callee_transceiver2.receiver.transport, null); // At this point, bundle should have kicked in. assert_equals(callee_transceiver1.receiver.transport, callee_transceiver2.receiver.transport);
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html new file mode 100644 index 0000000..971a6d7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + + <script> + let immersiveTestName = "XRFrame methods throw exceptions outside of the " + + "requestAnimationFrame callback for immersive sessions"; + let nonImmersiveTestName = "XRFrame methods throw exceptions outside of the " + + "requestAnimationFrame callback for non-immersive sessions"; + + let fakeDeviceInitParams = { supportsImmersive:true }; + + let immersiveSessionOptions = { mode: 'immersive-vr' }; + let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; + + let testFunction = (testSession, testController, t) => new Promise((resolve) => { + let staleFrame = null; + let currentReferenceSpace = null; + + function onFrame(time, xrFrame) { + t.step(() => { + assert_true(xrFrame instanceof XRFrame); + }); + + staleFrame = xrFrame; + step_timeout(afterFrame, 0); + } + + function afterFrame() { + t.step(() => { + // Attempting to call a method on the frame outside the callback that + // originally provided it should cause it to throw an exception. + assert_throws('InvalidStateError', () => staleFrame.getViewerPose(currentReferenceSpace)); + }); + + // Test does not complete until the this function has executed. + resolve(); + } + + testSession.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((referenceSpace) => { + currentReferenceSpace = referenceSpace; + testSession.requestAnimationFrame(onFrame); + }); + }); + + xr_session_promise_test(immersiveTestName, testFunction, + fakeDeviceInitParams, immersiveSessionOptions); + xr_session_promise_test(nonImmersiveTestName, testFunction, + fakeDeviceInitParams, nonImmersiveSessionOptions); + + </script> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/workers/baseurl/alpha/xhr-in-moduleworker-expected.txt b/third_party/blink/web_tests/external/wpt/workers/baseurl/alpha/xhr-in-moduleworker-expected.txt deleted file mode 100644 index 93eb19c..0000000 --- a/third_party/blink/web_tests/external/wpt/workers/baseurl/alpha/xhr-in-moduleworker-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Base URL in module dedicated workers: XHR assert_equals: expected "gamma\n" but got "beta\n" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-module-expected.txt b/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-module-expected.txt deleted file mode 100644 index bbf490d..0000000 --- a/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-module-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL WorkerLocation with redirects: module dedicated workers assert_equals: expected "http://web-platform.test:8001/workers/interfaces/WorkerGlobalScope/location/post-location-members.js?a" but got "http://web-platform.test:8001/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py?fail" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/fast/events/popup-blocking-timers6-expected.txt b/third_party/blink/web_tests/fast/events/popup-blocking-timers6-expected.txt index e5a528f..a4c9a08 100644 --- a/third_party/blink/web_tests/fast/events/popup-blocking-timers6-expected.txt +++ b/third_party/blink/web_tests/fast/events/popup-blocking-timers6-expected.txt
@@ -3,5 +3,5 @@ TEST COMPLETE -Test calling window.open() with a 1001 ms delay. A popup should not be allowed. +Test calling window.open() with a 5001 ms delay. A popup should not be allowed. PASS newWindow is null
diff --git a/third_party/blink/web_tests/fast/events/popup-blocking-timers6.html b/third_party/blink/web_tests/fast/events/popup-blocking-timers6.html index 06034d6..b69660e 100644 --- a/third_party/blink/web_tests/fast/events/popup-blocking-timers6.html +++ b/third_party/blink/web_tests/fast/events/popup-blocking-timers6.html
@@ -15,14 +15,14 @@ setTimeout(function() { newWindow = window.open("about:blank"); self.focus(); - debug("Test calling window.open() with a 1001 ms delay. A popup should not be allowed.") + debug("Test calling window.open() with a 5001 ms delay. A popup should not be allowed.") shouldBeNull("newWindow"); if (window.testRunner) testRunner.notifyDone(); - }, 1001); + }, 5001); if (window.eventSender) - eventSender.leapForward(1001); + eventSender.leapForward(5001); } function clickButton() {
diff --git a/third_party/blink/web_tests/fast/replaced/object-set-type-with-no-data-crash.html b/third_party/blink/web_tests/fast/replaced/object-set-type-with-no-data-crash.html new file mode 100644 index 0000000..f991c97 --- /dev/null +++ b/third_party/blink/web_tests/fast/replaced/object-set-type-with-no-data-crash.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<object id="target" type="text/html"></object> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> + test(()=> { + var target = document.getElementById("target"); + target.type = "text/html"; + }, "No crash or DCHECK failure"); +</script>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-cpm-loose-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-cpm-loose-expected.txt deleted file mode 100644 index 2195487b..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-cpm-loose-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -This is a testharness.js-based test. -PASS 30FB KATAKANA MIDDLE DOT may appear at line start if zh and loose -PASS FF1A FULLWIDTH COLON may appear at line start if zh and loose -PASS FF1B FULLWIDTH SEMICOLON may appear at line start if zh and loose -PASS FF65 HALFWIDTH KATAKANA MIDDLE DOT may appear at line start if zh and loose -PASS 203C DOUBLE EXCLAMATION MARK may appear at line start if zh and loose -PASS 2047 DOUBLE QUESTION MARK may appear at line start if zh and loose -PASS 2048 QUESTION EXCLAMATION MARK may appear at line start if zh and loose -PASS 2049 EXCLAMATION QUESTION MARK may appear at line start if zh and loose -PASS FF01 FULLWIDTH EXCLAMATION MARK may appear at line start if zh and loose -PASS FF1F FULLWIDTH QUESTION MARK may appear at line start if zh and loose -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-po-loose-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-po-loose-expected.txt deleted file mode 100644 index c182a8d..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/i18n/zh/css-text-line-break-zh-po-loose-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -This is a testharness.js-based test. -PASS 00B0 DEGREE SIGN may appear at line start if zh and loose -PASS 2030 PER MILLE SIGN may appear at line start if zh and loose -PASS 2032 PRIME may appear at line start if zh and loose -PASS 2033 DOUBLE PRIME may appear at line start if zh and loose -PASS 2035 REVERSED PRIME may appear at line start if zh and loose -PASS 2103 DEGREE CELSIUS may appear at line start if zh and loose -PASS 2109 DEGREE FAHRENHEIT may appear at line start if zh and loose -PASS FE6A SMALL PERCENT SIGN may appear at line start if zh and loose -PASS FF05 FULLWIDTH PERCENT SIGN may appear at line start if zh and loose -PASS FFE0 FULLWIDTH CENT SIGN may appear at line start if zh and loose -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/resources/cross-origin-module-script.html b/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/resources/cross-origin-module-script.html new file mode 100644 index 0000000..b51719a --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/resources/cross-origin-module-script.html
@@ -0,0 +1 @@ +<script type="module" src="http://localhost:8000/devtools/resources/v8-cache-script.cgi"></script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/resources/same-origin-module-script.html b/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/resources/same-origin-module-script.html new file mode 100644 index 0000000..42173b1 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/resources/same-origin-module-script.html
@@ -0,0 +1 @@ +<script type="module" src="/devtools/resources/v8-cache-script.cgi"></script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/same-origin-module-test-expected.txt b/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/same-origin-module-test-expected.txt new file mode 100644 index 0000000..c03e4f1 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/same-origin-module-test-expected.txt
@@ -0,0 +1,114 @@ +Tests V8 code cache for javascript resources + +--- Trace events related to code caches ------ +v8.compileModule Properties: +{ + data : { + columnNumber : 1 + lineNumber : 1 + notStreamedReason : "module script" + streamed : <boolean> + url : .../devtools/resources/v8-cache-script.cgi + } + endTime : <number> + startTime : <number> + type : "v8.compileModule" +} +Text details for v8.compileModule: v8-cache-script.cgi +v8.compileModule Properties: +{ + data : { + columnNumber : 1 + lineNumber : 1 + notStreamedReason : "module script" + streamed : <boolean> + url : .../devtools/resources/v8-cache-script.cgi + } + endTime : <number> + startTime : <number> + type : "v8.compileModule" +} +Text details for v8.compileModule: v8-cache-script.cgi +v8.compileModule Properties: +{ + data : { + cacheProduceOptions : "code" + columnNumber : 1 + lineNumber : 1 + notStreamedReason : "module script" + producedCacheSize : <number> + streamed : <boolean> + url : .../devtools/resources/v8-cache-script.cgi + } + endTime : <number> + startTime : <number> + type : "v8.compileModule" +} +Text details for v8.compileModule: v8-cache-script.cgi +v8.compileModule Properties: +{ + data : { + cacheConsumeOptions : "code" + cacheRejected : false + columnNumber : 1 + consumedCacheSize : <number> + lineNumber : 1 + notStreamedReason : "module script" + streamed : <boolean> + url : .../devtools/resources/v8-cache-script.cgi + } + endTime : <number> + startTime : <number> + type : "v8.compileModule" +} +Text details for v8.compileModule: v8-cache-script.cgi +v8.compileModule Properties: +{ + data : { + columnNumber : 1 + lineNumber : 1 + notStreamedReason : "module script" + streamed : <boolean> + url : .../devtools/resources/v8-cache-script.cgi + } + endTime : <number> + startTime : <number> + type : "v8.compileModule" +} +Text details for v8.compileModule: v8-cache-script.cgi +v8.compileModule Properties: +{ + data : { + cacheConsumeOptions : "code" + cacheRejected : false + columnNumber : 1 + consumedCacheSize : <number> + lineNumber : 1 + notStreamedReason : "module script" + streamed : <boolean> + url : .../devtools/resources/v8-cache-script.cgi + } + endTime : <number> + startTime : <number> + type : "v8.compileModule" +} +Text details for v8.compileModule: v8-cache-script.cgi +v8.compileModule Properties: +{ + data : { + cacheConsumeOptions : "code" + cacheRejected : false + columnNumber : 1 + consumedCacheSize : <number> + lineNumber : 1 + notStreamedReason : "module script" + streamed : <boolean> + url : .../devtools/resources/v8-cache-script.cgi + } + endTime : <number> + startTime : <number> + type : "v8.compileModule" +} +Text details for v8.compileModule: v8-cache-script.cgi +----------------------------------------------- +
diff --git a/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/same-origin-module-test.js b/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/same-origin-module-test.js new file mode 100644 index 0000000..de3e33a --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/isolated-code-cache/same-origin-module-test.js
@@ -0,0 +1,63 @@ +// 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. + +(async function() { + TestRunner.addResult(`Tests V8 code cache for javascript resources\n`); + await TestRunner.loadModule('performance_test_runner'); + await TestRunner.showPanel('timeline'); + + // Clear browser cache to avoid any existing entries for the fetched + // scripts in the cache. + SDK.multitargetNetworkManager.clearBrowserCache(); + + // There are two scripts: + // [A] http://127.0.0.1:8000/devtools/resources/v8-cache-script.cgi + // [B] http://localhost:8000/devtools/resources/v8-cache-script.cgi + + // An iframe that loads [A]. + // The script is executed as a parser-inserted script, + // to keep the ScriptResource on the MemoryCache. + // ScriptResources for dynamically-inserted <script>s can be + // garbage-collected and thus removed from MemoryCache after its execution. + const scope = 'resources/same-origin-module-script.html'; + // An iframe that loads [B]. + const scopeCrossOrigin = 'resources/cross-origin-module-script.html'; + + TestRunner.addResult('--- Trace events related to code caches ------'); + await PerformanceTestRunner.startTimeline(); + + // Load [A] thrice. With the current V8 heuristics (defined + // in third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc) we produce + // cache on second fetch and consume it in the third fetch. This tests these + // heuristics. + // Note that addIframe() waits for iframe's load event, which waits for the + // <script> loading. + await TestRunner.addIframe(scope); + await TestRunner.addIframe(scope); + await TestRunner.addIframe(scope); + + // Load [B]. Should not use the cached code. + await TestRunner.addIframe(scopeCrossOrigin); + + // Load [A] again from MemoryCache. Should use cached code. + await TestRunner.addIframe(scope); + + // Clear [A] from MemoryCache. Blink evicts previous Resource when a + // new request to the same URL but with different resource type is started. + // We fetch() to the URL of [A], and thus evicts the previous ScriptResource + // of [A]. + await TestRunner.evaluateInPageAsync( + `fetch('/devtools/resources/v8-cache-script.cgi')`); + + // Load [A] from Disk Cache. As we cleared [A] from MemoryCache, this + // doesn't hit MemoryCache, but still hits Disk Cache. + await TestRunner.addIframe(scope); + + await PerformanceTestRunner.stopTimeline(); + PerformanceTestRunner.printTimelineRecordsWithDetails( + TimelineModel.TimelineModel.RecordType.CompileModule); + + TestRunner.addResult('-----------------------------------------------'); + TestRunner.completeTest(); +})();
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 7630189..8fa8e25 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -748,6 +748,8 @@ static method createDataPipe static method createMessagePipe static method createSharedBuffer + static method getDocumentInterfaceBrokerHandle + static method replaceDocumentInterfaceBrokerForTesting attribute @@toStringTag attribute RESULT_ABORTED attribute RESULT_ALREADY_EXISTS
diff --git a/third_party/blink/web_tests/mojo/document-interface-broker-override.html b/third_party/blink/web_tests/mojo/document-interface-broker-override.html new file mode 100644 index 0000000..8e1da98b --- /dev/null +++ b/third_party/blink/web_tests/mojo/document-interface-broker-override.html
@@ -0,0 +1,45 @@ +<body> +<script src="../resources/document-interface-broker-helpers.js"></script> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script> +<script src="file:///gen/url/mojom/url.mojom-lite.js"></script> +<script src="file:///gen/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom-lite.js"></script> +<script src="file:///gen/third_party/blink/public/mojom/frame/document_interface_broker.mojom-lite.js"></script> +<script> +'use strict'; + +promise_test(async t => { + // Create a test implementation of FrameHostTestInterface + const frameHostTestImpl = new blink.mojom.FrameHostTestInterfaceCallbackRouter; + frameHostTestImpl.getName.addListener(() => ({ name: 'TestFrameHostTestImpl' })); + + const brokerProxy = new blink.mojom.DocumentInterfaceBrokerProxy( + Mojo.getDocumentInterfaceBrokerHandle()); + + const testInterfaceProxyBeforeOverride = new blink.mojom.FrameHostTestInterfaceProxy; + console.log("proxy" + typeof(testInterfaceProxyBeforeOverride)); + brokerProxy.getFrameHostTestInterface(testInterfaceProxyBeforeOverride.$.createRequest()); + + // Verify that RenderFrameHostImpl's implementation gets called without an override + testInterfaceProxyBeforeOverride.getName().then(reply => { + assert_equals(reply.name, 'RenderFrameHostImpl'); + }); + + setDocumentInterfaceBrokerOverrides({ getFrameHostTestInterface: request => { + frameHostTestImpl.bindHandle(request.handle); + }}); + + const testInterfaceProxyAfterOverride = new blink.mojom.FrameHostTestInterfaceProxy; + brokerProxy.getFrameHostTestInterface(testInterfaceProxyAfterOverride.$.createRequest()); + + // Verify that the test implementation gets called after the override + return testInterfaceProxyAfterOverride.getName().then(reply => { + assert_equals(reply.name, 'TestFrameHostTestImpl'); + }); +}, +'Appropriate DocumentInterfaceBroker implementations are called before and after overriding'); + +</script> + </body> + </html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/resources/document-interface-broker-helpers.js b/third_party/blink/web_tests/resources/document-interface-broker-helpers.js new file mode 100644 index 0000000..e27e910a --- /dev/null +++ b/third_party/blink/web_tests/resources/document-interface-broker-helpers.js
@@ -0,0 +1,29 @@ +'use strict'; + +/** + * Allows to override specific interface request handlers for + * DocumentInterfaceBroker for testing purposes + * @param {Object} overrides an object where the keys are names of + * DocumentInterfaceBroker's methods and the values are corresponding handler + * functions taking a request parameter and binding its handle to the relevant + * testing implementation. + * Example: + * const testFooImpl = new FooInterfaceCallbackRouter; + * ... override FooInterface methods ... + * setDocumentInterfaceBrokerOverrides({getFooInterface: request => { + * testFooImpl.bindHandle(request.handle); + * }}); + */ +function setDocumentInterfaceBrokerOverrides(overrides) { + const {handle0, handle1} = Mojo.createMessagePipe(); + const realBrokerProxy = new blink.mojom.DocumentInterfaceBrokerProxy( + Mojo.replaceDocumentInterfaceBrokerForTesting(handle0)); + + for (const method of Object.keys(overrides)) { + realBrokerProxy[method] = overrides[method]; + } + + // Use the real broker (with overrides) as the implementation of the JS-side broker + const testBrokerBinding = new blink.mojom.DocumentInterfaceBroker(realBrokerProxy); + testBrokerBinding.bindHandle(handle1); +}
diff --git a/third_party/blink/web_tests/resources/testdriver-vendor.js b/third_party/blink/web_tests/resources/testdriver-vendor.js index a806a721..95b584b 100644 --- a/third_party/blink/web_tests/resources/testdriver-vendor.js +++ b/third_party/blink/web_tests/resources/testdriver-vendor.js
@@ -84,6 +84,7 @@ for (let i = 0; i < actions.length; i++) { var last_x_position = 0; var last_y_position = 0; + var first_pointer_down = false; for (let j = 0; j < actions[i].actions.length; j++) { if ('origin' in actions[i].actions[j]) { if (actions[i].actions[j].origin == "viewport") { @@ -126,6 +127,16 @@ actions[i].actions[j].x = last_x_position; actions[i].actions[j].y = last_y_position; } + + if ('parameters' in actions[i] && actions[i].parameters.pointerType == "touch") { + if (actions[i].actions[j].type == "pointerMove" && !first_pointer_down) { + actions[i].actions[j].type = "pause"; + } else if (actions[i].actions[j].type == "pointerDown") { + first_pointer_down = true; + } else if (actions[i].actions[j].type == "pointerUp") { + first_pointer_down = false; + } + } } }
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/importScripts-in-sharedworker-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/importScripts-in-sharedworker-expected.txt deleted file mode 100644 index 4f65337..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/importScripts-in-sharedworker-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL importScripts assert_equals: expected "gamma/script.js" but got "beta/script.js" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/importScripts-in-worker-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/importScripts-in-worker-expected.txt deleted file mode 100644 index 4f65337..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/importScripts-in-worker-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL importScripts assert_equals: expected "gamma/script.js" but got "beta/script.js" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/worker-in-worker-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/worker-in-worker-expected.txt deleted file mode 100644 index a8ed8c5f..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/worker-in-worker-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Base URL in workers: new Worker() assert_equals: expected "gamma" but got "beta" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/xhr-in-sharedworker-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/xhr-in-sharedworker-expected.txt deleted file mode 100644 index 4bb4dcb..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/xhr-in-sharedworker-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL xhr-worker assert_equals: expected "gamma\n" but got "beta\n" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/xhr-in-worker-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/xhr-in-worker-expected.txt deleted file mode 100644 index 4bb4dcb..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/baseurl/alpha/xhr-in-worker-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL xhr-worker assert_equals: expected "gamma\n" but got "beta\n" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-expected.txt deleted file mode 100644 index 0fcc95f..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL WorkerLocation with redirects: classic dedicated workers assert_equals: expected "http://web-platform.test:8001/workers/interfaces/WorkerGlobalScope/location/post-location-members.js?a" but got "http://web-platform.test:8001/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py?fail" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-sharedworker-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-sharedworker-expected.txt deleted file mode 100644 index 600eacd..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect-sharedworker-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL redirect assert_equals: expected "/workers/interfaces/WorkerGlobalScope/location/redirect.js" but got "/common/redirect.py" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/http/tests/workers/worker-redirect-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/http/tests/workers/worker-redirect-expected.txt deleted file mode 100644 index d344f4d2..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/http/tests/workers/worker-redirect-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -CONSOLE ERROR: Unsafe attempt to load URL http://localhost:8000/workers/resources/worker-redirect-target.js from frame with URL http://127.0.0.1:8000/resources/redirect.php?url=http://localhost:8000/workers/resources/worker-redirect-target.js. Domains, protocols and ports must match. - -Test that loading the worker's script does not allow a cross origin redirect (bug 26146) - -SUCCESS: threw exception (SecurityError: Failed to construct 'Worker': Script at 'http://localhost:8000/workers/resources/worker-target.js' cannot be accessed from origin 'http://127.0.0.1:8000'.) when attempting to cross origin while loading the worker script. -SUCCESS: threw error when attempting to redirected cross origin while loading the worker script. -DONE -
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index f445684..07c27e5e 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -702,6 +702,8 @@ [Worker] static method createDataPipe [Worker] static method createMessagePipe [Worker] static method createSharedBuffer +[Worker] static method getDocumentInterfaceBrokerHandle +[Worker] static method replaceDocumentInterfaceBrokerForTesting [Worker] attribute @@toStringTag [Worker] attribute RESULT_ABORTED [Worker] attribute RESULT_ALREADY_EXISTS
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 0296a9e..4a0b0fa 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -4655,6 +4655,8 @@ static method createDataPipe static method createMessagePipe static method createSharedBuffer + static method getDocumentInterfaceBrokerHandle + static method replaceDocumentInterfaceBrokerForTesting attribute @@toStringTag attribute RESULT_ABORTED attribute RESULT_ALREADY_EXISTS
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index 51bdf80..570dd6f 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -687,6 +687,8 @@ [Worker] static method createDataPipe [Worker] static method createMessagePipe [Worker] static method createSharedBuffer +[Worker] static method getDocumentInterfaceBrokerHandle +[Worker] static method replaceDocumentInterfaceBrokerForTesting [Worker] attribute @@toStringTag [Worker] attribute RESULT_ABORTED [Worker] attribute RESULT_ALREADY_EXISTS
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js index 43af897..80dd6bc1 100644 --- a/third_party/closure_compiler/externs/automation.js +++ b/third_party/closure_compiler/externs/automation.js
@@ -1287,6 +1287,18 @@ chrome.automation.AutomationNode.prototype.lineThrough; /** + * The font family of this node. + * @type {string|undefined} + */ +chrome.automation.AutomationNode.prototype.fontFamily; + +/** + * The font size of this node. + * @type {number|undefined} + */ +chrome.automation.AutomationNode.prototype.fontSize; + +/** * Indicates whether this node is selected, unselected, or neither. * @type {(boolean|undefined)} * @see https://developer.chrome.com/extensions/automation#type-selected
diff --git a/third_party/grpc/BUILD.gn b/third_party/grpc/BUILD.gn index 0ff0399..190242d 100644 --- a/third_party/grpc/BUILD.gn +++ b/third_party/grpc/BUILD.gn
@@ -548,6 +548,10 @@ ] } +# A dummy group which is needed to make the fuzz targets discoverable. +group("fuzzers") { +} + fuzzer_test("grpc_alts_credentials_fuzzer") { sources = [ "src/test/core/security/alts_credentials_fuzzer.cc", @@ -578,6 +582,7 @@ ":grpc_internal_config", ] seed_corpus = "src/test/core/end2end/fuzzers/api_fuzzer_corpus" + dict = "src/test/core/end2end/fuzzers/api_fuzzer.dictionary" } fuzzer_test("grpc_client_fuzzer") { @@ -594,6 +599,7 @@ ":grpc_internal_config", ] seed_corpus = "src/test/core/end2end/fuzzers/client_fuzzer_corpus" + dict = "src/test/core/end2end/fuzzers/hpack.dictionary" } fuzzer_test("grpc_hpack_parser_fuzzer_test") {
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium index 5186ba0..99d42cb 100644 --- a/third_party/inspector_protocol/README.chromium +++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@ Short Name: inspector_protocol URL: https://chromium.googlesource.com/deps/inspector_protocol/ Version: 0 -Revision: b9f19d327ece7e05c74898fbb6fdc551c6d3f344 +Revision: f67ec5180f476830e839226b5ca948e43070fdab License: BSD License File: LICENSE Security Critical: no
diff --git a/third_party/inspector_protocol/lib/base_string_adapter_h.template b/third_party/inspector_protocol/lib/base_string_adapter_h.template index 2383777..b0215e0 100644 --- a/third_party/inspector_protocol/lib/base_string_adapter_h.template +++ b/third_party/inspector_protocol/lib/base_string_adapter_h.template
@@ -64,8 +64,12 @@ static String fromInteger(int number) { return base::NumberToString(number); } static String fromDouble(double number) { String s = base::NumberToString(number); - if (!s.empty() && s[0] == '.') - s = "0" + s; + if (!s.empty()) { // .123 -> 0.123; -.123 -> -0.123 for valid JSON. + if (s[0] == '.') + s.insert(/*index=*/ 0, /*count=*/ 1, /*ch=*/ '0'); + else if (s[0] == '-' && s.size() >= 2 && s[1] == '.') + s.insert(/*index=*/ 1, /*count=*/ 1, /*ch=*/ '0'); + } return s; } static double toDouble(const char* s, size_t len, bool* ok) {
diff --git a/third_party/jmake/BUILD.gn b/third_party/jmake/BUILD.gn deleted file mode 100644 index 2598dbe..0000000 --- a/third_party/jmake/BUILD.gn +++ /dev/null
@@ -1,31 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/rules.gni") - -java_binary("jmake") { - java_files = [ - "src/org/pantsbuild/jmake/CompatibilityChecker.java", - "src/org/pantsbuild/jmake/BinaryFileWriter.java", - "src/org/pantsbuild/jmake/PCDEntry.java", - "src/org/pantsbuild/jmake/TextProjectDatabaseWriter.java", - "src/org/pantsbuild/jmake/Base64.java", - "src/org/pantsbuild/jmake/PCDContainer.java", - "src/org/pantsbuild/jmake/Main.java", - "src/org/pantsbuild/jmake/ClassFileReader.java", - "src/org/pantsbuild/jmake/ClassPath.java", - "src/org/pantsbuild/jmake/BinaryFileReader.java", - "src/org/pantsbuild/jmake/PrivateException.java", - "src/org/pantsbuild/jmake/ClassInfo.java", - "src/org/pantsbuild/jmake/BinaryProjectDatabaseWriter.java", - "src/org/pantsbuild/jmake/PCDManager.java", - "src/org/pantsbuild/jmake/TextProjectDatabaseReader.java", - "src/org/pantsbuild/jmake/RefClassFinder.java", - "src/org/pantsbuild/jmake/Utils.java", - "src/org/pantsbuild/jmake/PublicExceptions.java", - "src/org/pantsbuild/jmake/BinaryProjectDatabaseReader.java", - ] - main_class = "org.pantsbuild.jmake.Main" - enable_incremental_javac_override = false -}
diff --git a/third_party/jmake/LICENSE b/third_party/jmake/LICENSE deleted file mode 100644 index 2fa033e..0000000 --- a/third_party/jmake/LICENSE +++ /dev/null
@@ -1,341 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. -
diff --git a/third_party/jmake/OWNERS b/third_party/jmake/OWNERS deleted file mode 100644 index b4eda11..0000000 --- a/third_party/jmake/OWNERS +++ /dev/null
@@ -1,4 +0,0 @@ -agrieve@chromium.org -yfriedman@chromium.org - -# COMPONENT: Build
diff --git a/third_party/jmake/README.chromium b/third_party/jmake/README.chromium deleted file mode 100644 index 0530d0f..0000000 --- a/third_party/jmake/README.chromium +++ /dev/null
@@ -1,17 +0,0 @@ -Name: JMake -URL: https://github.com/pantsbuild/jmake -Version: 0 -Revision: 7761ee3e1537ccc61820c0d30061eb09edaf1c93 -License: GPL 2.0 -License File: NOT_SHIPPED -Security Critical: No -License Android Compatible: No - -Description: -Formerly known as Javamake, jmake is a compiler wrapper that figures out the -minimal set of .java files that need to be rebuilt given a set of .java files -that have changed. - -Local Modifications: -* Removed unneeded files -* Added BUILD.gn
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/Base64.java b/third_party/jmake/src/org/pantsbuild/jmake/Base64.java deleted file mode 100644 index af02ca6..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/Base64.java +++ /dev/null
@@ -1,80 +0,0 @@ -/* Copyright (c) 2002-2013 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.util.Arrays; - - -/** - * JMake needs to run against old versions of Java, that may not have JAXB's - * javax.xml.bind.DatatypeConverter. And we don't want JMake to depend on third-party external libraries, - * especially not just for this. So we implement a lightweight Base64 converter here ourselves. - - * Note that sun.misc.BASE64Encoder is not official API and can go away at any time. Plus it inserts - * line breaks into its emitted string, which is not what we want. So we can't use that either. - */ - -public class Base64 { - // The easiest way to grok this code is to think of Base64 as the following chain of - // conversions (ignoring padding issues): - // 3 bytes -> 24 bits -> 4 6-bit nibbles -> 4 indexes from 0-63 -> 4 characters. - private static final char[] indexToDigit = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); - private static final int[] digitToIndex = new int[128]; - static { - assert(indexToDigit.length == 64); - Arrays.fill(digitToIndex, -1); - for (int i = 0; i < indexToDigit.length; i++) digitToIndex[(int)indexToDigit[i]] = i; - } - - private Base64() {} - - public static char[] encode(byte[] in) { - char[] ret = new char[(in.length + 2) / 3 * 4]; - int p = 0; - int i = 0; - while (i < in.length) { - // Lowest 24 bits count. - int bits = (in[i++] & 0xff) << 16 | (i < in.length ? in[i++] & 0xff : 0) << 8 | (i < in.length ? in[i++] & 0xff : 0); - ret[p++] = indexToDigit[(bits & 0xfc0000) >> 18]; - ret[p++] = indexToDigit[(bits & 0x3f000) >> 12]; - ret[p++] = indexToDigit[(bits & 0xfc0) >> 6]; - ret[p++] = indexToDigit[bits & 0x3f]; - } - assert(p == ret.length); - int padding = (3 - in.length % 3) % 3; - for (int j = ret.length - padding; j < ret.length; j++) ret[j] = '='; - return ret; - } - - public static byte[] decode(char[] in) { - if (in.length % 4 != 0) throw new IllegalArgumentException("Base64-encoded string must be of length that is a multiple of 4."); - int len = in.length; - while(len > 0 && in[len - 1] == '=') len--; - int padding = in.length - len; - byte[] ret = new byte[in.length / 4 * 3 - padding]; - int i = 0; - int p = 0; - while (i < len) { - char c0 = in[i++]; - char c1 = in[i++]; - char c2 = i < len ? in[i++] : 'A'; - char c3 = i < len ? in[i++] : 'A'; - if (c0 > 127 || c1 > 127 || c2 > 127 || c3 > 127) throw new IllegalArgumentException("Invalid Base64 digit in: " + c0 + c1 + c2 + c3); - int n0 = digitToIndex[c0]; - int n1 = digitToIndex[c1]; - int n2 = digitToIndex[c2]; - int n3 = digitToIndex[c3]; - if (n0 < 0 || n1 < 0 || n2 < 0 || n3 < 0) throw new IllegalArgumentException("Invalid Base64 digit in: " + c0 + c1 + c2 + c3); - int bits = (n0 << 18) | (n1 << 12) | (n2 << 6) | n3; - ret[p++] = (byte)((bits & 0xff0000) >> 16); - if (p < ret.length) ret[p++] = (byte)((bits & 0xff00) >> 8); - if (p < ret.length) ret[p++] = (byte)(bits & 0xff); - } - return ret; - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/BinaryFileReader.java b/third_party/jmake/src/org/pantsbuild/jmake/BinaryFileReader.java deleted file mode 100644 index 6e2cb4e..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/BinaryFileReader.java +++ /dev/null
@@ -1,96 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.DataInputStream; -import java.io.ByteArrayInputStream; -import java.io.IOException; - -/** - * Basic operations for reading a byte array representing a binary file. - * - * @author Misha Dmitriev - * 10 November 2001 - */ -public class BinaryFileReader { - - protected byte[] buf; - protected int curBufPos; - protected String fileFullPath; // Required only for nice error reports - - protected void initBuf(byte[] buf, String fileFullPath) { - this.buf = buf; - curBufPos = 0; - this.fileFullPath = fileFullPath; - } - - protected char nextChar() { - return (char) (((buf[curBufPos++] & 255) << 8) + (buf[curBufPos++] & 255)); - } - - protected char getChar(int bufPos) { - return (char) (((buf[bufPos] & 255) << 8) + (buf[bufPos+1] & 255)); - } - - protected int nextInt() { - return ((buf[curBufPos++] & 255) << 24) + ((buf[curBufPos++] & 255) << 16) + - ((buf[curBufPos++] & 255) << 8) + (buf[curBufPos++] & 255); - } - - protected int getInt(int bufPos) { - return ((buf[bufPos] & 255) << 24) + ((buf[bufPos+1] & 255) << 16) + - ((buf[bufPos+2] & 255) << 8) + (buf[bufPos+3] & 255); - } - - protected long nextLong() { - long res = getLong(curBufPos); - curBufPos += 8; - return res; - } - - protected long getLong(int bufPos) { - DataInputStream bufin = - new DataInputStream(new ByteArrayInputStream(buf, bufPos, 8)); - try { - return bufin.readLong(); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - protected float nextFloat() { - float res = getFloat(curBufPos); - curBufPos += 4; - return res; - } - - protected float getFloat(int bufPos) { - DataInputStream bufin = - new DataInputStream(new ByteArrayInputStream(buf, bufPos, 4)); - try { - return bufin.readFloat(); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - protected double nextDouble() { - double res = getDouble(curBufPos); - curBufPos += 8; - return res; - } - - protected double getDouble(int bufPos) { - DataInputStream bufin = - new DataInputStream(new ByteArrayInputStream(buf, bufPos, 8)); - try { - return bufin.readDouble(); - } catch (IOException e) { - throw new PrivateException(e); - } - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/BinaryFileWriter.java b/third_party/jmake/src/org/pantsbuild/jmake/BinaryFileWriter.java deleted file mode 100644 index 01de415..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/BinaryFileWriter.java +++ /dev/null
@@ -1,99 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -/** - * Basic operations for writing to a byte array representing a binary file. - * - * @author Misha Dmitriev - * 30 January 2002 - */ -public class BinaryFileWriter { - - protected byte[] buf; - protected int curBufSize, bufInc, curBufPos, threshold; - private boolean bufferIncreaseAllowed = true; - - protected void initBuf(int initSize) { - buf = new byte[initSize]; - curBufSize = initSize; - bufInc = initSize / 5; - curBufPos = 0; - threshold = curBufSize - bufInc; - } - - protected void increaseBuf() { - if (!bufferIncreaseAllowed) { - return; - } - byte newBuf[] = new byte[curBufSize + bufInc]; - System.arraycopy(buf, 0, newBuf, 0, curBufPos); - buf = newBuf; - curBufSize = buf.length; - threshold = curBufSize - bufInc; - } - - // This should be called with false only when we are sure that we set the exact size of the buffer - // and there is no need to increase it. - protected void setBufferIncreaseMode(boolean increaseMode) { - bufferIncreaseAllowed = increaseMode; - } - - public byte[] getBuffer() { - return buf; - } - - - protected void writeByte(byte b) { - if (curBufPos > threshold) { - increaseBuf(); - } - buf[curBufPos++] = b; - } - - protected void writeChar(int ch) { - buf[curBufPos++] = (byte) ((ch >> 8) & 255); - buf[curBufPos++] = (byte) (ch & 255); - if (curBufPos > threshold) { - increaseBuf(); - } - } - - protected void writeInt(int i) { - buf[curBufPos++] = (byte) ((i >> 24) & 255); - buf[curBufPos++] = (byte) ((i >> 16) & 255); - buf[curBufPos++] = (byte) ((i >> 8) & 255); - buf[curBufPos++] = (byte) (i & 255); - if (curBufPos > threshold) { - increaseBuf(); - } - } - - protected void writeLong(long l) { - buf[curBufPos++] = (byte) ((l >> 56) & 255); - buf[curBufPos++] = (byte) ((l >> 48) & 255); - buf[curBufPos++] = (byte) ((l >> 40) & 255); - buf[curBufPos++] = (byte) ((l >> 32) & 255); - buf[curBufPos++] = (byte) ((l >> 24) & 255); - buf[curBufPos++] = (byte) ((l >> 16) & 255); - buf[curBufPos++] = (byte) ((l >> 8) & 255); - buf[curBufPos++] = (byte) (l & 255); - if (curBufPos > threshold) { - increaseBuf(); - } - } - - protected void writeFloat(float f) { - int i = Float.floatToIntBits(f); - writeInt(i); - } - - protected void writeDouble(double d) { - long l = Double.doubleToLongBits(d); - writeLong(l); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/BinaryProjectDatabaseReader.java b/third_party/jmake/src/org/pantsbuild/jmake/BinaryProjectDatabaseReader.java deleted file mode 100644 index e75e206..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/BinaryProjectDatabaseReader.java +++ /dev/null
@@ -1,281 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.File; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * This class creates the internal representation of the project database from a byte array. - * - * @author Misha Dmitriev - * 2 March 2005 - */ -public class BinaryProjectDatabaseReader extends BinaryFileReader { - - private String stringTable[]; - private Map<String,PCDEntry> pcd; - private int nOfEntries; - private int pdbFormat; // Currently supported values: 0x01030300 (jmake 1.3.3 and newer versions); 1 (all older versions) - // These are defined in Utils as PDB_FORMAT_CODE_LATEST and PDB_FORMAT_CODE_OLD - - public Map<String,PCDEntry> readProjectDatabaseFromFile(File infile) { - byte buf[] = Utils.readFileIntoBuffer(infile); - return readProjectDatabase(buf, infile.toString()); - } - - public Map<String,PCDEntry> readProjectDatabase(byte[] pdbFile, - String pdbFileFullPath) { - initBuf(pdbFile, pdbFileFullPath); - - readPreamble(); - readStringTable(); - pcd = new LinkedHashMap<String,PCDEntry>(nOfEntries * 4 / 3); - - for (int i = 0; i < nOfEntries; i++) { - PCDEntry entry = readPCDEntry(); - pcd.put(entry.className, entry); - } - - stringTable = null; // Help the GC - return pcd; - } - - private void readPreamble() { - if (buf.length < Utils.magicLength + 8) { - pdbCorruptedException("file too short"); - } - - for (int i = 0; i < Utils.magicLength; i++) { - if (buf[i] != Utils.MAGIC[i]) { - pdbCorruptedException("wrong project database header"); - } - } - - curBufPos += Utils.magicLength; - pdbFormat = nextInt(); - if (pdbFormat != Utils.PDB_FORMAT_CODE_OLD && pdbFormat != Utils.PDB_FORMAT_CODE_LATEST) { - pdbCorruptedException("wrong version number"); - } - - int pdbSize = nextInt(); - if (buf.length != Utils.MAGIC.length + 8 + pdbSize) { - pdbCorruptedException("file size does not match stored value"); - } - - nOfEntries = nextInt(); - } - - private void readStringTable() { - int size = nextInt(); - stringTable = new String[size]; - for (int i = 0; i < size; i++) { - stringTable[i] = nextString(); - } - } - - private PCDEntry readPCDEntry() { - String className = nextStringRef(); - String javaFileFullPath = nextStringRef(); - long classFileLastModified = nextLong(); - long classFileFingerprint = nextLong(); - ClassInfo classInfo = readClassInfo(); - - return new PCDEntry(className, javaFileFullPath, classFileLastModified, classFileFingerprint, classInfo); - } - - private ClassInfo readClassInfo() { - int i, j, len; - ClassInfo res = new ClassInfo(); - - res.name = nextStringRef(); - if (pdbFormat >= Utils.PDB_FORMAT_CODE_133) { - res.javacTargetRelease = nextInt(); - } else { - res.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_OLDEST; - } - - len = nextChar(); - if (len > 0) { - String cpoolRefsToClasses[] = new String[len]; - for (i = 0; i < len; i++) { - cpoolRefsToClasses[i] = nextStringRef(); - } - res.cpoolRefsToClasses = cpoolRefsToClasses; - boolean isRefClassArray[] = new boolean[len]; - for (i = 0; i < len; i++) { - isRefClassArray[i] = (buf[curBufPos++] != 0); - } - res.isRefClassArray = isRefClassArray; - } - - len = nextChar(); - if (len > 0) { - String cpoolRefsToFieldClasses[] = new String[len]; - for (i = 0; i < len; i++) { - cpoolRefsToFieldClasses[i] = nextStringRef(); - } - res.cpoolRefsToFieldClasses = cpoolRefsToFieldClasses; - String cpoolRefsToFieldNames[] = new String[len]; - for (i = 0; i < len; i++) { - cpoolRefsToFieldNames[i] = nextStringRef(); - } - res.cpoolRefsToFieldNames = cpoolRefsToFieldNames; - String cpoolRefsToFieldSignatures[] = new String[len]; - for (i = 0; i < len; i++) { - cpoolRefsToFieldSignatures[i] = nextStringRef(); - } - res.cpoolRefsToFieldSignatures = cpoolRefsToFieldSignatures; - } - - len = nextChar(); - if (len > 0) { - String cpoolRefsToMethodClasses[] = new String[len]; - for (i = 0; i < len; i++) { - cpoolRefsToMethodClasses[i] = nextStringRef(); - } - res.cpoolRefsToMethodClasses = cpoolRefsToMethodClasses; - String cpoolRefsToMethodNames[] = new String[len]; - for (i = 0; i < len; i++) { - cpoolRefsToMethodNames[i] = nextStringRef(); - } - res.cpoolRefsToMethodNames = cpoolRefsToMethodNames; - String cpoolRefsToMethodSignatures[] = new String[len]; - for (i = 0; i < len; i++) { - cpoolRefsToMethodSignatures[i] = nextStringRef(); - } - res.cpoolRefsToMethodSignatures = cpoolRefsToMethodSignatures; - } - - res.accessFlags = nextChar(); - res.isNonMemberNestedClass = (buf[curBufPos++] != 0); - if (!"java/lang/Object".equals(res.name)) { - res.superName = nextStringRef(); - } - - len = nextChar(); - if (len > 0) { - String interfaces[] = new String[len]; - for (i = 0; i < len; i++) { - interfaces[i] = nextStringRef(); - } - res.interfaces = interfaces; - } - - len = nextChar(); - if (len > 0) { - String fieldNames[] = new String[len]; - for (i = 0; i < len; i++) { - fieldNames[i] = nextStringRef(); - } - res.fieldNames = fieldNames; - String fieldSignatures[] = new String[len]; - for (i = 0; i < len; i++) { - fieldSignatures[i] = nextStringRef(); - } - res.fieldSignatures = fieldSignatures; - char fieldAccessFlags[] = new char[len]; - for (i = 0; i < len; i++) { - fieldAccessFlags[i] = nextChar(); - } - res.fieldAccessFlags = fieldAccessFlags; - } - - len = nextChar(); - if (len > 0) { - Object primitiveConstantInitValues[] = new Object[len]; - for (i = 0; i < len; i++) { - byte code = buf[curBufPos++]; - switch (code) { - case 1: - primitiveConstantInitValues[i] = nextStringRef(); - break; - case 2: - primitiveConstantInitValues[i] = Integer.valueOf(nextInt()); - break; - case 3: - primitiveConstantInitValues[i] = Long.valueOf(nextLong()); - break; - case 4: - primitiveConstantInitValues[i] = Float.valueOf(nextFloat()); - break; - case 5: - primitiveConstantInitValues[i] = - Double.valueOf(nextDouble()); - break; - default: // Nothing to do - } - } - res.primitiveConstantInitValues = primitiveConstantInitValues; - } - - len = nextChar(); - if (len > 0) { - String methodNames[] = new String[len]; - for (i = 0; i < len; i++) { - methodNames[i] = nextStringRef(); - } - res.methodNames = methodNames; - String methodSignatures[] = new String[len]; - for (i = 0; i < len; i++) { - methodSignatures[i] = nextStringRef(); - } - res.methodSignatures = methodSignatures; - char methodAccessFlags[] = new char[len]; - for (i = 0; i < len; i++) { - methodAccessFlags[i] = nextChar(); - } - res.methodAccessFlags = methodAccessFlags; - } - - len = nextChar(); - if (len > 0) { - String checkedExceptions[][] = new String[len][]; - for (i = 0; i < len; i++) { - int len1 = nextChar(); - if (len1 > 0) { - checkedExceptions[i] = new String[len1]; - for (j = 0; j < len1; j++) { - checkedExceptions[i][j] = nextStringRef(); - } - } - } - res.checkedExceptions = checkedExceptions; - } - - len = nextChar(); - if (len > 0) { - String nestedClasses[] = new String[len]; - for (i = 0; i < len; i++) { - nestedClasses[i] = nextStringRef(); - } - res.nestedClasses = nestedClasses; - } - - res.initializeImmediateTransientFields(); - return res; - } - - private String nextString() { - int length = nextChar(); - if (buf.length < curBufPos + length) { - pdbCorruptedException("data error"); - } - String res = (new String(buf, curBufPos, length)).intern(); - curBufPos += length; - return res; - } - - private String nextStringRef() { - return stringTable[nextInt()]; - } - - private void pdbCorruptedException(String message) { - throw new PrivateException(new PublicExceptions.PDBCorruptedException(message)); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/BinaryProjectDatabaseWriter.java b/third_party/jmake/src/org/pantsbuild/jmake/BinaryProjectDatabaseWriter.java deleted file mode 100644 index fafaa39..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/BinaryProjectDatabaseWriter.java +++ /dev/null
@@ -1,363 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Map; - -/** - * This class implements writing into a byte array representing a project database - * - * @author Misha Dmitriev - * 2 March 2005 - */ -public class BinaryProjectDatabaseWriter extends BinaryFileWriter { - - private Map<String, PCDEntry> pcd = null; - private int nOfEntries; - private byte[] stringBuf; - private int curStringBufPos, stringBufInc, curStringBufWatermark, stringCount; - private StringHashTable stringHashTable = null; - - public void writeProjectDatabaseToFile(File outfile, Map<String, PCDEntry> pcd) { - try { - byte[] buf = new BinaryProjectDatabaseWriter().writeProjectDatabase(pcd); - FileOutputStream out = new FileOutputStream(outfile); - out.write(buf); - out.close(); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - public byte[] writeProjectDatabase(Map<String, PCDEntry> pcd) { - this.pcd = pcd; - nOfEntries = pcd.size(); - - // So far the constant here is chosen rather arbitrarily - initBuf(nOfEntries * 1000); - - stringBuf = new byte[nOfEntries * 300]; - stringBufInc = stringBuf.length / 5; - curStringBufWatermark = stringBuf.length - 20; - stringHashTable = new StringHashTable(stringBuf.length / 8); - - for (PCDEntry entry : pcd.values()) { - writePCDEntry(entry); - } - - // Now we have the string buffer and the main buffer. Write the end result - byte[] mainBuf = buf; - int mainBufSize = curBufPos; - int preambleSize = Utils.MAGIC.length + 8; - int stringBufSize = curStringBufPos; - int pdbSize = stringBufSize + mainBufSize + 8; // 8 is for nOfEntries and string table size - initBuf(preambleSize + pdbSize); - setBufferIncreaseMode(false); - - writePreamble(pdbSize); - writeStringTable(stringBufSize); - System.arraycopy(mainBuf, 0, buf, curBufPos, mainBufSize); - return buf; - } - - private void writePreamble(int pdbSize) { - System.arraycopy(Utils.MAGIC, 0, buf, 0, Utils.MAGIC.length); - curBufPos += Utils.MAGIC.length; - - writeInt(Utils.PDB_FORMAT_CODE_LATEST); // Version number - writeInt(pdbSize); - writeInt(pcd.size()); - } - - private void writeStringTable(int stringBufSize) { - writeInt(stringCount); - System.arraycopy(stringBuf, 0, buf, curBufPos, stringBufSize); - curBufPos += stringBufSize; - } - - private void writePCDEntry(PCDEntry entry) { - writeStringRef(entry.className); - writeStringRef(entry.javaFileFullPath); - writeLong(entry.oldClassFileLastModified); - writeLong(entry.oldClassFileFingerprint); - writeClassInfo(entry.oldClassInfo); - } - - private void writeClassInfo(ClassInfo ci) { - int i, j, len; - - writeStringRef(ci.name); - writeInt(ci.javacTargetRelease); - - len = ci.cpoolRefsToClasses != null ? ci.cpoolRefsToClasses.length : 0; - writeChar(len); - if (len > 0) { - String cpoolRefsToClasses[] = ci.cpoolRefsToClasses; - for (i = 0; i < len; i++) { - writeStringRef(cpoolRefsToClasses[i]); - } - boolean isRefClassArray[] = ci.isRefClassArray; - for (i = 0; i < len; i++) { - byte b = isRefClassArray[i] ? (byte) 1 : (byte) 0; - writeByte(b); - } - } - - len = ci.cpoolRefsToFieldClasses != null ? ci.cpoolRefsToFieldClasses.length - : 0; - writeChar(len); - if (len > 0) { - String cpoolRefsToFieldClasses[] = ci.cpoolRefsToFieldClasses; - for (i = 0; i < len; i++) { - writeStringRef(cpoolRefsToFieldClasses[i]); - } - String cpoolRefsToFieldNames[] = ci.cpoolRefsToFieldNames; - for (i = 0; i < len; i++) { - writeStringRef(cpoolRefsToFieldNames[i]); - } - String cpoolRefsToFieldSignatures[] = ci.cpoolRefsToFieldSignatures; - for (i = 0; i < len; i++) { - writeStringRef(cpoolRefsToFieldSignatures[i]); - } - } - - len = ci.cpoolRefsToMethodClasses != null ? ci.cpoolRefsToMethodClasses.length - : 0; - writeChar(len); - if (len > 0) { - String cpoolRefsToMethodClasses[] = ci.cpoolRefsToMethodClasses; - for (i = 0; i < len; i++) { - writeStringRef(cpoolRefsToMethodClasses[i]); - } - String cpoolRefsToMethodNames[] = ci.cpoolRefsToMethodNames; - for (i = 0; i < len; i++) { - writeStringRef(cpoolRefsToMethodNames[i]); - } - String cpoolRefsToMethodSignatures[] = - ci.cpoolRefsToMethodSignatures; - for (i = 0; i < len; i++) { - writeStringRef(cpoolRefsToMethodSignatures[i]); - } - } - - writeChar(ci.accessFlags); - byte b = ci.isNonMemberNestedClass ? (byte) 1 : (byte) 0; - writeByte(b); - if (!"java/lang/Object".equals(ci.name)) { - writeStringRef(ci.superName); - } - - len = ci.interfaces != null ? ci.interfaces.length : 0; - writeChar(len); - if (len > 0) { - String interfaces[] = ci.interfaces; - for (i = 0; i < len; i++) { - writeStringRef(interfaces[i]); - } - } - - len = ci.fieldNames != null ? ci.fieldNames.length : 0; - writeChar(len); - if (len > 0) { - String fieldNames[] = ci.fieldNames; - for (i = 0; i < len; i++) { - writeStringRef(fieldNames[i]); - } - String fieldSignatures[] = ci.fieldSignatures; - for (i = 0; i < len; i++) { - writeStringRef(fieldSignatures[i]); - } - char fieldAccessFlags[] = ci.fieldAccessFlags; - for (i = 0; i < len; i++) { - writeChar(fieldAccessFlags[i]); - } - } - - len = ci.primitiveConstantInitValues != null ? ci.primitiveConstantInitValues.length - : 0; - writeChar(len); - if (len > 0) { - Object primitiveConstantInitValues[] = - ci.primitiveConstantInitValues; - for (i = 0; i < len; i++) { - Object pc = primitiveConstantInitValues[i]; - if (pc != null) { - if (pc instanceof String) { - writeByte((byte)1); - writeStringRef((String) pc); - } else if (pc instanceof Integer) { - writeByte((byte)2); - writeInt(((Integer) pc).intValue()); - } else if (pc instanceof Long) { - writeByte((byte)3); - writeLong(((Long) pc).longValue()); - } else if (pc instanceof Float) { - writeByte((byte)4); - writeFloat(((Float) pc).floatValue()); - } else if (pc instanceof Double) { - writeByte((byte)5); - writeDouble(((Double) pc).doubleValue()); - } - } else { - writeByte((byte)0); - } - } - } - - len = ci.methodNames != null ? ci.methodNames.length : 0; - writeChar(len); - if (len > 0) { - String methodNames[] = ci.methodNames; - for (i = 0; i < len; i++) { - writeStringRef(methodNames[i]); - } - String methodSignatures[] = ci.methodSignatures; - for (i = 0; i < len; i++) { - writeStringRef(methodSignatures[i]); - } - char methodAccessFlags[] = ci.methodAccessFlags; - for (i = 0; i < len; i++) { - writeChar(methodAccessFlags[i]); - } - } - - len = ci.checkedExceptions != null ? ci.checkedExceptions.length : 0; - writeChar(len); - if (len > 0) { - String checkedExceptions[][] = ci.checkedExceptions; - for (i = 0; i < len; i++) { - int lenl = checkedExceptions[i] != null ? checkedExceptions[i].length - : 0; - writeChar(lenl); - if (lenl > 0) { - for (j = 0; j < lenl; j++) { - writeStringRef(checkedExceptions[i][j]); - } - } - } - } - - len = ci.nestedClasses != null ? ci.nestedClasses.length : 0; - writeChar(len); - if (len > 0) { - String nestedClasses[] = ci.nestedClasses; - for (i = 0; i < len; i++) { - writeStringRef(nestedClasses[i]); - } - } - } - - private void writeString(String s) { - byte sb[] = s.getBytes(); - int len = sb.length; - if (curStringBufPos + len > curStringBufWatermark) { - // May need to adapt stringBufInc - if (len >= stringBufInc) { - stringBufInc = (stringBufInc + len) * 2; - } else { - stringBufInc = (stringBufInc * 5) / 4; // Still increase a little - observations show that otherwise we usually get here 20 more times - } - byte newStringBuf[] = new byte[stringBuf.length + stringBufInc]; - System.arraycopy(stringBuf, 0, newStringBuf, 0, curStringBufPos); - stringBuf = newStringBuf; - curStringBufWatermark = stringBuf.length - 20; - } - stringBuf[curStringBufPos++] = (byte) ((len >> 8) & 255); - stringBuf[curStringBufPos++] = (byte) (len & 255); - System.arraycopy(sb, 0, stringBuf, curStringBufPos, len); - curStringBufPos += len; - } - - private void writeStringRef(String s) { - int stringRef = stringHashTable.get(s); - if (stringRef == -1) { - stringHashTable.add(s, stringCount); - stringRef = stringCount; - writeString(s); - stringCount++; - } - writeInt(stringRef); - } - - /** Maps Strings to integer numbers (their positions in String table) */ - static class StringHashTable { - - String keys[]; - int values[]; - int size, nOfElements, watermark; - - StringHashTable(int size) { - size = makeLikePrimeNumber(size); - this.size = size; - keys = new String[size]; - values = new int[size]; - nOfElements = 0; - watermark = size * 3 / 4; - } - - final int get(String key) { - int pos = (key.hashCode() & 0x7FFFFFFF) % size; - - while (keys[pos] != null && !keys[pos].equals(key)) { - pos = (pos + 3) % size; // Relies on the fact that size % 3 != 0 - } - if (key.equals(keys[pos])) { - return values[pos]; - } else { - return -1; - } - } - - final void add(String key, int value) { - if (nOfElements > watermark) { - rehash(); - } - - int pos = (key.hashCode() & 0x7FFFFFFF) % size; - while (keys[pos] != null) { - pos = (pos + 3) % size; // Relies on the fact that size % 3 != 0 - } - keys[pos] = key; - values[pos] = value; - nOfElements++; - } - - private final void rehash() { - String oldKeys[] = keys; - int oldValues[] = values; - int oldSize = size; - size = makeLikePrimeNumber(size * 3 / 2); - keys = new String[size]; - values = new int[size]; - nOfElements = 0; - watermark = size * 3 / 4; - - for (int i = 0; i < oldSize; i++) { - if (oldKeys[i] != null) { - add(oldKeys[i], oldValues[i]); - } - } - } - - private final int makeLikePrimeNumber(int no) { - no = (no / 2) * 2 + 1; // Make it an odd number - // Find the nearest "approximately prime" number - boolean prime = false; - do { - no += 2; - prime = - (no % 3 != 0 && no % 5 != 0 && no % 7 != 0 && no % 11 != 0 && - no % 13 != 0 && no % 17 != 0 && no % 19 != 0 && no % 23 != 0 && - no % 29 != 0 && no % 31 != 0 && no % 37 != 0 && no % 41 != 0); - } while (!prime); - return no; - } - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/ClassFileReader.java b/third_party/jmake/src/org/pantsbuild/jmake/ClassFileReader.java deleted file mode 100644 index 3ece22d9..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/ClassFileReader.java +++ /dev/null
@@ -1,595 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.lang.reflect.Modifier; - - -/** - * This class implements reading a byte array representing a class file and converting it into ClassInfo. - * - * @author Misha Dmitriev - * 2 March 2005 - */ -public class ClassFileReader extends BinaryFileReader { - - public static final int JAVA_MAGIC = -889275714; // 0xCAFEBABE - public static final int JAVA_MINOR_VERSION = 0; - public static final int JAVA_MIN_MAJOR_VERSION = 45; - public static final int JAVA_MIN_MINOR_VERSION = 3; - public static final int DEFAULT_MAJOR_VERSION = 46; - public static final int DEFAULT_MINOR_VERSION = 0; - public static final int JDK14_MAJOR_VERSION = 48; - public static final int JDK15_MAJOR_VERSION = 49; - public static final int JDK16_MAJOR_VERSION = 50; - public static final int JDK17_MAJOR_VERSION = 51; - public static final int JDK18_MAJOR_VERSION = 52; - public static final int CONSTANT_Utf8 = 1; - public static final int CONSTANT_Unicode = 2; - public static final int CONSTANT_Integer = 3; - public static final int CONSTANT_Float = 4; - public static final int CONSTANT_Long = 5; - public static final int CONSTANT_Double = 6; - public static final int CONSTANT_Class = 7; - public static final int CONSTANT_String = 8; - public static final int CONSTANT_Fieldref = 9; - public static final int CONSTANT_Methodref = 10; - public static final int CONSTANT_InterfaceMethodref = 11; - public static final int CONSTANT_NameandType = 12; - public static final int CONSTANT_MethodHandle = 15; - public static final int CONSTANT_MethodType = 16; - public static final int CONSTANT_InvokeDynamic = 18; - private ClassInfo classInfo = null; - private int cpOffsets[]; - private Object cpObjectCache[]; - private byte cpTags[]; - - public void readClassFile(byte[] classFile, ClassInfo classInfo, String classFileFullPath, boolean readFullInfo) { - initBuf(classFile, classFileFullPath); - this.classInfo = classInfo; - - readPreamble(); - readConstantPool(readFullInfo); - readIntermediate(); - if (readFullInfo) { - readFields(); - readMethods(); - readAttributes(); - } - } - - private int versionWord(int major, int minor) { - return major * 1000 + minor; - } - - private void readPreamble() { - int magic = nextInt(); - if (magic != JAVA_MAGIC) { - throw classFileParseException("Illegal start of class file"); - } - int minorVersion = nextChar(); - int majorVersion = nextChar(); - if (majorVersion > JDK14_MAJOR_VERSION || - versionWord(majorVersion, minorVersion) < - versionWord(JAVA_MIN_MAJOR_VERSION, JAVA_MIN_MINOR_VERSION) ) { - if (majorVersion == JDK18_MAJOR_VERSION) { - classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_18; - } else if (majorVersion == JDK17_MAJOR_VERSION) { - classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_17; - } else if (majorVersion == JDK16_MAJOR_VERSION) { - classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_16; - } else if (majorVersion == JDK15_MAJOR_VERSION) { - classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_15; - } else { - throw classFileParseException("Wrong version: " + majorVersion + "." + minorVersion); - } - } else { - classInfo.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_OLDEST; - } - } - - private void readConstantPool(boolean readFullInfo) { - int classRefsNo = 0; - int fieldRefsNo = 0; - int methodRefsNo = 0; - - cpOffsets = new int[nextChar()]; - cpTags = new byte[cpOffsets.length]; - int ofs, len, classIdx, nameAndTypeIdx, nameIdx, sigIdx, utf8Idx; - int i = 1; - while (i < cpOffsets.length) { - byte tag = buf[curBufPos++]; - cpOffsets[i] = curBufPos; - cpTags[i] = tag; - i++; - switch (tag) { - case CONSTANT_Utf8: - len = nextChar(); - curBufPos += len; - break; - - case CONSTANT_Class: - classRefsNo++; - curBufPos += 2; - break; - - case CONSTANT_String: - case CONSTANT_MethodType: - curBufPos += 2; - break; - - case CONSTANT_Fieldref: - fieldRefsNo++; - curBufPos += 4; - break; - - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - methodRefsNo++; - curBufPos += 4; - break; - - case CONSTANT_MethodHandle: - curBufPos += 3; - break; - - case CONSTANT_NameandType: - case CONSTANT_Integer: - case CONSTANT_Float: - case CONSTANT_InvokeDynamic: - curBufPos += 4; - break; - - case CONSTANT_Long: - case CONSTANT_Double: - curBufPos += 8; - i++; - break; - - default: - throw classFileParseException("Bad constant pool tag: " + tag + " at " + Integer.toString(curBufPos - 1)); - } - } - - cpObjectCache = new Object[cpOffsets.length]; - if (!readFullInfo) { - return; - } - - classInfo.cpoolRefsToClasses = new String[classRefsNo]; - classInfo.isRefClassArray = new boolean[classRefsNo]; - classInfo.cpoolRefsToFieldClasses = new String[fieldRefsNo]; - classInfo.cpoolRefsToFieldNames = new String[fieldRefsNo]; - classInfo.cpoolRefsToFieldSignatures = new String[fieldRefsNo]; - classInfo.cpoolRefsToMethodClasses = new String[methodRefsNo]; - classInfo.cpoolRefsToMethodNames = new String[methodRefsNo]; - classInfo.cpoolRefsToMethodSignatures = new String[methodRefsNo]; - - int curClassRef = 0; - int curFieldRef = 0; - int curMethodRef = 0; - - for (i = 0; i < cpOffsets.length; i++) { - ofs = cpOffsets[i]; - switch (cpTags[i]) { - case CONSTANT_Class: - utf8Idx = getChar(ofs); - classInfo.cpoolRefsToClasses[curClassRef++] = - classNameAtCPIndex(utf8Idx, classInfo.isRefClassArray, curClassRef - 1); - //System.out.println("Read cpool ref to class: " + classInfo.cpoolRefsToClasses[curClassRef-1]); - break; - - case CONSTANT_Fieldref: - classIdx = getChar(ofs); - nameAndTypeIdx = getChar(ofs + 2); - if (cpTags[classIdx] != CONSTANT_Class || cpTags[nameAndTypeIdx] != CONSTANT_NameandType) { - badCPReference(ofs, i); - } - classInfo.cpoolRefsToFieldClasses[curFieldRef] = - classNameAtCPIndex(getChar(cpOffsets[classIdx])); - - ofs = cpOffsets[nameAndTypeIdx]; - nameIdx = getChar(ofs); - sigIdx = getChar(ofs + 2); - if (cpTags[nameIdx] != CONSTANT_Utf8 || cpTags[sigIdx] != CONSTANT_Utf8) { - badCPReference(ofs, i); - } - classInfo.cpoolRefsToFieldNames[curFieldRef] = - utf8AtCPIndex(nameIdx); - classInfo.cpoolRefsToFieldSignatures[curFieldRef] = - signatureAtCPIndex(sigIdx); - //System.out.println("Read cpool ref to field: " + classInfo.cpoolRefsToFieldNames[curFieldRef] + " " + - // classInfo.cpoolRefsToFieldSignatures[curFieldRef]); - curFieldRef++; - break; - - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - classIdx = getChar(ofs); - nameAndTypeIdx = getChar(ofs + 2); - if (cpTags[classIdx] != CONSTANT_Class || cpTags[nameAndTypeIdx] != CONSTANT_NameandType) { - badCPReference(ofs, i); - } - classInfo.cpoolRefsToMethodClasses[curMethodRef] = - classNameAtCPIndex(getChar(cpOffsets[classIdx])); - - ofs = cpOffsets[nameAndTypeIdx]; - nameIdx = getChar(ofs); - sigIdx = getChar(ofs + 2); - if (cpTags[nameIdx] != CONSTANT_Utf8 || cpTags[sigIdx] != CONSTANT_Utf8) { - badCPReference(ofs, i); - } - classInfo.cpoolRefsToMethodNames[curMethodRef] = - utf8AtCPIndex(nameIdx); - classInfo.cpoolRefsToMethodSignatures[curMethodRef] = - signatureAtCPIndex(sigIdx); - //System.out.println("Read cpool ref to method: " + classInfo.cpoolRefsToMethodNames[curMethodRef] + " " + - // classInfo.cpoolRefsToMethodSignatures[curMethodRef]); - curMethodRef++; - break; - } - } - } - - private void readIntermediate() { - int i, classIdx, superClassIdx; - - classInfo.accessFlags = nextChar(); - classIdx = nextChar(); - if (cpTags[classIdx] != CONSTANT_Class) { - throw classFileParseException("Bad reference to this class name"); - } - classInfo.name = classNameAtCPIndex(getChar(cpOffsets[classIdx])); - superClassIdx = nextChar(); - if (!"java/lang/Object".equals(classInfo.name)) { - if (cpTags[superClassIdx] != CONSTANT_Class) { - throw classFileParseException("Bad reference to super class name"); - } - classInfo.superName = - classNameAtCPIndex(getChar(cpOffsets[superClassIdx])); - } - - char intfCount = nextChar(); - if (intfCount != 0) { - classInfo.interfaces = new String[intfCount]; - for (i = 0; i < intfCount; i++) { - classIdx = nextChar(); - if (cpTags[classIdx] != CONSTANT_Class) { - throw classFileParseException("Bad reference to an implemented interface"); - } - classInfo.interfaces[i] = - classNameAtCPIndex(getChar(cpOffsets[classIdx])); - } - } - } - - private void readFields() { - int i, j; - - char definedFieldCount = nextChar(); - if (definedFieldCount == 0) { - return; - } - - String names[] = new String[definedFieldCount]; - String signatures[] = new String[definedFieldCount]; - char accessFlags[] = new char[definedFieldCount]; - - // We are not going to record information on private fields which have either primitive or non-project-class - // (typically core-class) types. Such fields cannot affect anything except their own class, so we don't need them. - int ri = 0; - - for (i = 0; i < definedFieldCount; i++) { - char flags = nextChar(); - String name = utf8AtCPIndex(nextChar()); - String sig = signatureAtCPIndex(nextChar()); - - boolean recordField = - !(Modifier.isPrivate(flags) && - (ClassInfo.isPrimitiveFieldSig(sig) || classInfo.isNonProjectClassTypeFieldSig(sig))); - - int attrCount = nextChar(); - for (j = 0; j < attrCount; j++) { - int attrNameIdx = nextChar(); - int attrLen = nextInt(); - if (recordField && utf8AtCPIndex(attrNameIdx).equals("ConstantValue") && - Modifier.isFinal(flags)) { - if (classInfo.primitiveConstantInitValues == null) { - classInfo.primitiveConstantInitValues = - new Object[definedFieldCount]; - } - int constValueIdx = nextChar(); - switch (cpTags[constValueIdx]) { - case CONSTANT_String: - classInfo.primitiveConstantInitValues[ri] = - utf8AtCPIndex(getChar(cpOffsets[constValueIdx])); - break; - - case CONSTANT_Integer: - classInfo.primitiveConstantInitValues[ri] = - Integer.valueOf(getInt(cpOffsets[constValueIdx])); - break; - - case CONSTANT_Long: - classInfo.primitiveConstantInitValues[ri] = - Long.valueOf(getLong(cpOffsets[constValueIdx])); - break; - - case CONSTANT_Float: - classInfo.primitiveConstantInitValues[ri] = - Float.valueOf(getFloat(cpOffsets[constValueIdx])); - break; - - case CONSTANT_Double: - classInfo.primitiveConstantInitValues[ri] = - Double.valueOf(getDouble(cpOffsets[constValueIdx])); - break; - - default: - badCPEntry(constValueIdx); - } - - } else { - curBufPos += attrLen; - } - } - - if (recordField) { - names[ri] = name; - signatures[ri] = sig; - accessFlags[ri] = flags; - ri++; - } - } - - if (ri == definedFieldCount) { - classInfo.fieldNames = names; - classInfo.fieldSignatures = signatures; - classInfo.fieldAccessFlags = accessFlags; - } else if (ri > 0) { - classInfo.fieldNames = new String[ri]; - classInfo.fieldSignatures = new String[ri]; - classInfo.fieldAccessFlags = new char[ri]; - System.arraycopy(names, 0, classInfo.fieldNames, 0, ri); - System.arraycopy(signatures, 0, classInfo.fieldSignatures, 0, ri); - System.arraycopy(accessFlags, 0, classInfo.fieldAccessFlags, 0, ri); - } - } - - private void readMethods() { - int i, j; - - char methodCount = nextChar(); - if (methodCount == 0) { - return; - } - - String names[] = new String[methodCount]; - String signatures[] = new String[methodCount]; - char accessFlags[] = new char[methodCount]; - - for (i = 0; i < methodCount; i++) { - accessFlags[i] = nextChar(); - names[i] = utf8AtCPIndex(nextChar()); - signatures[i] = signatureAtCPIndex(nextChar()); - - int attrCount = nextChar(); - for (j = 0; j < attrCount; j++) { - int attrNameIdx = nextChar(); - int attrLen = nextInt(); - if (utf8AtCPIndex(attrNameIdx).equals("Exceptions")) { - if (classInfo.checkedExceptions == null) { - classInfo.checkedExceptions = new String[methodCount][]; - } - int nExceptions = nextChar(); - String exceptions[] = new String[nExceptions]; - for (int k = 0; k < nExceptions; k++) { - int excClassIdx = nextChar(); - if (cpTags[excClassIdx] != CONSTANT_Class) { - badCPEntry(excClassIdx); - } - exceptions[k] = - classNameAtCPIndex(getChar(cpOffsets[excClassIdx])); - } - classInfo.checkedExceptions[i] = exceptions; - } else { - curBufPos += attrLen; - } - } - } - - classInfo.methodNames = names; - classInfo.methodSignatures = signatures; - classInfo.methodAccessFlags = accessFlags; - } - - /** - * This method actually reads only the information related to the nested classes, and - * records only those of them which are first level nested classes of this class. The class - * may also reference other classes which are not package members through the same - * InnerClasses attribute - their names would be processed when their respective enclosing - * classes are read. - */ - private void readAttributes() { - String nestedClassPrefix = classInfo.name + "$"; - - char attrCount = nextChar(); - - for (int i = 0; i < attrCount; i++) { - int attrNameIdx = nextChar(); - int attrLen = nextInt(); - if (utf8AtCPIndex(attrNameIdx).equals("InnerClasses")) { - int nOfClasses = nextChar(); - String nestedClasses[] = new String[nOfClasses]; - char nestedClassAccessFlags[] = new char[nOfClasses]; - boolean nestedClassNonMember[] = new boolean[nOfClasses]; - int curIdx = 0; - for (int j = 0; j < nOfClasses; j++) { - int innerClassInfoIdx = nextChar(); - int outerClassInfoIdx = nextChar(); - int innerClassNameIdx = nextChar(); - char innerClassAccessFlags = nextChar(); - - // Even if a class is private or non-member (innerClassAccessFlags has private bit set or - // outerClassInfoIdx == 0), we still should take this class into account, since it may e.g. extend - // a public class/implement a public interface, which, in turn, may be changed incompatibly. - - String nestedClassFullName = classNameAtCPIndex(getChar(cpOffsets[innerClassInfoIdx])); - - // We are only interested the nested classes whose enclosing class is this one. - if (!nestedClassFullName.startsWith(nestedClassPrefix)) - continue; - - // We are only interested in the directly nested classes of this class. - String nestedClassNameSuffix = nestedClassFullName.substring(nestedClassPrefix.length()); - - if (innerClassNameIdx == 0) { - // Nested class is anonymous. Suffix must be all digits. - if (findFirstNonDigit(nestedClassNameSuffix) != -1) - continue; - } else { - // Nested class is named. - String nestedClassSimpleName = utf8AtCPIndex(innerClassNameIdx); - // The simple case is Outer$Inner. - if (!nestedClassNameSuffix.equals(nestedClassSimpleName)) { - // The more complicated case is a local class. In JDK 1.5+ These are named, - // e.g., Outer$1Inner. Pre-JDK 1.5 they are named e.g., Outer$1$Inner. - int p = findFirstNonDigit(nestedClassNameSuffix); - if (p == -1) - continue; - if (classInfo.javacTargetRelease == Utils.JAVAC_TARGET_RELEASE_OLDEST && - nestedClassNameSuffix.charAt(p++) != '$') - continue; - if (!nestedClassNameSuffix.substring(p).equals(nestedClassSimpleName)) - continue; - } - } - - // The name has passed all checks, so register it. - - nestedClasses[curIdx] = nestedClassFullName; - nestedClassAccessFlags[curIdx] = innerClassAccessFlags; - nestedClassNonMember[curIdx] = (outerClassInfoIdx == 0); - curIdx++; - } - if (curIdx == nOfClasses) { - classInfo.nestedClasses = nestedClasses; - classInfo.nestedClassAccessFlags = nestedClassAccessFlags; - classInfo.nestedClassNonMember = nestedClassNonMember; - } else if (curIdx > 0) { - // We found fewer nested classes for this class than we originally expected, but still more than 0. - // Create a new array to fit their number exactly. - classInfo.nestedClasses = new String[curIdx]; - classInfo.nestedClassAccessFlags = new char[curIdx]; - classInfo.nestedClassNonMember = new boolean[curIdx]; - System.arraycopy(nestedClasses, 0, classInfo.nestedClasses, 0, curIdx); - System.arraycopy(nestedClassAccessFlags, 0, classInfo.nestedClassAccessFlags, 0, curIdx); - System.arraycopy(nestedClassNonMember, 0, classInfo.nestedClassNonMember, 0, curIdx); - } - } else { - curBufPos += attrLen; - } - } - } - - private int findFirstNonDigit(String s) { - for (int i = 0; i < s.length(); i++) { - if (!Character.isDigit(s.charAt(i))) - return i; - } - return -1; - } - - private String utf8AtCPIndex(int idx) { - if (cpTags[idx] != CONSTANT_Utf8) { - throw classFileParseException("Constant pool entry " + idx + " should be UTF8 constant"); - } - if (cpObjectCache[idx] == null) { - int utf8Len = getChar(cpOffsets[idx]); - // String interning reduces the size of the disk database very significantly - // (by one-third in one observed case), and also speeds up database search. - cpObjectCache[idx] = - (new String(buf, cpOffsets[idx] + 2, utf8Len)).intern(); - } - return (String) cpObjectCache[idx]; - } - - private String classNameAtCPIndex(int idx) { - return classNameAtCPIndex(idx, null, 0); - } - - /** - * Read class name at the given CONSTANT_Utf8 constant pool index, and return it - * trimmed of the possible '[' and 'L' prefixes and the ';' suffix. - */ - private String classNameAtCPIndex(int idx, boolean isRefClassArray[], int isArrayIdx) { - if (cpTags[idx] != CONSTANT_Utf8) { - throw classFileParseException("Constant pool entry " + idx + " should be UTF8 constant"); - } - boolean isArray = false; - if (cpObjectCache[idx] == null) { - int utf8Len = getChar(cpOffsets[idx]); - int stPos = cpOffsets[idx] + 2; - int initStPos = stPos; - while (buf[stPos] == '[') { - stPos++; - } - if (stPos != initStPos) { - isArray = true; - if (buf[stPos] == 'L') { - stPos++; - utf8Len--; // To get rid of the terminating ';' - } - } - utf8Len = utf8Len - (stPos - initStPos); - cpObjectCache[idx] = (new String(buf, stPos, utf8Len)).intern(); - if (isRefClassArray != null) { - isRefClassArray[isArrayIdx] = isArray; - } - } - return (String) cpObjectCache[idx]; - } - - // We replace all "Lclassname;" in signatures with "@classname#" to simplify signature parsing during reference checking - private String signatureAtCPIndex(int idx) { - if (cpTags[idx] != CONSTANT_Utf8) { - throw classFileParseException("Constant pool entry " + idx + " should be UTF8 constant"); - } - if (cpObjectCache[idx] == null) { - int utf8Len = getChar(cpOffsets[idx]); - byte tmp[] = new byte[utf8Len]; - System.arraycopy(buf, cpOffsets[idx] + 2, tmp, 0, utf8Len); - boolean inClassName = false; - for (int i = 0; i < utf8Len; i++) { - if (!inClassName) { - if (tmp[i] == 'L') { - tmp[i] = '@'; - inClassName = true; - } - } else if (tmp[i] == ';') { - tmp[i] = '#'; - inClassName = false; - } - } - cpObjectCache[idx] = (new String(tmp)).intern(); - } - return (String) cpObjectCache[idx]; - } - - private void badCPReference(int ofs, int i) { - throw classFileParseException("Bad constant pool reference: " + ofs + " from entry " + i); - } - - private void badCPEntry(int entryNo) { - throw classFileParseException("Constant pool entry " + entryNo + " : invalid type"); - } - - private PrivateException classFileParseException(String msg) { - return new PrivateException(new PublicExceptions.ClassFileParseException( - "Error reading class file " + fileFullPath + ":\n" + msg)); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/ClassInfo.java b/third_party/jmake/src/org/pantsbuild/jmake/ClassInfo.java deleted file mode 100644 index 9bfcd5a..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/ClassInfo.java +++ /dev/null
@@ -1,746 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.Serializable; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -/** - * A reflection of a class, in the form that allows fast checks and information obtaining. - * - * @author Misha Dmitriev - * 5 April 2004 - */ -@SuppressWarnings("serial") -public class ClassInfo implements Serializable { - - public static final int VER_OLD = 0; // Old version - public static final int VER_NEW = 1; // New version - public static final int NO_VERSIONS = 2; // Non-project class, no change tracking - private transient PCDManager pcdm; - transient int verCode; // Version code for this ClassInfo - one of the above. - String name = null; - transient String packageName; // Package name; restored when database is reloaded - int javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_OLDEST; // Can have values from Utils.JAVAC_TARGET_RELEASE_xxx - String cpoolRefsToClasses[]; // Directly referenced class names trimmed of array and 'L' prefixes and ';' suffixes - boolean isRefClassArray[]; // Indicates if a directly referenced class is actually an array class - // In all signatures we replace the 'L' and ';' symbols that enclose non-primitive type names with '@' and '#' respectively, - // so that class names inside signatures can be located fast and unambiguously. - String cpoolRefsToFieldClasses[]; // Defining classes of referenced fields, trimmed of enclosing 'L' and ';' symbols - String cpoolRefsToFieldNames[]; // Names of referenced fields - String cpoolRefsToFieldSignatures[]; // Signatures of referenced fields - String cpoolRefsToMethodClasses[]; // Defining classes of referenced methods, trimmed of enclosing 'L' and ';' symbols - String cpoolRefsToMethodNames[]; // Names of referenced methods - String cpoolRefsToMethodSignatures[]; // Signatures of referenced methods - char accessFlags; // isInterface flag included - boolean isNonMemberNestedClass = false; // True if this is a non-member nested class - String superName; - String interfaces[]; - String fieldNames[]; - String fieldSignatures[]; - char fieldAccessFlags[]; - Object primitiveConstantInitValues[]; - String methodNames[]; - String methodSignatures[]; - char methodAccessFlags[]; - String checkedExceptions[][]; - transient ClassInfo directSubclasses[]; // Direct subclasses. Created lazily and not preserved on disk. - transient String directlyEnclosingClass; // Directly enclosing class name; restored when database is reloaded - transient String topLevelEnclosingClass; // Top-level enclosing class name; restored when database is reloaded - String nestedClasses[]; // Names of all nested classes. Don't make transient - it's used to check - // if nested classes for this class were added/deleted in new version - transient char nestedClassAccessFlags[]; // No need to store this information permanently - transient boolean nestedClassNonMember[]; // Ditto - - /** Creates new ClassInfo out of a class file. The last parameter is needed only to produce sensible error reports.*/ - public ClassInfo(byte[] classFileBytes, int verCode, PCDManager pcdm, String classFileFullPath) { - this.pcdm = pcdm; - this.verCode = verCode; - pcdm.getClassFileReader().readClassFile(classFileBytes, this, classFileFullPath, true); - packageName = Utils.getPackageName(name); - directlyEnclosingClass = - Utils.getDirectlyEnclosingClass(name, this.javacTargetRelease); - topLevelEnclosingClass = Utils.getTopLevelEnclosingClass(name); - } - - /** - * Create a "lightweight" ClassInfo, that contains just the class name, super name, interfaces, flags and verCode. - * Used for non-project classes, that don't change themselves, for which we are only interested in type hierarchy structure. - */ - public ClassInfo(byte[] classFileBytes, PCDManager pcdm, String classFileFullPath) { - this.pcdm = pcdm; - this.verCode = NO_VERSIONS; - pcdm.getClassFileReader().readClassFile(classFileBytes, this, classFileFullPath, false); - packageName = Utils.getPackageName(name); - directlyEnclosingClass = - Utils.getDirectlyEnclosingClass(name, this.javacTargetRelease); - topLevelEnclosingClass = Utils.getTopLevelEnclosingClass(name); - } - - /** Even more lightweight variant - created for a deleted non-project class, to enable minimum possible checks. */ - public ClassInfo(String name, PCDManager pcdm) { - this.pcdm = pcdm; - this.verCode = NO_VERSIONS; - this.name = name; - packageName = Utils.getPackageName(name); - directlyEnclosingClass = Utils.getDirectlyEnclosingClass(name, 0); - topLevelEnclosingClass = Utils.getTopLevelEnclosingClass(name); - } - - public ClassInfo() { - } - - /** Initialize transient data that can be initialized immediately after this ClassInfo is read from the project database */ - public void initializeImmediateTransientFields() { - verCode = VER_OLD; - - packageName = Utils.getPackageName(name); - - directlyEnclosingClass = - Utils.getDirectlyEnclosingClass(name, this.javacTargetRelease); - topLevelEnclosingClass = Utils.getTopLevelEnclosingClass(name); - } - - /** - * Called to restore the pointer to the current PCDManager after this ClassInfo is brought back - * from the store. - */ - public void restorePCDM(PCDManager pcdm) { - this.pcdm = pcdm; - } - - public boolean isInterface() { - return Modifier.isInterface(accessFlags); - } - - public boolean isAbstract() { - return Modifier.isAbstract(accessFlags); - } - - public boolean isPublic() { - return Modifier.isPublic(accessFlags); - } - - /** - * Returns the names of the superclasses of the given class (transitively), that belong - * to the same project, plus those of the superclasses that can be found on the class path - * supplied to jmake, and on the boot class path. - */ - public List<String> getAllSuperclassNames() { - List<String> res = new ArrayList<String>(); - String superName = this.superName; - while (superName != null && !"java/lang/Object".equals(superName)) { - res.add(superName); - ClassInfo classInfo = pcdm.getClassInfoForName(verCode, superName); - if (classInfo == null) { // Class not in project (or deleted?). Try to find it and further superclasses in non-project classes - ClassPath.getSuperclasses(superName, res, pcdm); - break; - } - superName = classInfo.superName; - } - return res; - } - - /** - * Returns the set of names of the interfaces transitively implemented by the given - * class, that belong to the same project. - */ - public Set<String> getAllImplementedIntfNames() { - Set<String> res = new LinkedHashSet<String>(); - addImplementedInterfaceNames(false, res); - return res; - } - - /** Add to the given set the names of direct/all interfaces implemented by the given class. */ - private void addImplementedInterfaceNames(boolean directOnly, - Set<String> intfSet) { - if (interfaces != null) { - for (int i = 0; i < interfaces.length; i++) { - String superIntfName = interfaces[i]; - intfSet.add(superIntfName); - if (directOnly) { - continue; - } - ClassInfo superIntfInfo = - pcdm.getClassInfoForName(verCode, superIntfName); - if (superIntfInfo == null) { // Class not in project - ClassPath.addAllImplementedInterfaceNames(superIntfName, intfSet, pcdm); - } else { - superIntfInfo.addImplementedInterfaceNames(false, intfSet); - } - } - } - - if (directOnly || superName == null || - "java/lang/Object".equals(superName)) { - return; - } - ClassInfo superInfo = pcdm.getClassInfoForName(verCode, superName); - if (superInfo == null) { // Class not in project - ClassPath.addAllImplementedInterfaceNames(superName, intfSet, pcdm); - } else { - superInfo.addImplementedInterfaceNames(false, intfSet); - } - } - - /** Returns the array of all direct subclasses of this class (array of zero length if there are none). */ - public ClassInfo[] getDirectSubclasses() { - if (directSubclasses != null) { - return directSubclasses; - } - - List<ClassInfo> listRes = new ArrayList<ClassInfo>(); - - for (PCDEntry entry : pcdm.entries()) { - ClassInfo classInfo = pcdm.getClassInfoForPCDEntry(verCode, entry); - if (classInfo == null) { - continue; // New or deleted class, depending on verCode - } - if (classInfo.superName.equals(name)) { - listRes.add(classInfo); - } - } - - directSubclasses = listRes.toArray(new ClassInfo[listRes.size()]); - return directSubclasses; - } - - /** Check if the initial values for the given primitive constatnts in two classes are the same. */ - public static boolean constFieldInitValuesEqual(ClassInfo oldClassInfo, int oldFieldNo, - ClassInfo newClassInfo, int newFieldNo) { - Object oldInitValue = oldClassInfo.primitiveConstantInitValues == null ? null - : oldClassInfo.primitiveConstantInitValues[oldFieldNo]; - Object newInitValue = newClassInfo.primitiveConstantInitValues == null ? null - : newClassInfo.primitiveConstantInitValues[newFieldNo]; - if (oldInitValue == newInitValue) { - return true; - } - if (oldInitValue == null || newInitValue == null) { - return false; - } - - if (oldInitValue instanceof Integer) { - if (((Integer) oldInitValue).intValue() == ((Integer) newInitValue).intValue()) { - return true; - } else { - return false; - } - } else if (oldInitValue instanceof String) { - if ( ((String) oldInitValue).equals((String) newInitValue) ) { - return true; - } else { - return false; - } - } else if (oldInitValue instanceof Long) { - if (((Long) oldInitValue).longValue() == ((Long) newInitValue).longValue()) { - return true; - } else { - return false; - } - } else if (oldInitValue instanceof Float) { - if (((Float) oldInitValue).floatValue() == ((Float) newInitValue).floatValue()) { - return true; - } else { - return false; - } - } else if (oldInitValue instanceof Double) { - if (((Double) oldInitValue).doubleValue() == ((Double) newInitValue).doubleValue()) { - return true; - } else { - return false; - } - } - - return true; - } - - public boolean implementsInterfaceDirectly(String intfName) { - if (interfaces == null) { - return false; - } - for (int i = 0; i < interfaces.length; i++) { - if (intfName.equals(interfaces[i])) { - return true; - } - } - return false; - } - - /** Check if this class implements interface I or any subinterface of I directly */ - public boolean implementsIntfOrSubintfDirectly(String intfName) { - if (interfaces == null) { - return false; - } - for (int i = 0; i < interfaces.length; i++) { - if (intfName.equals(interfaces[i])) { - return true; - } - // An interface can have multiple superinterfaces, all of which are listed in its "interfaces" array - // (although in the .java source it "extends" them all). - ClassInfo superIntfInfo = - pcdm.getClassInfoForName(verCode, interfaces[i]); - if (superIntfInfo == null) { - continue; // Class not in project - } - if (superIntfInfo.implementsIntfOrSubintfDirectly(intfName)) { - return true; - } - } - return false; - } - - /** - * Class C implements interface I indirectly, if C or some superclass of C directly implements I - * or some subinterface of I. - */ - public boolean implementsInterfaceDirectlyOrIndirectly(String intfName) { - if (interfaces == null) { - return false; - } - - if (implementsIntfOrSubintfDirectly(intfName)) { - return true; - } - - if (superName != null) { - ClassInfo superInfo = pcdm.getClassInfoForName(verCode, superName); - if (superInfo == null) { - return false; // Class not in project - } - return superInfo.implementsInterfaceDirectlyOrIndirectly(intfName); - } - - return false; - } - - /** - * Returns true if this class declares a field with the same name and type as - * the field number fieldNo in class classInfo. - */ - public boolean declaresField(ClassInfo classInfo, int fieldNo) { - if (fieldNames == null) { - return false; - } - String fieldName = classInfo.fieldNames[fieldNo]; - String fieldSignature = classInfo.fieldSignatures[fieldNo]; - - for (int i = 0; i < fieldNames.length; i++) { - if (fieldName.equals(fieldNames[i]) && - fieldSignature.equals(fieldSignatures[i])) { - return true; - } - } - return false; - } - - /** Returns true if this class declares a field with the given name, signature and access */ - public boolean declaresField(String name, String signature, boolean isStatic) { - if (fieldNames == null) { - return false; - } - signature = ("@" + signature + "#").intern(); - for (int i = 0; i < fieldNames.length; i++) { - if (name.equals(fieldNames[i]) && - signature.equals(fieldSignatures[i]) && - Modifier.isStatic(fieldAccessFlags[i]) == isStatic) { - return true; - } - } - return false; - } - - /** - * Returns true if this class declares a method with the same name and signature as - * the method number methodNo in class classInfo. - */ - public boolean declaresMethod(ClassInfo classInfo, int methodNo) { - if (methodNames == null) { - return false; - } - String methodName = classInfo.methodNames[methodNo]; - String methodSignature = classInfo.methodSignatures[methodNo]; - - for (int i = 0; i < methodNames.length; i++) { - if (methodName.equals(methodNames[i]) && - methodSignature.equals(methodSignatures[i])) { - return true; - } - } - return false; - } - - /** - * If this class declares a method with the same name and signature as the given method, - * return its position. Otherwise, return -1. - */ - public int getDeclaredMethodPos(ClassInfo classInfo, int methodNo) { - if (methodNames == null) { - return -1; - } - String methodName = classInfo.methodNames[methodNo]; - String methodSignature = classInfo.methodSignatures[methodNo]; - - for (int i = 0; i < methodNames.length; i++) { - if (methodName.equals(methodNames[i]) && - methodSignature.equals(methodSignatures[i])) { - return i; - } - } - return -1; - } - - /** - * Returns a nonnegative number (position in the method array) if this class declares a method with the - * name methodName, and -1 otherwise. - */ - public int declaresSameNameMethod(String methodName) { - if (methodNames == null) { - return -1; - } - for (int j = 0; j < methodNames.length; j++) { - if (methodName.equals(methodNames[j])) { - return j; - } - } - return -1; - } - - /** - * Check if this class references the given class in different ways, depending on thorDegree parameter. - * thorDegree = 0: the given class (but not its array class) directly from the constantpool. - * - * thorDegree = 1: the given class or its array class directly from the constantpool, as a - * type of a data field, as a type in a method signature or a thrown exception, as a directly - * implemented interface or a direct superclass - * - * thorDegree = 2: the given class or its array class directly or indirectly from the - * constantpool, as a type of a data field, as a type in a method signature or a thrown exception, - * as a directly/indirectly implemented interface or a direct/indirect superclass. - * - * isRefTypeInterface indicates whether className is an interface. - */ - public boolean referencesClass(String className, boolean isRefTypeInterface, int thorDegree) { - int i; - - if (thorDegree == 0) { - if (cpoolRefsToClasses == null) { - return false; - } - for (i = 0; i < cpoolRefsToClasses.length; i++) { - if (!isRefClassArray[i] && - className.equals(cpoolRefsToClasses[i])) { - return true; - } - } - } else { - if (isSubclassOf(className, (thorDegree == 1))) { - return true; - } - if (isRefTypeInterface) { - if (thorDegree == 1) { - if (implementsInterfaceDirectly(className)) { - return true; - } - } else { - // Check for indirectly implemented interfaces - if (implementsInterfaceDirectlyOrIndirectly(className)) { - return true; - } - } - } - - if (cpoolRefsToClasses != null) { - for (i = 0; i < cpoolRefsToClasses.length; i++) { - if (className.equals(cpoolRefsToClasses[i])) { - return true; - } - } - } - if (thorDegree == 2) { - // Check for indirect references from the constantpool - if (cpoolRefsToFieldSignatures != null) { - for (i = 0; i < cpoolRefsToFieldSignatures.length; i++) { - if (signatureIncludesClassName(cpoolRefsToFieldSignatures[i], className)) { - return true; - } - } - } - if (cpoolRefsToMethodNames != null) { - for (i = 0; i < cpoolRefsToMethodSignatures.length; i++) { - if (signatureIncludesClassName(cpoolRefsToMethodSignatures[i], className)) { - return true; - } - } - } - } - - if (fieldSignatures != null) { - for (i = 0; i < fieldSignatures.length; i++) { - if (signatureIncludesClassName(fieldSignatures[i], className)) { - return true; - } - } - } - if (methodSignatures != null) { - for (i = 0; i < methodSignatures.length; i++) { - if (signatureIncludesClassName(methodSignatures[i], className)) { - return true; - } - } - } - if (checkedExceptions != null) { - for (i = 0; i < checkedExceptions.length; i++) { - if (checkedExceptions[i] != null) { - String excArray[] = checkedExceptions[i]; - for (int j = 0; j < excArray.length; j++) { - if (className.equals(excArray[j])) { - return true; - } - } - } - } - } - } - - return false; - } - - private static boolean signatureIncludesClassName(String signature, String className) { - int stIndex = signature.indexOf(className); - if (stIndex == -1) { - return false; - } - return ((stIndex != 0 && signature.charAt(stIndex - 1) == '@' && signature.charAt(stIndex + className.length()) == '#') || - (stIndex == 0 && signature.length() == className.length())); - } - - public boolean isSubclassOf(String className, boolean directOnly) { - if (className.equals(superName)) { - return true; - } - if (directOnly) { - return false; - } - String superName = this.superName; - while (superName != null) { - if (className.equals(superName)) { - return true; - } - ClassInfo classInfo = pcdm.getClassInfoForName(verCode, superName); - if (classInfo == null) { - break; // Class not in project - } - superName = classInfo.superName; - } - return false; - } - - /** - * Check if this class references field number fieldNo of class fieldDefClassInfo. Let us call - * this field C.f. Actual reference contained in the constant pool may be not to C.f itself, - * but to Csub.f, where Csub is some subclass of C such that neither Csub nor any other class - * located between C and Csub in the class hierarchy redeclares f. We look up both "real" - * references C.f and "fake" references such as Csub.f. - */ - public boolean referencesField(ClassInfo fieldDefClassInfo, int fieldNo) { - if (cpoolRefsToFieldNames == null) { - return false; - } - String fieldDefClassName = fieldDefClassInfo.name; - String fieldName = fieldDefClassInfo.fieldNames[fieldNo]; - String fieldSig = fieldDefClassInfo.fieldSignatures[fieldNo]; - for (int i = 0; i < cpoolRefsToFieldNames.length; i++) { - if (fieldName.equals(cpoolRefsToFieldNames[i]) && - fieldSig.equals(cpoolRefsToFieldSignatures[i]) ) { - if (fieldDefClassName.equals(cpoolRefsToFieldClasses[i]) ) { - return true; // "real" reference - } else { // Check if this is a "fake" reference that resolves to the above "real" reference - ClassInfo classInThisCpool = - pcdm.getClassInfoForName(verCode, cpoolRefsToFieldClasses[i]); - if (classInThisCpool == null) { - continue; // Class not in project - } - if (!classInThisCpool.isSubclassOf(fieldDefClassInfo.name, false)) { - continue; - } - - // Ok, now check that this field is not actually redeclared in fieldDefClassInfo or - // somewhere in between it and classInThisCpool - boolean redeclared = false; - ClassInfo curClass = classInThisCpool; - do { - if (curClass.declaresField(fieldDefClassInfo, fieldNo)) { - redeclared = true; - break; - } - String superName = curClass.superName; - curClass = pcdm.getClassInfoForName(verCode, superName); - if (curClass == null) { - break; - } - } while (curClass != fieldDefClassInfo); - if (!redeclared) { - return true; - } - } - } - } - return false; - } - - /** - * Check if this class references method number methodNo of class methodDefClassInfo. Let us - * call this method C.m. Actual reference contained in the constant pool may be not to C.m - * itself, but to Csub.m, where Csub is some subclass of C such that neither Csub nor any - * other class located between C and Csub in the class hierarchy redeclares m. We look up - * both "real" references C.m and "fake" references such as Csub.m. - */ - public boolean referencesMethod(ClassInfo methodDefClassInfo, int methodNo) { - if (cpoolRefsToMethodNames == null) { - return false; - } - String methodDefClassName = methodDefClassInfo.name; - String methodName = methodDefClassInfo.methodNames[methodNo]; - String methodSig = methodDefClassInfo.methodSignatures[methodNo]; - for (int i = 0; i < cpoolRefsToMethodNames.length; i++) { - if (methodName.equals(cpoolRefsToMethodNames[i]) && - methodSig.equals(cpoolRefsToMethodSignatures[i])) { - if (methodDefClassName.equals(cpoolRefsToMethodClasses[i])) { - return true; // "real" reference - } else { // Check if this is a "fake" reference that resolves to the above "real" reference - // Be careful - class in the cpool may be not a project class (e.g. a core class). - ClassInfo classInThisCpool = - pcdm.getClassInfoForName(verCode, cpoolRefsToMethodClasses[i]); - if (classInThisCpool == null) { - continue; // Class not in project - } - if (classInThisCpool.isSubclassOf(methodDefClassInfo.name, false)) { - // Ok, now check that this method is not actually redeclared in classInThisCpool (which is - // lower in the hierarchy) or somewhere in between it and classInThisCpool - boolean redeclared = false; - ClassInfo curClass = classInThisCpool; - do { - if (curClass.declaresMethod(methodDefClassInfo, methodNo)) { - redeclared = true; - break; - } - String superName = curClass.superName; - curClass = - pcdm.getClassInfoForName(verCode, superName); - if (curClass == null) { - break; - } - } while (curClass != methodDefClassInfo); - if (!redeclared) { - return true; - } - } else if (methodDefClassInfo.isInterface() && classInThisCpool.implementsIntfOrSubintfDirectly(methodDefClassName)) { - return true; - } - } - } - } - return false; - } - - /** - * If this class has a method that throws the given exception, return its index. Otherwise return -1. - * The search starts from method with index startMethodIdx. - */ - public int hasMethodThrowingException(ClassInfo excClassInfo, int startMethodIdx) { - if (checkedExceptions == null) { - return -1; - } - if (startMethodIdx >= checkedExceptions.length) { - return -1; - } - String excName = excClassInfo.name; - for (int i = startMethodIdx; i < checkedExceptions.length; i++) { - if (checkedExceptions[i] == null) { - continue; - } - String[] exc = checkedExceptions[i]; - for (int j = 0; j < exc.length; j++) { - if (exc[j].equals(excName)) { - return i; - } - } - } - return -1; - } - - public static abstract class MethodHandler { - - abstract void handleMethod(ClassInfo ci, int methodIdx); - } - - /** - * Check this class and all its superclasses (if includeSuperclasses == true) and superinterfaces (if includeInterfaces == true) - * for a method with the given name. If such a method is found, call h.handleMethod(classInfo, methodIdx). - */ - public void findExistingSameNameMethods(String methodName, boolean includeSuperclasses, boolean includeInterfaces, MethodHandler h) { - String className = name; - ClassInfo classInfo; - while (className != null) { - classInfo = pcdm.getClassInfoForName(verCode, className); - if (classInfo == null) { - break; // Class not in project - } - String mNames[] = classInfo.methodNames; - int mNamesLen = mNames != null ? mNames.length : 0; - for (int i = 0; i < mNamesLen; i++) { - if (methodName.equals(mNames[i])) { - h.handleMethod(classInfo, i); - } - } - if (includeInterfaces && classInfo.interfaces != null) { - String intfNames[] = classInfo.interfaces; - for (int i = 0; i < intfNames.length; i++) { - ClassInfo superIntfInfo = - pcdm.getClassInfoForName(verCode, intfNames[i]); - if (superIntfInfo == null) { - continue; // Class not in project - } - superIntfInfo.findExistingSameNameMethods(methodName, true, includeInterfaces, h); - } - } - if (includeSuperclasses) { - className = classInfo.superName; - } else { - return; - } - } - } - - public static boolean isPrimitiveFieldSig(String fieldSig) { - return fieldSig.indexOf('@') == -1; - } - - /** - * Check if the given signature is of a class type, and that class does not belong to the project. - * It used to be a check for just a core type name, but sometimes people use JDK sources as e.g. a test - * case - so better perform a universal (and entirely correct, unlike just a core type name) test here. - */ - public boolean isNonProjectClassTypeFieldSig(String fieldSig) { - int stPos = fieldSig.indexOf('@'); - if (stPos == -1) { - return false; - } - int endPos = fieldSig.indexOf('#'); - String className = fieldSig.substring(stPos + 1, endPos); - return (!pcdm.isProjectClass(verCode, className)); - } - - /** For debugging. */ - public String toString() { - return name + (verCode == VER_OLD ? " OLD" : " NEW"); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/ClassPath.java b/third_party/jmake/src/org/pantsbuild/jmake/ClassPath.java deleted file mode 100644 index e6e1aebd..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/ClassPath.java +++ /dev/null
@@ -1,448 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * An instance of this class represents a class path, on which binary classes can be looked up. - * It also provides several static methods to create and utilize several specific class paths used - * throughout jmake. - * - * @author Misha Dmitriev - * 12 October 2004 - */ -public class ClassPath { - - private PathEntry[] paths; - private static ClassPath projectClassPath; // Class path (currently it can contain only JARs) containing sourceless project classes. - // See also the comment to standardClassPath. - private static ClassPath standardClassPath; // Class path that the user specifies via the -classpath option. A sum of the - // standardClassPath, the projectClassPath, and the virtualPath is passed to the compiler. Each of these - // class paths are also used to look up non-project superclasses/superinterfaces of - // project classes. - private static ClassPath bootClassPath, extClassPath; // Class paths that by default are sun.boot.class.path and all JARs on - // java.ext.class.path, respectively. They are used to look up non-project - // superclasses/superinterfaces of project classes. Their values can be changed using - // setBootClassPath() and setExtDirs(). - private static ClassPath virtualPath; // Class path that the user specifies via the -vpath option. - private static String compilerUserClassPath; // Class path to be passed to the compiler; equals to the sum of values of parameters of - // setClassPath() and setProjectClassPath() methods. - private static String standardClassPathStr, projectClassPathStr, bootClassPathStr, extDirsStr, - virtualPathStr; - private static Map<String,ClassInfo> classCache; - - - static { - resetOnFinish(); - } - - /** - * Needed since some environments, e.g. NetBeans, can keep jmake classes in memory - * permanently. Thus unchanged class paths from previous, possibly unrelated invocations - * of jmake, may interfere with the current settings. - */ - public static void resetOnFinish() { - projectClassPath = standardClassPath = bootClassPath = extClassPath = virtualPath = - null; - compilerUserClassPath = null; - standardClassPathStr = projectClassPathStr = bootClassPathStr = - extDirsStr = virtualPathStr = null; - classCache = new LinkedHashMap<String,ClassInfo>(); - } - - public static void setClassPath(String value) throws PublicExceptions.InvalidCmdOptionException { - standardClassPathStr = value; - standardClassPath = new ClassPath(value, false); - } - - public static void setProjectClassPath(String value) throws PublicExceptions.InvalidCmdOptionException { - projectClassPathStr = value; - projectClassPath = new ClassPath(value, true); - } - - public static void setBootClassPath(String value) throws PublicExceptions.InvalidCmdOptionException { - bootClassPathStr = value; - bootClassPath = new ClassPath(value, false); - } - - public static void setExtDirs(String value) throws PublicExceptions.InvalidCmdOptionException { - extDirsStr = value; - // Extension class path needs special handling, since it consists of directories, which contain .jars - // So we need to find all these .jars in all these dirs and add them to extClassPathElementList - List<String> extClassPathElements = new ArrayList<String>(); - for (StringTokenizer tok = - new StringTokenizer(value, File.pathSeparator); tok.hasMoreTokens();) { - File extDir = new File(tok.nextToken()); - String[] extJars = extDir.list(new FilenameFilter() { - - public boolean accept(File dir, String name) { - name = name.toLowerCase(Locale.ENGLISH); - return name.endsWith(".zip") || name.endsWith(".jar"); - } - }); - if (extJars == null) { - continue; - } - for (int i = 0; i < extJars.length; i++) { - extClassPathElements.add(extDir + File.separator + extJars[i]); - } - } - extClassPath = new ClassPath(extClassPathElements, false); - } - - public static void setVirtualPath(String value) throws PublicExceptions.InvalidCmdOptionException { - if (value == null) { - throw new PublicExceptions.InvalidCmdOptionException("null argument"); - } - StringTokenizer st = new StringTokenizer(value, File.pathSeparator); - while (st.hasMoreElements()) { - String dir = st.nextToken(); - if ( ! (new File(dir)).isDirectory()) { - throw new PublicExceptions.InvalidCmdOptionException("Virtual path must contain only directories." + - " Entry " + dir + " is not a directory."); - } - } - virtualPathStr = value; - virtualPath = new ClassPath(value, false); - } - - public static void initializeAllClassPaths() { - // First set the compiler class path value - if (standardClassPathStr == null && projectClassPathStr == null) { - compilerUserClassPath = "."; - } else if (standardClassPathStr == null) { - compilerUserClassPath = projectClassPathStr; - } else if (projectClassPathStr == null) { - compilerUserClassPath = standardClassPathStr; - } else { - compilerUserClassPath = - standardClassPathStr + File.pathSeparator + projectClassPathStr; - } - - if (virtualPathStr != null) { - compilerUserClassPath += File.pathSeparator + virtualPathStr; - } - - if (standardClassPathStr == null) { - try { - String tmp = "."; - if (virtualPathStr != null) { - tmp += File.pathSeparator + virtualPathStr; - } - standardClassPath = new ClassPath(tmp, false); - } catch (PublicExceptions.InvalidCmdOptionException ex) { /* Should not happen */ } - } - if (projectClassPathStr == null) { - projectClassPath = new ClassPath(); - } - - // Create the core class path as a combination of sun.boot.class.path and java.ext.dirs contents - if (bootClassPathStr == null) { - try { - bootClassPath = - new ClassPath(System.getProperty("sun.boot.class.path"), false); - } catch (PublicExceptions.InvalidCmdOptionException ex) { /* Shouldn't happen */ } - // bootClassPathStr should remain null, so that nothing that the user didn't specify is passed to the compiler - } - - if (extDirsStr == null) { - try { - setExtDirs(System.getProperty("java.ext.dirs")); - } catch (PublicExceptions.InvalidCmdOptionException ex) { /* Shouldn't happen */ } - // extDirsStr should remain null, so that nothing that the user didn't specify is passed to the compiler - extDirsStr = null; - } - } - - /** Never returns null - if classpath wasn't set explicitly, returns "." */ - public static String getCompilerUserClassPath() { - return compilerUserClassPath; - } - - /** Will return null if boot class path wasn't explicitly specified */ - public static String getCompilerBootClassPath() { - return bootClassPathStr; - } - - /** Will return null if extdirs weren't explicitly specified */ - public static String getCompilerExtDirs() { - return extDirsStr; - } - - /** Will return null if virtualPath wasn't explicitly specified */ - public static String getVirtualPath() { - return virtualPathStr; - } - - /** - * For the given class return the list of all of its superclasses (excluding Object), that can be loaded from - * projectClassPath or standardClassPath, plus the first superclass that can be loaded from coreClassPath. - * The latter is an optimization based on the assumption that core classes never change, or rather the programmer - * will recompile everything when they switch to a new JDK version. The optimization prevents us from wasting time - * repeatedly loading the same sets of core classes. - */ - public static void getSuperclasses(String className, - Collection<String> res, PCDManager pcdm) { - int iterNo = 0; - while (!"java/lang/Object".equals(className)) { - ClassInfo ci = getClassInfoForName(className, pcdm); - if (ci == null) { - return; - } - if (iterNo++ > 0) { - res.add(ci.name); - } - className = ci.superName; - } - } - - /** - * Add to the given set the names of all interfaces implemented by the given class, that can be loaded from - * projectClassPath or standardClassPath, plus the first interface on each branch that can be loaded from - * coreClassPath. It's the same optimization as in getSuperclasses(). - */ - public static void addAllImplementedInterfaceNames(String className, - Set<String> intfSet, PCDManager pcdm) { - if ("java/lang/Object".equals(className)) { - return; - } - ClassInfo ci = getClassInfoForName(className, pcdm); - if (ci == null) { - return; - } - String[] interfaces = ci.interfaces; - if (interfaces != null) { - for (int i = 0; i < interfaces.length; i++) { - intfSet.add(interfaces[i]); - addAllImplementedInterfaceNames(interfaces[i], intfSet, pcdm); - } - } - - String superName = ci.superName; - if (superName != null) { - addAllImplementedInterfaceNames(superName, intfSet, pcdm); - } - } - - public static String[] getProjectJars() { - if (projectClassPath == null || projectClassPath.isEmpty()) { - return null; - } - PathEntry paths[] = projectClassPath.paths; - String[] ret = new String[paths.length]; - for (int i = 0; i < paths.length; i++) { - ret[i] = paths[i].toString(); - } - return ret; - } - - public static ClassInfo getClassInfoForName(String className, PCDManager pcdm) { - ClassInfo info = classCache.get(className); - if (info != null) { - return info; - } - - byte buf[] = bootClassPath.getBytesForClass(className); - if (buf == null) { - buf = extClassPath.getBytesForClass(className); - } - if (buf == null) { - buf = standardClassPath.getBytesForClass(className); - } - if (buf == null) { - buf = projectClassPath.getBytesForClass(className); - } - if (buf == null) { - return null; - } - - info = new ClassInfo(buf, pcdm, className); - classCache.put(className, info); - return info; - } - - /** Returns the class loader that would load classes from the given class path. */ - public static ClassLoader getClassLoaderForPath(String classPath) throws Exception { - boolean isWindows = System.getProperty("os.name").startsWith("Win"); - ClassPath cp = new ClassPath(classPath, false); - PathEntry[] paths = cp.paths; - URL[] urls = new URL[paths.length]; - for (int i = 0; i < paths.length; i++) { - String dirOrJar = paths[i].toString(); - if (!(dirOrJar.startsWith("file://") || dirOrJar.startsWith("http://"))) { - // On Windows, if I have path specified as "file://c:\...", (i.e. with the drive name) URLClassLoader works - // unbelievably slow. However, if an additional slash is added, like : "file:///c:\...", the speed becomes - // normal. To me it looks like a bug, but, anyway, I am taking measure here. - if (isWindows && dirOrJar.charAt(1) == ':') { - dirOrJar = "/" + dirOrJar; - } - dirOrJar = new File(dirOrJar).toURI().toString(); - } - if (!(dirOrJar.endsWith(".jar") || dirOrJar.endsWith(".zip") || dirOrJar.endsWith(File.separator))) { - dirOrJar += File.separator; // So that URLClassLoader correctly handles it as a directory - } - urls[i] = new URL(dirOrJar); - } - - return new URLClassLoader(urls); - //} catch (java.net.MalformedURLException e) { - - //} - } - - - // ------------------------------------ Private implementation -------------------------------------------- - private ClassPath() { - paths = new PathEntry[0]; - } - - private ClassPath(String classPath, boolean isJarOnly) throws PublicExceptions.InvalidCmdOptionException { - if (classPath == null) { - throw new PublicExceptions.InvalidCmdOptionException("null argument"); - } - List<String> vec = new ArrayList<String>(); - - for (StringTokenizer tok = - new StringTokenizer(classPath, File.pathSeparator); tok.hasMoreTokens();) { - String path = tok.nextToken(); - vec.add(path); - } - init(vec, isJarOnly); - } - - private ClassPath(List<String> pathEntries, boolean isJarOnly) throws PublicExceptions.InvalidCmdOptionException { - init(pathEntries, isJarOnly); - } - - private void init(List<String> pathEntries, boolean isJarOnly) throws PublicExceptions.InvalidCmdOptionException { - if (pathEntries == null) { - throw new PublicExceptions.InvalidCmdOptionException("null argument"); - } - List<PathEntry> vec = new ArrayList<PathEntry>(pathEntries.size()); - for (int i = 0; i < pathEntries.size(); i++) { - String path = pathEntries.get(i); - if (!path.equals("")) { - File file = new File(path); - try { - if (file.exists() && file.canRead()) { - if (file.isDirectory()) { - if (isJarOnly) { - throw new PublicExceptions.InvalidCmdOptionException("directories are not allowed on this class path: " + path); - } - vec.add(new Dir(file)); - } else { - vec.add(new Zip(new ZipFile(file))); - } - } else if (isJarOnly) { - throw new IOException("file does not exist"); - } - } catch (IOException e) { - if (isJarOnly) { - throw new PublicExceptions.InvalidCmdOptionException("error initializing class path component " + path + ": " + e.getMessage()); - } - } - } - } - - paths = new PathEntry[vec.size()]; - vec.toArray(paths); - } - - private boolean isEmpty() { - return paths.length == 0; - } - - private byte[] getBytesForClass(String className) { - String fileName = className + ".class"; - for (int i = 0; i < paths.length; i++) { - byte buf[] = paths[i].getBytesForClassFile(fileName); - if (buf != null) { - return buf; - } - } - return null; - } - - public String toString() { - if (paths == null) { - return "NULL"; - } - StringBuilder res = new StringBuilder(); - for (int i = 0; i < paths.length; i++) { - res.append(paths[i].toString()); - } - return res.toString(); - } - - - // ------------------------------------ Private helper classes -------------------------------------------- - private static abstract class PathEntry { - - abstract byte[] getBytesForClassFile(String fileName); - - public abstract String toString(); - } - - private static class Dir extends PathEntry { - - private String dir; - - Dir(File f) throws IOException { - dir = f.getCanonicalPath(); - } - - byte[] getBytesForClassFile(String fileName) { - File file = new File(dir + File.separatorChar + fileName); - if (file.exists()) { - return Utils.readFileIntoBuffer(file); - } else { - return null; - } - } - - public String toString() { - return dir; - } - } - - private static class Zip extends PathEntry { - - private ZipFile zip; - - Zip(ZipFile z) { - zip = z; - } - - byte[] getBytesForClassFile(String fileName) { - ZipEntry entry = zip.getEntry(fileName); - if (entry != null) { - return Utils.readZipEntryIntoBuffer(zip, entry); - } else { - return null; - } - } - - public String toString() { - return zip.getName(); - } - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/CompatibilityChecker.java b/third_party/jmake/src/org/pantsbuild/jmake/CompatibilityChecker.java deleted file mode 100644 index bd74cfb3..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/CompatibilityChecker.java +++ /dev/null
@@ -1,610 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.lang.reflect.Modifier; -import java.util.List; -import java.util.Set; - -/** - * This class implements checking of source compatibility of classes and supporting operations - * - * @author Misha Dmitriev - * 12 March 2004 - */ -public class CompatibilityChecker { - - private PCDManager pcdm; - private RefClassFinder rf; - ClassInfo oldClassInfo = null; - ClassInfo newClassInfo = null; - private boolean versionsCompatible; - private boolean publicConstantChanged; - - public CompatibilityChecker(PCDManager pcdm, boolean failOnDependentJar, boolean noWarnOnDependentJar) { - this.pcdm = pcdm; - publicConstantChanged = false; - rf = new RefClassFinder(pcdm, failOnDependentJar, noWarnOnDependentJar); - } - - /** - * Compares the two class versions for the given PCDEntry. Returns true if all changes are source - * compatible, and false otherwise. - */ - public boolean compareClassVersions(PCDEntry entry) { - // I once had the following optimization here with the comment "No sense to make any further checks if - // everything is recompiled anyway", but now I believe it's wrong. For each class that was found changed - // we need to know whether the new version is compatible with the old or not, since this may determine - // whether the new version of this class is promoted into the pdb or not (see PCDManager.updateClassInfoInPCD()). - // So, all changed classes should be checked just to correctly determine version compatibility. - // if (publicConstantChanged) return false; - - oldClassInfo = pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, entry); - newClassInfo = pcdm.getClassInfoForPCDEntry(ClassInfo.VER_NEW, entry); - - rf.initialize(oldClassInfo.name, entry.javaFileFullPath.endsWith(".jar")); - versionsCompatible = true; - - checkAccessFlags(); - checkSuperclasses(); - checkImplementedInterfaces(); - checkFields(); - checkMethodsAndConstructors(); - - return versionsCompatible; - } - - /** Find all dependent classes for a deleted class. */ - public void checkDeletedClass(PCDEntry entry) { - oldClassInfo = entry.oldClassInfo; - rf.initialize(oldClassInfo.name, entry.javaFileFullPath.endsWith(".jar")); - rf.findReferencingClassesForDeletedClass(oldClassInfo); - // It may happen that the only reference to deleted class X is via "X.class" construct - String packageToLookIn = - oldClassInfo.isPublic() ? null : oldClassInfo.packageName; - rf.findClassesDeclaringField(("class$" + oldClassInfo.name).intern(), "java/lang/Class", true, packageToLookIn); - checkForFinalFields(); - } - - /** Returns the names of classes affected by source incompatible changes to the new version of the checked class. */ - public String[] getAffectedClasses() { - return rf.getAffectedClassNames(); - } - - /** All of the following methods return true if no source incompatible changes found, and false otherwise */ - private void checkAccessFlags() { - char oldClassFlags = oldClassInfo.accessFlags; - char newClassFlags = newClassInfo.accessFlags; - if (oldClassFlags == newClassFlags) { - return; - } - - if (!Modifier.isFinal(oldClassFlags) && Modifier.isFinal(newClassFlags)) { - versionsCompatible = false; - rf.findDirectSubclasses(oldClassInfo); - } - - if (!Modifier.isAbstract(oldClassFlags) && Modifier.isAbstract(newClassFlags)) { - versionsCompatible = false; - rf.findReferencingClasses0(oldClassInfo); - } - - // Now to accessibility modifiers checking... - if (Modifier.isPublic(newClassFlags)) { - return; - } - - if (Modifier.isProtected(newClassFlags)) { - if (Modifier.isPublic(oldClassFlags)) { - versionsCompatible = false; - rf.findDiffPackageAndNotSubReferencingClasses1(oldClassInfo); - } - } else if (Modifier.isPrivate(newClassFlags)) { - if (!Modifier.isPrivate(oldClassFlags)) { - versionsCompatible = false; - } else { - return; // private -> private, nothing more to check - } - if (Modifier.isPublic(oldClassFlags)) { - rf.findReferencingClasses1(oldClassInfo); - } else if (Modifier.isProtected(oldClassFlags)) { - rf.findThisPackageOrSubReferencingClasses1(oldClassInfo); - } else { - rf.findThisPackageReferencingClasses1(oldClassInfo); - } - } else { // newClassFlags has default access, since public has already been excluded - if (Modifier.isPublic(oldClassFlags)) { - versionsCompatible = false; - rf.findDiffPackageReferencingClasses1(oldClassInfo); - } else if (Modifier.isProtected(oldClassFlags)) { - versionsCompatible = false; - rf.findDiffPackageAndSubReferencingClasses1(oldClassInfo); - } - } - } - - private void checkSuperclasses() { - List<String> oldSuperNames = oldClassInfo.getAllSuperclassNames(); - List<String> newSuperNames = newClassInfo.getAllSuperclassNames(); - - int oldNamesSizeMinusOne = oldSuperNames.size() - 1; - for (int i = 0; i <= oldNamesSizeMinusOne; i++) { - String oldSuperName = oldSuperNames.get(i); - if (!newSuperNames.contains(oldSuperName)) { - versionsCompatible = false; - ClassInfo missingSuperClass = - pcdm.getClassInfoForName(ClassInfo.VER_OLD, oldSuperName); - if (missingSuperClass == null) { // This class is not in project - missingSuperClass = - ClassPath.getClassInfoForName(oldSuperName, pcdm); - if (missingSuperClass == null) { - missingSuperClass = new ClassInfo(oldSuperName, pcdm); - } - } - rf.findReferencingClasses2(missingSuperClass, oldClassInfo); - } - } - - // Now check if the class is an exception, and its kind has changed from unchecked to checked - if (oldClassInfo.isInterface() || oldSuperNames.size() == 0) { - return; - } - if (!(oldSuperNames.contains("java/lang/RuntimeException") || oldSuperNames.contains("java/lang/Error"))) { - return; - } - if (!(newSuperNames.contains("java/lang/RuntimeException") || newSuperNames.contains("java/lang/Error"))) { - if (!newSuperNames.contains("java/lang/Throwable")) { - return; - } - // Ok, exception kind has changed from unchecked to checked. - versionsCompatible = false; - rf.findReferencingClasses0(oldClassInfo); - rf.findRefsToMethodsThrowingException(oldClassInfo); - } - } - - private void checkImplementedInterfaces() { - Set<String> oldIntfNames = oldClassInfo.getAllImplementedIntfNames(); - Set<String> newIntfNames = newClassInfo.getAllImplementedIntfNames(); - - for (String oldIntfName : oldIntfNames) { - if (!newIntfNames.contains(oldIntfName)) { - versionsCompatible = false; - ClassInfo missingSuperInterface = - pcdm.getClassInfoForName(ClassInfo.VER_OLD, oldIntfName); - if (missingSuperInterface == null) { // This class is not in project - missingSuperInterface = - ClassPath.getClassInfoForName(oldIntfName, pcdm); - if (missingSuperInterface == null) { - missingSuperInterface = new ClassInfo(oldIntfName, pcdm); - } - } - rf.findReferencingClasses2(missingSuperInterface, oldClassInfo); - } - } - - // Check if the class is abstract, and an interface has been added to its list of implemented interfaces - if (newClassInfo.isAbstract()) { - for (String newIntfName : newIntfNames) { - if (!oldIntfNames.contains(newIntfName)) { - versionsCompatible = false; - rf.findConcreteSubclasses(oldClassInfo); - break; - } - } - } - } - - private void checkFields() { - String oFNames[] = oldClassInfo.fieldNames; - String oFSignatures[] = oldClassInfo.fieldSignatures; - char oFFlags[] = oldClassInfo.fieldAccessFlags; - String nFNames[] = newClassInfo.fieldNames; - String nFSignatures[] = newClassInfo.fieldSignatures; - char nFFlags[] = newClassInfo.fieldAccessFlags; - int oFLen = oFNames != null ? oFNames.length : 0; - int nFLen = nFNames != null ? nFNames.length : 0; - - int oFMod, nFMod; - String oFName, oFSig, nFName; - int i, j, k, endIdx; - int nonMatchingNewFields = nFLen; - - for (i = 0; i < oFLen; i++) { - oFMod = oFFlags[i]; - if (Modifier.isPrivate(oFMod)) { - continue; // Changes to private fields don't affect compatibility - } - oFName = oFNames[i]; - oFSig = oFSignatures[i]; - boolean found = false; - - // Look for the same field in the new version considering name and type - endIdx = nFLen - 1; - k = i < nFLen ? i : endIdx; - for (j = 0; j < nFLen; j++) { - if (oFName.equals(nFNames[k]) && - oFSig.equals(nFSignatures[k])) { - found = true; - break; - } - if (k < endIdx) { - k++; - } else { - k = 0; - } - } - - if (found) { - nonMatchingNewFields--; - nFMod = nFFlags[k]; - checkFieldModifiers(oFMod, nFMod, i, k); - if (publicConstantChanged) { - return; - } - } else { // Matching field not found - if (Modifier.isStatic(oFMod) && Modifier.isFinal(oFMod) && - oldClassInfo.primitiveConstantInitValues != null && - oldClassInfo.primitiveConstantInitValues[i] != null) { - // Compile-time constant deleted - versionsCompatible = false; - rf.findAllProjectClasses(oldClassInfo, i); - if (Modifier.isPublic(oFMod)) { - publicConstantChanged = true; - return; - } - } else { - versionsCompatible = false; - rf.findReferencingClassesForField(oldClassInfo, i); - } - } - } - - if (nonMatchingNewFields > 0) { // There are some fields declared in the new version which don't exist in the old one - // Look for fields hiding same-named fields in superclasses - for (i = 0; i < nFLen; i++) { - nFName = nFNames[i]; - - boolean found = false; - for (j = 0; j < oFLen; j++) { - if (nFName.equals(oFNames[j])) { - found = true; - break; - } - } - if (found) { - continue; // nFName is not an added field - } - String superName = oldClassInfo.superName; - ClassInfo superInfo; - while (superName != null) { - superInfo = - pcdm.getClassInfoForName(ClassInfo.VER_OLD, superName); - if (superInfo == null) { - break; - } - String[] superOFNames = superInfo.fieldNames; - int superOFNamesLen = superOFNames != null ? superOFNames.length - : 0; - for (j = 0; j < superOFNamesLen; j++) { - if (nFName == superOFNames[j]) { - versionsCompatible = false; - rf.findReferencingClassesForField(superInfo, j); - } - } - superName = superInfo.superName; - } - } - } - } - - /** It is already known that old field is not private */ - private void checkFieldModifiers(int oFMod, int nFMod, int oldFieldIdx, int newFieldIdx) { - if (oFMod == nFMod) { - if (Modifier.isFinal(oFMod) && - (!ClassInfo.constFieldInitValuesEqual(oldClassInfo, oldFieldIdx, newClassInfo, newFieldIdx))) { - versionsCompatible = false; - rf.findAllProjectClasses(oldClassInfo, oldFieldIdx); - if (Modifier.isPublic(oFMod)) { - publicConstantChanged = true; // Means we will have to recompile ALL project classes - } - return; - } - } - - // These tests are ordered such that if a previous test succeeds, there is no need to do further tests, since that - // former test will cause more classes to be checked than any of the further tests. That is why it is possible to - // check properties that are in fact independent (e.g. accessibility vs. static/non-static) together. But this - // optimization only works since all kinds of tests result in the same kind of find..ReferencingClassesForField() - // outcome. For methods this is not true, and so there we have to check independent properties separately. - if (Modifier.isStatic(oFMod) && Modifier.isFinal(oFMod) && // oFMod is known to be non-private - (!Modifier.isFinal(nFMod) || !ClassInfo.constFieldInitValuesEqual(oldClassInfo, oldFieldIdx, newClassInfo, newFieldIdx))) { - versionsCompatible = false; - rf.findAllProjectClasses(oldClassInfo, oldFieldIdx); - if (Modifier.isPublic(oFMod)) { - publicConstantChanged = true; - } - } else if (Modifier.isPrivate(nFMod) || // oFMod is known to be non-private - (!Modifier.isFinal(oFMod) && Modifier.isFinal(nFMod)) || - (Modifier.isStatic(oFMod) != Modifier.isStatic(nFMod)) || - (Modifier.isVolatile(oFMod) != Modifier.isVolatile(nFMod))) { - versionsCompatible = false; - rf.findReferencingClassesForField(oldClassInfo, oldFieldIdx); - } else if (Modifier.isPublic(oFMod) && Modifier.isProtected(nFMod)) { - versionsCompatible = false; - rf.findDiffPackageReferencingClassesForField(oldClassInfo, oldFieldIdx); - } else if ((Modifier.isPublic(oFMod) || Modifier.isProtected(oFMod)) && - (!(Modifier.isPublic(nFMod) || Modifier.isProtected(nFMod) || Modifier.isPrivate(nFMod)))) { - versionsCompatible = false; - if (Modifier.isPublic(oFMod)) { - rf.findDiffPackageReferencingClassesForField(oldClassInfo, oldFieldIdx); - } else { - rf.findDiffPackageAndSubReferencingClassesForField(oldClassInfo, oldFieldIdx); - } - } - } - - private void checkForFinalFields() { - char oFFlags[] = oldClassInfo.fieldAccessFlags; - int oFLen = oldClassInfo.fieldNames != null ? oldClassInfo.fieldNames.length - : 0; - int oFMod; - - for (int i = 0; i < oFLen; i++) { - oFMod = oFFlags[i]; - if (Modifier.isPrivate(oFMod)) { - continue; // Changes to private fields don't affect compatibility - } - if (Modifier.isStatic(oFMod) && Modifier.isFinal(oFMod)) { - rf.findAllProjectClasses(oldClassInfo, i); - if (Modifier.isPublic(oFMod)) { - publicConstantChanged = true; - return; - } - } - } - } - - private void checkMethodsAndConstructors() { - String oMNames[] = oldClassInfo.methodNames; - String oMSignatures[] = oldClassInfo.methodSignatures; - char oMFlags[] = oldClassInfo.methodAccessFlags; - String nMNames[] = newClassInfo.methodNames; - String nMSignatures[] = newClassInfo.methodSignatures; - char nMFlags[] = newClassInfo.methodAccessFlags; - int oMLen = oMNames != null ? oMNames.length : 0; - int nMLen = nMNames != null ? nMNames.length : 0; - - int oMMod, nMMod; - String oMName, oMSig, nMName, nMSig; - int i, j, k, endIdx; - int nonMatchingNewMethods = nMLen; - - for (i = 0; i < oMLen; i++) { - oMMod = oMFlags[i]; - if (Modifier.isPrivate(oMMod)) { - continue; // Changes to private methods don't affect compatibility - } - oMName = oMNames[i]; - oMSig = oMSignatures[i]; - boolean found = false; - - // Look for the same method in the new version considering name and signature - endIdx = nMLen - 1; - k = i < nMLen ? i : endIdx; - for (j = 0; j < nMLen; j++) { - if (oMName == nMNames[k] && oMSig == nMSignatures[k]) { - found = true; - break; - } - if (k < endIdx) { - k++; - } else { - k = 0; - } - } - - if (found) { - nonMatchingNewMethods--; - nMMod = nMFlags[k]; - if (oMMod != nMMod) { - checkMethodModifiers(oMMod, nMMod, i); - } - - // Check if the new method throws more exceptions than the old one - if (newClassInfo.checkedExceptions != null && newClassInfo.checkedExceptions[k] != null) { - if (oldClassInfo.checkedExceptions == null) { - versionsCompatible = false; - rf.findReferencingClassesForMethod(oldClassInfo, i); - } else if (oldClassInfo.checkedExceptions[i] == null) { - versionsCompatible = false; - rf.findReferencingClassesForMethod(oldClassInfo, i); - } else { - String oldExceptions[] = - oldClassInfo.checkedExceptions[i]; - String newExceptions[] = - newClassInfo.checkedExceptions[k]; - for (int ei = 0; ei < newExceptions.length; ei++) { - String newEx = newExceptions[ei]; - found = false; - for (int ej = 0; ej < oldExceptions.length; ej++) { - if (newEx.equals(oldExceptions[ej])) { - found = true; - break; - } - } - if (!found) { - versionsCompatible = false; - rf.findReferencingClassesForMethod(oldClassInfo, i); - break; - } - } - } - } - } else { // Matching method not found - versionsCompatible = false; - rf.findReferencingClassesForMethod(oldClassInfo, i); - // Deleting a concrete method from an abstract class is a special case - if (oldClassInfo.isAbstract() && !Modifier.isAbstract(oMMod)) { - rf.findConcreteSubclassesNotOverridingAbstractMethod(oldClassInfo, oldClassInfo, i); - } - } - } - - if (nonMatchingNewMethods > 0) { // There are some methods/constructors declared in the new version which don't exist in the old one - if (!oldClassInfo.isInterface()) { - for (i = 0; i < nMLen; i++) { - nMMod = nMFlags[i]; - if (Modifier.isPrivate(nMMod)) { - continue; - } - String newMName = nMNames[i]; - final String newMSig = nMSignatures[i]; - final boolean isStatic = Modifier.isStatic(nMMod); - - boolean found = false; - for (j = 0; j < oMLen; j++) { - if (newMName.equals(oMNames[j]) && - newMSig.equals(oMSignatures[j])) { - found = true; - break; - } - } - if (found) { - continue; // nMName is not an added method - } - // Check if the new method is a static one that hides an inherited static method - // Check if the new method overloads an existing (declared or inherited) method. Overloading test is rough - - // we just check if the number of parameters is the same. Note that if a new constructor has been added, it - // can be treated in the same way, except that we shouldn't look up "same name methods" for it in superclasses. - oldClassInfo.findExistingSameNameMethods(newMName, - !newMName.equals("<init>"), false, - new ClassInfo.MethodHandler() { - - void handleMethod(ClassInfo classInfo, int methodIdx) { - String otherMSig = - classInfo.methodSignatures[methodIdx]; - if ((newMSig.equals(otherMSig) && isStatic && - classInfo != oldClassInfo) || - (newMSig != otherMSig && - Utils.sameParamNumber(newMSig, otherMSig))) { - versionsCompatible = false; - rf.findReferencingClassesForMethod(classInfo, methodIdx); - } - } - }); - - if (Modifier.isAbstract(nMMod)) { - // An abstract method added to the class. Find any concrete subclasses that don't override - // or inherit a concrete implementation of this method. - versionsCompatible = false; - rf.findConcreteSubclassesNotOverridingAbstractMethod(oldClassInfo, newClassInfo, i); - } - // Check if there is a method with the same name in some subclass, such that it now overrides - // or overloads the added method. - if (subclassesDeclareSameNameMethod(oldClassInfo, newMName)) { - versionsCompatible = false; - } - } - } else { // We are checking an interface. - for (i = 0; i < nMLen; i++) { - String newMName = nMNames[i]; - final String newMSig = nMSignatures[i]; - - boolean found = false; - for (j = 0; j < oMLen; j++) { - if (newMName == oMNames[j] && newMSig == oMSignatures[j]) { - found = true; - break; - } - } - - if (!found) { - versionsCompatible = false; - - // Check if the new method overloads an existing (declared or inherited) method. Overloading test is rough - - // we just check if the number of parameters is the same. - oldClassInfo.findExistingSameNameMethods(newMName, true, true, new ClassInfo.MethodHandler() { - - void handleMethod(ClassInfo classInfo, int methodIdx) { - String otherMSig = - classInfo.methodSignatures[methodIdx]; - if (newMSig != otherMSig && - Utils.sameParamNumber(newMSig, otherMSig)) { - rf.findReferencingClassesForMethod(classInfo, methodIdx); - } - } - }); - - rf.findDirectlyAndOtherwiseImplementingConcreteClasses(oldClassInfo); - rf.findAbstractSubtypesWithSameNameMethod(oldClassInfo, newMName, newMSig); - break; - } - } - } - } - } - - private void checkMethodModifiers(int oMMod, int nMMod, int oldMethodIdx) { - if (Modifier.isPrivate(nMMod)) { - versionsCompatible = false; - rf.findReferencingClassesForMethod(oldClassInfo, oldMethodIdx); - } else if (Modifier.isPublic(oMMod) && Modifier.isProtected(nMMod)) { - versionsCompatible = false; - rf.findDiffPackageReferencingClassesForMethod(oldClassInfo, oldMethodIdx); - } else if ((Modifier.isPublic(oMMod) || Modifier.isProtected(oMMod)) && - (!(Modifier.isPublic(nMMod) || Modifier.isProtected(nMMod) || Modifier.isPrivate(nMMod)))) { - versionsCompatible = false; - if (Modifier.isPublic(oMMod)) { - rf.findDiffPackageReferencingClassesForMethod(oldClassInfo, oldMethodIdx); - } else { - rf.findDiffPackageAndSubReferencingClassesForMethod(oldClassInfo, oldMethodIdx); - } - } else if ((Modifier.isPrivate(oMMod) && !Modifier.isPrivate(nMMod)) || - (Modifier.isProtected(oMMod) && Modifier.isPublic(nMMod)) || - (!(Modifier.isPublic(oMMod) || Modifier.isProtected(oMMod) || Modifier.isPrivate(oMMod)) && - (Modifier.isPublic(nMMod) || Modifier.isProtected(nMMod)))) { - versionsCompatible = false; - rf.findSubclassesReimplementingMethod(oldClassInfo, oldMethodIdx); - } - - if ((!Modifier.isAbstract(oMMod) && Modifier.isAbstract(nMMod)) || - (Modifier.isStatic(oMMod) != Modifier.isStatic(nMMod))) { - versionsCompatible = false; - rf.findReferencingClassesForMethod(oldClassInfo, oldMethodIdx); - if (!Modifier.isAbstract(oMMod) && Modifier.isAbstract(nMMod)) { - rf.findConcreteSubclassesNotOverridingAbstractMethod(oldClassInfo, newClassInfo, oldMethodIdx); - } - } - if (!Modifier.isFinal(oMMod) && Modifier.isFinal(nMMod)) { - versionsCompatible = false; - rf.findSubclassesReimplementingMethod(oldClassInfo, oldMethodIdx); - } - } - - /** - * Returns true if any subclass(es), direct or indirect, declare a method with name methodName. - * For each such occurence, referencing classes are looked up and added to the list of affected classes. - */ - private boolean subclassesDeclareSameNameMethod(ClassInfo oldClassInfo, String methodName) { - boolean res = false; - ClassInfo[] directSubclasses = oldClassInfo.getDirectSubclasses(); - for (int i = 0; i < directSubclasses.length; i++) { - ClassInfo subclass = directSubclasses[i]; - int methNo = subclass.declaresSameNameMethod(methodName); - if (methNo >= 0) { - rf.addToAffectedClassNames(subclass.name); - rf.findReferencingClassesForMethod(subclass, methNo); - res = true; - } - if (subclassesDeclareSameNameMethod(subclass, methodName)) { - res = true; - } - } - return res; - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/Main.java b/third_party/jmake/src/org/pantsbuild/jmake/Main.java deleted file mode 100644 index 0e805548..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/Main.java +++ /dev/null
@@ -1,899 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintStream; -import java.io.Reader; -import java.io.StreamTokenizer; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -/** - * The main class of the <b>jmake</b> tool.<p> - * - * Has several entrypoints: <code>main</code>, <code>mainExternal</code>, <code>mainProgrammatic</code>, - * <code>mainExternalControlled</code> and <code>mainProgrammaticControlled</code>. - * The first is not intended to be used by applications other than <b>jmake</b> itself, whereas the - * rest can be used to call <b>jmake</b> externally with various degrees of control over its behaviour. - * See method comments for more details. - * - * @author Misha Dmitriev - * 12 October 2004 - */ -public class Main { - - static final String DEFAULT_STORE_NAME = "jmake.pdb"; - static final String VERSION = "1.3.8-11"; - private String pdbFileName = null; - private List<String> allProjectJavaFileNamesList = - new ArrayList<String>(100); - private String allProjectJavaFileNames[]; - private String addedJavaFileNames[], removedJavaFileNames[], updatedJavaFileNames[]; - private String destDir = ""; - private List<String> javacAddArgs = new ArrayList<String>(); - private String jcPath, jcMainClass, jcMethod; - private String jcExecApp; - boolean controlledExecution = false; - Object externalApp = null; - Method externalCompileSourceFilesMethod = null; - private boolean failOnDependentJar = false, noWarnOnDependentJar = false; - private boolean pdbTextFormat = false; - private PCDManager pcdm = null; - private String dependencyFile; - private static final String optNames[] = {"-h", "-help", "-d", "-pdb", "-C", "-jcpath", "-jcmainclass", "-jcmethod", "-jcexec", "-Xtiming", "-version", - "-warnlimit", "-failondependentjar", "-nowarnondependentjar", "-classpath", "-projclasspath", "-bootclasspath", "-extdirs", "-vpath", "-pdb-text-format", - "-depfile"}; - private static final int optArgs[] = {0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1}; - private static final int OPT_H = 0; - private static final int OPT_HELP = 1; - private static final int OPT_D = 2; - private static final int OPT_STORE = 3; - private static final int OPT_JAVAC_OPT = 4; - private static final int OPT_JCPATH = 5; - private static final int OPT_JCMAINCLASS = 6; - private static final int OPT_JCMETHOD = 7; - private static final int OPT_JCEXEC = 8; - private static final int OPT_TIMING = 9; - private static final int OPT_VERSION = 10; - private static final int OPT_WARNLIMIT = 11; - private static final int OPT_FAILONDEPJAR = 12; - private static final int OPT_NOWARNONDEPJAR = 13; - private static final int OPT_CLASSPATH = 14; - private static final int OPT_PROJECTCLASSPATH = 15; - private static final int OPT_BOOTCLASSPATH = 16; - private static final int OPT_EXTDIRS = 17; - private static final int OPT_VPATH = 18; - private static final int OPT_PDB_TEXT_FORMAT = 19; - private static final int OPT_DEPENDENCY_FILE = 20; - - /** Construct a new instance of Main. */ - public Main() { - } - - /** - * Checks whether the argument is a legal jmake option. Returns its number or - * -1 if not found. - */ - private static int inOptions(String option) { - if (option.startsWith(optNames[OPT_JAVAC_OPT])) { - return OPT_JAVAC_OPT; - } - for (int i = 0; i < optNames.length; i++) { - if (option.equals(optNames[i])) { - return i; - } - } - return -1; - } - - private void processCommandLine(String args[]) { - if ((args.length == 0) || (args.length == 1 && args[0].equals(optNames[OPT_HELP]))) { - printUsage(); - throw new PrivateException(new PublicExceptions.NoActionRequestedException()); - } - - List<String> argsV = new ArrayList<String>(); - for (int i = 0; i < args.length; i++) { - argsV.add(args[i]); - } - int argsSt = 0; - String arg; - - while (argsSt < argsV.size()) { - arg = argsV.get(argsSt++); - if (arg.charAt(0) == '-') { - int argN = inOptions(arg); - if (argN != -1) { - if (argsSt + optArgs[argN] > argsV.size()) { - optRequiresArg("\"" + optNames[argN] + "\""); - } - } else { - bailOut(arg + ERR_IS_INVALID_OPTION); - } - - switch (argN) { - case OPT_H: - case OPT_HELP: - printUsage(); - throw new PrivateException(new PublicExceptions.NoActionRequestedException()); - case OPT_D: - destDir = argsV.get(argsSt); - javacAddArgs.add("-d"); - javacAddArgs.add(argsV.get(argsSt)); - argsSt++; - break; - case OPT_CLASSPATH: - try { - setClassPath(argsV.get(argsSt++)); - } catch (PublicExceptions.InvalidCmdOptionException ex) { - bailOut(ex.getMessage()); - } - break; - case OPT_PROJECTCLASSPATH: - try { - setProjectClassPath(argsV.get(argsSt++)); - } catch (PublicExceptions.InvalidCmdOptionException ex) { - bailOut(ex.getMessage()); - } - break; - case OPT_STORE: - pdbFileName = argsV.get(argsSt++); - break; - case OPT_JAVAC_OPT: - String javacArg = - (argsV.get(argsSt - 1)).substring(2); - if (javacArg.equals("-d") || - javacArg.equals("-classpath") || - javacArg.equals("-bootclasspath") || - javacArg.equals("-extdirs")) { - bailOut(javacArg + ERR_SHOULD_BE_EXPLICIT); - } - javacAddArgs.add(javacArg); - break; - case OPT_JCPATH: - if (jcExecApp != null) { - bailOut(ERR_NO_TWO_COMPILER_OPTIONS); - } - jcPath = argsV.get(argsSt++); - break; - case OPT_JCMAINCLASS: - if (jcExecApp != null) { - bailOut(ERR_NO_TWO_COMPILER_OPTIONS); - } - jcMainClass = argsV.get(argsSt++); - break; - case OPT_JCMETHOD: - if (jcExecApp != null) { - bailOut(ERR_NO_TWO_COMPILER_OPTIONS); - } - jcMethod = argsV.get(argsSt++); - break; - case OPT_JCEXEC: - if (jcPath != null || jcMainClass != null || jcMethod != null) { - bailOut(ERR_NO_TWO_COMPILER_OPTIONS); - } - jcExecApp = argsV.get(argsSt++); - break; - case OPT_TIMING: - Utils.setTimingOn(); - break; - case OPT_VERSION: - // Utils.printInfoMessage("jmake version " + VERSION); // Printed anyway at present... - throw new PrivateException(new PublicExceptions.NoActionRequestedException()); - case OPT_WARNLIMIT: - try { - Utils.warningLimit = - Integer.parseInt(argsV.get(argsSt++)); - } catch (NumberFormatException e) { - Utils.ignore(e); - bailOut(argsV.get(argsSt) + ERR_IS_INVALID_OPTION); - } - break; - case OPT_FAILONDEPJAR: - if (noWarnOnDependentJar) { - bailOut("it is not allowed to use -nowarnondependentjar and -failondependentjar together"); - } - failOnDependentJar = true; - break; - case OPT_NOWARNONDEPJAR: - if (failOnDependentJar) { - bailOut("it is not allowed to use -failondependentjar and -nowarnondependentjar together"); - } - noWarnOnDependentJar = true; - break; - case OPT_BOOTCLASSPATH: - try { - setBootClassPath(argsV.get(argsSt++)); - } catch (PublicExceptions.InvalidCmdOptionException ex) { - bailOut(ex.getMessage()); - } - break; - case OPT_EXTDIRS: - try { - setExtDirs(argsV.get(argsSt++)); - } catch (PublicExceptions.InvalidCmdOptionException ex) { - bailOut(ex.getMessage()); - } - break; - case OPT_VPATH: - try { - setVirtualPath(argsV.get(argsSt++)); - } catch (PublicExceptions.InvalidCmdOptionException ex) { - bailOut(ex.getMessage()); - } - break; - case OPT_PDB_TEXT_FORMAT: - pdbTextFormat = true; - break; - case OPT_DEPENDENCY_FILE: - dependencyFile = argsV.get(argsSt++); - break; - default: - bailOut(arg + ERR_IS_INVALID_OPTION); - } - } else { // Not an option, at least does not start with "-". Treat it as a command line file name or source name. - if (arg.length() > 1 && arg.charAt(0) == '@') { - arg = arg.substring(1); - loadCmdFile(arg, argsV); - } else { - if (!arg.endsWith(".java")) { - bailOut(arg + ERR_IS_INVALID_OPTION); - } - allProjectJavaFileNamesList.add(arg); - } - } - } - } - - /** Load @-file that can contain anything that command line can contain. */ - private void loadCmdFile(String name, List<String> argsV) { - try { - Reader r = new BufferedReader(new FileReader(name)); - StreamTokenizer st = new StreamTokenizer(r); - st.resetSyntax(); - st.wordChars(' ', 255); - st.whitespaceChars(0, ' '); - st.commentChar('#'); - st.quoteChar('"'); - st.quoteChar('\''); - while (st.nextToken() != StreamTokenizer.TT_EOF) { - argsV.add(st.sval); - } - r.close(); - } catch (IOException e) { - throw new PrivateException(new PublicExceptions.CommandFileReadException(name + ":\n" + e.getMessage())); - } - } - - /** - * Main entrypoint for applications that want to call <b>jmake</b> externally and are willing - * to handle exceptions that it may throw. - * - * @param args command line arguments passed to <b>jmake</b>. - * - * @throws PublicExceptions.NoActionRequestedException if <b>jmake</b> was not requested to do any real work; - * @throws PublicExceptions.InvalidCmdOptionException if invalid command line option was detected; - * @throws PublicExceptions.PDBCorruptedException if project database is corrupted; - * @throws PublicExceptions.CommandFileReadException if there was error reading a command file; - * @throws PublicExceptions.CompilerInteractionException if there was a problem initializing or calling the compiler, - * or compilation errors were detected; - * @throws PublicExceptions.ClassFileParseException if there was error parsing a class file; - * @throws PublicExceptions.ClassNameMismatchException if there is a mismatch between the deduced and the actual class name; - * @throws PublicExceptions.InvalidSourceFileExtensionException if a supplied source file has an invalid extension (not .java); - * @throws PublicExceptions.JarDependsOnSourceException if a class in a <code>JAR</code> is found dependent on a class with the .java source; - * @throws PublicExceptions.DoubleEntryException if more than one entry for the same class is found in the project - * @throws FileNotFoundException if a <code>.java</code> or a <code>.class</code> file was not found; - * @throws IOException if there was an I/O problem of any kind; - * @throws PublicExceptions.InternalException if an internal problem that should never happen was detected. - */ - public void mainProgrammatic(String args[]) throws - PublicExceptions.NoActionRequestedException, - PublicExceptions.InvalidCmdOptionException, - PublicExceptions.PDBCorruptedException, - PublicExceptions.CommandFileReadException, - PublicExceptions.CompilerInteractionException, - PublicExceptions.ClassFileParseException, - PublicExceptions.ClassNameMismatchException, - PublicExceptions.InvalidSourceFileExtensionException, - PublicExceptions.JarDependsOnSourceException, - PublicExceptions.DoubleEntryException, - FileNotFoundException, - IOException, - PublicExceptions.InternalException { - try { - Utils.printInfoMessage("Jmake version " + VERSION); - if (!controlledExecution) { - processCommandLine(args); - String[] projectJars = ClassPath.getProjectJars(); - if (projectJars != null) { - for (int i = 0; i < projectJars.length; i++) { - allProjectJavaFileNamesList.add(projectJars[i]); - } - } - allProjectJavaFileNames = - allProjectJavaFileNamesList.toArray(new String[allProjectJavaFileNamesList.size()]); - } else { - String[] projectJars = ClassPath.getProjectJars(); - if (projectJars != null) { - String newNames[] = - new String[allProjectJavaFileNames.length + projectJars.length]; - System.arraycopy(allProjectJavaFileNames, 0, newNames, 0, allProjectJavaFileNames.length); - System.arraycopy(projectJars, 0, newNames, allProjectJavaFileNames.length, projectJars.length); - allProjectJavaFileNames = newNames; - } - } - - Utils.startTiming(Utils.TIMING_PDBREAD); - PCDContainer pcdc; - pcdc = PCDContainer.load(pdbFileName, pdbTextFormat); - Utils.stopAndPrintTiming("DB read", Utils.TIMING_PDBREAD); - - pcdm = new PCDManager(pcdc, allProjectJavaFileNames, - addedJavaFileNames, removedJavaFileNames, updatedJavaFileNames, - destDir, javacAddArgs, failOnDependentJar, noWarnOnDependentJar, - dependencyFile); - - pcdm.initializeCompiler(jcExecApp, jcPath, jcMainClass, jcMethod, externalApp, externalCompileSourceFilesMethod); - - pcdm.run(); - } catch (PrivateException e) { - Throwable origException = e.getOriginalException(); - if (origException instanceof PublicExceptions.NoActionRequestedException) { - throw (PublicExceptions.NoActionRequestedException) origException; - } else if (origException instanceof PublicExceptions.InvalidCmdOptionException) { - throw (PublicExceptions.InvalidCmdOptionException) origException; - } else if (origException instanceof PublicExceptions.CommandFileReadException) { - throw (PublicExceptions.CommandFileReadException) origException; - } else if (origException instanceof PublicExceptions.PDBCorruptedException) { - throw (PublicExceptions.PDBCorruptedException) origException; - } else if (origException instanceof PublicExceptions.CompilerInteractionException) { - throw (PublicExceptions.CompilerInteractionException) origException; - } else if (origException instanceof PublicExceptions.ClassFileParseException) { - throw (PublicExceptions.ClassFileParseException) origException; - } else if (origException instanceof PublicExceptions.ClassNameMismatchException) { - throw (PublicExceptions.ClassNameMismatchException) origException; - } else if (origException instanceof PublicExceptions.InvalidSourceFileExtensionException) { - throw (PublicExceptions.InvalidSourceFileExtensionException) origException; - } else if (origException instanceof PublicExceptions.JarDependsOnSourceException) { - throw (PublicExceptions.JarDependsOnSourceException) origException; - } else if (origException instanceof PublicExceptions.DoubleEntryException) { - throw (PublicExceptions.DoubleEntryException) origException; - } else if (origException instanceof FileNotFoundException) { - throw (FileNotFoundException) origException; - } else if (origException instanceof IOException) { - throw (IOException) origException; - } else if (origException instanceof PublicExceptions.InternalException) { - throw (PublicExceptions.InternalException) origException; - } - } finally { - ClassPath.resetOnFinish(); - } - } - - /** - * Main entrypoint for applications that want to call <b>jmake</b> externally and would prefer - * receiving an error code instead of an exception in case something goes wrong.<p> - * - * @param args command line arguments passed to <b>jmake</b>. - * - * @return <dl> - * <dt><code> 0</code> if everything was successful; - * <dt><code> -1</code> invalid command line option detected; - * <dt><code> -2</code> error reading command file; - * <dt><code> -3</code> project database corrupted; - * <dt><code> -4</code> error initializing or calling the compiler; - * <dt><code> -5</code> compilation error; - * <dt><code> -6</code> error parsing a class file; - * <dt><code> -7</code> file not found; - * <dt><code> -8</code> I/O exception; - * <dt><code> -9</code> internal jmake exception; - * <dt><code>-10</code> deduced and actual class name mismatch; - * <dt><code>-11</code> invalid source file extension; - * <dt><code>-12</code> a class in a <code>JAR</code> is found dependent on a class with the .java source; - * <dt><code>-13</code> more than one entry for the same class is found in the project - * <dt><code>-20</code> internal Java error (caused by <code>java.lang.InternalError</code>); - * <dt><code>-30</code> internal Java error (caused by <code>java.lang.RuntimeException</code>). - * </dl> - */ - public int mainExternal(String args[]) { - try { - mainProgrammatic(args); - } catch (PublicExceptions.NoActionRequestedException e0) { - // Nothing to do - } catch (PublicExceptions.InvalidCmdOptionException e1) { - Utils.printErrorMessage(e1.getMessage()); - return -1; - } catch (PublicExceptions.CommandFileReadException e2) { - Utils.printErrorMessage("error parsing command file:"); - Utils.printErrorMessage(e2.getMessage()); - return -2; - } catch (PublicExceptions.PDBCorruptedException e3) { - Utils.printErrorMessage("project database corrupted: " + e3.getMessage()); - return -3; - } catch (PublicExceptions.CompilerInteractionException e4) { - if (e4.getOriginalException() != null) { - Utils.printErrorMessage("error interacting with the compiler: "); - Utils.printErrorMessage(e4.getMessage()); - Utils.printErrorMessage("original exception:"); - Utils.printErrorMessage(e4.getOriginalException().getMessage()); - return -4; - } else { // Otherwise there is a compilation error, and the compiler has already printed a lot... - return -5; - } - } catch (PublicExceptions.ClassFileParseException e6) { - Utils.printErrorMessage(e6.getMessage()); - return -6; - } catch (FileNotFoundException e7) { - Utils.printErrorMessage(e7.getMessage()); - return -7; - } catch (IOException e8) { - Utils.printErrorMessage(e8.getMessage()); - return -8; - } catch (PublicExceptions.InternalException e9) { - Utils.printErrorMessage("internal jmake exception detected:"); - Utils.printErrorMessage(e9.getMessage()); - Utils.printErrorMessage(Utils.REPORT_PROBLEM); - Utils.printErrorMessage("the stack trace is as follows:"); - e9.printStackTrace(); - return -9; - } catch (PublicExceptions.ClassNameMismatchException e10) { - Utils.printErrorMessage(e10.getMessage()); - return -10; - } catch (PublicExceptions.InvalidSourceFileExtensionException e11) { - Utils.printErrorMessage(e11.getMessage()); - return -11; - } catch (PublicExceptions.JarDependsOnSourceException e12) { - Utils.printErrorMessage(e12.getMessage()); - return -12; - } catch (PublicExceptions.DoubleEntryException e13) { - Utils.printErrorMessage(e13.getMessage()); - return -13; - } catch (InternalError e20) { - Utils.printErrorMessage("internal Java error: " + e20); - Utils.printErrorMessage("Consult the following stack trace for more info:"); - e20.printStackTrace(); - return -20; - } catch (RuntimeException e30) { - Utils.printErrorMessage("internal Java exception: " + e30); - Utils.printErrorMessage("Consult the following stack trace for more info:"); - e30.printStackTrace(); - return -30; - } - - return 0; - } - - /** - * Main entrypoint for applications such as Ant, that want to have full control over - * compilations that <b>jmake</b> invokes, and are willing to handle exceptions - * that it may throw. - * - * @param javaFileNames array of strings that specify <code>.java</code> file names. - * @param destDirName name of the destination directory (<b>jmake</b> will look up binary classes - * in there, it should be the same as the one used by the Java compiler method). - * If <code>null</code> is passed, classes will be looked up in the same directories - * as their sources, in agreement with the default Java compiler behaviour. - * @param pdbFileName project database file name (if <code>null</code> is passed, - * a file with the default name placed in the current directory will be used). - * @param externalApp an object on which to invoke <code>externalCompileSourceFilesMethod</code> method. - * @param externalCompileSourceFilesMethod a method of the form <code>int x(String[] args)</code>. It - * should return <code>0</code> if compilation is successful and any non-zero value - * otherwise. <b>jmake</b> passes it a list of the <code>.java</code> files to - * recompile in the form of canonical full path file names. - * - * @throws PublicExceptions.NoActionRequestedException if <b>jmake</b> was not requested to do any real work; - * @throws PublicExceptions.InvalidCmdOptionException if invalid command line option was detected; - * @throws PublicExceptions.PDBCorruptedException if project database is corrupted; - * @throws PublicExceptions.CommandFileReadException if there was error reading a command file; - * @throws PublicExceptions.CompilerInteractionException if there was a problem initializing or calling the compiler, - * or compilation errors were detected; - * @throws PublicExceptions.ClassFileParseException if there was error parsing a class file; - * @throws PublicExceptions.ClassNameMismatchException if there is a mismatch between the deduced and the actual class name; - * @throws PublicExceptions.InvalidSourceFileExtensionException if a specified source file has an invalid extension (not .java); - * @throws PublicExceptions.JarDependsOnSourceException if a class in a <code>JAR</code> is found dependent on a class with the .java source; - * @throws PublicExceptions.DoubleEntryException if more than one entry for the same class is found in the project - * @throws PublicExceptions.InternalException if an internal problem that should never happen was detected. - * @throws FileNotFoundException if a <code>.java</code> or a <code>.class</code> file was not found; - * @throws IOException if there was an I/O problem of any kind; - */ - public void mainProgrammaticControlled(String javaFileNames[], String destDirName, String pdbFileName, - Object externalApp, Method externalCompileSourceFilesMethod) throws - PublicExceptions.NoActionRequestedException, - PublicExceptions.InvalidCmdOptionException, - PublicExceptions.PDBCorruptedException, - PublicExceptions.CommandFileReadException, - PublicExceptions.CompilerInteractionException, - PublicExceptions.ClassFileParseException, - PublicExceptions.ClassNameMismatchException, - PublicExceptions.InvalidSourceFileExtensionException, - PublicExceptions.JarDependsOnSourceException, - PublicExceptions.DoubleEntryException, - PublicExceptions.InternalException, - FileNotFoundException, - IOException { - - controlledExecution = true; - this.pdbFileName = pdbFileName; - this.destDir = destDirName; - this.allProjectJavaFileNames = javaFileNames; - this.externalApp = externalApp; - this.externalCompileSourceFilesMethod = externalCompileSourceFilesMethod; - - mainProgrammatic(null); - } - - /** - * Main entrypoint for applications such as Ant, that want to have full control over - * compilations that <b>jmake</b> invokes, and do not want to handle exceptions that it - * may throw. Error codes returned are the same as <code>mainExternal(String[])</code> returns. - * - * @param javaFileNames array of strings that specify <code>.java</code> file names. - * @param destDirName name of the destination directory (<b>jmake</b> will look up binary classes - * in there, it should be the same as the one used by the Java compiler method). - * If <code>null</code> is passed, classes will be looked up in the same directories - * as their sources, in agreement with the default Java compiler behaviour. - * @param pdbFileName project database file name (if <code>null</code> is passed, - * a file with the default name placed in the current directory will be used). - * @param externalApp an object on which to invoke <code>externalCompileSourceFilesMethod</code> method. - * @param externalCompileSourceFilesMethod a method of the form <code>int x(String[] args)</code>. It - * should return <code>0</code> if compilation is successful and any non-zero value - * otherwise. <b>jmake</b> passes it a list of the <code>.java</code> files to - * recompile in the form of canonical full path file names. - * - * @see #mainExternal(String[]) - */ - public int mainExternalControlled(String javaFileNames[], String destDirName, String pdbFileName, - Object externalApp, Method externalCompileSourceFilesMethod) { - controlledExecution = true; - this.pdbFileName = pdbFileName; - this.destDir = destDirName; - this.allProjectJavaFileNames = javaFileNames; - this.externalApp = externalApp; - this.externalCompileSourceFilesMethod = externalCompileSourceFilesMethod; - - return mainExternal(null); - } - - /** - * Main entrypoint for applications such as IDEs, that themselves keep track of updated/added/removed sources, - * want to have full control over compilations that <b>jmake</b> invokes, and are willing to handle exceptions - * that it may throw. - * - * @param addedJavaFileNames names of <code>.java</code> files just added to the project - * @param removedJavaFileNames names of <code>.java</code> files just removed from the project - * @param updatedJavaFileNames names of updated project <code>.java</code> files - * @param destDirName name of the destination directory (<b>jmake</b> will look up binary classes - * in there, it should be the same as the one used by the Java compiler method). - * If <code>null</code> is passed, classes will be looked up in the same directories - * as their sources, in agreement with the default Java compiler behaviour. - * @param pdbFileName project database file name (if <code>null</code> is passed, - * a file with the default name placed in the current directory will be used). - * @param externalApp an object on which to invoke <code>externalCompileSourceFilesMethod</code> method. - * @param externalCompileSourceFilesMethod a method of the form <code>int x(String[] args)</code>. It - * should return <code>0</code> if compilation is successful and any non-zero value - * otherwise. <b>jmake</b> passes it a list of the <code>.java</code> files to - * recompile in the form of canonical full path file names. - * - * @throws PublicExceptions.NoActionRequestedException if <b>jmake</b> was not requested to do any real work; - * @throws PublicExceptions.InvalidCmdOptionException if invalid command line option was detected; - * @throws PublicExceptions.PDBCorruptedException if project database is corrupted; - * @throws PublicExceptions.CommandFileReadException if there was error reading a command file; - * @throws PublicExceptions.CompilerInteractionException if there was a problem initializing or calling the compiler, - * or compilation errors were detected; - * @throws PublicExceptions.ClassFileParseException if there was error parsing a class file; - * @throws PublicExceptions.ClassNameMismatchException if there is a mismatch between the deduced and the actual class name; - * @throws PublicExceptions.InvalidSourceFileExtensionException if a specified source file has an invalid extension (not .java); - * @throws PublicExceptions.JarDependsOnSourceException if a class in a <code>JAR</code> is found dependent on a class with the .java source; - * @throws PublicExceptions.DoubleEntryException if more than one entry for the same class is found in the project - * @throws PublicExceptions.InternalException if an internal problem that should never happen was detected. - * @throws FileNotFoundException if a <code>.java</code> or a <code>.class</code> file was not found; - * @throws IOException if there was an I/O problem of any kind; - */ - public void mainProgrammaticControlled(String addedJavaFileNames[], String removedJavaFileNames[], String updatedJavaFileNames[], - String destDirName, String pdbFileName, - Object externalApp, Method externalCompileSourceFilesMethod) throws - PublicExceptions.NoActionRequestedException, - PublicExceptions.InvalidCmdOptionException, - PublicExceptions.PDBCorruptedException, - PublicExceptions.CommandFileReadException, - PublicExceptions.CompilerInteractionException, - PublicExceptions.ClassFileParseException, - PublicExceptions.ClassNameMismatchException, - PublicExceptions.InvalidSourceFileExtensionException, - PublicExceptions.JarDependsOnSourceException, - PublicExceptions.DoubleEntryException, - PublicExceptions.InternalException, - FileNotFoundException, - IOException { - - controlledExecution = true; - this.pdbFileName = pdbFileName; - this.destDir = destDirName; - this.addedJavaFileNames = addedJavaFileNames; - this.removedJavaFileNames = removedJavaFileNames; - this.updatedJavaFileNames = updatedJavaFileNames; - this.externalApp = externalApp; - this.externalCompileSourceFilesMethod = externalCompileSourceFilesMethod; - - mainProgrammatic(null); - } - - /** - * Main entrypoint for applications such as IDEs, that themselves keep track of updated/added/removed sources, - * want to have full control over compilations that <b>jmake</b> invokes, and do not want to handle exceptions - * that it may throw. Error codes returned are the same as <code>mainExternal(String[])</code> returns. - * - * @param addedJavaFileNames names of <code>.java</code> files just added to the project - * @param removedJavaFileNames names of <code>.java</code> files just removed from the project - * @param updatedJavaFileNames names of updated project <code>.java</code> files - * @param destDirName name of the destination directory (<b>jmake</b> will look up binary classes - * in there, it should be the same as the one used by the Java compiler method). - * If <code>null</code> is passed, classes will be looked up in the same directories - * as their sources, in agreement with the default Java compiler behaviour. - * @param pdbFileName project database file name (if <code>null</code> is passed, - * a file with the default name placed in the current directory will be used). - * @param externalApp an object on which to invoke <code>externalCompileSourceFilesMethod</code> method. - * @param externalCompileSourceFilesMethod a method of the form <code>int x(String[] args)</code>. It - * should return <code>0</code> if compilation is successful and any non-zero value - * otherwise. <b>jmake</b> passes it a list of the <code>.java</code> files to - * recompile in the form of canonical full path file names. - * - * @see #mainExternal(String[]) - */ - public int mainExternalControlled(String addedJavaFileNames[], String removedJavaFileNames[], String updatedJavaFileNames[], - String destDirName, String pdbFileName, - Object externalApp, Method externalCompileSourceFilesMethod) { - controlledExecution = true; - this.pdbFileName = pdbFileName; - this.destDir = destDirName; - this.addedJavaFileNames = addedJavaFileNames; - this.removedJavaFileNames = removedJavaFileNames; - this.updatedJavaFileNames = updatedJavaFileNames; - this.externalApp = externalApp; - this.externalCompileSourceFilesMethod = externalCompileSourceFilesMethod; - - return mainExternal(null); - } - - /** - * Main entrypoint for the standalone <b>jmake</b> application. This method calls does little but calling - * <code>mainExternal</code>, and its execution always completes with <code>System.exit(code)</code>, - * where <code>code</code> is the value returned by <code>mainExternal</code>. - * - * @see #mainExternal(String[]) - * @see #mainProgrammatic(String[]) - * - * @param args command line arguments passed to <b>jmake</b> - */ - public static void main(String args[]) { - Utils.startTiming(Utils.TIMING_TOTAL); - - Main m = new Main(); - int exitCode = m.mainExternal(args); - - Utils.stopAndPrintTiming("Total", Utils.TIMING_TOTAL); - if ( exitCode != 0 ) { - System.exit(exitCode); - } - } - - /** - * Customize the output of <b>jmake</b>. - * - * @see #setOutputStreams(PrintStream, PrintStream, PrintStream) - * - * @param printInfoMessages specify whether to print information messages - * @param printWarningMessages specify whether to print warning messages - * @param printErrorMessages specify whether to print error messages - */ - public static void customizeOutput(boolean printInfoMessages, - boolean printWarningMessages, - boolean printErrorMessages) { - Utils.customizeOutput(printInfoMessages, printWarningMessages, printErrorMessages); - } - - /** - * Set the class path to be used by the compiler, and also by the dependency checker for the purposes of - * superclass/superinterface change tracking. For the compiler, this class path will be merged with the - * project class path (set via setProjectClassPath(String)). Other than that, its value will be used only to - * look up superclasses/superinterfaces of project classes. Note that non-project superclasses and - * superinterfaces are first looked up at the boot class path, then on the extension class path, and then - * on this class path. - * - * @see #setProjectClassPath(String) - * @see #setBootClassPath(String) - * @see #setExtDirs(String) - * - * @param classPath the value of the class path, in the usual format (i.e. entries that are directories - * or JARs, separated by colon or semicolon depending on the platform). - * - * @throws PublicExceptions.InvalidCmdOptionException if invalid class path value is specified. - */ - public static void setClassPath(String classPath) throws PublicExceptions.InvalidCmdOptionException { - ClassPath.setClassPath(classPath); - } - - /** - * Set the class path to be used by the compiler, and also by the dependency checker for the purposes of - * superclass/superinterface change tracking and sourceless class dependency checking. For the compiler, - * and also in order to look up superclasses/superinterfaces of project classes, this class path will be - * merged with the standard class path (set via setClassPath(String)). But in addition, all binary classes - * that are on this class path are stored in the project database and checked for updates every time jmake - * is invoked. Any changes to these classes trigger the standard dependency checking procedure. However, - * dependent classes are looked up only among the "normal" project classes, i.e. those that have sources. - * Therefore sourceless classes are assumed to always be mutually consistent. - * - * Currently only JAR files can be present on this class path. - * - * @see #setClassPath(String) - * - * @param projectClassPath the value of the class path, in the usual format (i.e. entries that are directories - * or JARs, separated by colon or semicolon depending on the platform). - * - * @throws PublicExceptions.InvalidCmdOptionException if invalid class path value is specified. - */ - public static void setProjectClassPath(String projectClassPath) throws PublicExceptions.InvalidCmdOptionException { - ClassPath.setProjectClassPath(projectClassPath); - } - - /** - * Set the boot class path to be used by the compiler (-bootclasspath option) and also by the dependency - * checker (by default, the value of "sun.boot.class.path" property is used). - * - * @see #setClassPath(String) - * - * @param classPath the value of the boot class path, in the usual format (i.e. entries that are directories - * or JARs, separated by colon or semicolon depending on the platform). - * - * @throws PublicExceptions.InvalidCmdOptionException if invalid class path value is specified. - */ - public static void setBootClassPath(String classPath) throws PublicExceptions.InvalidCmdOptionException { - ClassPath.setBootClassPath(classPath); - } - - /** - * Set the extensions location to be used by the compiler (-extdirs option) and also by the dependency - * checker (by default, the value of "java.ext.dirs" property is used). - * - * @see #setClassPath(String) - * - * @param dirs the value of extension directories, in the usual format (one or more directory names - * separated by colon or semicolon depending on the platform). - * - * @throws PublicExceptions.InvalidCmdOptionException if invalid class path value is specified. - */ - public static void setExtDirs(String dirs) throws PublicExceptions.InvalidCmdOptionException { - ClassPath.setExtDirs(dirs); - } - - /** - * Set the virtual path used to find both source and class files that are part of the project - * but are not in the local directory. - * - * @see #setClassPath(String) - * - * @param dirs the value of extension directories, in the usual format (one or more directory names - * separated by colon or semicolon depending on the platform). - * - * @throws PublicExceptions.InvalidCmdOptionException if invalid path value is specified. - */ - public static void setVirtualPath(String dirs) throws PublicExceptions.InvalidCmdOptionException { - ClassPath.setVirtualPath(dirs); - } - - /** Produce no warning or error message upon a dependent <code>JAR</code> detection. */ - public static final int DEPJAR_NOWARNORERROR = 0; - /** Produce a warning upon a dependent <code>JAR</code> detection. */ - public static final int DEPJAR_WARNING = 1; - /** Produce an error message (throw an exception) upon a dependent <code>JAR</code> detection. */ - public static final int DEPJAR_ERROR = 2; - - /** - * Set the response of <b>jmake</b> in case a dependence of a class located in a <code>JAR</code> file on a - * class with a <code>.java</code> source is detected (such dependencies are highly discouraged, since it is not - * possible to recompile a class in the <code>JAR</code> that has no source). - * - * @param code response type: DEPJAR_NOWARNORERROR, DEPJAR_WARNING (default behaviour) or DEPJAR_ERROR. - */ - public void setResponseOnDependentJar(int code) { - switch (code) { - case DEPJAR_NOWARNORERROR: - noWarnOnDependentJar = true; - failOnDependentJar = false; - break; - case DEPJAR_WARNING: - noWarnOnDependentJar = false; - failOnDependentJar = false; - break; - case DEPJAR_ERROR: - noWarnOnDependentJar = false; - failOnDependentJar = true; - break; - } - } - - /** - * Return the names of all classes that <b>jmake</b>, on this invocation, found updated - either because - * <b>jmake</b> itself recompiled them or because they were updated independently (their timestamp/checksum - * found different from those contained in the project database). - */ - public String[] getUpdatedClasses() { - return pcdm.getAllUpdatedClassesAsStringArray(); - } - - /** - * Set the output print streams to be used by <b>jmake</b>. - * - * @see #customizeOutput(boolean, boolean, boolean) - * - * @param out print stream to be used for information ("logging") messages that <b>jmake</b> emits - * @param warn print stream to be used for warning messages - * @param err print stream to be used for error messages - */ - public static void setOutputStreams(PrintStream out, PrintStream warn, PrintStream err) { - Utils.setOutputStreams(out, warn, err); - } - - /** Get the version of this copy of <b>jmake</b> */ - public static String getVersion() { - return VERSION; - } - private static final String ERR_IS_INVALID_OPTION = - " is an invalid option or argument."; - private static final String ERR_NO_TWO_COMPILER_OPTIONS = - "You may not specify both compiler class and compiler executable application"; - private static final String ERR_SHOULD_BE_EXPLICIT = - " compiler option should be specified directly as a jmake option"; - - private static void bailOut(String s) { - throw new PrivateException(new PublicExceptions.InvalidCmdOptionException("jmake: " + s + "\nRun \"jmake -h\" for help.")); - } - - private static void optRequiresArg(String s) { - bailOut("the " + s + " option requires an argument."); - } - - private static void printUsage() { - Utils.printInfoMessage("Usage: jmake <options> <.java files> <@files>"); - Utils.printInfoMessage("where possible options include:"); - Utils.printInfoMessage(" -h, -help print this help message"); - Utils.printInfoMessage(" -version print the product version number"); - Utils.printInfoMessage(" -pdb <file name> specify non-default project database file"); - Utils.printInfoMessage(" -pdb-text-format if specified, pdb file is stored in text format"); - Utils.printInfoMessage(" -d <directory> specify where to place generated class files"); - Utils.printInfoMessage(" -classpath <path> specify where to find user class files"); - Utils.printInfoMessage(" -projclasspath <path> specify where to find sourceless project classes"); - Utils.printInfoMessage(" (currently only JARs are allowed on this path)"); - Utils.printInfoMessage(" -C<option> specify an option to be passed to the Java compiler"); - Utils.printInfoMessage(" (this option's arguments should also be preceded by -C)"); - Utils.printInfoMessage(" -jcpath <path> specify the class path for a non-default Java compiler"); - Utils.printInfoMessage(" (default is <JAVAHOME>/lib/tools.jar)"); - Utils.printInfoMessage(" -jcmainclass <class> specify the main class for a non-default Java compiler"); - Utils.printInfoMessage(" (default is com.sun.tools.javac.Main)"); - Utils.printInfoMessage(" -jcmethod <method> specify the method to call in the Java compiler class"); - Utils.printInfoMessage(" (default is \"compile(String args[])\")"); - Utils.printInfoMessage(" -jcexec <file name> specify a binary non-default Java compiler application"); - Utils.printInfoMessage(" -failondependentjar fail if a class on projectclasspath depends on a class"); - Utils.printInfoMessage(" with .java source (by default, a warning is issued)"); - Utils.printInfoMessage(" -nowarnondependentjar no warning or error if a class on projectclasspath"); - Utils.printInfoMessage(" depends on a class with a .java source (use with care)"); - Utils.printInfoMessage(" -warnlimit <number> specify the maximum number of warnings (20 by default)"); - Utils.printInfoMessage(" -bootclasspath <path> override location of bootstrap class files"); - Utils.printInfoMessage(" -extdirs <dirs> override location of installed extensions"); - Utils.printInfoMessage(" -vpath <dirs> a list of directories to search for Java and class files similar to GNUMake's VPATH"); - Utils.printInfoMessage(" -depfile <path> a file generated by the compiler containing additional java->class mappings"); - Utils.printInfoMessage(""); - Utils.printInfoMessage("Examples:"); - Utils.printInfoMessage(" jmake -d classes -classpath .;mylib.jar X.java Y.java Z.java"); - Utils.printInfoMessage(" jmake -pdb myproject.pdb -jcexec c:\\java\\jikes\\jikes.exe @myproject.src"); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/PCDContainer.java b/third_party/jmake/src/org/pantsbuild/jmake/PCDContainer.java deleted file mode 100644 index b02cfa4..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/PCDContainer.java +++ /dev/null
@@ -1,64 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.File; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * This class is a persistent container for the Project Class Directory, that can - * read and write itself from/to disk. - * - * @author Misha Dmitriev - * 12 November 2001 - */ -public class PCDContainer { - - /** The data structure (currently {@link LinkedHashMap}) for PCD, that maps class name to - record containing information about the class */ - Map<String,PCDEntry> pcd; - String storeName; - boolean textFormat; - - private PCDContainer(Map<String,PCDEntry> pcd, String storeName, boolean textFormat) { - this.storeName = storeName; - this.pcd = pcd; - this.textFormat = textFormat; - } - - public static PCDContainer load(String storeName, boolean textFormat) { - if (storeName == null) { - storeName = Main.DEFAULT_STORE_NAME; - } - File storeFile = Utils.checkFileForName(storeName); - if (storeFile != null) { - Utils.printInfoMessageNoEOL("Opening project database... "); - Map<String,PCDEntry> pcd; - if (textFormat) { - pcd = new TextProjectDatabaseReader().readProjectDatabaseFromFile(storeFile); - } else { - pcd = new BinaryProjectDatabaseReader().readProjectDatabaseFromFile(storeFile); - } - PCDContainer pcdc = new PCDContainer(pcd, storeName, textFormat); - Utils.printInfoMessage("Done."); - return pcdc; - } - return new PCDContainer(null, storeName, textFormat); - } - - public void save() { - Utils.printInfoMessageNoEOL("Writing project database... "); - File outfile = new File(storeName); - if (textFormat) { - new TextProjectDatabaseWriter().writeProjectDatabaseToFile(outfile, pcd); - } else { - new BinaryProjectDatabaseWriter().writeProjectDatabaseToFile(outfile, pcd); - } - Utils.printInfoMessage("Done."); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/PCDEntry.java b/third_party/jmake/src/org/pantsbuild/jmake/PCDEntry.java deleted file mode 100644 index 72fb3a4..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/PCDEntry.java +++ /dev/null
@@ -1,111 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.File; - -/** - * An instance of this class represents an entry in the Project Class Directory. - * - * @author Misha Dmitriev - * 29 March 2002 - */ -public class PCDEntry { - // Class versions compare results - - static final int CV_UNCHECKED = 0; - static final int CV_COMPATIBLE = 1; - static final int CV_INCOMPATIBLE = 2; - static final int CV_DELETED = 3; - static final int CV_NEW = 4; - static final int CV_NEWER_FOUND_NEARER = 5; - String className; // Dots are replaced with slashes for convenience - transient String classFileFullPath; - String javaFileFullPath; - long oldClassFileLastModified; - transient long newClassFileLastModified; - long oldClassFileFingerprint; - transient long newClassFileFingerprint; - ClassInfo oldClassInfo; - transient ClassInfo newClassInfo; - transient int checkResult; // Reflects the result of class version comparison - transient boolean checked; // Mark entries for classes that have been checked and found existing. - // It helps to detect double entries for the same class in the project file list, - // and also not to confuse them with the case when a .java source for a class is moved. - - /** This constructor is called to initialize a record for a class that has just been added to the project. */ - public PCDEntry(String className, - String javaFileFullPath, - String classFileFullPath, - long classFileLastModified, - long classFileFingerprint, - ClassInfo classInfo) { - this.className = className; - this.classFileFullPath = classFileFullPath; - this.javaFileFullPath = javaFileFullPath; - this.oldClassFileLastModified = this.newClassFileLastModified = - classFileLastModified; - this.oldClassFileFingerprint = this.newClassFileFingerprint = - classFileFingerprint; - this.newClassInfo = classInfo; - checked = true; - } - - /** - * This constructor is called to initialize a record for a class that - * exists at least in the previous version of the project. - */ - public PCDEntry(String className, - String javaFileFullPath, - long classFileLastModified, - long classFileFingerprint, - ClassInfo classInfo) { - this.className = className; - this.javaFileFullPath = javaFileFullPath; - this.oldClassFileLastModified = classFileLastModified; - this.oldClassFileFingerprint = classFileFingerprint; - this.oldClassInfo = classInfo; - } - - // Debugging - public String toString() { - return "className = " + className + - "; classFileFullPath = " + classFileFullPath + - "; javaFileFullPath = " + javaFileFullPath; - } - - /** - * Returns the name of the class that corresponds to the file name, i.e. the public class - */ - private String getExpectedClassName() { - File path = new File(javaFileFullPath); - int index = -1; - do { - index = className.indexOf('/', index + 1); - path = path.getParentFile(); - } while (index != -1); - String pathString = path.toString(); - if (!pathString.endsWith("/")) - pathString += "/"; - // It is assumed that the javaFileFillPath ends with .java - int javaPathWithoutSuffix = javaFileFullPath.length() - 5; - return javaFileFullPath.substring(pathString.length(), - javaPathWithoutSuffix); - } - - /** - * A class that neither has the same name as the java file, nor an inner class, is - * package-private. - */ - public boolean isPackagePrivateClass() { - String expectedClassName = getExpectedClassName(); - - return !(className.equals(expectedClassName) - || (className.startsWith(expectedClassName) - && className.charAt(expectedClassName.length()) == '$')); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/PCDManager.java b/third_party/jmake/src/org/pantsbuild/jmake/PCDManager.java deleted file mode 100644 index 5ff3cd1..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/PCDManager.java +++ /dev/null
@@ -1,1603 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.zip.Adler32; - -/** - * This class implements management of the Project Class Directory, automatic tracking - * of changes and recompilation of .java sources for a project. - * - * @author Misha Dmitriev - * 23 January 2003 - */ -public class PCDManager { - - private PCDContainer pcdc; - private Map<String,PCDEntry> pcd; // Maps project class names to PCDEntries - private String projectJavaAndJarFilesArray[]; - private String addedJavaAndJarFilesArray[], removedJavaAndJarFilesArray[], updatedJavaAndJarFilesArray[]; - private List<String> newJavaFiles; - private Set<String> updatedJavaFiles; - private Set<String> recompiledJavaFiles; - private Set<String> updatedClasses; // This set is emptied on every new internal jmake iteration... - private Set<String> allUpdatedClasses; // whereas in this one the names of all updated classes found during this jmake invocation are stored. - private Set<String> updatedAndCheckedClasses; - private Set<String> deletedClasses; - private Set<String> updatedJarFiles; - private Set<String> stableJarFiles; - private Set<String> newJarFiles; - private Set<String> deletedJarFiles; - /* Dependencies from the dependencyFile, if any */ - private Map<String, List<String>> extraDependencies; - - private String destDir; - private boolean destDirSpecified; - private List<String> javacAddArgs; - private Class<?> compilerClass; - private Method compileMethod; - private String jcExecApp; - private Object externalApp; - private Method externalCompileSourceFilesMethod; - private Adler32 checkSum; - private CompatibilityChecker cv; - private ClassFileReader cfr; - private boolean newProject = false; - private String dependencyFile = null; - private static boolean backSlashFileSeparator = File.separatorChar != '/'; - - /**** Interface to the class ****/ - /** - * Either projectJavaAndJarFilesArray != null and added.. == removed.. == updatedJavaAndJarFilesArray == null, - * or projectJavaAndJarFilesArray == null and one or more of others != null. - * When PCDManager is called from Main, this is guaranteed, since separate entrypoint functions initialize - * either one or another of the above argument groups, but never both. - */ - public PCDManager(PCDContainer pcdc, - String projectJavaAndJarFilesArray[], - String addedJavaAndJarFilesArray[], - String removedJavaAndJarFilesArray[], - String updatedJavaAndJarFilesArray[], - String in_destDir, - List<String> javacAddArgs, - boolean failOnDependentJar, - boolean noWarnOnDependentJar, - String dependencyFile) { - this.pcdc = pcdc; - if (pcdc.pcd == null) { - pcd = new LinkedHashMap<String,PCDEntry>(); - pcdc.pcd = pcd; - newProject = true; - } else { - pcd = pcdc.pcd; - } - - this.projectJavaAndJarFilesArray = projectJavaAndJarFilesArray; - this.addedJavaAndJarFilesArray = addedJavaAndJarFilesArray; - this.removedJavaAndJarFilesArray = removedJavaAndJarFilesArray; - this.updatedJavaAndJarFilesArray = updatedJavaAndJarFilesArray; - this.dependencyFile = dependencyFile; - newJavaFiles = new ArrayList<String>(); - updatedJavaFiles = new LinkedHashSet<String>(); - recompiledJavaFiles = new LinkedHashSet<String>(); - updatedAndCheckedClasses = new LinkedHashSet<String>(); - deletedClasses = new LinkedHashSet<String>(); - allUpdatedClasses = new LinkedHashSet<String>(); - - updatedJarFiles = new LinkedHashSet<String>(); - stableJarFiles = new LinkedHashSet<String>(); - newJarFiles = new LinkedHashSet<String>(); - deletedJarFiles = new LinkedHashSet<String>(); - - initializeDestDir(in_destDir); - this.javacAddArgs = javacAddArgs; - - checkSum = new Adler32(); - - cv = new CompatibilityChecker(this, failOnDependentJar, noWarnOnDependentJar); - cfr = new ClassFileReader(); - } - - public Collection<PCDEntry> entries() { - return pcd.values(); - } - - public ClassFileReader getClassFileReader() { - return cfr; - } - - public ClassInfo getClassInfoForName(int verCode, String className) { - PCDEntry pcde = pcd.get(className); - if (pcde != null) { - return getClassInfoForPCDEntry(verCode, pcde); - } else { - return null; - } - } - - public boolean isProjectClass(int verCode, String className) { - if (verCode == ClassInfo.VER_OLD) { - return pcd.containsKey(className); - } else { - PCDEntry pcde = pcd.get(className); - return (pcde != null && pcde.checkResult != PCDEntry.CV_DELETED); - } - } - - /** - * Get an instance of ClassInfo (load a class file if necessary) for the given version (old or new) of - * the class determined by pcde. For an old class version, always returns a non-null result; but for a new - * version, null is returned if class file is not found. In most of the current uses of this method null result - * is not checked, because it's either called for an old version or it is already known that the .class file - * should be present; nevertheless, beware! - */ - public ClassInfo getClassInfoForPCDEntry(int verCode, PCDEntry pcde) { - if (verCode == ClassInfo.VER_OLD) { - return pcde.oldClassInfo; - } - - ClassInfo res = pcde.newClassInfo; - if (res == null) { - byte classFileBytes[]; - String classFileFullPath = null; - if (pcde.javaFileFullPath.endsWith(".java")) { - File classFile = Utils.checkFileForName(pcde.classFileFullPath); - if (classFile == null) { - return null; // Class file not found. - } - classFileBytes = Utils.readFileIntoBuffer(classFile); - classFileFullPath = pcde.classFileFullPath; - } else { - try { - JarFile jarFile = new JarFile(pcde.javaFileFullPath); - JarEntry jarEntry = - jarFile.getJarEntry(pcde.className + ".class"); - if (jarEntry == null) { - return null; - } - classFileBytes = - Utils.readZipEntryIntoBuffer(jarFile, jarEntry); - } catch (IOException ex) { - throw new PrivateException(ex); - } - } - res = - new ClassInfo(classFileBytes, verCode, this, classFileFullPath); - pcde.newClassInfo = res; - } - return res; - } - - /** - * Returns null if class is compileable (has a .java source) and not recompiled yet, "" if - * class has already been recompiled or has been deleted from project, and the class's .jar - * name if class comes from a jar, hence is uncompileable. - */ - public String classAlreadyRecompiledOrUncompileable(String className) { - PCDEntry pcde = pcd.get(className); - if (pcde == null) { - //!!! - for (String keyName : pcd.keySet()) { - PCDEntry entry = pcd.get(keyName); - if (entry.className.equals(className)) { - System.out.println("ERROR: inconsistent entry: key = " + - keyName + ", name in entry = " + entry.className); - } - } - //!!! - throw internalException(className + " not in project when it should be"); - } - if (pcde.checkResult == PCDEntry.CV_DELETED) { - return ""; - } - if (pcde.javaFileFullPath.endsWith(".jar")) { - return pcde.javaFileFullPath; - } else { - return (recompiledJavaFiles.contains(pcde.javaFileFullPath) ? "" : null); - } - } - - /** - * Compiler initialization depends on compiler type specified. - * If jcExecApp != null, i.e. an external executable compiler application is used, and nothing has to be done. - * If externalApp != null, that is, jmake is called by an external application such as Ant, which - * manages compilation in its own way, and also nothing has to be done. - * Otherwise, load the compiler class and method (either specified through jcPath, jcMainClass and jcMethod, - * or the default one. - */ - public void initializeCompiler(String jcExecApp, - String jcPath, String jcMainClass, String jcMethod, - Object externalApp, Method externalCompileSourceFilesMethod) { - ClassPath.initializeAllClassPaths(); - - if (externalApp != null) { - this.externalApp = externalApp; - this.externalCompileSourceFilesMethod = - externalCompileSourceFilesMethod; - return; - } - if (jcExecApp != null) { - this.jcExecApp = jcExecApp; - return; - } - - if (jcPath == null) { - String javaHome = System.getProperty("java.home"); - // In my tests it ends with '/jre'. Or it could be ending with '/bin' as well? Let's assume it can be both and delete - // this latter directory. - if (javaHome.endsWith(File.separator + "jre") || javaHome.endsWith(File.separator + "bin")) { - javaHome = javaHome.substring(0, javaHome.length() - 4); - } - jcPath = javaHome + "/lib/tools.jar"; - } - ClassLoader compilerLoader; - try { - compilerLoader = ClassPath.getClassLoaderForPath(jcPath); - } catch (Exception ex) { - throw compilerInteractionException("error opening compiler path", ex, 0); - } - - if (jcMainClass == null) { - jcMainClass = "com.sun.tools.javac.Main"; - } - if (jcMethod == null) { - jcMethod = "compile"; - } - - try { - compilerClass = compilerLoader.loadClass(jcMainClass); - } catch (ClassNotFoundException e) { - throw compilerInteractionException("error loading compiler main class " + jcMainClass, e, 0); - } - - Class<?>[] args = new Class<?>[]{String[].class}; - try { - compileMethod = compilerClass.getMethod(jcMethod, args); - } catch (Exception e) { - throw compilerInteractionException("error getting method com.sun.tools.javac.Main.compile(String args[])", e, 0); - } - } - - /** Main entrypoint for this class */ - public void run() { - Utils.startTiming(Utils.TIMING_SYNCHRO); - synchronizeProjectFilesAndPCD(); - Utils.stopAndPrintTiming("Synchro", Utils.TIMING_SYNCHRO); - Utils.printTiming("of which synchro check file", Utils.TIMING_SYNCHRO_CHECK_JAVA_FILES); - - Utils.startTiming(Utils.TIMING_FIND_UPDATED_JAVA_FILES); - findUpdatedJavaAndJarFiles(); - Utils.stopAndPrintTiming("findUpdatedJavaAndJarFiles", Utils.TIMING_FIND_UPDATED_JAVA_FILES); - Utils.printTiming("of which classFileObsoleteOrDeleted", Utils.TIMING_CLASS_FILE_OBSOLETE_OR_DELETED); - - // Let's free some memory - projectJavaAndJarFilesArray = null; - - updatedClasses = new LinkedHashSet<String>(); - dealWithClassesInUpdatedJarFiles(); - - int iterNo = 0; - int res = 0; - while (iterNo == 0 || updatedJavaFiles.size() != 0 || newJavaFiles.size() != 0) { - // It may happen that we didn't find any updated or new .java files. However, we still need to enter - // this loop because there may be some class files that need compatibility checking. This can happen - // either if somebody had recompiled their sources bypassing jmake, or if their checking during the - // previous invocation of jmake failed, because their dependent code recompilation failed. - if (updatedJavaFiles.size() > 0 || newJavaFiles.size() > 0) { - Utils.startTiming(Utils.TIMING_COMPILE); - int intermediateRes = recompileUpdatedJavaFiles(); - Utils.stopAndPrintTiming("Compile", Utils.TIMING_COMPILE); - if (intermediateRes != 0) { - res = intermediateRes; - } - } - - Utils.startTiming(Utils.TIMING_PDBUPDATE); - // New classes can be added to pdb only if compilation was successful, i.e. the new project version is consistent. - if (iterNo++ == 0 && res == 0) { - findClassFilesForNewJavaAndJarFiles(); - findClassFilesForUpdatedJavaFiles(); - dealWithNestedClassesForUpdatedJavaFiles(); - } - Utils.stopAndPrintTiming("Entering new classes in PDB", Utils.TIMING_PDBUPDATE); - - updatedJavaFiles.clear(); - newJavaFiles.clear(); - - Utils.startTiming(Utils.TIMING_FIND_UPDATED_CLASSES); - findUpdatedClasses(); - Utils.stopAndPrintTiming("Find updated classes", Utils.TIMING_FIND_UPDATED_CLASSES); - - Utils.startTiming(Utils.TIMING_CHECK_UPDATED_CLASSES); - checkDeletedClasses(); - checkUpdatedClasses(); - Utils.stopAndPrintTiming("Check updated classes", Utils.TIMING_CHECK_UPDATED_CLASSES); - - updatedClasses = new LinkedHashSet<String>(); - if (ClassPath.getVirtualPath() != null) { - if (res != 0) - break; - } - } - - Utils.startTiming(Utils.TIMING_PDBWRITE); - updateClassFilesInfoInPCD(res); - pcdc.save(); - Utils.stopAndPrintTiming("PDB write", Utils.TIMING_PDBWRITE); - - if (res != 0) { - throw compilerInteractionException("compilation error(s)", null, res); - } - } - - /** - * Find the newly-created class files for existing java files. - */ - private void findClassFilesForUpdatedJavaFiles() { - if (dependencyFile == null) - return; - - Set<String> allClasses = new HashSet<String>(); - - Map<String, List<String>> dependencies = parseDependencyFile(); - for (String file : updatedJavaFiles) { - List<String> myDeps = dependencies.get(file); - if (myDeps != null) { - PCDEntry parent = getNamedPCDE(file, dependencies); - for (String dependency : myDeps) { - allClasses.add(dependency); - if (pcd.containsKey(dependency)) - continue; - findClassFileOnFilesystem(file, parent, dependency, false); - } - } - } - for (Map.Entry<String, PCDEntry> entry : pcd.entrySet()) { - String cls = entry.getKey(); - if (!allClasses.contains(cls)) { - PCDEntry pcde = entry.getValue(); - if (updatedJavaFiles.contains(pcde.javaFileFullPath)) { - deletedClasses.add(cls); - } - } - } - } - - public String[] getAllUpdatedClassesAsStringArray() { - String[] res = new String[allUpdatedClasses.size()]; - int i = 0; - for (String updatedClass : allUpdatedClasses) { - res[i++] = updatedClass.replace('/', '.'); - } - return res; - } - - /** - * Synchronize projectJavaAndJarFilesArray and PCD, i.e. leave only those entries in the PCD which have their - * .java (.jar) files in projectJavaAndJarFilesArray. New .java files in projectJavaAndJarFilesArray (i.e. those - * for which there are no entries in the PCD yet) are added to newJavaFiles; new .jar files are added to newJarFiles. - * Alternatively, just use the supplied arrays of added and deleted .java and .jar files. - * - * For entries whose .java files are not in the PCD anymore, try to delete .class files. We need to do that before - * compilation to avoid the situation when a .java file is removed but compilation succeeds because the .class file - * is still there. - * - * Unfortunately, we also need to delete all class files for non-nested classes whose names differ from their .java - * file name, because we can't tell when they've been removed from their .java files -- but it's only safe to do this - * for files that originate from java files that we're compiling this round. - * - * Upon return from this method, all of the .java and .jar files in the PCD are known to exist. - */ - private void synchronizeProjectFilesAndPCD() { - if (projectJavaAndJarFilesArray != null) { - Set<String> pcdJavaFilesSet = new LinkedHashSet<String>(pcd.size() * 3 / 2); - for(PCDEntry entry : entries()) { - pcdJavaFilesSet.add(entry.javaFileFullPath); - } - - Set<String> canonicalPJF = - new LinkedHashSet<String>(projectJavaAndJarFilesArray.length * 3 / 2); - - // Add .java files that are not in PCD to newJavaFiles; add .jar files that are not in PCD to newJarFiles. - for (int i = 0; i < projectJavaAndJarFilesArray.length; i++) { - String projFileName = projectJavaAndJarFilesArray[i]; - Utils.startTiming(Utils.TIMING_SYNCHRO_CHECK_TMP); - File projFile = Utils.checkFileForName(projFileName); - Utils.stopAndAddTiming(Utils.TIMING_SYNCHRO_CHECK_TMP, Utils.TIMING_SYNCHRO_CHECK_JAVA_FILES); - if (projFile == null) { - throw new PrivateException(new FileNotFoundException("specified source file " + projFileName + " not found.")); - } - // The main reason for using getAbsolutePath() instead of more reliable getCanonicalPath() is the fact that - // sometimes users may name the actual files containing Java code in some custom way, and give javac/jmake - // symbolic links to these files (that have correct .java names) instead. getCanonicalPath(), however, returns the - // real (i.e. user custom) file name, which will confuse our test below and then javac. - String absoluteProjFileName = projFile.getAbsolutePath(); - // On Windows, make sure the drive letter is always in lower case - if (backSlashFileSeparator) { - absoluteProjFileName = - Utils.convertDriveLetterToLowerCase(absoluteProjFileName); - } - canonicalPJF.add(absoluteProjFileName); - if (!pcdJavaFilesSet.contains(absoluteProjFileName)) { - if (absoluteProjFileName.endsWith(".java")) { - newJavaFiles.add(absoluteProjFileName); - } else if (absoluteProjFileName.endsWith(".jar")) { - newJarFiles.add(absoluteProjFileName); - } else { - throw new PrivateException(new PublicExceptions.InvalidSourceFileExtensionException("specified source file " + projFileName + " has an invalid extension (not .java or .jar).")); - } - } - } - - // Find the entries containing .java or .jar files that are not in project anymore - for (Entry<String, PCDEntry> entry : pcd.entrySet()) { - String key = entry.getKey(); - PCDEntry e = entry.getValue(); - e.oldClassInfo.restorePCDM(this); - if (canonicalPJF.contains(e.javaFileFullPath)) { - if (e.isPackagePrivateClass()) { - initializeClassFileFullPath(e); - new File(e.classFileFullPath).delete(); - } - } else { - if (ClassPath.getVirtualPath() == null) { - deletedClasses.add(key); - } else { - // Okay, not found locally, but virtual path was defined, so try it now.... - if ( (e.oldClassFileFingerprint == projectJavaAndJarFilesArray.length && - newJavaFiles.size() == 0) || - Utils.checkFileForName(e.javaFileFullPath) != null) - { - e.checkResult = PCDEntry.CV_NEWER_FOUND_NEARER; - e.oldClassFileFingerprint = projectJavaAndJarFilesArray.length; - } - else - { - String classFound = null; - String sourceFound = null; - // Find source and class file via virtual path - String path = ClassPath.getVirtualPath(); - // TODO(Eric Ayers): IntelliJ static analysis shows several useless - // expressions that make this loop a no-op. - for (StringTokenizer st = new StringTokenizer(path, File.pathSeparator); - !(classFound != null && sourceFound != null) && st.hasMoreTokens();) - { - String fullPath = st.nextToken()+File.separator+e.className; - if (sourceFound != null && new File(fullPath+".java").exists()) - { - sourceFound = fullPath + ".java"; - } - if (classFound != null && new File(fullPath+".class").exists()) - { - classFound = fullPath + ".class"; - } - } - // TODO(Eric Ayers): IntelliJ static analysis shows that this expression - // is always true. - if (classFound == null) - { - deletedClasses.add(key); - if (e.javaFileFullPath.endsWith(".jar")) - { - deletedJarFiles.add(e.javaFileFullPath); - } - else - { - initializeClassFileFullPath(e); - (new File(e.classFileFullPath)).delete(); - } - } - else if (sourceFound != null) - { - newJavaFiles.add(sourceFound); - e.checkResult = PCDEntry.CV_NEWER_FOUND_NEARER; - e.oldClassFileFingerprint = projectJavaAndJarFilesArray.length; - } - else - { - classFound = classFound.replace('/', File.separatorChar); - throw new PrivateException(new FileNotFoundException("deleted class " + classFound + " still exists.")); - } - } - } - if (e.javaFileFullPath.endsWith(".jar")) { - deletedJarFiles.add(e.javaFileFullPath); - } else { // Try to delete a class file for the removed project class. - initializeClassFileFullPath(e); - (new File(e.classFileFullPath)).delete(); - } - } - } - } else { // projectJavaAndJarFilesArray == null - use supplied arrays of added and removed .java and .jar files - if (addedJavaAndJarFilesArray != null) { - for (String fileName : addedJavaAndJarFilesArray) { - fileName = fileName.intern(); - if (fileName.endsWith(".java")) { - newJavaFiles.add(fileName); - } else if (fileName.endsWith(".jar")) { - newJarFiles.add(fileName); - } else { - throw new PrivateException(new PublicExceptions.InvalidSourceFileExtensionException( - "specified source file " + fileName + " has an invalid extension (not .java or .jar).")); - } - } - } - - Set<String> removedJavaAndJarFilesSet = null; - if (removedJavaAndJarFilesArray != null) { - removedJavaAndJarFilesSet = new LinkedHashSet<String>(); - for (String fileName : removedJavaAndJarFilesArray) { - fileName = fileName.intern(); - removedJavaAndJarFilesSet.add(fileName); - if (fileName.endsWith(".jar")) { - deletedJarFiles.add(fileName); - } - } - } - - for (Entry<String, PCDEntry> entry : pcd.entrySet()) { - String key = entry.getKey(); - PCDEntry e = entry.getValue(); - e.oldClassInfo.restorePCDM(this); - if (removedJavaAndJarFilesSet != null && - removedJavaAndJarFilesSet.contains(e.javaFileFullPath)) { - deletedClasses.add(key); - if (!e.javaFileFullPath.endsWith(".jar")) { // Try to delete a class file for the removed project class. - initializeClassFileFullPath(e); - (new File(e.classFileFullPath)).delete(); - } - } - } - } - } - - /** - * In the end of run, update the information in the project database for the class files which have - * been updated and checked, or deleted. If compilationResult == 0, i.e. all recompilations were - * successful, information for new versions of all of the classes is made permanent, and entries - * for deleted classes are removed permanently. Otherwise, information is updated only for those - * classes whose old and new versions were found source compatible. - */ - private void updateClassFilesInfoInPCD(int compilationResult) { - // If the project appears to be inconsistent after changes, make a preliminary pass that will deal with enclosing - // classes for deleted nested classes. The problem with them can be as follows: we delete a nested class C$X, - // which is still referenced from somewhere. However, C has not changed at all or at least incompatibly, and - // thus we update its PCDEntry, which now does not reference C$X. Other parts of jmake require that a nested - // class is always referenced from its directly enclusing class, thus to keep the PCD consistent we have to remove - // C$X from the PCD. On the next invocation of jmake, C$X is not in the PDB at all, and thus any classes that - // may still reference it and have not been updated are not checked => project becomes inconsistent. We could do - // better by immediately marking enclosing classes incompatible once we detect that a deleted nested class is - // really referenced from somewhere, but the solution below seems to be more robust. - if (compilationResult != 0) { - for (String className : updatedAndCheckedClasses) { - PCDEntry entry = pcd.get(className); - if (entry.checkResult == PCDEntry.CV_DELETED && - !"".equals(entry.oldClassInfo.directlyEnclosingClass)) { - PCDEntry enclEntry = - pcd.get(entry.oldClassInfo.directlyEnclosingClass); - enclEntry.checkResult = PCDEntry.CV_INCOMPATIBLE; - } - } - } - - for (String className : updatedAndCheckedClasses) { - PCDEntry entry = pcd.get(className); - if (entry.checkResult == PCDEntry.CV_UNCHECKED) { - continue; - } - if (ClassPath.getVirtualPath() != null) { - if (entry.checkResult == PCDEntry.CV_NEWER_FOUND_NEARER) { - continue; - } - } - if (entry.checkResult == PCDEntry.CV_DELETED) { - if (compilationResult == 0) { - pcd.remove(className); // Only if consistency checking is ok, a deleted class can be safely removed from the PCD - } - } else if (entry.checkResult == PCDEntry.CV_COMPATIBLE || - entry.checkResult == PCDEntry.CV_NEW || - (entry.checkResult == PCDEntry.CV_INCOMPATIBLE && compilationResult == 0)) { - if (entry.newClassInfo == null) { // "Safety net" for the (hopefully unlikely) case we overlooked something before... - Utils.printWarningMessage("Warning: internal information inconsistency detected during pdb updating"); - Utils.printWarningMessage(Utils.REPORT_PROBLEM); - Utils.printWarningMessage("Class name: " + className); - if (entry.checkResult == PCDEntry.CV_NEW) { - pcd.remove(className); - } else { - continue; - } - } - entry.oldClassFileLastModified = entry.newClassFileLastModified; - entry.oldClassFileFingerprint = entry.newClassFileFingerprint; - entry.oldClassInfo = entry.newClassInfo; - } - } - } - - /** - * Find all .java files on the filesystem, for which the .class file does not exist - * or is newer than the .java file. Also find all .jar files for which the timestamp - * has changed. Alternatively, just use the supplied array of updated .java/.jar files. - */ - private void findUpdatedJavaAndJarFiles() { - boolean projectSpecifiedAsAllSources = - projectJavaAndJarFilesArray != null; - for (PCDEntry entry : entries()) { - if (deletedClasses.contains(entry.className)) { - continue; - } - if (entry.javaFileFullPath.endsWith(".java")) { - initializeClassFileFullPath(entry); - if (projectSpecifiedAsAllSources) { - if (ClassPath.getVirtualPath() != null) { - String paths[] = ClassPath.getVirtualPath().split(File.pathSeparator); - String tmpClassName = entry.className; - tmpClassName = tmpClassName.replaceAll("\\Q$\\E.*$", ""); - for (int i=0; i<paths.length; i++) { - String tmpFilename = paths[i] + File.separator + tmpClassName + ".java"; - File tmpFile = new File(tmpFilename); - if (tmpFile.exists()) { - entry.javaFileFullPath = tmpFile.getAbsolutePath(); - break; - } - } - } - Utils.startTiming(Utils.TIMING_CLASS_FILE_OBSOLETE_TMP); - if (classFileObsoleteOrDeleted(entry)) { - updatedJavaFiles.add(entry.javaFileFullPath); - } - Utils.stopAndAddTiming(Utils.TIMING_CLASS_FILE_OBSOLETE_TMP, Utils.TIMING_CLASS_FILE_OBSOLETE_OR_DELETED); - } - entry.checked = true; - } else { // Class coming from a .jar file. Mark this entry as checked only if its JAR hasn't changed - if (projectJavaAndJarFilesArray != null) { - entry.checked = !checkJarFileForUpdate(entry); - } - } - } - - // Lists of updated/added/deleted source files specified instead of a full list of project sources - if (!projectSpecifiedAsAllSources && updatedJavaAndJarFilesArray != null) { - for (int i = 0; i < updatedJavaAndJarFilesArray.length; i++) { - if (updatedJavaAndJarFilesArray[i].endsWith(".java")) { - updatedJavaFiles.add(updatedJavaAndJarFilesArray[i]); - } else { - updatedJarFiles.add(updatedJavaAndJarFilesArray[i]); - } - } - } - } - - private boolean classFileObsoleteOrDeleted(PCDEntry entry) { - if (ClassPath.getVirtualPath() != null) { - File file1 = new File(entry.javaFileFullPath); - if (!file1.exists()) - throw new PrivateException(new FileNotFoundException("specified source file " + - entry.javaFileFullPath + " not found.")); - if (file1.lastModified() < entry.oldClassFileLastModified) - { - return false; - } - } - File classFile = Utils.checkFileForName(entry.classFileFullPath); - if (classFile == null || !classFile.exists()) { - return true; // Class file has been deleted - } - File javaFile = new File(entry.javaFileFullPath); // Guaranteed to exist at this point - if (classFile.lastModified() <= javaFile.lastModified()) { - return true; - } - return false; - } - - private boolean checkJarFileForUpdate(PCDEntry entry) { - String jarFileName = entry.javaFileFullPath; - if (stableJarFiles.contains(jarFileName)) { - return false; - } else if (updatedJarFiles.contains(jarFileName) || - newJarFiles.contains(jarFileName) || - deletedJarFiles.contains(jarFileName)) { - return true; - } else { - File jarFile = new File(jarFileName); // Guaranteed to exist at this point. - if (entry.oldClassFileLastModified != jarFile.lastModified()) { - updatedJarFiles.add(jarFileName); - return true; - } else { - stableJarFiles.add(jarFileName); - return false; - } - } - } - - public int recompileUpdatedJavaFiles() { - if (externalApp != null) { - return recompileUpdatedJavaFilesUsingExternalMethod(); - } else { - return recompileUpdatedJavaFilesOurselves(); - } - } - - private int recompileUpdatedJavaFilesOurselves() { - int filesNo = updatedJavaFiles.size() + newJavaFiles.size(); - int addArgsNo = javacAddArgs.size(); - int argsNo = addArgsNo + filesNo + 2; - String compilerBootClassPath, compilerExtDirs; - if ((compilerBootClassPath = ClassPath.getCompilerBootClassPath()) != null) { - argsNo += 2; - } - if ((compilerExtDirs = ClassPath.getCompilerExtDirs()) != null) { - argsNo += 2; - } - if (jcExecApp != null) { - argsNo++; - } - String args[] = new String[argsNo]; - int pos = 0; - if (jcExecApp != null) { - args[pos++] = jcExecApp; - } - for (int i = 0; i < addArgsNo; i++) { - args[pos++] = javacAddArgs.get(i); - } - args[pos++] = "-classpath"; - args[pos++] = ClassPath.getCompilerUserClassPath(); - if (compilerBootClassPath != null) { - args[pos++] = "-bootclasspath"; - args[pos++] = compilerBootClassPath; - } - if (compilerExtDirs != null) { - args[pos++] = "-extdirs"; - args[pos++] = compilerExtDirs; - } - if (!newProject) { - Utils.printInfoMessage("Recompiling source files:"); - } - for (String javaFileFullPath : updatedJavaFiles) { - if (!newProject) { - Utils.printInfoMessage(javaFileFullPath); - } - recompiledJavaFiles.add(args[pos++] = javaFileFullPath); - } - for (int j = 0; j < newJavaFiles.size(); j++) { - String javaFileFullPath = newJavaFiles.get(j); - if (!newProject) { - Utils.printInfoMessage(javaFileFullPath); - } - recompiledJavaFiles.add(args[pos++] = javaFileFullPath); - } - - if (jcExecApp == null) { // Executing javac or some other compiler within the same JVM - Object reflectArgs[] = new Object[1]; - reflectArgs[0] = args; - try { - Object dummy = compilerClass.newInstance(); - Integer res = (Integer) compileMethod.invoke(dummy, reflectArgs); - return res.intValue(); - } catch (Exception e) { - throw compilerInteractionException("exception thrown when trying to invoke the compiler method", e, 0); - } - } else { // Executing an external Java compiler, such as jikes - int exitCode = 0; - try { - Process p = Runtime.getRuntime().exec(args); - InputStream pErr = p.getErrorStream(); - InputStream pOut = p.getInputStream(); - boolean terminated = false; - - while (!terminated) { - try { - exitCode = p.exitValue(); - terminated = true; - } catch (IllegalThreadStateException itse) { // Process not yet terminated, wait for some time - Utils.ignore(itse); - Utils.delay(100); - } - try { - Utils.readAndPrintBytesFromStream(pErr, System.err); - Utils.readAndPrintBytesFromStream(pOut, System.out); - } catch (IOException ioe1) { - throw compilerInteractionException("I/O error when reading the compiler application output", ioe1, exitCode); - } - } - return exitCode; - } catch (IOException ioe2) { - throw compilerInteractionException("I/O error when trying to invoke the compiler application", ioe2, exitCode); - } - } - } - - /** Execution under complete control of external app - use externally supplied method to recompile classes */ - private int recompileUpdatedJavaFilesUsingExternalMethod() { - int filesNo = updatedJavaFiles.size() + newJavaFiles.size(); - String[] fileNames = new String[filesNo]; - int i = 0; - for (String updatedFile : updatedJavaFiles) { - recompiledJavaFiles.add(fileNames[i] = updatedFile); - } - for (int j = 0; j < newJavaFiles.size(); j++) { - recompiledJavaFiles.add(fileNames[i++] = newJavaFiles.get(j)); - } - - try { - Integer res = - (Integer) externalCompileSourceFilesMethod.invoke(externalApp, new Object[]{fileNames}); - return res.intValue(); - } catch (IllegalAccessException e1) { - throw compilerInteractionException("compiler method is not accessible", e1, 0); - } catch (IllegalArgumentException e2) { - throw compilerInteractionException("illegal arguments passed to compiler method", e2, 0); - } catch (InvocationTargetException e3) { - throw compilerInteractionException("exception when executing the compiler method", e3, 0); - } - } - - /** - * For each .java file from newJavaFiles, find all of the .class files, the names of which we can - * logically deduce (a top-level class with the same name, and all of the nested classes), - * and put the info on them into the PCD. Also include any class files from the dependencyFile, - * if any. For each .jar file from newJarFiles, find all of the .class files in that archive and - * put info on them into the PCD. - */ - private void findClassFilesForNewJavaAndJarFiles() { - for (String javaFileFullPath : newJavaFiles) { - PCDEntry pcde = - findClassFileOnFilesystem(javaFileFullPath, null, null, false); - - if (pcde == null) { - // .class file not found - possible compilation error - if (missingClassIsOk(javaFileFullPath)) { - continue; - } else { - throw new PrivateException(new PublicExceptions.ClassNameMismatchException( - "Could not find class file for " + javaFileFullPath)); - } - } - Set<String> entries = new HashSet<String>(); - if (pcde.checkResult == PCDEntry.CV_NEW) { // It's really a new .java file, not a moved one - entries.addAll(findAndUpdateAllNestedClassesForClass(pcde, false)); - } else { - entries.addAll(findAndUpdateAllNestedClassesForClass(pcde, true)); - } - entries.add(pcde.className); - if (dependencyFile != null) { - Map<String, List<String>> dependencies = parseDependencyFile(); - List<String> myDeps = dependencies.get(javaFileFullPath); - if (myDeps != null) { - for (String dependency : myDeps) { - if (entries.contains(dependency)) - continue; - findClassFileOnFilesystem(javaFileFullPath, pcde, - dependency, false); - } - } - } - } - - for (String newJarFile : newJarFiles) { - processAllClassesFromJarFile(newJarFile); - } - } - - /** - * Parse an extra dependency file. The format of the file is a series of lines, - * each consisting of: - * SourceFileName.java -> ClassName - * (these file names are relative to destDir) - */ - private Map<String, List<String>> parseDependencyFile() { - if (!destDirSpecified) - throw new RuntimeException("Dependency files require destDir"); - if (extraDependencies != null) - return extraDependencies; - BufferedReader in = null; - try { - extraDependencies = new HashMap<String, List<String>>(); - in = new BufferedReader(new FileReader(dependencyFile)); - int lineNumber = 0; - while (true) { - lineNumber ++; - String line = in.readLine(); - if (line == null) - break; - String[] parts = line.split("->"); - if (parts.length != 2) { - throw new RuntimeException("Failed to parse line " + lineNumber + " of " + dependencyFile - + ". Expected {foo.java} -> {classname}."); - } - String src = parts[0].trim(); - src = new File(destDir, src).getCanonicalPath(); - String cls = parts[1].trim(); - List<String> classes = extraDependencies.get(src); - if (classes == null) { - classes = new ArrayList<String>(); - extraDependencies.put(src, classes); - } - cls = cls.substring(0, cls.length() - 6); // strip trailing ".class" - classes.add(cls); - } - } catch (IOException e) { - throw new PrivateException(e); - } finally { - if (in != null) - try { - in.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - return extraDependencies; - } - - /** - * In most cases we want to fail the build if a class cannot be found. - * - * However there is one common valid case where a .java file might not contain - * a class: package-info.java files. - * - * See this doc for more info: http://docs.oracle.com/javase/specs/jls/se7/html/jls-7.html - */ - private boolean missingClassIsOk(String javaFileFullPath) { - return javaFileFullPath != null && "package-info.java".equals(new File(javaFileFullPath).getName()); - } - - /** - * Find the .class file for the given javaFileFullPath and create a new PCDEntry for it. - * If enclosingClassPCDE is null, the named top-level class for the given .java file is looked up. - * Otherwise, the specified class specified by nestedClassFullName is looked up. - */ - private PCDEntry findClassFileOnFilesystem(String javaFileFullPath, PCDEntry enclosingClassPCDE, String nestedClassFullName, boolean isNested) { - String classFileFullPath = null; - String fullClassName; - File classFile = null; - - if (enclosingClassPCDE == null) { // Looking for a top-level class. May need to locate an appropriate directory. - // Remove the ".java" suffix. A Windows disk-name prefix, such as 'c:', will be cut off later automatically - fullClassName = - javaFileFullPath.substring(0, javaFileFullPath.length() - 5); - if (destDirSpecified) { - // Search for the .class file. We first assume the longest possible name. In case of failure, - // we cut the assumed top-most package from it and repeat the search. - while (classFile == null) { - classFileFullPath = destDir + fullClassName + ".class"; - classFile = Utils.checkFileForName(classFileFullPath); - if (classFile == null) { - int cutIndex = fullClassName.indexOf(File.separatorChar); - if (cutIndex == -1) { - // Most probably, there was an error during compilation of this file. - // This does not prevent us from continuing. - Utils.printWarningMessage("Warning: unable to find .class file corresponding to source " + javaFileFullPath + ": expected " + classFileFullPath); - - return null; - } - fullClassName = fullClassName.substring(cutIndex + 1); - } - } - } else { - classFileFullPath = fullClassName + ".class"; - classFile = Utils.checkFileForName(classFileFullPath); - if (classFile == null) { - Utils.printWarningMessage("Warning: unable to find .class file corresponding to source " + javaFileFullPath); - return null; - } - } - } else { // Looking for a nested class, which always sits in the same directory as its enclosing class - classFileFullPath = - Utils.getClassFileFullPathForNestedClass(enclosingClassPCDE.classFileFullPath, nestedClassFullName); - classFile = Utils.checkFileForName(classFileFullPath); - if (classFile == null) { - Utils.printWarningMessage("Warning: unable to find .class file corresponding to nested class " + nestedClassFullName); - return null; - } - fullClassName = nestedClassFullName; - } - - if (backSlashFileSeparator) { - fullClassName = fullClassName.replace(File.separatorChar, '/'); - } - - byte classFileBytes[] = Utils.readFileIntoBuffer(classFile); - ClassInfo classInfo = - new ClassInfo(classFileBytes, ClassInfo.VER_NEW, this, classFileFullPath); - if (isNested) { - if (!classInfo.directlyEnclosingClass.equals(enclosingClassPCDE.newClassInfo.name)) { - // Check if the above strings are like A and A$1. If so, there is actually no problem - the correct - // answer is A$1. The reason why just A was determined as a directly enclosing class when parsing - // class classInfo is due to the ambiguous interpretation of names like A$1$B. Such a name may mean - // (1) a non-member local nested class B of A, or (2) a member class B of an anonymous nested class A$1. - // When parsing any non-toplevel class, the first interpretation is always used. - // NOTE FOR JDK 1.5 - starting from this version, there is no ambiguity anymore. - // (1) will be called A$1B, and (2) will still be A$1$B - String a = classInfo.directlyEnclosingClass; - String ad1 = enclosingClassPCDE.newClassInfo.name; - if (!((classInfo.javacTargetRelease == Utils.JAVAC_TARGET_RELEASE_OLDEST) && - (ad1.startsWith(a + "$") && Character.isDigit(ad1.charAt(a.length() + 1))))) { - throw new PrivateException(new PublicExceptions.ClassFileParseException( - "Enclosing class names for class " + classInfo.name + " don't match:\n" + - classInfo.directlyEnclosingClass + " and " + enclosingClassPCDE.newClassInfo.name)); - } - } - } - - // If dest dir was specified, check if the deduced name is equal to the one in this class (in this case - // they should necessarily match). Otherwise, without parsing the .java file, we can't reliably say what the - // full class name (actually, its package part) should be - so we just note the name. - if (destDirSpecified) { - if (!fullClassName.equals(classInfo.name)) { - throw new PrivateException(new PublicExceptions.ClassNameMismatchException( - "Error: deduced class name is different from the real one for source " + - javaFileFullPath + "\n" + fullClassName + " and " + classInfo.name)); - } - } else { - fullClassName = classInfo.name; - } - - if (enclosingClassPCDE != null) { - javaFileFullPath = enclosingClassPCDE.javaFileFullPath; - } - long classFileLastMod = classFile.lastModified(); - long classFileFP = computeFP(classFileBytes); - - if (pcd.containsKey(fullClassName)) { - PCDEntry pcde = pcd.get(fullClassName); - // If this entry has already been checked, it's a second entry for the same class, which is illegal. - if (pcde.checkResult == PCDEntry.CV_NEWER_FOUND_NEARER) { - // Newer copy of same file found in closer layer - // Reset to CV_UNCHECKED and skip redundnacy check - // as we know this would be redundant - pcde.checkResult = PCDEntry.CV_UNCHECKED; - } else { - if (pcde.checked) { - throw new PrivateException(new PublicExceptions.DoubleEntryException( - "Two entries for class " + classInfo.name + " detected: " + pcde.javaFileFullPath + " and " + javaFileFullPath)); - } - } - // Otherwise, it means that the .java file for this class has been moved. jmake initially interprets - // a new source file name as a new class, and it's only at this point that we can actually see that it was - // only a move. We update javaFileFullPath for nested classes after we return from here. - pcde.javaFileFullPath = javaFileFullPath; - pcde.classFileFullPath = classFileFullPath; - pcde.newClassInfo = classInfo; - if (deletedClasses.contains(fullClassName)) { - deletedClasses.remove(fullClassName); - } - return pcde; - } - - PCDEntry pcde = new PCDEntry(fullClassName, - javaFileFullPath, - classFileFullPath, classFileLastMod, classFileFP, - classInfo); - pcde.checkResult = PCDEntry.CV_NEW; // So that later it's promoted into oldClassInfo correctly - updatedAndCheckedClasses.add(fullClassName); // So that the above happens - pcd.put(fullClassName, pcde); - return pcde; - } - - /** - * For the given class, find all direct nested classes (which may include reading their .class files from the - * class path) and set their access flags (contained in this, enclosing class, object) appropriately. If - * this class is a one coming from a .java source, repeat the procedure for each nested class in turn. - * Otherwise, i.e. if a class comes from a .jar, don't bother, since we will come across each of these - * classes anyway - when scanning their .jar. If 'move' parameter is true, it means that this method is called for - * a class that is not new, but has been moved (and possibly updated). - */ - private Set<String> findAndUpdateAllNestedClassesForClass(PCDEntry pcde, boolean move) { - ClassInfo classInfo = pcde.newClassInfo; - if (classInfo.nestedClasses == null) { - return Collections.emptySet(); - } - Set<String> entries = new LinkedHashSet<String>(); - String nestedClasses[] = classInfo.nestedClasses; - String javaFileFullPath = pcde.javaFileFullPath; - String enclosingClassFileFullPath = pcde.classFileFullPath; - boolean isJavaSourceFile = javaFileFullPath.endsWith(".java"); - - for (int i = 0; i < nestedClasses.length; i++) { - PCDEntry nestedPCDE = pcd.get(nestedClasses[i]); - if (nestedPCDE == null) { - if (isJavaSourceFile) { - nestedPCDE = - findClassFileOnFilesystem(null, pcde, nestedClasses[i], true); - } - // For classes that come from a .jar, pcde should already be there. Otherwise this class just doesn't exist. - if (nestedPCDE == null) { - // Probably a compilation error, such that enclosing class is compiled but nested is not. - throw new PrivateException(new PublicExceptions.ClassNameMismatchException( - "Could not find class file for " + pcde.toString())); - } - } - if (move) { - if (deletedClasses.contains(nestedClasses[i])) { - deletedClasses.remove(nestedClasses[i]); - } - nestedPCDE.javaFileFullPath = javaFileFullPath; - if (javaFileFullPath.endsWith(".java")) { - nestedPCDE.classFileFullPath = - Utils.getClassFileFullPathForNestedClass(enclosingClassFileFullPath, nestedClasses[i]); - } else { - nestedPCDE.classFileFullPath = javaFileFullPath; - } - } - if (nestedPCDE.newClassInfo == null) { - getClassInfoForPCDEntry(ClassInfo.VER_NEW, nestedPCDE); - } - nestedPCDE.newClassInfo.accessFlags = - pcde.newClassInfo.nestedClassAccessFlags[i]; - nestedPCDE.newClassInfo.isNonMemberNestedClass = - pcde.newClassInfo.nestedClassNonMember[i]; - - entries.add(nestedPCDE.className); - entries.addAll(findAndUpdateAllNestedClassesForClass(nestedPCDE, move)); - } - return entries; - } - - /** - * Take care of new nested classes that could have been generated from already existing .java sources, - * and of nested classes that do not exist anymore because they were deleted from these sources. - */ - private void dealWithNestedClassesForUpdatedJavaFiles() { - if (updatedJavaFiles.size() == 0) { - return; - } - - // First put PCDEntries for all updated classes that have nested classes into a temporary list. - // That's because we can then find new nested classes, which we will need to add to the PCD, which - // may probably conflict with us still iterating over it. - List<PCDEntry> updatedEntries = new ArrayList<PCDEntry>(); - for (PCDEntry pcde : entries()) { - if (pcde.checkResult == PCDEntry.CV_NEW) { - continue; // This class has just been added to the PCD - } - if (updatedJavaFiles.contains(pcde.javaFileFullPath)) { - ClassInfo oldClassInfo = pcde.oldClassInfo; - ClassInfo newClassInfo = - getClassInfoForPCDEntry(ClassInfo.VER_NEW, pcde); - if (newClassInfo == null) { - deletedClasses.add(pcde.className); - continue; // Class file deleted then not re-created due to a compilation error somewhere. - } - if (oldClassInfo.nestedClasses != null || newClassInfo.nestedClasses != null) { - updatedEntries.add(pcde); - } - } - } - - if (dependencyFile != null) { - Map<String, List<String>> dependencies = parseDependencyFile(); - for (String file : updatedJavaFiles) { - List<String> myDeps = dependencies.get(file); - if (myDeps == null) - continue; - PCDEntry pcde = getNamedPCDE(file, dependencies); - for (String dependency : myDeps) { - PCDEntry dep = pcd.get(dependency); - if (dep != null) - // This is an existing dep. - continue; - dep = findClassFileOnFilesystem(file, pcde, dependency, false); - getClassInfoForPCDEntry(ClassInfo.VER_NEW, dep); - if (dep.newClassInfo.nestedClasses != null) - updatedEntries.add(dep); - } - } - } - dealWithNestedClassesForUpdatedPCDEntries(updatedEntries, false); - } - - private PCDEntry getNamedPCDE(String file, Map<String, List<String>> dependencies) { - List<String> depsForFile = dependencies.get(file); - PCDEntry pcde = null; - // Find a non-nested class for this java file for which we already have - // a pcde - for (String dependency : depsForFile) { - if (dependency.indexOf('$') != -1) - continue; - pcde = pcd.get(dependency); - if (pcde != null) - break; - } - if (pcde == null) { - throw new PrivateException(new PublicExceptions.InternalException(file - + " was supposed to be an updated file, but there are no PCDEntries for any of its deps")); - } - return pcde; - } - - private void dealWithNestedClassesForUpdatedPCDEntries(List<PCDEntry> entries, boolean move) { - for (int i = 0; i < entries.size(); i++) { - PCDEntry pcde = entries.get(i); - ClassInfo oldClassInfo = pcde.oldClassInfo; - ClassInfo newClassInfo = pcde.newClassInfo; - if (newClassInfo.nestedClasses != null) { - Set<String> nested = findAndUpdateAllNestedClassesForClass(pcde, move); - if (oldClassInfo.nestedClasses != null) { // Check if any old nested classes don't exist anymore - for (int j = 0; j < oldClassInfo.nestedClasses.length; j++) { - boolean found = false; - String oldNestedClass = oldClassInfo.nestedClasses[j]; - for (int k = 0; k < newClassInfo.nestedClasses.length; k++) { - if (oldNestedClass.equals(newClassInfo.nestedClasses[k])) { - found = true; - break; - } - } - if (!found) { - deletedClasses.add(oldNestedClass); - } - } - } - } else { // newNestedClasses == null and oldNestedClasses != null, so all nested classes have been removed in the new version - for (int j = 0; j < oldClassInfo.nestedClasses.length; j++) { - deletedClasses.add(oldClassInfo.nestedClasses[j]); - } - } - } - } - - private void findUpdatedClasses() { - // This (iterating over all of the classes once again after performing that in classFileObsoleteOrDeleted()) may - // seem time-consuming, but in reality it isn't, since the most time-consuming operation of obtaining internal - // file handles for class files has already been performed in classFileObsoleteOrDeleted(). Once we have done that, - // this re-iteration takes very small amount of time. However, if we switch from "class file older than .java - // file" to ".java file timestamp changed" condition for recompilation, this will have to be changed as well. - for (PCDEntry entry : entries()) { - String className = entry.className; - if (updatedAndCheckedClasses.contains(className) || - deletedClasses.contains(className)) { - continue; - } - if (!entry.javaFileFullPath.endsWith(".java")) { - continue; // classes from (updated) .jars have been dealt with separately - } - //DAB TODO understand this bit better. It is needed to support -vpath, I'm just not sure why.... - if (entry.checkResult != PCDEntry.CV_NEWER_FOUND_NEARER && - !updatedAndCheckedClasses.contains(className) && - !deletedClasses.contains(className) && - entry.javaFileFullPath.endsWith(".java") && - classFileUpdated(entry)) - { - //DAB TODO this is the old way.... - //DAB if (classFileUpdated(entry)) { - updatedClasses.add(className); - allUpdatedClasses.add(className); - } - } - } - - private boolean classFileUpdated(PCDEntry entry) { - File classFile = Utils.checkFileForName(entry.classFileFullPath); - if (classFile == null) { - return false; - } - // The only case when the above can happen is if class file was first deleted, and then there - // was an error recompiling its source - - long classFileLastMod = classFile.lastModified(); - - if (classFileLastMod > entry.oldClassFileLastModified) { - entry.newClassFileLastModified = classFileLastMod; - // Check if the class was actually modified, to avoid the costly procedure of detailed version compare - long classFileFP = computeFP(classFile); - if (classFileFP != entry.oldClassFileFingerprint) { - entry.newClassFileFingerprint = classFileFP; - return true; - } - } - return false; - } - - /** - * Compare old (preserved in pdb) and new (file system) versions of updated classes, and find all - * potentially affected dependent classes. - */ - private void checkUpdatedClasses() { - for (String className : updatedClasses) { - PCDEntry pcde = pcd.get(className); - getClassInfoForPCDEntry(ClassInfo.VER_NEW, pcde); - if (!"".equals(pcde.oldClassInfo.directlyEnclosingClass)) { - // The following problem can occur with nested classes. A C.java source has been changed, so that C.class is - // not changed or changed in a compatible way, whereas the access modifiers of C$X.class are changed in an - // incompatible way, so that something is broken in the project. When jmake is called for the first time, - // it reports the problem, then saves the info on the new version of C in the pdb. Of course, the record for - // C$X in the pdb is not updated, since the change to it is incompatible and recompilation of dependent sources - // has failed. Suppose we don't change anything and invoke jmake again. C$X is found different from its old - // version and is checked here again. The outcome should be the same. But since C has not changed, C.class is - // not read from disk and the access flags of C$X, which are stored in C.class, are not set appropriately. So - // in such circumstances we have wrong access flags for C$X here. To fix the problem we need to load C explicitly. - ClassInfo enclosingClassInfo = - getClassInfoForName(ClassInfo.VER_NEW, pcde.oldClassInfo.directlyEnclosingClass); - //if (enclosingClassInfo == null || enclosingClassInfo.nestedClasses == null) { - // System.out.println("!!! Suspicious updated class name = " + className); - // System.out.println("!!! enclosingClassInfo for it = " + enclosingClassInfo); - // if (enclosingClassInfo != null) { - // System.out.println("!!! enclosingClassInfo.name = " + enclosingClassInfo.name); - // if (enclosingClassInfo.nestedClasses == null) System.out.println("!!! enclosingClassInfo.nestedClasses = null"); - // } - //} - if (enclosingClassInfo.nestedClasses != null) { // Can be that this nested class was the only one for enclosing class, and it's deleted now - for (int i = 0; i < enclosingClassInfo.nestedClasses.length; i++) { - if (className.equals(enclosingClassInfo.nestedClasses[i])) { - pcde.newClassInfo.accessFlags = - enclosingClassInfo.nestedClassAccessFlags[i]; - pcde.newClassInfo.isNonMemberNestedClass = - enclosingClassInfo.nestedClassNonMember[i]; - break; - } - } - } - } - if (!(pcde.oldClassInfo.isNonMemberNestedClass && pcde.newClassInfo.isNonMemberNestedClass)) { - Utils.printInfoMessage("Checking " + pcde.className); - pcde.checkResult = cv.compareClassVersions(pcde) ? PCDEntry.CV_COMPATIBLE - : PCDEntry.CV_INCOMPATIBLE; - String affectedClasses[] = cv.getAffectedClasses(); - if (affectedClasses != null) { - for (int i = 0; i < affectedClasses.length; i++) { - PCDEntry affEntry = pcd.get(affectedClasses[i]); - updatedJavaFiles.add(affEntry.javaFileFullPath); - } - } - } else { - // A non-member nested class can not be referenced by the source code of any class defined outside the - // immediately enclosing source code block for this class. Therefore, any incompatibility in the new - // version of this class can affect only classes that are defined in the same source file - and they - // are necessarily recompiled together with this class. So there is no point in initiating version - // compare for this class. However, the new class version should always tembe promoted into the store, since - // this class itself may depend on other changing classes. - pcde.checkResult = PCDEntry.CV_COMPATIBLE; - } - - updatedAndCheckedClasses.add(className); - } - } - - /** Find all dependent classes for deleted classes. */ - private void checkDeletedClasses() { - for (String className : deletedClasses) { - PCDEntry pcde = pcd.get(className); - - if (pcde == null) { // "Safety net" for the (hopefully unlikely) case. I observed it just once and couldn't identify the reason - Utils.printWarningMessage("Warning: internal information inconsistency when checking deleted classes"); - Utils.printWarningMessage(Utils.REPORT_PROBLEM); - Utils.printWarningMessage("Class name: " + className); - continue; - } - - ClassInfo oldCI = pcde.oldClassInfo; - if (!oldCI.isNonMemberNestedClass) { // See the comment above - Utils.printInfoMessage("Checking deleted class " + oldCI.name); - cv.checkDeletedClass(pcde); - String[] affectedClasses = cv.getAffectedClasses(); - if (affectedClasses != null) { - for (int i = 0; i < affectedClasses.length; i++) { - PCDEntry affEntry = pcd.get(affectedClasses[i]); - if (deletedClasses.contains(affEntry.className)) { - continue; - } - updatedJavaFiles.add(affEntry.javaFileFullPath); - } - } - } - pcde.checkResult = PCDEntry.CV_DELETED; - updatedAndCheckedClasses.add(className); - } - deletedClasses.clear(); - } - - /** - * Determine what classes in the given .jar (which may be an existing updated one, or a new one) are new, - * updated, or moved, and treat them accordingly. - */ - private void processAllClassesFromJarFile(String jarFileName) { - JarFile jarFile; - long jarFileLastMod = 0; - try { - File file = new File(jarFileName); - jarFileLastMod = file.lastModified(); - jarFile = new JarFile(jarFileName); - } catch (IOException ex) { - throw new PrivateException(ex); - } - - List<PCDEntry> newEntries = new ArrayList<PCDEntry>(); - List<PCDEntry> updatedEntries = new ArrayList<PCDEntry>(); - List<PCDEntry> movedEntries = new ArrayList<PCDEntry>(); - - for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) { - JarEntry jarEntry = entries.nextElement(); - String fullClassName = jarEntry.getName(); - if (!fullClassName.endsWith(".class")) { - continue; - } - fullClassName = - fullClassName.substring(0, fullClassName.length() - 6).intern(); - byte classFileBytes[]; - classFileBytes = Utils.readZipEntryIntoBuffer(jarFile, jarEntry); - long classFileFP = computeFP(classFileBytes); - - PCDEntry pcde = pcd.get(fullClassName); - if (pcde != null) { - if (pcde.checked) { - throw new PrivateException(new PublicExceptions.DoubleEntryException( - "Two entries for class " + fullClassName + " detected: " + pcde.javaFileFullPath + " and " + jarFileName)); - } - pcde.checked = true; - pcde.newClassFileLastModified = jarFileLastMod; - // If we are scanning an existing updated .jar file, and there is no change to the class itself, - // and it previously was located in the same .jar, do nothing. - if (pcde.oldClassFileFingerprint == classFileFP && - pcde.javaFileFullPath.equals(jarFileName)) { - pcde.oldClassFileLastModified = jarFileLastMod; // So that next time jmake is inoked, checking - continue; // of this.jar is not triggered. - } - if (pcde.oldClassFileFingerprint != classFileFP) { // This class has been updated - updatedClasses.add(fullClassName); - allUpdatedClasses.add(fullClassName); - pcde.newClassFileLastModified = jarFileLastMod; - pcde.newClassFileFingerprint = classFileFP; - pcde.newClassInfo = - new ClassInfo(classFileBytes, ClassInfo.VER_NEW, this, fullClassName); - if (pcde.oldClassInfo.nestedClasses != null || pcde.newClassInfo.nestedClasses != null) { - updatedEntries.add(pcde); - } - } else { - pcde.oldClassFileLastModified = jarFileLastMod; - } - if (!pcde.javaFileFullPath.equals(jarFileName)) { - // Found an existing class in a different .jar file. - // May happen if the class file has been moved from one .jar to another (or into a .jar, losing its - // .java source). It's only at this point that we can actually see that it was really a move. - if (deletedClasses.contains(fullClassName)) { - deletedClasses.remove(fullClassName); - } - if (pcde.oldClassInfo.nestedClasses != null) { - movedEntries.add(pcde); - pcde.newClassInfo = - new ClassInfo(classFileBytes, ClassInfo.VER_NEW, this, fullClassName); - } - } - pcde.javaFileFullPath = jarFileName; - } else { // New class file - ClassInfo classInfo = - new ClassInfo(classFileBytes, ClassInfo.VER_NEW, this, fullClassName); - pcde = new PCDEntry(fullClassName, - jarFileName, - jarFileName, jarFileLastMod, classFileFP, - classInfo); - pcde.checkResult = PCDEntry.CV_NEW; // So that later it's promoted into oldClassInfo correctly - updatedAndCheckedClasses.add(fullClassName); // So that the above happens - pcd.put(fullClassName, pcde); - if (pcde.newClassInfo.nestedClasses != null) { - newEntries.add(pcde); - } - } - } - - dealWithNestedClassesForUpdatedPCDEntries(updatedEntries, false); - dealWithNestedClassesForUpdatedPCDEntries(movedEntries, true); - for (int i = 0; i < newEntries.size(); i++) { - findAndUpdateAllNestedClassesForClass(newEntries.get(i), false); - } - } - - /** Determine new, deleted and updated classes coming from updated .jar files. */ - private void dealWithClassesInUpdatedJarFiles() { - if (updatedJarFiles.size() == 0) { - return; - } - - for (String updatedJarFile : updatedJarFiles) { - processAllClassesFromJarFile(updatedJarFile); - } - - // Now scan the PCD to check which classes that come from updated .jar files have not been marked as checked - for (PCDEntry pcde : entries()) { - if (updatedJarFiles.contains(pcde.javaFileFullPath)) { - if (!pcde.checked) { - deletedClasses.add(pcde.className); - } - } - } - } - - /** Check if the destination directory exists, and get the canonical path for it. */ - private void initializeDestDir(String inDestDir) { - if (!(inDestDir == null || inDestDir.equals(""))) { - File dir = Utils.checkOrCreateDirForName(inDestDir); - if (dir == null) { - throw new PrivateException(new IOException("specified directory " + inDestDir + " cannot be created.")); - } - inDestDir = getCanonicalPath(dir); - if (!inDestDir.endsWith(File.separator)) { - inDestDir += File.separatorChar; - } - destDir = inDestDir; - destDirSpecified = true; - } else { - destDirSpecified = false; - } - } - - /** - * For the given PCDEntry, set the entry.classFileFullPath according to the value of the .java file full - * path and the value of the "-d" option at this particular jmake invocation - */ - private void initializeClassFileFullPath(PCDEntry entry) { - String classFileFullPath; - if (destDirSpecified) { - classFileFullPath = destDir + entry.className + ".class"; - } else { - String javaFileDir = entry.javaFileFullPath; - int cutIndex = javaFileDir.lastIndexOf(File.separatorChar); - if (cutIndex != -1) { - javaFileDir = javaFileDir.substring(0, cutIndex + 1); - } - String classFileName = entry.className; - cutIndex = classFileName.lastIndexOf('/'); - if (cutIndex != -1) { - classFileName = classFileName.substring(cutIndex + 1); - } - classFileFullPath = javaFileDir + classFileName + ".class"; - } - if (backSlashFileSeparator) { - classFileFullPath = - classFileFullPath.replace('/', File.separatorChar); - } - entry.classFileFullPath = classFileFullPath; - } - - private static String getCanonicalPath(File file) { - try { - return file.getCanonicalPath().intern(); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - private long computeFP(File file) { - byte buf[] = Utils.readFileIntoBuffer(file); - return computeFP(buf); - } - - private long computeFP(byte[] buf) { - checkSum.reset(); - checkSum.update(buf); - return checkSum.getValue(); - } - - private PrivateException compilerInteractionException(String message, Exception origException, int errCode) { - return new PrivateException(new PublicExceptions.CompilerInteractionException(message, origException, errCode)); - } - - private PrivateException internalException(String message) { - return new PrivateException(new PublicExceptions.InternalException(message)); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/PrivateException.java b/third_party/jmake/src/org/pantsbuild/jmake/PrivateException.java deleted file mode 100644 index b8b0c789..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/PrivateException.java +++ /dev/null
@@ -1,28 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -/** - * This class is used as a wrapper for a number of exceptions that are thrown by jmake. Its - * only purpose is to help avoid using endless "throws" clauses in the code. - * - * @author Misha Dmitriev - * 12 November 2001 - */ -public class PrivateException extends RuntimeException { - - private static final long serialVersionUID = 1L; - private Throwable originalException; - - public PrivateException(Throwable e) { - originalException = e; - } - - public Throwable getOriginalException() { - return originalException; - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/PublicExceptions.java b/third_party/jmake/src/org/pantsbuild/jmake/PublicExceptions.java deleted file mode 100644 index 4009745..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/PublicExceptions.java +++ /dev/null
@@ -1,169 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -/** - * This class is a wrapper for a number of nested classes. They define exceptions that may be thrown - * by the <b>jmake</b> code. These exceptions are caught in the <code>Main.mainExternal</code> method, - * or they may be caught and handled by an application invoking <b>jmake</b> programmatically - * through <code>Main.mainProgrammatic</code> method. - * - * @see Main#mainExternal(String[]) - * @see Main#mainProgrammatic(String[]) - * - * @author Misha Dmitriev - * 17 January 2003 - */ -public class PublicExceptions { - - /** - * This exception is thrown whenever there is any problem initializing or calling the compiler, or - * when the compiler itself reports compilation errors. Depending on the nature of the problem, an - * instance of this class is initialized with, and then returns, an original exception signalling - * the problem, or the compiler application exit code. - */ - public static class CompilerInteractionException extends Exception { - - private static final long serialVersionUID = 1L; - private Exception originalException; - private int compilerExitCode; - - /** - * Initialize an instance of this exception with an error message and either an original - * exception or a compiler exit code. - */ - CompilerInteractionException(String msg, Exception originalException, int compilerExitCode) { - super(msg); - this.originalException = originalException; - this.compilerExitCode = compilerExitCode; - } - - /** - * Get the original exception that caused this exception. <code>null</code> is returned if there - * were no original exception. In that case, there was a compilation error and the compiler has - * returned with the exit code that can be obtained using <code>getCompilerExitCode</code> method. - * - * @see #getCompilerExitCode() - */ - public Exception getOriginalException() { - return originalException; - } - - /** - * Get the compiler exit code. If <code>0</code> is returned, this indicates that an exception was - * thrown during compiler initialization, or inside the compiler itself. Use <code>getOriginalExcepion</code> - * method to obtain that exception. - * - * @see #getOriginalException - */ - public int getCompilerExitCode() { - return compilerExitCode; - } - } - - /** Exception signalling a problem with reading project database file. */ - public static class PDBCorruptedException extends Exception { - - private static final long serialVersionUID = 1L; - - PDBCorruptedException(String msg) { - super(msg); - } - } - - /** Exception signalling a problem when parsing a class file */ - public static class ClassFileParseException extends Exception { - - private static final long serialVersionUID = 1L; - - ClassFileParseException(String msg) { - super(msg); - } - } - - /** Exception signalling that <b>jmake</b> was not requested to do any real work. */ - public static class NoActionRequestedException extends Exception { - - private static final long serialVersionUID = 1L; - } - - /** Exception signalling that an invalid command line option has been passed to jmake. */ - public static class InvalidCmdOptionException extends Exception { - - private static final long serialVersionUID = 1L; - - InvalidCmdOptionException(String msg) { - super(msg); - } - } - - /** - * Exception signalling a problem (typically an I/O exception) when parsing a command line file - * passed to <b>jmake</b>. - */ - public static class CommandFileReadException extends Exception { - - private static final long serialVersionUID = 1L; - - CommandFileReadException(String msg) { - super(msg); - } - } - - /** - * Exception signalling that for some class the deduced name (that is, name based on the source file name and - * directory) and the real name (the one read from the class file) are different. - */ - public static class ClassNameMismatchException extends Exception { - - private static final long serialVersionUID = 1L; - - ClassNameMismatchException(String msg) { - super(msg); - } - } - - /** Exception thrown if any specified source file has an invalid extension (not <code>.java</code> or <code>.jar</code>). */ - public static class InvalidSourceFileExtensionException extends Exception { - - private static final long serialVersionUID = 1L; - - InvalidSourceFileExtensionException(String msg) { - super(msg); - } - } - - /** Exception thrown if a dependence of a class in a <code>JAR</code> file on a class with a <code>.java</code> source is detected. */ - public static class JarDependsOnSourceException extends Exception { - - private static final long serialVersionUID = 1L; - - JarDependsOnSourceException(String msg) { - super(msg); - } - } - - /** Exception thrown if more than one entry for the same class is detected in the project */ - public static class DoubleEntryException extends Exception { - - private static final long serialVersionUID = 1L; - - DoubleEntryException(String msg) { - super(msg); - } - } - - /** Exception thrown if an internal problem that should never happen is detected. */ - public static class InternalException extends Exception { - - private static final long serialVersionUID = 1L; - - InternalException(String msg) { - super(msg); - } - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/RefClassFinder.java b/third_party/jmake/src/org/pantsbuild/jmake/RefClassFinder.java deleted file mode 100644 index 58c8884..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/RefClassFinder.java +++ /dev/null
@@ -1,697 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.lang.reflect.Modifier; -import java.util.LinkedHashSet; -import java.util.Set; - -/** - * This class implements finding classes referencing other classes and members in various ways. - * - * @author Misha Dmitriev - * 12 March 2004 - */ -public class RefClassFinder { - - private boolean failOnDependentJar; // If true, will fail if a dependency of a sourceless class - // (coming from a .jar) on a "normal" class is detected - private boolean noWarnOnDependentJar; // If true, not even a warning will be issued in the above case. - private String checkedClassName; - private PCDManager pcdm; - private Set<String> affectedClassNames; - private boolean checkedClassIsFromJar; - - /** An instance of RefClassFinder is created once per session, passing it the global options that do not change */ - public RefClassFinder(PCDManager pcdm, boolean failOnDependentJar, boolean noWarnOnDependentJar) { - this.pcdm = pcdm; - this.failOnDependentJar = failOnDependentJar; - this.noWarnOnDependentJar = noWarnOnDependentJar; - } - - /** This method is called every time we are going to check a new class */ - public void initialize(String checkedClassName, boolean checkedClassIsFromJar) { - this.checkedClassName = checkedClassName; - this.checkedClassIsFromJar = checkedClassIsFromJar; - affectedClassNames = new LinkedHashSet<String>(); - } - - /** - * Returns the names of project classes that were found potentially affec - * by the changes to the checked class. - */ - public String[] getAffectedClassNames() { - int size = affectedClassNames.size(); - if (size == 0) { - return null; - } else { - String[] ret = new String[size]; - int i = 0; - for (String className : affectedClassNames) { - ret[i++] = className; - } - return ret; - } - } - - /** - * Find all project classes that can access field fieldNo of class fieldClassInfo. - * Used if a compile-time constant is changed. - */ - public void findAllProjectClasses(ClassInfo fieldClassInfo, int fieldNo) { - for (PCDEntry pcde : pcdm.entries()) { - if (pcde.checkResult == PCDEntry.CV_DELETED) { - continue; - } - if (pcde.javaFileFullPath.endsWith(".jar")) { - continue; - } - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (clientInfo == null) { - continue; // New class - } - if (memberAccessibleFrom(fieldClassInfo, fieldNo, clientInfo, true)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - - /** - * Find all project classes that reference class with the given name - * (but not its array class) directly from the constantpool. - */ - public void findReferencingClasses0(ClassInfo classInfo) { - findReferencingClasses(classInfo, 0, false, null); - } - - - /* In the following "find...ReferencingClasses1" methods, "referencing C" means - * "referencing C or its array class directly from the constant pool, as a type of a data - * field, as a type in a method signature or a thrown exception, as a directly implemented - * interface or a direct superclass". - */ - /** Used for deleted classes. */ - public void findReferencingClassesForDeletedClass(ClassInfo classInfo) { - String packageName = classInfo.packageName; - boolean isPublic = classInfo.isPublic(); - boolean isInterface = classInfo.isInterface(); - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (clientInfo == null) { - continue; // New class - } - if (!isPublic && packageName.equals(clientInfo.packageName)) { - continue; - } - if (clientInfo.referencesClass(classInfo.name, isInterface, 1)) { - addToAffectedClassNames(clientInfo.name); - } - } - - } - - /** - * For the given class p.C, find each project class X referencing C, that is not a member of - * package p and is not a direct or indirect subclass of C's directly enclosing class. - * (public -> protected transformation) - */ - public void findDiffPackageAndNotSubReferencingClasses1(ClassInfo classInfo) { - String packageName = classInfo.packageName; - String directlyEnclosingClass = classInfo.directlyEnclosingClass; - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (clientInfo == null) { - continue; // New class - } - if (packageName.equals(clientInfo.packageName) || - clientInfo.isSubclassOf(directlyEnclosingClass, false)) { - continue; - } - if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface(), 1)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - - /** - * For class p.C, find each project class X referencing C, whose top level enclosing - * class is different from that of C. - * (public -> private transformation) - */ - public void findReferencingClasses1(ClassInfo classInfo) { - String topLevelEnclosingClass = classInfo.topLevelEnclosingClass; - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (clientInfo == null) { - continue; // New class - } - if (topLevelEnclosingClass.equals(clientInfo.topLevelEnclosingClass)) { - continue; - } - if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface(), 1)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - - /** - * For class p.C, find each project class X referencing C, whose direct or indirect superclass - * is C's directly enclosing class, or which is a member of package p, whose top level enclosing - * class is different from that of C. - * (protected -> private transformation) - */ - public void findThisPackageOrSubReferencingClasses1(ClassInfo classInfo) { - String directlyEnclosingClass = classInfo.directlyEnclosingClass; - String topLevelEnclosingClass = classInfo.topLevelEnclosingClass; - String packageName = classInfo.packageName; - for (PCDEntry entry : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, entry); - if (clientInfo == null) { - continue; // New class - } - if ((!clientInfo.packageName.equals(packageName)) && - !clientInfo.isSubclassOf(directlyEnclosingClass, false)) { - continue; - } - if (clientInfo.topLevelEnclosingClass.equals(topLevelEnclosingClass)) { - continue; - } - if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface(), 1)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - - /** - * For class p.C, find each project class X referencing C, which is a member of package p and whose - * top level enclosing class is different from that of C. - * (default -> private transformation) - */ - public void findThisPackageReferencingClasses1(ClassInfo classInfo) { - String topLevelEnclosingClass = classInfo.topLevelEnclosingClass; - String packageName = classInfo.packageName; - for (PCDEntry entry : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, - entry); - if (clientInfo == null) { - continue; // New class - } - if (!clientInfo.packageName.equals(packageName)) { - continue; - } - if (topLevelEnclosingClass.equals(clientInfo.topLevelEnclosingClass)) { - continue; - } - if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface(), 1)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - - /** - * For class p.C, find each project class X referencing C, which is not a member of package p. - * (public -> default transformation) - */ - public void findDiffPackageReferencingClasses1(ClassInfo classInfo) { - String packageName = classInfo.packageName; - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (clientInfo == null) { - continue; // New class - } - if (clientInfo.packageName.equals(packageName)) { - continue; - } - if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface(), 1)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - - /** - * For class p.C, find each project class X referencing C, which is not a member of package p and - * whose direct or indirect superclass is C's directly enclosing class. - * (protected -> default transformation) - */ - public void findDiffPackageAndSubReferencingClasses1(ClassInfo classInfo) { - String packageName = classInfo.packageName; - String directlyEnclosingClass = classInfo.directlyEnclosingClass; - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (clientInfo == null) { - continue; // New class - } - if (clientInfo.packageName.equals(packageName)) { - continue; - } - if (!clientInfo.isSubclassOf(directlyEnclosingClass, false)) { - continue; - } - if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface(), 1)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - - /** - * Find all project classes that reference both of the classes with the - * given names (or array classes of one or both) directly or indirectly from the - * constantpool, as a type of a data field, as a type in a method signature or a - * thrown exception, as a directly/indirectly implemented interface or a - * direct/indirect superclass. - */ - public void findReferencingClasses2(ClassInfo classInfo1, ClassInfo classInfo2) { - Set<String> refClazz1 = new LinkedHashSet<String>(); - findReferencingClasses(classInfo1, 2, false, refClazz1); - Set<String> refClazz2 = new LinkedHashSet<String>(); - findReferencingClasses(classInfo2, 2, false, refClazz2); - - for (String className1 : refClazz1) { - if (refClazz2.contains(className1)) { - addToAffectedClassNames(className1); - } - } - } - - /** Find all project classes which are direct subclasses of the given class */ - public void findDirectSubclasses(ClassInfo classInfo) { - for (ClassInfo subclassInfo : classInfo.getDirectSubclasses()) { - addToAffectedClassNames(subclassInfo.name); - } - } - - /** - * Find all non-abstract project classes that implement the given interface or any of its - * subclasses directly, and all non-abstract classes that are direct descendants of abstract - * classes that implement the given interface directly or indirectly. Class C implements - * interface I indirectly, if C or some superclass of C directly implements I or some sublcass of I. - */ - public void findDirectlyAndOtherwiseImplementingConcreteClasses(ClassInfo intfInfo) { - for (PCDEntry entry : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, entry); - if (clientInfo == null) { - continue; // New class - } - if (clientInfo.isInterface()) { - continue; - } - if (clientInfo.isAbstract()) { - if (clientInfo.implementsInterfaceDirectlyOrIndirectly(intfInfo.name)) { - findAllNearestConcreteSubclasses(clientInfo); - } - } else { - if (clientInfo.implementsIntfOrSubintfDirectly(intfInfo.name)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - } - - private void findAllNearestConcreteSubclasses(ClassInfo classInfo) { - for (ClassInfo subclassInfo : classInfo.getDirectSubclasses()) { - if (subclassInfo.isAbstract()) { - findAllNearestConcreteSubclasses(subclassInfo); - } else { - addToAffectedClassNames(subclassInfo.name); - } - } - } - - /** - * Find all interfaces and abstract classes that implement the given interface and declare or inherit - * a method with the given name. For those that overload this method, find referencing classes. - */ - public void findAbstractSubtypesWithSameNameMethod(ClassInfo intfInfo, String mName, final String mSig) { - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo ci = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (ci == null) { - continue; // New class or not in project - } - if (!(ci.isInterface() || ci.isAbstract())) { - continue; - } - if (ci.implementsInterfaceDirectlyOrIndirectly(intfInfo.name)) { - addToAffectedClassNames(ci.name); - // Check if the new method overloads an existing (declared or inherited) method. Overloading test is rough - - // we just check if the number of parameters is the same. - ci.findExistingSameNameMethods(mName, true, true, new ClassInfo.MethodHandler() { - - void handleMethod(ClassInfo classInfo, int otherMethodIdx) { - String otherMSig = - classInfo.methodSignatures[otherMethodIdx]; - if ( (!mSig.equals(otherMSig)) && - Utils.sameParamNumber(mSig, otherMSig)) { - findReferencingClassesForMethod(classInfo, otherMethodIdx); - } - } - }); - } - } - } - - /** Find all project classes that reference the given field. */ - public void findReferencingClassesForField(ClassInfo classInfo, int fieldNo) { - findReferencingClassesForMember(classInfo, fieldNo, true, false, false); - } - - /** - * Find all project classes that reference the given field and which are in - * different packages. - */ - public void findDiffPackageReferencingClassesForField(ClassInfo classInfo, int fieldNo) { - findReferencingClassesForMember(classInfo, fieldNo, true, true, false); - } - - /** - * Find all project classes that reference the given field, which are in different - * packages and are direct or indirect subclasses of the member's declaring class - * (protected -> default transformation). - */ - public void findDiffPackageAndSubReferencingClassesForField(ClassInfo classInfo, int fieldNo) { - findReferencingClassesForMember(classInfo, fieldNo, true, true, true); - } - - /** Find all project classes that reference the given method. */ - public void findReferencingClassesForMethod(ClassInfo classInfo, int methodNo) { - findReferencingClassesForMember(classInfo, methodNo, false, false, false); - } - - /** - * Find all project classes that reference the given method and which are in - * different packages. - */ - public void findDiffPackageReferencingClassesForMethod(ClassInfo classInfo, int methodNo) { - findReferencingClassesForMember(classInfo, methodNo, false, true, false); - } - - /** - * Find all project classes that reference the given method, which are in different - * packages and are direct or indirect subclasses of the member's declaring class - * (protected -> default transformation) - */ - public void findDiffPackageAndSubReferencingClassesForMethod(ClassInfo classInfo, int methodNo) { - findReferencingClassesForMember(classInfo, methodNo, false, true, true); - } - - /** - * Find all project classes that re-implement the given method and that are - * direct/indirect subclasses of this method's declaring class. If some subclass C - * re-implements the given method, we don't have to search C's subclasses further. - */ - public void findSubclassesReimplementingMethod(ClassInfo classInfo, int methodNo) { - findSubclassesReimplementingMethod(classInfo, classInfo, methodNo); - } - - private void findSubclassesReimplementingMethod(ClassInfo targetClass, ClassInfo methodDeclaringClass, int methodNo) { - for (ClassInfo subclass : targetClass.getDirectSubclasses()) { - if (subclass.declaresMethod(methodDeclaringClass, methodNo)) { - addToAffectedClassNames(subclass.name); - } else { - findSubclassesReimplementingMethod(subclass, methodDeclaringClass, methodNo); - } - } - } - - /** - * For a given class C, find all concrete direct subclasses, and all direct concrente subclasses of C's direct - * or indirect abstract subclasses. - */ - public void findConcreteSubclasses(ClassInfo targetClass) { - for (ClassInfo subclass : targetClass.getDirectSubclasses()) { - if (subclass.isAbstract()) { - findConcreteSubclasses(subclass); - } else { - addToAffectedClassNames(subclass.name); - } - } - } - - /** - * Find any concrete subclasses of targetClass that don't override or inherit a concrete implementation - * of the given method. - */ - public void findConcreteSubclassesNotOverridingAbstractMethod(ClassInfo targetClass, ClassInfo methodDeclaringClass, int methodNo) { - for (ClassInfo subclass : targetClass.getDirectSubclasses()) { - int pos = - subclass.getDeclaredMethodPos(methodDeclaringClass, methodNo); - if (pos == -1) { // This method is not overridden in this class - if (!subclass.isAbstract()) { - addToAffectedClassNames(subclass.name); - } else { - findConcreteSubclassesNotOverridingAbstractMethod(subclass, methodDeclaringClass, methodNo); - } - } else { // A chance that this method is declared abstract once again... - if (Modifier.isAbstract(subclass.methodAccessFlags[pos])) { - findConcreteSubclassesNotOverridingAbstractMethod(subclass, methodDeclaringClass, methodNo); - } - } - } - } - - /** Find all project classes that reference any method that throws the given exception. */ - public void findRefsToMethodsThrowingException(ClassInfo excClassInfo) { - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo classInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (classInfo == null) { - continue; // New class - } - int methodIdx = -1; - do { - methodIdx = - classInfo.hasMethodThrowingException(excClassInfo, methodIdx + 1); - if (methodIdx != -1) { - findReferencingClassesForMethod(classInfo, methodIdx); - } - } while (methodIdx != -1); - } - } - - /** - * Find all project classes declaring a static field with the given name. Currently used only to look up - * classes referencing given class X via the "X.class" construct. - */ - public void findClassesDeclaringField(String name, String signature, boolean isStatic, String packageToLookIn) { - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo classInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (classInfo == null) { - continue; // New class - } - if (packageToLookIn != null && - !classInfo.packageName.equals(packageToLookIn)) { - continue; - } - if (classInfo.declaresField(name, signature, isStatic)) { - addToAffectedClassNames(classInfo.name); - } - } - } - - public void addToAffectedClassNames(String className) { - String res = pcdm.classAlreadyRecompiledOrUncompileable(className); - if (res == null) { - affectedClassNames.add(className); - } else if (!"".equals(res)) { // The dependent class comes from a .jar. - if (checkedClassIsFromJar || noWarnOnDependentJar) { - return; - } - String message = "Class " + className + " is affected by a change to " + checkedClassName + ", but can't be recompiled, " + - "since it is located in archive " + res; - if (failOnDependentJar) { - throw new PrivateException(new PublicExceptions.JarDependsOnSourceException(message)); - } else { - Utils.printWarningMessage("Warning: " + message); - } - } - } - - /** - * Find all project classes that reference the class with the given name. - * The second parameter controls the "thoroughness degree", and its value is passed to ClassInfo.referencesClass() - * method (see the comment to it). The fromDiffPackages parameter defines whether all such classes - * or only classes from different packages are required. - */ - private void findReferencingClasses(ClassInfo classInfo, - int thorDegree, boolean fromDiffPackages, - Set<String> ret) { - String packageName = classInfo.packageName; - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (clientInfo == null) { - continue; // New class - } - if (fromDiffPackages && packageName.equals(clientInfo.packageName)) { - continue; - } - // If thorDegree == 2, i.e. indirect references from the constantpool (e.g. a reference to a method which - // has classInfo as one of its formal parameter types) are taken into account, then we should check all of - // the classes, whether classInfo is directly accessible from them or not. - if (thorDegree != 2 && (!classAccessibleFrom(classInfo, clientInfo))) { - continue; - } - - if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface(), thorDegree)) { - if (ret == null) { - addToAffectedClassNames(clientInfo.name); - } else { - ret.add(clientInfo.name); - } - } - } - } - - /** - * Find all project classes that reference the given member. If fromDiffPackages - * is true, then only classes that do not belong to the package of the member's - * declaring class should be returned. If onlySubclasses is true, then only - * classes that are subclasses of member's declaring class should be returned. - */ - private void findReferencingClassesForMember(ClassInfo declaringClassInfo, int memberNo, - boolean isField, - boolean fromDiffPackages, boolean onlySubclasses) { - String declaringClassName = declaringClassInfo.name; - String declaringClassPackage = declaringClassInfo.packageName; - for (PCDEntry pcde : pcdm.entries()) { - ClassInfo clientInfo = - pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde); - if (clientInfo == null) { - continue; // New class - } - String className = clientInfo.name; - if (className.equals(declaringClassName)) { - continue; - } - if (!memberAccessibleFrom(declaringClassInfo, memberNo, clientInfo, isField)) { - continue; - } - if (fromDiffPackages && - declaringClassPackage.equals(clientInfo.packageName)) { - continue; - } - if (onlySubclasses && !clientInfo.isSubclassOf(declaringClassName, false)) { - continue; - } - - if (isField) { - if (clientInfo.referencesField(declaringClassInfo, memberNo)) { - addToAffectedClassNames(clientInfo.name); - } - } else { - if (clientInfo.referencesMethod(declaringClassInfo, memberNo)) { - addToAffectedClassNames(clientInfo.name); - } - } - } - } - - /** Checks if class classInfo is accessible from class clientClassInfo. */ - private boolean classAccessibleFrom(ClassInfo classInfo, ClassInfo clientClassInfo) { - char classFlags = classInfo.accessFlags; - String classPackage = classInfo.packageName; - String clientClassPackage = clientClassInfo.packageName; - - if (Modifier.isPublic(classFlags)) { - return true; - } else if (Modifier.isProtected(classFlags)) { - if (classPackage.equals(clientClassPackage) || - clientClassInfo.isSubclassOf(classInfo.directlyEnclosingClass, false)) { - return true; - } - } else if (Modifier.isPrivate(classFlags)) { - if (classInfo.topLevelEnclosingClass.equals(clientClassInfo.topLevelEnclosingClass)) { - return true; - } - } else { - if (classPackage.equals(clientClassPackage)) { - return true; - } - } - - return false; - } - - /** - * Checks if member memberNo (which is a field if isField == true, and method otherwise) of class memberClassInfo is - * accessible from class clientClassInfo. - */ - private boolean memberAccessibleFrom(ClassInfo memberClassInfo, - int memberNo, ClassInfo clientClassInfo, boolean isField) { - char memberClassFlags = memberClassInfo.accessFlags; - char memberFlags = isField ? memberClassInfo.fieldAccessFlags[memberNo] - : memberClassInfo.methodAccessFlags[memberNo]; - String memberClassPackage = memberClassInfo.packageName; - String clientClassPackage = clientClassInfo.packageName; - - if (Modifier.isPublic(memberClassFlags)) { - if (Modifier.isPublic(memberFlags)) { - return true; - } else if (Modifier.isProtected(memberFlags) && - (memberClassPackage.equals(clientClassPackage) || - clientClassInfo.isSubclassOf(memberClassInfo.name, false))) { - return true; - } else if (Modifier.isPrivate(memberFlags)) { - if (memberClassInfo.topLevelEnclosingClass.equals( - clientClassInfo.topLevelEnclosingClass)) { - return true; - } - } else if (memberClassPackage.equals(clientClassPackage)) { - return true; - } - } else if (Modifier.isProtected(memberClassFlags)) { - if (!(memberClassPackage.equals(clientClassPackage) || - clientClassInfo.isSubclassOf(memberClassInfo.directlyEnclosingClass, false))) { - return true; - } - if (Modifier.isPublic(memberFlags) || - Modifier.isProtected(memberFlags)) { - return true; - } else if (Modifier.isPrivate(memberFlags)) { - if (memberClassInfo.topLevelEnclosingClass.equals( - clientClassInfo.topLevelEnclosingClass)) { - return true; - } - } else { - if (memberClassPackage.equals(clientClassPackage)) { - return true; - } - } - } else if (Modifier.isPrivate(memberClassFlags)) { - if (memberClassInfo.topLevelEnclosingClass.equals( - clientClassInfo.topLevelEnclosingClass)) { - return true; - } - } else { // memberClassInfo is package-private - if (!memberClassPackage.equals(clientClassPackage)) { - return false; - } - if (Modifier.isPublic(memberFlags) || Modifier.isProtected(memberFlags)) { - return true; - } else if (Modifier.isPrivate(memberFlags)) { - if (memberClassInfo.topLevelEnclosingClass.equals( - clientClassInfo.topLevelEnclosingClass)) { - return true; - } - } else { - return true; - } - } - - return false; - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseReader.java b/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseReader.java deleted file mode 100644 index d227a8e..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseReader.java +++ /dev/null
@@ -1,107 +0,0 @@ -/* Copyright (c) 2002-2013 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.ObjectInputStream; -import java.io.UnsupportedEncodingException; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * This class creates the internal representation of the project database from a text buffer. - * - * The Pants build tool manipulates this data in various ways, and it's easiest for it - * to do so by parsing text files directly. This brings JMake into line with Zinc (the - * Scala incremental compiler) and allows Pants to handle both uniformly. - * - * @author Benjy Weinberger - * 13 January 2013 - */ -public class TextProjectDatabaseReader { - public Map<String,PCDEntry> readProjectDatabaseFromFile(File infile) { - try { - BufferedReader in = - new BufferedReader(new InputStreamReader(new FileInputStream(infile), "UTF-8")); - try { - return readProjectDatabase(in); - } finally { - in.close(); - } - } catch (FileNotFoundException e) { - throw new PrivateException(e); - } catch (UnsupportedEncodingException e) { - throw new PrivateException(e); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - public Map<String,PCDEntry> readProjectDatabase(BufferedReader in) { - Map<String,PCDEntry> pcd; - try { - String line = in.readLine(); - if (!"pcd entries:".equals(line)) - throw error("Expected: 'pcd entries:', got: " + line); - line = in.readLine(); - Matcher m = Pattern.compile("^(\\d+) items$").matcher(line); - if (!m.matches()) - throw error("Expected: '<n> items', got: " + line); - int numEntries = Integer.parseInt(m.group(1)); - pcd = new LinkedHashMap<String, PCDEntry>(numEntries); - for (int i = 0; i < numEntries; i++) { - line = in.readLine(); - if (line == null) - throw error("Unexpected EOF"); - String[] parts = line.split("\t"); - if (parts.length != 5) { - throw error("Invalid line: " + line); - } - String className = parts[0]; - String javaFullFilePath = parts[1]; - long oldClassFileLastModified = Long.parseLong(parts[2]); - long oldClassFileFingerprint = Long.parseLong(parts[3]); - ClassInfo ci = classInfoFromBase64(parts[4]); - PCDEntry entry = new PCDEntry(className, javaFullFilePath, oldClassFileLastModified, - oldClassFileFingerprint, ci); - pcd.put(entry.className, entry); - } - // We're done: We have detailed dep information in the PCD entries, so we don't - // need to read the dep information lines from the file. - } catch (IOException e) { - throw new PrivateException(e); - } - return pcd; - } - - private PrivateException error(String msg) { - return new PrivateException(new IllegalArgumentException(msg)); - } - - private ClassInfo classInfoFromBase64(String s) { - try { - byte[] bytes = Base64.decode(s.toCharArray()); - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); - ClassInfo ret = (ClassInfo)ois.readObject(); - ret.initializeImmediateTransientFields(); - return ret; - } catch (IOException e) { - throw new PrivateException(e); - } catch (ClassNotFoundException e) { - throw new PrivateException(e); - } - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseWriter.java b/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseWriter.java deleted file mode 100644 index ee5c08f5..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseWriter.java +++ /dev/null
@@ -1,144 +0,0 @@ -/* Copyright (c) 2002-2013 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.BufferedWriter; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - - -/** - * This class implements writing a text stream representing a project database. - * - * @see TextProjectDatabaseReader for details. - * - * @author Benjy Weinberger - * 13 January 2013 - */ -public class TextProjectDatabaseWriter { - private static Set<String> primitives = new LinkedHashSet<String>( - Arrays.asList("boolean", "byte", "char", "double", "float", "int", "long", "short", - "Z", "B", "C", "D", "F", "I", "J", "S")); - - private ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Reusable temp buffer. - - public void writeProjectDatabaseToFile(File outfile, Map<String, PCDEntry> pcd) { - try { - Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outfile), "UTF-8")); - try { - writeProjectDatabase(out, pcd); - } finally { - out.close(); - } - } catch (FileNotFoundException e) { - throw new PrivateException(e); - } catch (UnsupportedEncodingException e) { - throw new PrivateException(e); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - public void writeProjectDatabase(Writer out, Map<String,PCDEntry> pcd) { - try { - out.write("pcd entries:\n"); - out.write(Integer.toString(pcd.size())); - out.write(" items\n"); - Map<String, Set<String>> depsBySource = new LinkedHashMap<String, Set<String>>(); - for (PCDEntry entry : pcd.values()) { - writePCDEntry(out, entry); - Set<String> deps = depsBySource.get(entry.javaFileFullPath); - if (deps == null) { - deps = new LinkedHashSet<String>(); - depsBySource.put(entry.javaFileFullPath, deps); - } - addDepsFromClassInfo(deps, entry.oldClassInfo); - } - // Write out dependency information. Note that we don't need to read this back to recreate - // the PCD. We write it out here just as a convenience, so that external readers of the PDB - // file don't have to grok our internal ClassInfo structures. - out.write("dependencies:\n"); - out.write(Integer.toString(depsBySource.size())); - out.write(" items\n"); - for (Map.Entry<String, Set<String>> item : depsBySource.entrySet()) { - out.write(item.getKey()); - for (String s : item.getValue()) { - out.write('\t'); - out.write(s); - } - out.write('\n'); - } - } catch (IOException e) { - throw new PrivateException(e); - } - } - - private void addDepsFromClassInfo(Set<String> deps, ClassInfo ci) { - for (String s : ci.cpoolRefsToClasses) { - int i = 0; - int j = s.length(); - - // Fix some inconsistencies in how we represent types internally: - // Despite the comment on ci.cpoolRefsToClasses, class names may be - // representing in it with '['s and with '@', '#' instead of 'L', ';'. - while (s.charAt(i) == '[') i++; - if (s.charAt(i) == '@') i++; - if (s.endsWith("#")) j--; - int k = s.indexOf('$'); - - // Take the outer class, on references to nested classes. - if (k != -1) j = k; - if (i > 0 || j < s.length()) - s = s.substring(i, j); - - // We don't need to record deps on primitive types, or arrays of them. - if (!primitives.contains(s)) - deps.add(s); - } - } - - private void writePCDEntry(Writer out, PCDEntry entry) { - try { - out.write(entry.className); - out.write('\t'); - out.write(entry.javaFileFullPath); - out.write('\t'); - out.write(Long.toString(entry.oldClassFileLastModified)); - out.write('\t'); - out.write(Long.toString(entry.oldClassFileFingerprint)); - out.write('\t'); - out.write(classInfoToBase64(entry.oldClassInfo)); - out.write('\n'); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - private char[] classInfoToBase64(ClassInfo ci) { - baos.reset(); - try { - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(ci); - oos.close(); - } catch (IOException e) { - throw new PrivateException(e); - } - return Base64.encode(baos.toByteArray()); - } -}
diff --git a/third_party/jmake/src/org/pantsbuild/jmake/Utils.java b/third_party/jmake/src/org/pantsbuild/jmake/Utils.java deleted file mode 100644 index 38566a9..0000000 --- a/third_party/jmake/src/org/pantsbuild/jmake/Utils.java +++ /dev/null
@@ -1,355 +0,0 @@ -/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved - * - * This program is distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ -package org.pantsbuild.jmake; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * Utility functions used by other classes from this package. - * - * @author Misha Dmitriev - * 23 January 2003 - */ -public class Utils { - - static final String REPORT_PROBLEM = - "Please report this problem to Mikhail.Dmitriev@sun.com"; - static final byte[] MAGIC = {'J', 'a', 'v', 'a', 'm', 'a', 'k', 'e', ' ', 'P', 'r', 'o', 'j', 'e', 'c', 't', ' ', 'D', 'a', 't', 'a', 'b', 'a', 's', 'e', ' ', 'F', 'i', 'l', 'e'}; - static final int magicLength = MAGIC.length; - static final int PDB_FORMAT_CODE_OLD = 1; - static final int PDB_FORMAT_CODE_133 = 0x01030300; - static final int PDB_FORMAT_CODE_LATEST = PDB_FORMAT_CODE_133; - static final int JAVAC_TARGET_RELEASE_OLDEST = 0x01040000; // 1.4 and previous versions - static final int JAVAC_TARGET_RELEASE_15 = 0x01050000; // if class is compiled with -target 1.5 - static final int JAVAC_TARGET_RELEASE_16 = 0x01060000; // if class is compiled with -target 1.6 - static final int JAVAC_TARGET_RELEASE_17 = 0x01070000; // if class is compiled with -target 1.7 - static final int JAVAC_TARGET_RELEASE_18 = 0x01080000; // if class is compiled with -target 1.8 - static int warningLimit = 20; // Maximum number of warnings to print - static final int TIMING_TOTAL = 0; - static final int TIMING_PDBREAD = 1; - static final int TIMING_SYNCHRO = 2; - static final int TIMING_SYNCHRO_CHECK_JAVA_FILES = 3; - static final int TIMING_FIND_UPDATED_JAVA_FILES = 4; - static final int TIMING_CLASS_FILE_OBSOLETE_OR_DELETED = 5; - static final int TIMING_COMPILE = 6; - static final int TIMING_FIND_UPDATED_CLASSES = 7; - static final int TIMING_CHECK_UPDATED_CLASSES = 8; - static final int TIMING_PDBWRITE = 9; - static final int TIMING_SYNCHRO_CHECK_TMP = 10; - static final int TIMING_CLASS_FILE_OBSOLETE_TMP = 11; - static final int TIMING_PDBUPDATE = 12; - static final int TIMING_ARRAY_LENGTH = 13; - private static long timings[] = new long[TIMING_ARRAY_LENGTH]; - private static boolean timingOn = false; - - - // ------------------------------------------------------------------------------- - // Name manipulation stuff - // ------------------------------------------------------------------------------- - /** - * Returns package name for the given class. In case of no package, returns an - * empty, but non-null string. Returned string is interned. - */ - public static String getPackageName(String clazzName) { - int ldi = clazzName.lastIndexOf('/'); // For convenience, we use system-internal slashes, not dots - if (ldi == -1) { - return ""; - } else { - return clazzName.substring(0, ldi).intern(); - } - } - - /** - * Returns directly enclosing class name for the given class. If the given class is not a - * nested class, returns empty, but non-null string. Returned string is interned. - * NOTE FOR JDK 1.5: this function has to work with both old (1.4 and before) and new (1.5) ways - * of naming non-member classes. javacTargetRelease determines the javac version for this class; - * however on rare occasions (when checking a deleted non-project class) it may be 0, denoting - * that javac version is not known. - * In that case, we use the old algorithm, which is error-prone due to a bug in nested class - * naming that existed prior to JDK 1.5, where both a non-member local nested class B of A, and a - * member nested class B of anonymous class A$1, are named A$1$B. - */ - public static String getDirectlyEnclosingClass(String clazzName, int javacTargetRelease) { - int ldi = clazzName.lastIndexOf('$'); - if (ldi == -1) { - return ""; - } - - if (javacTargetRelease >= JAVAC_TARGET_RELEASE_15) { - return clazzName.substring(0, ldi).intern(); - } else { // JAVAC_TARGET_RELEASE_OLDEST or unknown - // Take into account local classes which are named like "EncClass$1$LocalClass", where EncClass - // is directly enclosing class. - int lldi = clazzName.lastIndexOf('$', ldi - 1); - if (lldi == -1 || !Character.isDigit(clazzName.charAt(lldi + 1))) { - return clazzName.substring(0, ldi).intern(); - } else { - return clazzName.substring(0, lldi).intern(); - } - } - } - - /** - * Returns top-level enclosing class name for the given class. If the given class is not a - * nested class, returns empty, but non-null string. Returned string is interned. - */ - public static String getTopLevelEnclosingClass(String clazzName) { - int fdi = clazzName.indexOf('$'); - if (fdi == -1) { - return ""; - } - - return clazzName.substring(0, fdi).intern(); - } - - /** - * Given the full path for the enclosing class file and the full name for the nested class, return the supposed - * full path for the nested class. - */ - public static String getClassFileFullPathForNestedClass(String enclosingClassFileFullPath, String nestedClassFullName) { - String enclosingClassDir = enclosingClassFileFullPath; - int cutIndex = enclosingClassDir.lastIndexOf(File.separatorChar); - enclosingClassDir = enclosingClassDir.substring(0, cutIndex + 1); // If slash is present, it's included, otherwise we get "" - cutIndex = nestedClassFullName.lastIndexOf('/'); - String nestedClassLocalName; - if (cutIndex < 0) { - nestedClassLocalName = nestedClassFullName; - } else { - nestedClassLocalName = nestedClassFullName.substring(cutIndex + 1); - } - return enclosingClassDir + nestedClassLocalName + ".class"; - } - - /** - * For two strings representing signatures, check if the number of parameters in - * both is the same. - */ - public static boolean sameParamNumber(String sig1, String sig2) { - return getParamNumber(sig1) == getParamNumber(sig2); - } - - private static int getParamNumber(String sig) { - char ch; - int parNo = 0, pos = 0; - do { - ch = sig.charAt(++pos); - if (ch == ')') { - break; - } - while (ch == '[') { - ch = sig.charAt(++pos); - } - parNo++; - if (ch == '@') { - // We replaced all "Lclassname;" in signatures with "@classname#" - while (ch != '#') { - ch = sig.charAt(++pos); - } - } - } while (ch != ')'); - return parNo; - } - - - // ------------------------------------------------------------------------------- - // File related stuff - // ------------------------------------------------------------------------------- - public static File checkFileForName(String name) { - // For each .java file, a File object is created two times when jmake executes: first when we synchronise the PCD - // and the supplied .java file list (we make sure that the .java file exists), and second time when we check if a class - // file was updated (we compare time stamps of the .java and the .class file). I tried to call this routine for a .java - // class both times, and cached File objects, but it looks as if this does not bring any real speed-up (and in fact may - // even slow down the application). Most of the time seems to go to the underlying code creating internal File - // representation; once it is created, it takes little time to execute another "new File()" for it. Also, all operations - // on files like getCanonicalPath() or lastModified() seem to be quite expensive, so their unnecessary repetition should - // be avoided as much as possible. - if (name == null) { - return null; - } - File file = new File(name); - if (file.exists()) { - return file; - } - return null; - } - - public static File checkOrCreateDirForName(String name) { - File file = new File(name); - if (!file.exists()) { - file.mkdirs(); - } - if (file.exists()) { - if (!file.isDirectory()) { - throw new PrivateException(new PublicExceptions.InternalException(file + " is not a directory.")); - } - return file; - } - return null; - } - - public static byte[] readFileIntoBuffer(File file) { - try { - InputStream in = new FileInputStream(file); - int len = (int) file.length(); - return readInputStreamIntoBuffer(in, len); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - public static byte[] readZipEntryIntoBuffer(ZipFile file, ZipEntry entry) { - try { - InputStream in = file.getInputStream(entry); - int len = (int) entry.getSize(); - return Utils.readInputStreamIntoBuffer(in, len); - } catch (IOException e) { - throw new PrivateException(e); - } - } - - public static byte[] readInputStreamIntoBuffer(InputStream in, int len) throws IOException { - byte buf[] = new byte[len]; - int readBytes, ofs = 0, remBytes = len; - do { - readBytes = in.read(buf, ofs, remBytes); - ofs += readBytes; - remBytes -= readBytes; - } while (ofs < len); - in.close(); - return buf; - } - - public static void readAndPrintBytesFromStream(InputStream in, OutputStream out) throws IOException { - int avail = in.available(); - if (avail > 0) { - byte outbytes[] = new byte[avail]; - int realOutBytes = in.read(outbytes); - out.write(outbytes, 0, realOutBytes); - } - } - - /** For a Windows path, convert the drive letter to the lower case */ - public static String convertDriveLetterToLowerCase(String path) { - if (path.charAt(1) != ':') { - return path; - } - char drive = path.charAt(0); - if (Character.isUpperCase(drive)) { - drive = Character.toLowerCase(drive); - char[] chars = path.toCharArray(); - chars[0] = drive; - path = new String(chars); - } - return path; - } - - public static void ignore(Exception e) { - // Ignore this exception - } - - /** Used when invoking a third-party executable compiler app */ - public static void delay(int ms) { - Object o = new Object(); - synchronized (o) { - try { - o.wait(ms); - } catch (InterruptedException e) { - } - } - } - // ------------------------------------------------------------------------------- - // Custom printing stuff - // ------------------------------------------------------------------------------- - private static PrintStream out = System.out; - private static PrintStream warn = System.out; - private static PrintStream err = System.err; - private static boolean printInfoMessages = true; - private static boolean printWarningMessages = true; - private static boolean printErrorMessages = true; - private static int warningNo; - - public static void setOutputStreams(PrintStream out, PrintStream warn, PrintStream err) { - Utils.out = out; - Utils.warn = warn; - Utils.err = err; - } - - public static void customizeOutput(boolean printInfoMessages, boolean printWarningMessages, boolean printErrorMessages) { - Utils.printInfoMessages = printInfoMessages; - Utils.printWarningMessages = printWarningMessages; - Utils.printErrorMessages = printErrorMessages; - } - - public static void printInfoMessage(String message) { - if (printInfoMessages) { - out.println(message); - } - } - - public static void printInfoMessageNoEOL(String message) { - if (printInfoMessages) { - out.print(message); - } - } - - public static void printWarningMessage(String message) { - if (!printWarningMessages) { - return; - } - if (warningNo < warningLimit) { - warn.println(message); - } else if (warningNo == warningLimit) { - warn.println("jmake: more than " + warningLimit + " warnings."); - } - warningNo++; - } - - public static void printErrorMessage(String message) { - if (printErrorMessages) { - err.println("jmake: " + message); - } - } - - // ------------------------------------------------------------------------------- - // Measuring stuff - // ------------------------------------------------------------------------------- - public static void setTimingOn() { - timingOn = true; - } - - public static void startTiming(int slot) { - timings[slot] = System.currentTimeMillis(); - } - - public static void stopAndPrintTiming(String message, int slot) { - if (timingOn) { - long time = System.currentTimeMillis() - timings[slot]; - printInfoMessage("========== " + message + " time = " + time); - } - } - - public static void printTiming(String message, int slot) { - if (timingOn) { - printInfoMessage("========== " + message + " time = " + timings[slot]); - } - } - - public static void stopAndAddTiming(int slot1, int slot2) { - if (timingOn) { - long time = System.currentTimeMillis() - timings[slot1]; - timings[slot2] += time; - } - } -}
diff --git a/third_party/robolectric/BUILD.gn b/third_party/robolectric/BUILD.gn index 3b90a712..3bc3d7e 100644 --- a/third_party/robolectric/BUILD.gn +++ b/third_party/robolectric/BUILD.gn
@@ -466,9 +466,6 @@ # here which requires_android. bypass_platform_checks = true - # TODO(mikecase): Remove this once crbug.com/638875 is fixed. - enable_incremental_javac_override = false - testonly = true processor_args_javac = [ "org.robolectric.annotation.processing.shadowPackage=org.robolectric" ]
diff --git a/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy b/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy index 41892a1..05c0faa 100644 --- a/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy +++ b/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
@@ -170,6 +170,9 @@ // Target .aar file contains .so libraries that need to be extracted, // and android_aar_prebuilt template will fail if it's not set explictly. sb.append(' extract_native_libraries = true\n') + // InstallActivity class is downloaded as a part of DFM & we need to inject + // a call to SplitCompat.install() into it. + sb.append(' split_compat_class_names = [ "com/google/ar/core/InstallActivity" ]\n') break } }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 5673c42..29de6638 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2049,6 +2049,7 @@ <int value="6" label="kSetup"/> <int value="7" label="kStylus"/> <int value="8" label="kLauncherSearchResult"/> + <int value="9" label="kLauncherSearchBoxMic"/> </enum> <enum name="AssistantExitPoint"> @@ -7697,7 +7698,7 @@ <int value="-143" label="SPDY_SESSION_ALREADY_EXISTS"/> <int value="-142" label="MSG_TOO_BIG"/> <int value="-141" label="SSL_CLIENT_AUTH_SIGNATURE_FAILED"/> - <int value="-140" label="HTTPS_PROXY_TUNNEL_RESPONSE"/> + <int value="-140" label="HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT"/> <int value="-139" label="TEMPORARILY_THROTTLED"/> <int value="-138" label="NETWORK_ACCESS_DENIED"/> <int value="-137" label="NAME_RESOLUTION_FAILED"/> @@ -31227,8 +31228,10 @@ <int value="-1349826793" label="ArcInputMethod:disabled"/> <int value="-1349532167" label="enable-wifi-credential-sync"/> <int value="-1346722635" label="gesture-selection"/> + <int value="-1346288427" label="AutofillShowFullDisclosureLabel:disabled"/> <int value="-1344375439" label="ServiceWorkerPaymentApps:disabled"/> <int value="-1343259222" label="RegionalLocalesAsDisplayUI:disabled"/> + <int value="-1342961844" label="InlineUpdateFlow:disabled"/> <int value="-1342039126" label="AshNewSystemMenu:enabled"/> <int value="-1341092934" label="enable-accelerated-overflow-scroll"/> <int value="-1340055960" label="enable-streamlined-hosted-apps"/> @@ -31946,6 +31949,7 @@ <int value="-102227288" label="PasswordExport:disabled"/> <int value="-99781021" label="disable-roboto-font-ui"/> <int value="-97145978" label="DesktopPWAsStayInWindow:enabled"/> + <int value="-92116820" label="InlineUpdateFlow:enabled"/> <int value="-89690053" label="MaterialDesignUserManager:enabled"/> <int value="-88822940" label="ssl-version-min"/> <int value="-88273414" label="ContentSuggestionsShowSummary:enabled"/> @@ -32245,6 +32249,7 @@ <int value="417709910" label="AutofillSendExperimentIdsInPaymentsRPCs:disabled"/> <int value="422307097" label="PhysicalWeb:disabled"/> + <int value="422426657" label="AutofillShowFullDisclosureLabel:enabled"/> <int value="423615350" label="enable-tab-audio-muting"/> <int value="423855924" label="enable-tab-switcher-theme-colors"/> <int value="430959979" label="SyncStandaloneTransport:disabled"/> @@ -36618,7 +36623,7 @@ <int value="137" label="NAME_RESOLUTION_FAILED"/> <int value="138" label="NETWORK_ACCESS_DENIED"/> <int value="139" label="TEMPORARILY_THROTTLED"/> - <int value="140" label="HTTPS_PROXY_TUNNEL_RESPONSE"/> + <int value="140" label="HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT"/> <int value="141" label="SSL_CLIENT_AUTH_SIGNATURE_FAILED"/> <int value="142" label="MSG_TOO_BIG"/> <int value="143" label="SPDY_SESSION_ALREADY_EXISTS"/> @@ -53126,6 +53131,13 @@ <int value="3" label="Fallback for Status Bar and content"/> </enum> +<enum name="TunnelRedirectHistogramValue"> + <int value="0" label="Subresource fetched using an explicit proxy"/> + <int value="1" label="Mainframe fetched using an explicit proxy"/> + <int value="2" label="Subresource fetched using an auto-detected proxy"/> + <int value="3" label="Mainframe fetched using an auto-detected proxy"/> +</enum> + <enum name="UIEventType"> <int value="0" label="Unknown"/> <int value="1" label="Touch released"/>
diff --git a/tools/metrics/histograms/generate_expired_histograms_array.py b/tools/metrics/histograms/generate_expired_histograms_array.py index cf10df7..be99d8a 100755 --- a/tools/metrics/histograms/generate_expired_histograms_array.py +++ b/tools/metrics/histograms/generate_expired_histograms_array.py
@@ -46,9 +46,10 @@ # Some extra "grace" time is given to expired histograms during which they # will contintue to be collected and reported. The dashboard should ignore # data from this period making the expiry noticeable and giving time for -# owners to re-enable them without any discontinuity of data. +# owners to re-enable them without any discontinuity of data. Releases are +# geneally 6 weeks apart but sometimes 7 so +2 to be safe. _EXPIRE_GRACE_MSTONES = 2 -_EXPIRE_GRACE_WEEKS = _EXPIRE_GRACE_MSTONES * 6 +_EXPIRE_GRACE_WEEKS = _EXPIRE_GRACE_MSTONES * 6 + 2 class Error(Exception):
diff --git a/tools/metrics/histograms/generate_expired_histograms_array_unittest.py b/tools/metrics/histograms/generate_expired_histograms_array_unittest.py index a4f2d721..d93eb6a 100755 --- a/tools/metrics/histograms/generate_expired_histograms_array_unittest.py +++ b/tools/metrics/histograms/generate_expired_histograms_array_unittest.py
@@ -155,7 +155,7 @@ <histograms><!-- Must be alphabetical. --> <histogram name="FirstHistogram" expires_after="2010-11-01"/> <histogram name="FourthHistogram" expires_after="M61"/> - <histogram name="SecondHistogram" expires_after="2010-10-01"/> + <histogram name="SecondHistogram" expires_after="2010-09-01"/> <histogram name="ThirdHistogram" expires_after="M60"/> </histograms> </histogram-configuration> @@ -166,7 +166,7 @@ content = generate_expired_histograms_array._GenerateFileContent( histograms, branch_data, mstone_data, "header.h", "uma") - # These have expired but are within the 12-week/2-milestone grace period. + # These have expired but are within the 14-week/2-milestone grace period. self.assertNotIn("FirstHistogram", content); self.assertNotIn("FourthHistogram", content); # These have expired and are outside of the grace period.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index b23fe2c..d6a449d 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -26439,7 +26439,7 @@ <summary>Status of drive cache metadata database open.</summary> </histogram> -<histogram name="Drive.DeltaFeedLoadTime" units="ms" expires_after="M74"> +<histogram name="Drive.DeltaFeedLoadTime" units="ms" expires_after="M75"> <owner>slangley@chromium.org</owner> <owner>weifangsun@chromium.org</owner> <summary> @@ -26447,7 +26447,7 @@ </summary> </histogram> -<histogram name="Drive.DirectoryFeedLoadTime" units="ms" expires_after="M74"> +<histogram name="Drive.DirectoryFeedLoadTime" units="ms" expires_after="M75"> <owner>slangley@chromium.org</owner> <owner>weifangsun@chromium.org</owner> <summary> @@ -26523,7 +26523,7 @@ </summary> </histogram> -<histogram name="Drive.FullFeedLoadTime" units="ms" expires_after="M74"> +<histogram name="Drive.FullFeedLoadTime" units="ms" expires_after="M75"> <owner>slangley@chromium.org</owner> <owner>weifangsun@chromium.org</owner> <summary> @@ -56926,8 +56926,7 @@ <summary> Tracks events when the currently navigated domain name is a lookalike to one of the top 10K domains or a domain that the user interacted with, resulting - in a navigation suggestion in the form of "Did you mean to go to - ...". + in a navigation suggestion interstitial. </summary> </histogram> @@ -62249,6 +62248,22 @@ </summary> </histogram> +<histogram name="Net.Proxy.RedirectDuringConnect" + enum="TunnelRedirectHistogramValue" expires_after="2019-05-19"> + <owner>eroman@chromium.org</owner> + <owner>mmenke@chromium.org</owner> + <summary> + Counts how often a 302 (redirect) response is observed during CONNECT (proxy + tunnel establishment). The counts are bucketed by proxy settings source + (auto-detect vs explicit) and load type (subresource vs main frame). + + To interpret this histogram, the most interesting property will be the + number of users in each of the buckets, which can be used to approximate + what fraction of users would be affected by a policy change that blocked + redirects on subresources/non-autodetected proxies. + </summary> +</histogram> + <histogram name="Net.ProxyAuthRequested.HasConnection"> <owner>rch@chromium.org</owner> <summary> @@ -125680,6 +125695,9 @@ </histogram> <histogram name="VRAutopresentedWebVR" enum="Boolean"> + <obsolete> + Deprecated as of 02/2019, VR DLAs are no longer supported. + </obsolete> <owner>ymalik@chromium.org</owner> <summary> Whether we're auto-presenting the first time we enter WebVR mode. @@ -125725,6 +125743,9 @@ </histogram> <histogram name="VRSessionTimeFromDLA" units="ms"> + <obsolete> + Deprecated as of 02/2019, VR DLAs are no longer supported. + </obsolete> <owner>ymalik@chromium.org</owner> <summary> The duration of a single VR session initiated via a deep-linked WebVR app.
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc index 7f9a33d..8348620 100644 --- a/ui/accessibility/ax_tree.cc +++ b/ui/accessibility/ax_tree.cc
@@ -931,7 +931,7 @@ void AXTree::PopulateOrderedSetItems(const AXNode* ordered_set, const AXNode* local_parent, std::vector<const AXNode*>& items, - bool node_is_radio_button) const { + const AXNode& original_node) const { // Stop searching current path if roles of local_parent and ordered set match. // Don't compare the container to itself. if (!(ordered_set == local_parent)) { @@ -939,6 +939,24 @@ return; } + // Initialize necessary variables. + // Default hierarchical_level is 0, which represents that no hierarchical + // level was detected on original_node. + int original_level = original_node.GetIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel); + // If original node is ordered set, then set its hierarchical level equal to + // its first child to ensure the items vector gets populated. + // This is due to ordered sets having a hierarchical level of 0, while their + // nodes have non-zero hierarchical values. + if ((ordered_set == &original_node) && + ordered_set->GetUnignoredChildAtIndex(0)) { + original_level = ordered_set->GetUnignoredChildAtIndex(0)->GetIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel); + } + int original_node_index = original_node.GetUnignoredIndexInParent(); + bool node_is_radio_button = + (original_node.data().role == ax::mojom::Role::kRadioButton); + for (int i = 0; i < local_parent->child_count(); ++i) { const AXNode* child = local_parent->GetUnignoredChildAtIndex(i); @@ -953,6 +971,23 @@ continue; } + int child_level = + child->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel); + + if (child_level < original_level) { + // If a decrease in level occurs after the original node has been + // examined, stop adding to this set. + if (original_node_index < i) + break; + // If a decrease in level has been detected before the original node + // has been examined, then everything previously added to items actually + // belongs to a different set. Clear items vector. + items.clear(); + continue; + } else if (child_level > original_level) { + continue; + } + // If role of node is kRadioButton, only add other kRadioButtons. if (node_is_radio_button && child->data().role == ax::mojom::Role::kRadioButton) @@ -967,7 +1002,7 @@ // Recurse if there is a generic container or is ignored. if (child->data().role == ax::mojom::Role::kGenericContainer || child->data().role == ax::mojom::Role::kIgnored) { - PopulateOrderedSetItems(ordered_set, child, items, node_is_radio_button); + PopulateOrderedSetItems(ordered_set, child, items, original_node); } } } @@ -979,20 +1014,15 @@ const AXNode* ordered_set) { DCHECK(ordered_set); std::vector<const AXNode*> items; - - // True if the role of AXNode GetPosInSet() was called on is a kRadioButton. - bool node_is_radio_button = - (node.data().role == ax::mojom::Role::kRadioButton); - // Find all items within ordered_set and add to vector. - PopulateOrderedSetItems(ordered_set, ordered_set, items, - node_is_radio_button); + PopulateOrderedSetItems(ordered_set, ordered_set, items, node); // Keep track of the number of elements ordered_set has. int32_t num_elements = 0; - // Necessary for calculating set_size. int32_t largest_assigned_set_size = 0; + int hierarchical_level = + node.GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel); // Compute pos_in_set_values. for (size_t i = 0; i < items.size(); ++i) { @@ -1009,6 +1039,13 @@ std::max(pos_in_set_value, item->GetIntAttribute(ax::mojom::IntAttribute::kPosInSet)); + // If level is specified, use author-provided value, if present. + if (hierarchical_level != 0 && + item->HasIntAttribute(ax::mojom::IntAttribute::kPosInSet)) { + pos_in_set_value = + item->GetIntAttribute(ax::mojom::IntAttribute::kPosInSet); + } + // Assign pos_in_set and update role counts. ordered_set_info_map_[item->id()].pos_in_set = pos_in_set_value; num_elements = pos_in_set_value; @@ -1035,22 +1072,29 @@ int32_t set_size_value = std::max( std::max(num_elements, largest_assigned_set_size), ordered_set_candidate); - // If ordered_set is not in the cache, assign it a new set_size. - if (ordered_set_info_map_.find(ordered_set->id()) == - ordered_set_info_map_.end()) - ordered_set_info_map_[ordered_set->id()] = OrderedSetInfo(); - // Assign set_size to ordered_set. // Must meet one of two conditions: // 1. Node role matches ordered set role. // 2. The node that calculations were called on is the ordered_set. - if (node.SetRoleMatchesItemRole(ordered_set) || ordered_set == &node) - ordered_set_info_map_[ordered_set->id()].set_size = set_size_value; + if (node.SetRoleMatchesItemRole(ordered_set) || ordered_set == &node) { + // If ordered_set is not in the cache, assign it a new set_size. + if (ordered_set_info_map_.find(ordered_set->id()) == + ordered_set_info_map_.end()) { + ordered_set_info_map_[ordered_set->id()] = OrderedSetInfo(); + ordered_set_info_map_[ordered_set->id()].set_size = set_size_value; + } + } // Assign set_size to items. for (size_t j = 0; j < items.size(); ++j) { const AXNode* item = items[j]; - ordered_set_info_map_[item->id()].set_size = set_size_value; + // If level is specified, use author-provided value, if present. + if (hierarchical_level != 0 && + item->HasIntAttribute(ax::mojom::IntAttribute::kSetSize)) + ordered_set_info_map_[item->id()].set_size = + item->GetIntAttribute(ax::mojom::IntAttribute::kSetSize); + else + ordered_set_info_map_[item->id()].set_size = set_size_value; } }
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h index 66be06f..9dff309 100644 --- a/ui/accessibility/ax_tree.h +++ b/ui/accessibility/ax_tree.h
@@ -245,7 +245,7 @@ void PopulateOrderedSetItems(const AXNode* ordered_set, const AXNode* local_parent, std::vector<const AXNode*>& items, - bool node_is_radio_button) const; + const AXNode& original_node) const; // Helper for GetPosInSet and GetSetSize. Computes the pos_in_set and set_size // values of all items in ordered_set and caches those values.
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index d92c2a6ac..2b470c8 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -2192,4 +2192,112 @@ EXPECT_EQ(list->GetSetSize(), 2); } +// Tests GetPosInSet and GetSetSize on a flat tree representation. According +// to the tree representation, the three elements are siblings. However, +// due to the presence of the kHierarchicalLevel attribute, they all belong +// to different sets. +TEST(AXTreeTest, TestSetSizePosInSetFlatTree) { + AXTreeUpdate tree_update; + tree_update.root_id = 1; + tree_update.nodes.resize(4); + tree_update.nodes[0].id = 1; + tree_update.nodes[0].role = ax::mojom::Role::kTree; + tree_update.nodes[0].child_ids = {2, 3, 4}; + tree_update.nodes[1].id = 2; + tree_update.nodes[1].role = ax::mojom::Role::kTreeItem; // 1 of 1 + tree_update.nodes[1].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 1); + tree_update.nodes[2].id = 3; + tree_update.nodes[2].role = ax::mojom::Role::kTreeItem; // 1 of 1 + tree_update.nodes[2].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 2); + tree_update.nodes[3].id = 4; + tree_update.nodes[3].role = ax::mojom::Role::kTreeItem; // 1 of 1 + tree_update.nodes[3].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 3); + AXTree tree(tree_update); + + AXNode* item1_level1 = tree.GetFromId(2); + EXPECT_EQ(item1_level1->GetPosInSet(), 1); + EXPECT_EQ(item1_level1->GetSetSize(), 1); + AXNode* item1_level2 = tree.GetFromId(3); + EXPECT_EQ(item1_level2->GetPosInSet(), 1); + EXPECT_EQ(item1_level2->GetSetSize(), 1); + AXNode* item1_level3 = tree.GetFromId(4); + EXPECT_EQ(item1_level3->GetPosInSet(), 1); + EXPECT_EQ(item1_level3->GetSetSize(), 1); +} + +// Tests GetPosInSet and GetSetSize on a flat tree representation, where only +// the level is specified. +TEST(AXTreeTest, TestSetSizePosInSetFlatTreeLevelsOnly) { + AXTreeUpdate tree_update; + tree_update.root_id = 1; + tree_update.nodes.resize(9); + tree_update.nodes[0].id = 1; + tree_update.nodes[0].role = ax::mojom::Role::kTree; + tree_update.nodes[0].child_ids = {2, 3, 4, 5, 6, 7, 8, 9}; + tree_update.nodes[1].id = 2; + tree_update.nodes[1].role = ax::mojom::Role::kTreeItem; // 1 of 3 + tree_update.nodes[1].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 1); + tree_update.nodes[2].id = 3; + tree_update.nodes[2].role = ax::mojom::Role::kTreeItem; // 1 of 2 + tree_update.nodes[2].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 2); + tree_update.nodes[3].id = 4; + tree_update.nodes[3].role = ax::mojom::Role::kTreeItem; // 2 of 2 + tree_update.nodes[3].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 2); + tree_update.nodes[4].id = 5; + tree_update.nodes[4].role = ax::mojom::Role::kTreeItem; // 2 of 3 + tree_update.nodes[4].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 1); + tree_update.nodes[5].id = 6; + tree_update.nodes[5].role = ax::mojom::Role::kTreeItem; // 1 of 3 + tree_update.nodes[5].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 2); + tree_update.nodes[6].id = 7; + tree_update.nodes[6].role = ax::mojom::Role::kTreeItem; // 2 of 3 + tree_update.nodes[6].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 2); + tree_update.nodes[7].id = 8; + tree_update.nodes[7].role = ax::mojom::Role::kTreeItem; // 3 of 3 + tree_update.nodes[7].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 2); + tree_update.nodes[8].id = 9; + tree_update.nodes[8].role = ax::mojom::Role::kTreeItem; // 3 of 3 + tree_update.nodes[8].AddIntAttribute( + ax::mojom::IntAttribute::kHierarchicalLevel, 1); + AXTree tree(tree_update); + + // The order in which we query the nodes should not matter. + AXNode* item3_level1 = tree.GetFromId(9); + EXPECT_EQ(item3_level1->GetPosInSet(), 3); + EXPECT_EQ(item3_level1->GetSetSize(), 3); + AXNode* item3_level2a = tree.GetFromId(8); + EXPECT_EQ(item3_level2a->GetPosInSet(), 3); + EXPECT_EQ(item3_level2a->GetSetSize(), 3); + AXNode* item2_level2a = tree.GetFromId(7); + EXPECT_EQ(item2_level2a->GetPosInSet(), 2); + EXPECT_EQ(item2_level2a->GetSetSize(), 3); + AXNode* item1_level2a = tree.GetFromId(6); + EXPECT_EQ(item1_level2a->GetPosInSet(), 1); + EXPECT_EQ(item1_level2a->GetSetSize(), 3); + AXNode* item2_level1 = tree.GetFromId(5); + EXPECT_EQ(item2_level1->GetPosInSet(), 2); + EXPECT_EQ(item2_level1->GetSetSize(), 3); + AXNode* item2_level2 = tree.GetFromId(4); + EXPECT_EQ(item2_level2->GetPosInSet(), 2); + EXPECT_EQ(item2_level2->GetSetSize(), 2); + AXNode* item1_level2 = tree.GetFromId(3); + EXPECT_EQ(item1_level2->GetPosInSet(), 1); + EXPECT_EQ(item1_level2->GetSetSize(), 2); + AXNode* item1_level1 = tree.GetFromId(2); + EXPECT_EQ(item1_level1->GetPosInSet(), 1); + EXPECT_EQ(item1_level1->GetSetSize(), 3); + AXNode* ordered_set = tree.GetFromId(1); + EXPECT_EQ(ordered_set->GetSetSize(), 3); +} + } // namespace ui
diff --git a/ui/aura/mus/input_method_mus.cc b/ui/aura/mus/input_method_mus.cc index a523876..ac30d5a 100644 --- a/ui/aura/mus/input_method_mus.cc +++ b/ui/aura/mus/input_method_mus.cc
@@ -37,6 +37,12 @@ .Run(handled ? EventResult::HANDLED : EventResult::UNHANDLED); } +void OnDispatchKeyEventPostIME(InputMethodMus::EventResultCallback callback, + bool handled, + bool stopped_propagation) { + CallEventResultCallback(std::move(callback), handled); +} + ws::mojom::TextInputClientDataPtr GetTextInputClientData( const ui::TextInputClient* client) { auto data = ws::mojom::TextInputClientData::New(); @@ -112,7 +118,7 @@ if (!GetTextInputClient() || (event->flags() & ui::EF_IS_SYNTHESIZED)) { return DispatchKeyEventPostIME( event, - base::BindOnce(&CallEventResultCallback, std::move(ack_callback))); + base::BindOnce(&OnDispatchKeyEventPostIME, std::move(ack_callback))); } return SendKeyEventToInputMethod(*event, std::move(ack_callback)); @@ -162,11 +168,14 @@ if (!IsTextInputClientFocused(client)) return; + // Sends text input client data (if changed) before caret change because + // InputMethodChromeOS accesses the data in its OnCaretBoundsChanged. + OnTextInputClientDataChanged(client); + if (input_method_) input_method_->OnCaretBoundsChanged(client->GetCaretBounds()); NotifyTextInputCaretBoundsChanged(client); - OnTextInputClientDataChanged(client); } void InputMethodMus::CancelComposition(const ui::TextInputClient* client) {
diff --git a/ui/aura/mus/input_method_mus_unittest.cc b/ui/aura/mus/input_method_mus_unittest.cc index 0dd1b83..4c60a4f 100644 --- a/ui/aura/mus/input_method_mus_unittest.cc +++ b/ui/aura/mus/input_method_mus_unittest.cc
@@ -8,6 +8,8 @@ #include <utility> #include "base/bind.h" +#include "base/callback.h" +#include "base/test/bind_test_util.h" #include "services/ws/public/mojom/ime/ime.mojom.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/mus/input_method_mus_test_api.h" @@ -21,8 +23,8 @@ // Empty implementation of InputMethodDelegate. class TestInputMethodDelegate : public ui::internal::InputMethodDelegate { public: - TestInputMethodDelegate() {} - ~TestInputMethodDelegate() override {} + TestInputMethodDelegate() = default; + ~TestInputMethodDelegate() override = default; bool was_dispatch_key_event_post_ime_called() const { return was_dispatch_key_event_post_ime_called_; @@ -31,9 +33,9 @@ // ui::internal::InputMethodDelegate: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* key, - base::OnceCallback<void(bool)> ack_callback) override { + DispatchKeyEventPostIMECallback callback) override { was_dispatch_key_event_post_ime_called_ = true; - CallDispatchKeyEventPostIMEAck(key, std::move(ack_callback)); + RunDispatchKeyEventPostIMECallback(key, std::move(callback)); return ui::EventDispatchDetails(); } @@ -51,13 +53,17 @@ // ProcessKeyEvent(). class TestInputMethod : public ws::mojom::InputMethod { public: - TestInputMethod() {} - ~TestInputMethod() override {} + TestInputMethod() = default; + ~TestInputMethod() override = default; ProcessKeyEventCallbacks* process_key_event_callbacks() { return &process_key_event_callbacks_; } + void set_on_carent_bounds_changed_closure(base::OnceClosure closure) { + on_caret_bounds_changed_closure_ = std::move(closure); + } + // ui::ime::InputMethod: void OnTextInputStateChanged( ws::mojom::TextInputStatePtr text_input_state) override { @@ -65,6 +71,8 @@ } void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override { was_on_caret_bounds_changed_called_ = true; + if (on_caret_bounds_changed_closure_) + std::move(on_caret_bounds_changed_closure_).Run(); } void OnTextInputClientDataChanged( ws::mojom::TextInputClientDataPtr data) override { @@ -119,8 +127,8 @@ bool was_cancel_composition_called_ = false; bool was_show_virtual_keyboard_if_enabled_called_ = false; ProcessKeyEventCallbacks process_key_event_callbacks_; - ws::mojom::TextInputClientDataPtr text_input_client_data_; + base::OnceClosure on_caret_bounds_changed_closure_; DISALLOW_COPY_AND_ASSIGN(TestInputMethod); }; @@ -279,10 +287,10 @@ // ui::internal::InputMethodDelegate: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* key, - base::OnceCallback<void(bool)> ack_callback) override { + DispatchKeyEventPostIMECallback callback) override { was_dispatch_key_event_post_ime_called_ = true; input_method_mus_->SetFocusedTextInputClient(text_input_client_); - CallDispatchKeyEventPostIMEAck(key, std::move(ack_callback)); + RunDispatchKeyEventPostIMECallback(key, std::move(callback)); return ui::EventDispatchDetails(); } @@ -491,4 +499,26 @@ } } +// Tests that text input client data is sent over before caret change. +TEST_F(InputMethodMusTest, TextInputClientDataAvailableBeforeCaretChange) { + TestTextInputClient focused_input_client; + TestInputMethodDelegate input_method_delegate; + InputMethodMus input_method_mus(&input_method_delegate, nullptr); + input_method_mus.SetFocusedTextInputClient(&focused_input_client); + + TestInputMethod test_input_method; + InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method); + + EXPECT_FALSE( + test_input_method.was_on_text_input_client_data_changed_called()); + + test_input_method.set_on_carent_bounds_changed_closure( + base::BindLambdaForTesting([&] { + EXPECT_TRUE( + test_input_method.was_on_text_input_client_data_changed_called()); + })); + InputMethodMusTestApi::CallOnCaretBoundsChanged(&input_method_mus, + &focused_input_client); +} + } // namespace aura
diff --git a/ui/aura/mus/text_input_client_impl.cc b/ui/aura/mus/text_input_client_impl.cc index 82640cd..22621d6 100644 --- a/ui/aura/mus/text_input_client_impl.cc +++ b/ui/aura/mus/text_input_client_impl.cc
@@ -20,9 +20,10 @@ // event was handled. void OnKeyEventProcessed( ws::mojom::TextInputClient::DispatchKeyEventPostIMECallback callback, - bool handled) { + bool handled, + bool stopped_propagation) { if (callback) - std::move(callback).Run(handled); + std::move(callback).Run(handled, stopped_propagation); } } // namespace @@ -82,8 +83,10 @@ std::unique_ptr<ui::Event> event, DispatchKeyEventPostIMECallback callback) { if (!delegate_) { - if (callback) - std::move(callback).Run(false); + if (callback) { + std::move(callback).Run(/* handled */ false, + /* stopped_propagation */ false); + } return; } ui::KeyEvent* key_event = event->AsKeyEvent(); @@ -100,8 +103,8 @@ return; // Event is being processed async. // The delegate finished processing the event. Run the ack now. - const bool handled = key_event->handled(); - key_event->WillHandleAsync().Run(handled); + key_event->WillHandleAsync().Run(key_event->handled(), + key_event->stopped_propagation()); } void TextInputClientImpl::EnsureCaretNotInRect(const gfx::Rect& rect) {
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index 346f1c8c..8950782 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -640,10 +640,17 @@ // Server should always supply a LocalSurfaceIdAllocation for roots. DCHECK(local_surface_id_allocation); + WindowTreeHostMus* window_tree_host = GetWindowTreeHostMus(window); + // This function is always called with the most recent LocalSurfaceId from the + // server. As such, the pending LocalSurfaceId is no longer applicabable and + // should be discarded. If we didn't reset it here, it's entirely possible a + // future change could attempt to incorrectly apply an old LocalSurfaceId. + if (window_tree_host->has_pending_local_surface_id_from_server()) + window_tree_host->TakePendingLocalSurfaceIdFromServer(); window->UpdateLocalSurfaceIdFromParent(*local_surface_id_allocation); - GetWindowTreeHostMus(window)->SetBoundsFromServer( - revert_bounds, window->GetLocalSurfaceIdAllocation()); + window_tree_host->SetBoundsFromServer(revert_bounds, + window->GetLocalSurfaceIdAllocation()); window->DidSetWindowTreeHostBoundsFromServer(); } @@ -663,9 +670,12 @@ window->GetWindow()->GetLocalSurfaceIdAllocation(); window_tree_host->SetBoundsFromServer(window_tree_host->bounds_in_dip(), lsia); - // This does *not* use SetWindowBoundsFromServer() as it leads to race - // conditions. In particular, it might incorrectly lead to the client - // changing the bounds when the server is also trying to change the bounds. + // Send the newly generated id to the server. This does *not* use + // WindowTreeHost:SetBounds() (which notifies the server of a bounds and id) + // as WindowTreeHost::SetBounds() leads to race conditions. In particular, + // it might incorrectly lead to the client changing the bounds when the + // server is also trying to change the bounds. The important thing here is + // to update the server of the id, not the bounds. tree_->UpdateLocalSurfaceIdFromChild(window->server_id(), lsia); } else { window_tree_host->SetBoundsFromServer(
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc index 6109d54..b614be2 100644 --- a/ui/aura/mus/window_tree_client_unittest.cc +++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -2886,6 +2886,10 @@ // No new bounds changes should be generated. EXPECT_EQ(0u, window_tree()->GetChangeCountForType(WindowTreeChangeType::BOUNDS)); + + // As the server supplied a new LocalSurfaceId the pending LocalSurfaceId + // should be cleared. + EXPECT_FALSE(top_level->host->has_pending_local_surface_id_from_server()); } TEST_F(WindowTreeClientTest, OnEmbedGetsLocalSurfaceId) {
diff --git a/ui/aura/screen_ozone.cc b/ui/aura/screen_ozone.cc index 28493ac..f99141b 100644 --- a/ui/aura/screen_ozone.cc +++ b/ui/aura/screen_ozone.cc
@@ -4,6 +4,7 @@ #include "ui/aura/screen_ozone.h" +#include "ui/aura/client/screen_position_client.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/display/display.h" @@ -30,7 +31,18 @@ aura::WindowTreeHost* host = aura::WindowTreeHost::GetForAcceleratedWidget(widget); - return host ? host->window() : nullptr; + if (!host) + return nullptr; + + gfx::NativeWindow window = host->window(); + gfx::Point local_point = point; + + aura::client::ScreenPositionClient* position_client = + aura::client::GetScreenPositionClient(window); + if (position_client) + position_client->ConvertPointFromScreen(window, &local_point); + + return window->GetEventHandlerForPoint(local_point); } int ScreenOzone::GetNumDisplays() const { @@ -89,4 +101,4 @@ return host->GetAcceleratedWidget(); } -} // namespace aura \ No newline at end of file +} // namespace aura
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc index b3db18d..7e3e64b 100644 --- a/ui/aura/window_tree_host.cc +++ b/ui/aura/window_tree_host.cc
@@ -259,7 +259,7 @@ ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) { + DispatchKeyEventPostIMECallback callback) { // If dispatch to IME is already disabled we shouldn't reach here. DCHECK(!dispatcher_->should_skip_ime()); dispatcher_->set_skip_ime(true); @@ -268,7 +268,7 @@ event_sink()->OnEventFromSource(event); if (!dispatch_details.dispatcher_destroyed) dispatcher_->set_skip_ime(false); - CallDispatchKeyEventPostIMEAck(event, std::move(ack_callback)); + RunDispatchKeyEventPostIMECallback(event, std::move(callback)); return dispatch_details; }
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h index 5a33164..e4a397b 100644 --- a/ui/aura/window_tree_host.h +++ b/ui/aura/window_tree_host.h
@@ -178,7 +178,7 @@ // Overridden from ui::internal::InputMethodDelegate: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) final; + DispatchKeyEventPostIMECallback callback) final; // Overridden from ui::EventSource: ui::EventSink* GetEventSink() override;
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index b1d52ade..6bc20ff9 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -317,6 +317,13 @@ "dragdrop/file_info.cc", "dragdrop/file_info.h", "emoji/emoji_panel_helper.h", + "idle/idle.cc", + "idle/idle.h", + "idle/idle_android.cc", + "idle/idle_chromeos.cc", + "idle/idle_linux.cc", + "idle/idle_mac.mm", + "idle/idle_win.cc", "pointer/pointer_device.h", "pointer/pointer_device_util.cc", "pointer/touch_editing_controller.cc", @@ -365,6 +372,7 @@ if (is_fuchsia) { sources += [ + "idle/idle_fuchsia.cc", "l10n/l10n_util_posix.cc", "resource/resource_bundle_fuchsia.cc", ] @@ -425,6 +433,17 @@ if (use_x11) { public_deps += [ "//ui/base/x" ] configs += [ "//build/config/linux:x11" ] + + if (!is_chromeos) { + sources += [ + "idle/idle_query_x11.cc", + "idle/idle_query_x11.h", + "idle/screensaver_window_finder_x11.cc", + "idle/screensaver_window_finder_x11.h", + ] + configs += [ "//build/config/linux:xscrnsaver" ] + deps += [ "//ui/gfx/x" ] + } } if (use_x11 && use_aura) { @@ -475,6 +494,14 @@ ] } + if (is_chromeos) { + deps += [ + "//chromeos", + "//chromeos/dbus", + ] + sources -= [ "idle/idle_linux.cc" ] + } + if (is_chromeos || (use_aura && is_linux && !use_x11)) { sources += [ "dragdrop/os_exchange_data_provider_aura.cc", @@ -572,6 +599,7 @@ sources -= [ "cursor/cursor_android.cc", "default_theme_provider.cc", + "idle/idle.cc", "l10n/l10n_font_util.cc", "models/button_menu_item_model.cc", "pointer/touch_editing_controller.cc",
diff --git a/ui/base/idle/BUILD.gn b/ui/base/idle/BUILD.gn deleted file mode 100644 index 30cafe4b..0000000 --- a/ui/base/idle/BUILD.gn +++ /dev/null
@@ -1,70 +0,0 @@ -# Copyright 2019 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("//build/config/jumbo.gni") -import("//build/config/ui.gni") -import("//testing/test.gni") -if (is_android) { - import("//build/config/android/rules.gni") -} else if (is_mac) { - import("//build/config/mac/rules.gni") -} -jumbo_component("idle") { - output_name = "ui_base_idle" - defines = [ "IS_UI_BASE_IDLE_IMPL" ] - sources = [ - "idle.cc", - "idle.h", - "idle_android.cc", - "idle_chromeos.cc", - "idle_linux.cc", - "idle_mac.mm", - "idle_win.cc", - ] - - deps = [ - "//ui/base", - ] - public_deps = [] - libs = [] - - if (is_fuchsia) { - sources += [ "idle_fuchsia.cc" ] - } - - if (use_x11) { - public_deps += [ "//ui/base/x" ] - deps += [ "//ui/gfx/x" ] - configs += [ - "//build/config/linux:x11", - "//build/config/linux:xscrnsaver", - ] - sources += [ - "idle_query_x11.cc", - "idle_query_x11.h", - "screensaver_window_finder_x11.cc", - "screensaver_window_finder_x11.h", - ] - } - - if (is_chromeos) { - deps += [ - "//chromeos", - "//chromeos/dbus", - ] - sources -= [ "idle_linux.cc" ] - } - - if (is_android) { - sources -= [ "idle.cc" ] - deps += [ "//ui/base:ui_base_jni_headers" ] - } - - if (is_mac) { - libs += [ - "Carbon.framework", - "Foundation.framework", - ] - } -}
diff --git a/ui/base/idle/idle.h b/ui/base/idle/idle.h index 83420c7..269ca44 100644 --- a/ui/base/idle/idle.h +++ b/ui/base/idle/idle.h
@@ -5,8 +5,8 @@ #ifndef UI_BASE_IDLE_IDLE_H_ #define UI_BASE_IDLE_IDLE_H_ -#include "base/component_export.h" #include "build/build_config.h" +#include "ui/base/ui_base_export.h" namespace ui { @@ -20,18 +20,18 @@ // For MacOSX, InitIdleMonitor needs to be called first to setup the monitor. #if defined(OS_MACOSX) -COMPONENT_EXPORT(UI_BASE_IDLE) void InitIdleMonitor(); +UI_BASE_EXPORT void InitIdleMonitor(); #endif // Calculate the Idle state. |idle_threshold| is the amount of time (in seconds) // before the user is considered idle. -COMPONENT_EXPORT(UI_BASE_IDLE) IdleState CalculateIdleState(int idle_threshold); +UI_BASE_EXPORT IdleState CalculateIdleState(int idle_threshold); // Calculate Idle time in seconds. -COMPONENT_EXPORT(UI_BASE_IDLE) int CalculateIdleTime(); +UI_BASE_EXPORT int CalculateIdleTime(); // Checks synchronously if Idle state is IDLE_STATE_LOCKED. -COMPONENT_EXPORT(UI_BASE_IDLE) bool CheckIdleStateIsLocked(); +UI_BASE_EXPORT bool CheckIdleStateIsLocked(); } // namespace ui
diff --git a/ui/base/ime/input_method_auralinux_unittest.cc b/ui/base/ime/input_method_auralinux_unittest.cc index 589c998..594e063 100644 --- a/ui/base/ime/input_method_auralinux_unittest.cc +++ b/ui/base/ime/input_method_auralinux_unittest.cc
@@ -172,7 +172,7 @@ ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* key_event, - base::OnceCallback<void(bool)> ack_callback) override { + DispatchKeyEventPostIMECallback callback) override { std::string action; switch (key_event->type()) { case ET_KEY_PRESSED: @@ -188,7 +188,7 @@ ss << key_event->key_code(); action += std::string(ss.str()); TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16(action)); - CallDispatchKeyEventPostIMEAck(key_event, std::move(ack_callback)); + RunDispatchKeyEventPostIMECallback(key_event, std::move(callback)); return ui::EventDispatchDetails(); }
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc index c57c8b57..13e0005 100644 --- a/ui/base/ime/input_method_base.cc +++ b/ui/base/ime/input_method_base.cc
@@ -163,12 +163,14 @@ ui::EventDispatchDetails InputMethodBase::DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) const { - if (delegate_) - return delegate_->DispatchKeyEventPostIME(event, std::move(ack_callback)); + ResultCallback result_callback) const { + if (delegate_) { + return delegate_->DispatchKeyEventPostIME(event, + std::move(result_callback)); + } - if (ack_callback) - std::move(ack_callback).Run(false); + if (result_callback) + std::move(result_callback).Run(false, false); return EventDispatchDetails(); }
diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h index 10a89ff..bd5b8cfc 100644 --- a/ui/base/ime/input_method_base.h +++ b/ui/base/ime/input_method_base.h
@@ -71,6 +71,9 @@ InputMethodKeyboardController* GetInputMethodKeyboardController() override; protected: + // See InputMethodDelegate for details on this. + using ResultCallback = base::OnceCallback<void(bool, bool)>; + explicit InputMethodBase(internal::InputMethodDelegate* delegate = nullptr); InputMethodBase(internal::InputMethodDelegate* delegate, std::unique_ptr<InputMethodKeyboardController> controller); @@ -106,9 +109,11 @@ // input type is not TEXT_INPUT_TYPE_NONE. void OnInputMethodChanged() const; + // See InputMethodDelegate::DispatchKeyEventPostIME(() for details on + // callback. virtual ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) const WARN_UNUSED_RESULT; + ResultCallback result_callback) const WARN_UNUSED_RESULT; // Convenience method to notify all observers of TextInputClient changes. void NotifyTextInputStateChanged(const TextInputClient* client);
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc index cb583c9..61dc589 100644 --- a/ui/base/ime/input_method_chromeos.cc +++ b/ui/base/ime/input_method_chromeos.cc
@@ -30,6 +30,32 @@ #include "ui/gfx/geometry/rect.h" namespace ui { +namespace { + +void RunAckCallbackFromPostImeCallback( + InputMethodChromeOS::AckCallback callback, + bool handled, + bool stopped_propagation) { + if (callback) + std::move(callback).Run(handled); +} + +void RunImeCallbackIfValid( + internal::InputMethodDelegate::DispatchKeyEventPostIMECallback callback, + bool handled, + bool stopped_propagation) { + if (!callback) + return; + std::move(callback).Run(handled, stopped_propagation); +} + +internal::InputMethodDelegate::DispatchKeyEventPostIMECallback +CreateResultCallbackFromAckCallback(InputMethodChromeOS::AckCallback callback) { + return base::BindOnce(&RunAckCallbackFromPostImeCallback, + std::move(callback)); +} + +} // namespace // InputMethodChromeOS implementation ----------------------------------------- InputMethodChromeOS::InputMethodChromeOS( @@ -58,6 +84,9 @@ ui::EventDispatchDetails InputMethodChromeOS::DispatchKeyEvent( ui::KeyEvent* event, AckCallback ack_callback) { + ResultCallback result_callback = + CreateResultCallbackFromAckCallback(std::move(ack_callback)); + DCHECK(event->IsKeyEvent()); DCHECK(!(event->flags() & ui::EF_IS_SYNTHESIZED)); @@ -106,7 +135,7 @@ // TODO(shuchen): Eventually, the language input keys should be handed // over to the IME extension to process. And IMF can handle if the IME // extension didn't handle. - return DispatchKeyEventPostIME(event, std::move(ack_callback)); + return DispatchKeyEventPostIME(event, std::move(result_callback)); } } } @@ -121,12 +150,13 @@ if (ExecuteCharacterComposer(*event)) { // Treating as PostIME event if character composer handles key event and // generates some IME event, - return ProcessKeyEventPostIME(event, std::move(ack_callback), false, - true); + return ProcessKeyEventPostIME(event, std::move(result_callback), false, + /* handled */ true, + /* stopped_propagation */ true); } - return ProcessUnfilteredKeyPressEvent(event, std::move(ack_callback)); + return ProcessUnfilteredKeyPressEvent(event, std::move(result_callback)); } - return DispatchKeyEventPostIME(event, std::move(ack_callback)); + return DispatchKeyEventPostIME(event, std::move(result_callback)); } handling_key_event_ = true; @@ -136,23 +166,23 @@ weak_ptr_factory_.GetWeakPtr(), // Pass the ownership of the new copied event. base::Owned(new ui::KeyEvent(*event)), - std::move(ack_callback)); + std::move(result_callback)); GetEngine()->ProcessKeyEvent(*event, std::move(callback)); return ui::EventDispatchDetails(); } - return ProcessKeyEventDone(event, std::move(ack_callback), false); + return ProcessKeyEventDone(event, std::move(result_callback), false); } void InputMethodChromeOS::KeyEventDoneCallback(ui::KeyEvent* event, - AckCallback ack_callback, + ResultCallback result_callback, bool is_handled) { ignore_result( - ProcessKeyEventDone(event, std::move(ack_callback), is_handled)); + ProcessKeyEventDone(event, std::move(result_callback), is_handled)); } ui::EventDispatchDetails InputMethodChromeOS::ProcessKeyEventDone( ui::KeyEvent* event, - AckCallback ack_callback, + ResultCallback result_callback, bool is_handled) { DCHECK(event); if (event->type() == ET_KEY_PRESSED) { @@ -168,8 +198,9 @@ } ui::EventDispatchDetails details; if (event->type() == ET_KEY_PRESSED || event->type() == ET_KEY_RELEASED) { - details = ProcessKeyEventPostIME(event, std::move(ack_callback), false, - is_handled); + details = + ProcessKeyEventPostIME(event, std::move(result_callback), false, + is_handled, /* stopped_propagation */ false); } handling_key_event_ = false; return details; @@ -367,25 +398,26 @@ ui::EventDispatchDetails InputMethodChromeOS::ProcessKeyEventPostIME( ui::KeyEvent* event, - AckCallback ack_callback, + ResultCallback result_callback, bool skip_process_filtered, - bool handled) { + bool handled, + bool stopped_propagation) { TextInputClient* client = GetTextInputClient(); if (!client) { // As ibus works asynchronously, there is a chance that the focused client // loses focus before this method gets called. - return DispatchKeyEventPostIME(event, std::move(ack_callback)); + return DispatchKeyEventPostIME(event, std::move(result_callback)); } ui::EventDispatchDetails dispatch_details; if (event->type() == ET_KEY_PRESSED && handled && !skip_process_filtered) - return ProcessFilteredKeyPressEvent(event, std::move(ack_callback)); + return ProcessFilteredKeyPressEvent(event, std::move(result_callback)); // In case the focus was changed by the key event. The |context_| should have // been reset when the focused window changed. if (client != GetTextInputClient()) { - if (ack_callback) - std::move(ack_callback).Run(false); + RunImeCallbackIfValid(std::move(result_callback), /* handled */ false, + /* stopped_propagation*/ false); return dispatch_details; } if (HasInputMethodResult()) @@ -394,32 +426,32 @@ // In case the focus was changed when sending input method results to the // focused window. if (client != GetTextInputClient()) { - if (ack_callback) - std::move(ack_callback).Run(false); + RunImeCallbackIfValid(std::move(result_callback), /* handled */ false, + /* stopped_propagation */ false); return dispatch_details; } if (handled) { - if (ack_callback) - std::move(ack_callback).Run(true); + RunImeCallbackIfValid(std::move(result_callback), + /* handled */ true, stopped_propagation); return dispatch_details; // IME handled the key event. do not forward. } if (event->type() == ET_KEY_PRESSED) - return ProcessUnfilteredKeyPressEvent(event, std::move(ack_callback)); + return ProcessUnfilteredKeyPressEvent(event, std::move(result_callback)); if (event->type() == ET_KEY_RELEASED) - return DispatchKeyEventPostIME(event, std::move(ack_callback)); + return DispatchKeyEventPostIME(event, std::move(result_callback)); return dispatch_details; } ui::EventDispatchDetails InputMethodChromeOS::ProcessFilteredKeyPressEvent( ui::KeyEvent* event, - AckCallback ack_callback) { + ResultCallback result_callback) { auto callback = base::Bind( &InputMethodChromeOS::PostProcessFilteredKeyPressEvent, weak_ptr_factory_.GetWeakPtr(), base::Owned(new ui::KeyEvent(*event)), - GetTextInputClient(), Passed(&ack_callback)); + GetTextInputClient(), Passed(&result_callback)); if (NeedInsertChar()) return DispatchKeyEventPostIME(event, std::move(callback)); @@ -440,7 +472,8 @@ void InputMethodChromeOS::PostProcessFilteredKeyPressEvent( ui::KeyEvent* event, TextInputClient* prev_client, - AckCallback ack_callback, + ResultCallback result_callback, + bool handled, bool stopped_propagation) { // In case the focus was changed by the key event. if (GetTextInputClient() != prev_client) @@ -448,34 +481,35 @@ if (stopped_propagation) { ResetContext(); - if (ack_callback) - std::move(ack_callback).Run(true); + RunImeCallbackIfValid(std::move(result_callback), handled, + /* stopped_propagation */ true); return; } - ignore_result( - ProcessKeyEventPostIME(event, std::move(ack_callback), true, true)); + ignore_result(ProcessKeyEventPostIME(event, std::move(result_callback), true, + true, false)); } ui::EventDispatchDetails InputMethodChromeOS::ProcessUnfilteredKeyPressEvent( ui::KeyEvent* event, - AckCallback ack_callback) { + ResultCallback result_callback) { return DispatchKeyEventPostIME( event, base::BindOnce(&InputMethodChromeOS::PostProcessUnfilteredKeyPressEvent, weak_ptr_factory_.GetWeakPtr(), base::Owned(new ui::KeyEvent(*event)), - GetTextInputClient(), std::move(ack_callback))); + GetTextInputClient(), std::move(result_callback))); } void InputMethodChromeOS::PostProcessUnfilteredKeyPressEvent( ui::KeyEvent* event, TextInputClient* prev_client, - AckCallback ack_callback, + ResultCallback result_callback, + bool handled, bool stopped_propagation) { if (stopped_propagation) { ResetContext(); - if (ack_callback) - std::move(ack_callback).Run(true); // true matches |stopped_propagation|. + RunImeCallbackIfValid(std::move(result_callback), handled, + /* stopped_propagation */ true); return; } @@ -488,8 +522,8 @@ // We should return here not to send the Tab key event to RWHV. TextInputClient* client = GetTextInputClient(); if (!client || client != prev_client) { - if (ack_callback) - std::move(ack_callback).Run(false); + RunImeCallbackIfValid(std::move(result_callback), /* handled */ false, + /* stopped_propagation */ false); return; } @@ -500,8 +534,8 @@ if (ch) client->InsertChar(*event); - if (ack_callback) - std::move(ack_callback).Run(false); + RunImeCallbackIfValid(std::move(result_callback), handled, + stopped_propagation); } void InputMethodChromeOS::ProcessInputMethodResult(ui::KeyEvent* event,
diff --git a/ui/base/ime/input_method_chromeos.h b/ui/base/ime/input_method_chromeos.h index 7787491..300dd23 100644 --- a/ui/base/ime/input_method_chromeos.h +++ b/ui/base/ime/input_method_chromeos.h
@@ -56,9 +56,10 @@ // Process a key returned from the input method. virtual ui::EventDispatchDetails ProcessKeyEventPostIME( ui::KeyEvent* event, - AckCallback ack_callback, + ResultCallback result_callback, bool skip_process_filtered, - bool handled) WARN_UNUSED_RESULT; + bool handled, + bool stopped_propagation) WARN_UNUSED_RESULT; // Resets context and abandon all pending results and key events. void ResetContext(); @@ -79,23 +80,25 @@ // when dispatching post IME. ui::EventDispatchDetails ProcessFilteredKeyPressEvent( ui::KeyEvent* event, - AckCallback ack_callback) WARN_UNUSED_RESULT; + ResultCallback result_callback) WARN_UNUSED_RESULT; // Post processes a key event that was already filtered by the input method. void PostProcessFilteredKeyPressEvent(ui::KeyEvent* event, TextInputClient* prev_client, - AckCallback ack_callback, + ResultCallback result_callback, + bool handled, bool stopped_propagation); // Processes a key event that was not filtered by the input method. ui::EventDispatchDetails ProcessUnfilteredKeyPressEvent( ui::KeyEvent* event, - AckCallback ack_callback) WARN_UNUSED_RESULT; + ResultCallback result_callback) WARN_UNUSED_RESULT; // Post processes a key event that was unfiltered by the input method. void PostProcessUnfilteredKeyPressEvent(ui::KeyEvent* event, TextInputClient* prev_client, - AckCallback ack_callback, + ResultCallback result_callback, + bool handled, bool stopped_propagation); // Sends input method result caused by the given key event to the focused text @@ -125,10 +128,10 @@ // Callback function for IMEEngineHandlerInterface::ProcessKeyEvent. void KeyEventDoneCallback(ui::KeyEvent* event, - AckCallback ack_callback, + ResultCallback result_callback, bool is_handled); ui::EventDispatchDetails ProcessKeyEventDone(ui::KeyEvent* event, - AckCallback ack_callback, + ResultCallback result_callback, bool is_handled) WARN_UNUSED_RESULT;
diff --git a/ui/base/ime/input_method_chromeos_unittest.cc b/ui/base/ime/input_method_chromeos_unittest.cc index 559f34d..fd1101d1 100644 --- a/ui/base/ime/input_method_chromeos_unittest.cc +++ b/ui/base/ime/input_method_chromeos_unittest.cc
@@ -8,11 +8,13 @@ #include <stdint.h> #include <memory> -#include <cstring> +#include <queue> +#include <string> #include "base/i18n/char_iterator.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/bind_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ime/chromeos/mock_ime_candidate_window_handler.h" @@ -69,13 +71,16 @@ }; // Overridden from InputMethodChromeOS: - ui::EventDispatchDetails ProcessKeyEventPostIME(ui::KeyEvent* key_event, - AckCallback ack_callback, - bool skip_process_filtered, - bool handled) override { + ui::EventDispatchDetails ProcessKeyEventPostIME( + ui::KeyEvent* key_event, + ResultCallback result_callback, + bool skip_process_filtered, + bool handled, + bool stopped_propagation) override { ui::EventDispatchDetails details = InputMethodChromeOS::ProcessKeyEventPostIME( - key_event, std::move(ack_callback), skip_process_filtered, handled); + key_event, std::move(result_callback), skip_process_filtered, + handled, stopped_propagation); if (!skip_process_filtered) { process_key_event_post_ime_args_.event = *key_event; process_key_event_post_ime_args_.handled = handled; @@ -196,6 +201,29 @@ void(const std::string&, uint32_t, uint32_t, uint32_t)); }; +class CachingInputMethodDelegate : public internal::InputMethodDelegate { + public: + CachingInputMethodDelegate() = default; + ~CachingInputMethodDelegate() override = default; + + std::queue<DispatchKeyEventPostIMECallback>& callbacks() { + return callbacks_; + } + + // internal::InputMethodDelegate: + EventDispatchDetails DispatchKeyEventPostIME( + KeyEvent* key_event, + DispatchKeyEventPostIMECallback callback) override { + callbacks_.emplace(std::move(callback)); + return EventDispatchDetails(); + } + + private: + std::queue<DispatchKeyEventPostIMECallback> callbacks_; + + DISALLOW_COPY_AND_ASSIGN(CachingInputMethodDelegate); +}; + class InputMethodChromeOSTest : public internal::InputMethodDelegate, public testing::Test, public DummyTextInputClient { @@ -221,7 +249,13 @@ IMEBridge::Get()->SetCandidateWindowHandler( mock_ime_candidate_window_handler_.get()); - ime_.reset(new TestableInputMethodChromeOS(this)); + internal::InputMethodDelegate* ime_delegate = this; + if (ShouldCreateCachingInputMethodDelegate()) { + caching_input_method_delegate_ = + std::make_unique<CachingInputMethodDelegate>(); + ime_delegate = caching_input_method_delegate_.get(); + } + ime_ = std::make_unique<TestableInputMethodChromeOS>(ime_delegate); ime_->SetFocusedTextInputClient(this); // InputMethodManager owns and delete it in InputMethodManager::Shutdown(). @@ -247,11 +281,11 @@ // Overridden from ui::internal::InputMethodDelegate: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* event, - base::OnceCallback<void(bool)> ack_callback) override { + DispatchKeyEventPostIMECallback callback) override { dispatched_key_event_ = *event; if (stop_propagation_post_ime_) event->StopPropagation(); - CallDispatchKeyEventPostIMEAck(event, std::move(ack_callback)); + RunDispatchKeyEventPostIMECallback(event, std::move(callback)); return ui::EventDispatchDetails(); } @@ -318,8 +352,13 @@ caret_bounds_ = gfx::Rect(); } + protected: + virtual bool ShouldCreateCachingInputMethodDelegate() { return false; } + std::unique_ptr<TestableInputMethodChromeOS> ime_; + std::unique_ptr<CachingInputMethodDelegate> caching_input_method_delegate_; + // Copy of the dispatched key event. ui::KeyEvent dispatched_key_event_; @@ -1019,8 +1058,9 @@ 0, DomKey::DeadKeyFromCombiningCharacter('^'), EventTimeForNow()); - ime_->ProcessKeyEventPostIME(&eventA, InputMethodChromeOS::AckCallback(), - false, true); + ime_->ProcessKeyEventPostIME( + &eventA, InputMethodDelegate::DispatchKeyEventPostIMECallback(), false, + true, true); const ui::KeyEvent& key_event = dispatched_key_event_; @@ -1054,4 +1094,98 @@ EXPECT_FALSE(input_method_manager_->state()->is_jp_ime()); } +class InputMethodChromeOSAsyncTest : public InputMethodChromeOSTest { + public: + InputMethodChromeOSAsyncTest() = default; + ~InputMethodChromeOSAsyncTest() override = default; + + protected: + // InputMethodChromeOSTest: + bool ShouldCreateCachingInputMethodDelegate() override { return true; } + + private: + DISALLOW_COPY_AND_ASSIGN(InputMethodChromeOSAsyncTest); +}; + +TEST_F(InputMethodChromeOSAsyncTest, StopPropagation) { + KeyEvent event(ET_KEY_PRESSED, VKEY_A, EF_NONE); + + // As CachingInputMethodDelegate doesn't immediately dispatch, the callback + // should not be run immediately. + bool async_callback_run = false; + bool async_callback_handled_result = false; + ime_->DispatchKeyEvent(&event, base::BindLambdaForTesting([&](bool handled) { + async_callback_handled_result = handled; + async_callback_run = true; + })); + EXPECT_FALSE(async_callback_run); + ASSERT_EQ(1u, caching_input_method_delegate_->callbacks().size()); + + // Run the queued callback in the delegate, which should then notify the + // callback supplied to DispatchKeyEvent(). + auto callback = + std::move(caching_input_method_delegate_->callbacks().front()); + caching_input_method_delegate_->callbacks().pop(); + std::move(callback).Run(/* handled */ true, /* stopped_propagation */ true); + EXPECT_TRUE(async_callback_run); + EXPECT_TRUE(async_callback_handled_result); + + // Because |stopped_propagation| was false, no character should be inserted. + EXPECT_FALSE(inserted_char_); +} + +TEST_F(InputMethodChromeOSAsyncTest, DidNotStopPropagation) { + KeyEvent event(ET_KEY_PRESSED, VKEY_A, EF_NONE); + + // As CachingInputMethodDelegate doesn't immediately dispatch, the callback + // should not be run immediately. + bool async_callback_run = false; + bool async_callback_handled_result = false; + ime_->DispatchKeyEvent(&event, base::BindLambdaForTesting([&](bool handled) { + async_callback_handled_result = handled; + async_callback_run = true; + })); + EXPECT_FALSE(async_callback_run); + ASSERT_EQ(1u, caching_input_method_delegate_->callbacks().size()); + + // Run the queued callback in the delegate, which should then notify the + // callback supplied to DispatchKeyEvent(). + auto callback = + std::move(caching_input_method_delegate_->callbacks().front()); + caching_input_method_delegate_->callbacks().pop(); + std::move(callback).Run(/* handled */ true, /* stopped_propagation */ false); + EXPECT_TRUE(async_callback_run); + EXPECT_TRUE(async_callback_handled_result); + + // Because |stopped_propagation| was true, a character should be inserted. + EXPECT_TRUE(inserted_char_); +} + +TEST_F(InputMethodChromeOSAsyncTest, UnhandledAndDidNotStopPropatation) { + KeyEvent event(ET_KEY_PRESSED, VKEY_A, EF_NONE); + + // As CachingInputMethodDelegate doesn't immediately dispatch, the callback + // should not be run immediately. + bool async_callback_run = false; + bool async_callback_handled_result = false; + ime_->DispatchKeyEvent(&event, base::BindLambdaForTesting([&](bool handled) { + async_callback_handled_result = handled; + async_callback_run = true; + })); + EXPECT_FALSE(async_callback_run); + ASSERT_EQ(1u, caching_input_method_delegate_->callbacks().size()); + + // Run the queued callback in the delegate, which should then notify the + // callback supplied to DispatchKeyEvent(). + auto callback = + std::move(caching_input_method_delegate_->callbacks().front()); + caching_input_method_delegate_->callbacks().pop(); + std::move(callback).Run(/* handled */ false, /* stopped_propagation */ false); + EXPECT_TRUE(async_callback_run); + EXPECT_FALSE(async_callback_handled_result); + + // Because |stopped_propagation| was true, a character should be inserted. + EXPECT_TRUE(inserted_char_); +} + } // namespace ui
diff --git a/ui/base/ime/input_method_delegate.cc b/ui/base/ime/input_method_delegate.cc index f2578a514..dc950847 100644 --- a/ui/base/ime/input_method_delegate.cc +++ b/ui/base/ime/input_method_delegate.cc
@@ -11,11 +11,13 @@ namespace internal { // static -void InputMethodDelegate::CallDispatchKeyEventPostIMEAck( +void InputMethodDelegate::RunDispatchKeyEventPostIMECallback( KeyEvent* key_event, - base::OnceCallback<void(bool)> ack_callback) { - if (ack_callback) - std::move(ack_callback).Run(key_event->stopped_propagation()); + DispatchKeyEventPostIMECallback callback) { + if (!callback) + return; + std::move(callback).Run(key_event->handled(), + key_event->stopped_propagation()); } } // namespace internal
diff --git a/ui/base/ime/input_method_delegate.h b/ui/base/ime/input_method_delegate.h index 4bfae03..70a1460 100644 --- a/ui/base/ime/input_method_delegate.h +++ b/ui/base/ime/input_method_delegate.h
@@ -22,19 +22,22 @@ public: virtual ~InputMethodDelegate() {} + using DispatchKeyEventPostIMECallback = base::OnceCallback<void(bool, bool)>; // Dispatch a key event already processed by the input method. Returns the - // status of processing, as well as running the callback |ack_callback| with - // the result of processing. |ack_callback| may be run asynchronously (if the - // delegate does processing async). |ack_callback| may not be null. - // Subclasses can use CallDispatchKeyEventPostIMEAck() to run the callback. + // status of processing, as well as running the callback |callback| with the + // result of processing. |callback| may be run asynchronously (if the + // delegate does processing async). Subclasses can use + // RunDispatchKeyEventPostIMECallback() to run the callback. |callback| is + // supplied two booleans that correspond to event->handled() and + // event->stopped_propagation(). virtual EventDispatchDetails DispatchKeyEventPostIME( KeyEvent* key_event, - base::OnceCallback<void(bool)> ack_callback) = 0; + DispatchKeyEventPostIMECallback callback) = 0; protected: - static void CallDispatchKeyEventPostIMEAck( + static void RunDispatchKeyEventPostIMECallback( KeyEvent* key_event, - base::OnceCallback<void(bool)> ack_callback); + DispatchKeyEventPostIMECallback callback); }; } // namespace internal
diff --git a/ui/base/ime/input_method_minimal_unittest.cc b/ui/base/ime/input_method_minimal_unittest.cc index 9eadb6a..146b02a 100644 --- a/ui/base/ime/input_method_minimal_unittest.cc +++ b/ui/base/ime/input_method_minimal_unittest.cc
@@ -22,10 +22,10 @@ ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* key_event, - base::OnceCallback<void(bool)> ack_callback) override { + DispatchKeyEventPostIMECallback callback) override { if (!propagation_post_ime_) key_event->StopPropagation(); - CallDispatchKeyEventPostIMEAck(key_event, std::move(ack_callback)); + RunDispatchKeyEventPostIMECallback(key_event, std::move(callback)); return ui::EventDispatchDetails(); }
diff --git a/ui/events/blink/scroll_predictor.cc b/ui/events/blink/scroll_predictor.cc index aa0580f1..ab396ffd 100644 --- a/ui/events/blink/scroll_predictor.cc +++ b/ui/events/blink/scroll_predictor.cc
@@ -63,8 +63,6 @@ return; if (event->GetType() == WebInputEvent::kGestureScrollUpdate) { - TRACE_EVENT_BEGIN0("input", "ScrollPredictor::ResampleScrollEvents"); - // TODO(eirage): When scroll events are coalesced with pinch, we can have // empty original event list. In that case, we can't use the original events // to update the prediction. We don't want to use the aggregated event to @@ -72,6 +70,8 @@ if (original_events.empty()) return; + TRACE_EVENT_BEGIN0("input", "ScrollPredictor::ResampleScrollEvents"); + temporary_accumulated_delta_ = current_accumulated_delta_; for (auto& coalesced_event : original_events) ComputeAccuracy(coalesced_event.event_);
diff --git a/ui/events/event.cc b/ui/events/event.cc index 2f70fa5..5191a68 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc
@@ -1149,7 +1149,7 @@ set_flags(flags() & ~mask); } -base::OnceCallback<void(bool)> KeyEvent::WillHandleAsync() { +base::OnceCallback<void(bool, bool)> KeyEvent::WillHandleAsync() { if (cancelable()) SetHandled(); return std::move(async_callback_);
diff --git a/ui/events/event.h b/ui/events/event.h index df7d1a5..c0dcecb 100644 --- a/ui/events/event.h +++ b/ui/events/event.h
@@ -834,7 +834,7 @@ public: explicit KeyDispatcherApi(KeyEvent* event) : event_(event) {} - void set_async_callback(base::OnceCallback<void(bool)> callback) { + void set_async_callback(base::OnceCallback<void(bool, bool)> callback) { event_->async_callback_ = std::move(callback); } @@ -955,7 +955,7 @@ // Called if the event is handled asynchronously. If the returned callback is // non-null, it *must* be run once async handling is complete. The argument // to the callback indicates if the event was handled or not. - base::OnceCallback<void(bool)> WillHandleAsync(); + base::OnceCallback<void(bool, bool)> WillHandleAsync(); bool HasAsyncCallback() const { return !async_callback_.is_null(); } protected: @@ -996,7 +996,7 @@ // it may be set only if and when GetCharacter() or GetDomKey() is called. mutable DomKey key_ = DomKey::NONE; - base::OnceCallback<void(bool)> async_callback_; + base::OnceCallback<void(bool, bool)> async_callback_; static KeyEvent* last_key_event_; #if defined(USE_X11)
diff --git a/ui/file_manager/file_manager/foreground/js/directory_model.js b/ui/file_manager/file_manager/foreground/js/directory_model.js index 183e75d..4547508 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_model.js +++ b/ui/file_manager/file_manager/foreground/js/directory_model.js
@@ -1223,15 +1223,16 @@ } // If a new file backed provided volume is mounted, // then redirect to it in the focused window. - // If crostini is mounted, redirect even if window is not focused. // Note, that this is a temporary solution for https://crbug.com/427776. + // If crostini is mounted, redirect if it is the currently selected dir. if (event.added.length !== 1) { return; } if ((window.isFocused() && event.added[0].volumeType === VolumeManagerCommon.VolumeType.PROVIDED && event.added[0].source === VolumeManagerCommon.Source.FILE) || - event.added[0].volumeType === VolumeManagerCommon.VolumeType.CROSTINI) { + (event.added[0].volumeType === VolumeManagerCommon.VolumeType.CROSTINI && + this.getCurrentRootType() === VolumeManagerCommon.RootType.CROSTINI)) { event.added[0].resolveDisplayRoot().then((displayRoot) => { // Resolving a display root on FSP volumes is instant, despite the // asynchronous call.
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.h b/ui/views/cocoa/bridged_native_widget_host_impl.h index 2f82d8e9..86b1588 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.h +++ b/ui/views/cocoa/bridged_native_widget_host_impl.h
@@ -353,7 +353,7 @@ // ui::internal::InputMethodDelegate: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* key, - base::OnceCallback<void(bool)> ack_callback) override; + DispatchKeyEventPostIMECallback callback) override; // ui::AccessibilityFocusOverrider::Client: id GetAccessibilityFocusedUIElement() override;
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.mm b/ui/views/cocoa/bridged_native_widget_host_impl.mm index a156f05..6f40be4 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.mm +++ b/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -1318,13 +1318,13 @@ ui::EventDispatchDetails BridgedNativeWidgetHostImpl::DispatchKeyEventPostIME( ui::KeyEvent* key, - base::OnceCallback<void(bool)> ack_callback) { + DispatchKeyEventPostIMECallback callback) { DCHECK(focus_manager_); if (!focus_manager_->OnKeyEvent(*key)) key->StopPropagation(); else native_widget_mac_->GetWidget()->OnKeyEvent(key); - CallDispatchKeyEventPostIMEAck(key, std::move(ack_callback)); + RunDispatchKeyEventPostIMECallback(key, std::move(callback)); return ui::EventDispatchDetails(); }
diff --git a/ui/views/cocoa/drag_drop_client_mac.h b/ui/views/cocoa/drag_drop_client_mac.h index 065e730..e976b2e 100644 --- a/ui/views/cocoa/drag_drop_client_mac.h +++ b/ui/views/cocoa/drag_drop_client_mac.h
@@ -65,7 +65,7 @@ DropHelper drop_helper_; // The drag and drop operation. - int operation_; + int operation_ = 0; // The bridge between the content view and the drag drop client. BridgedNativeWidgetImpl* bridge_; // Weak. Owns |this|. @@ -74,7 +74,7 @@ base::Closure quit_closure_; // Whether |this| is the source of current dragging session. - bool is_drag_source_; + bool is_drag_source_ = false; DISALLOW_COPY_AND_ASSIGN(DragDropClientMac); };
diff --git a/ui/views/cocoa/drag_drop_client_mac.mm b/ui/views/cocoa/drag_drop_client_mac.mm index 60475b3..c8ffe5d 100644 --- a/ui/views/cocoa/drag_drop_client_mac.mm +++ b/ui/views/cocoa/drag_drop_client_mac.mm
@@ -18,11 +18,7 @@ DragDropClientMac::DragDropClientMac(BridgedNativeWidgetImpl* bridge, View* root_view) - : drop_helper_(root_view), - operation_(0), - bridge_(bridge), - quit_closure_(base::Closure()), - is_drag_source_(false) { + : drop_helper_(root_view), bridge_(bridge) { DCHECK(bridge); }
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h index 5353a55..a25c050 100644 --- a/ui/views/controls/menu/menu_controller.h +++ b/ui/views/controls/menu/menu_controller.h
@@ -176,12 +176,12 @@ void OnDragEnteredScrollButton(SubmenuView* source, bool is_up); void OnDragExitedScrollButton(SubmenuView* source); - // Called by the Widget when a drag is about to start on a child view. This - // could be initiated by one of our MenuItemViews, or could be through another - // child View. + // Called by the MenuHost when a drag is about to start on a child view. + // This could be initiated by one of our MenuItemViews, or could be through + // another child View. void OnDragWillStart(); - // Called by the Widget when the drag has completed. |should_close| + // Called by the MenuHost when the drag has completed. |should_close| // corresponds to whether or not the menu should close. void OnDragComplete(bool should_close);
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc index a746afb..ab55ce0 100644 --- a/ui/views/controls/menu/menu_controller_unittest.cc +++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -14,6 +14,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" +#include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_node_data.h" #include "ui/events/event.h" #include "ui/events/event_constants.h" @@ -2309,5 +2310,28 @@ EXPECT_EQ(5, data.GetIntAttribute(ax::mojom::IntAttribute::kSetSize)); } +// Tests that a menu opened asynchronously, will notify its +// MenuControllerDelegate when accessibility performs a do default action. +TEST_F(MenuControllerTest, AccessibilityDoDefaultCallsAccept) { + views::test::DisableMenuClosureAnimations(); + + MenuController* controller = menu_controller(); + controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), + MENU_ANCHOR_TOPLEFT, false, false); + TestMenuControllerDelegate* delegate = menu_controller_delegate(); + EXPECT_EQ(0, delegate->on_menu_closed_called()); + + MenuItemView* accepted = menu_item()->GetSubmenu()->GetMenuItemAt(0); + ui::AXActionData data; + data.action = ax::mojom::Action::kDoDefault; + accepted->HandleAccessibleAction(data); + views::test::WaitForMenuClosureAnimation(); + + EXPECT_EQ(1, delegate->on_menu_closed_called()); + EXPECT_EQ(accepted, delegate->on_menu_closed_menu()); + EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, + delegate->on_menu_closed_notify_type()); +} + } // namespace test } // namespace views
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc index 9e1b05f..d762be8 100644 --- a/ui/views/controls/menu/menu_item_view.cc +++ b/ui/views/controls/menu/menu_item_view.cc
@@ -10,6 +10,7 @@ #include "base/i18n/case_conversion.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/menu_model.h" @@ -212,6 +213,13 @@ } } +bool MenuItemView::HandleAccessibleAction(const ui::AXActionData& action_data) { + if (action_data.action != ax::mojom::Action::kDoDefault) + return View::HandleAccessibleAction(action_data); + GetMenuController()->Accept(this, ui::EF_NONE); + return true; +} + // static bool MenuItemView::IsBubble(MenuAnchorPosition anchor) { return anchor == MENU_ANCHOR_BUBBLE_LEFT ||
diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h index 1821609..09b9b5b 100644 --- a/ui/views/controls/menu/menu_item_view.h +++ b/ui/views/controls/menu/menu_item_view.h
@@ -134,6 +134,7 @@ bool GetTooltipText(const gfx::Point& p, base::string16* tooltip) const override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + bool HandleAccessibleAction(const ui::AXActionData& action_data) override; // Returns the preferred height of menu items. This is only valid when the // menu is about to be shown.
diff --git a/ui/views/controls/webview/web_dialog_view.cc b/ui/views/controls/webview/web_dialog_view.cc index dcf1cd2..b5a32f36 100644 --- a/ui/views/controls/webview/web_dialog_view.cc +++ b/ui/views/controls/webview/web_dialog_view.cc
@@ -268,10 +268,12 @@ } bool WebDialogView::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { if (delegate_) - return delegate_->HandleContextMenu(params); - return WebDialogWebContentsDelegate::HandleContextMenu(params); + return delegate_->HandleContextMenu(render_frame_host, params); + return WebDialogWebContentsDelegate::HandleContextMenu(render_frame_host, + params); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/controls/webview/web_dialog_view.h b/ui/views/controls/webview/web_dialog_view.h index 27e9742e..af89035 100644 --- a/ui/views/controls/webview/web_dialog_view.h +++ b/ui/views/controls/webview/web_dialog_view.h
@@ -93,7 +93,8 @@ void OnCloseContents(content::WebContents* source, bool* out_close_dialog) override; bool ShouldShowDialogTitle() const override; - bool HandleContextMenu(const content::ContextMenuParams& params) override; + bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params) override; // Overridden from content::WebContentsDelegate: void SetContentsBounds(content::WebContents* source,
diff --git a/ui/web_dialogs/web_dialog_delegate.cc b/ui/web_dialogs/web_dialog_delegate.cc index b2ecbf6..1ec8b495 100644 --- a/ui/web_dialogs/web_dialog_delegate.cc +++ b/ui/web_dialogs/web_dialog_delegate.cc
@@ -34,6 +34,7 @@ } bool WebDialogDelegate::HandleContextMenu( + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { return false; }
diff --git a/ui/web_dialogs/web_dialog_delegate.h b/ui/web_dialogs/web_dialog_delegate.h index ee639fd..436b17b9 100644 --- a/ui/web_dialogs/web_dialog_delegate.h +++ b/ui/web_dialogs/web_dialog_delegate.h
@@ -17,6 +17,7 @@ class GURL; namespace content { +class RenderFrameHost; class RenderViewHost; class WebContents; class WebUI; @@ -116,7 +117,8 @@ // customized menu. // Returns true iff you do NOT want the standard context menu to be // shown (because you want to handle it yourself). - virtual bool HandleContextMenu(const content::ContextMenuParams& params); + virtual bool HandleContextMenu(content::RenderFrameHost* render_frame_host, + const content::ContextMenuParams& params); // A callback to allow the delegate to open a new URL inside |source|. // On return |out_new_contents| should contain the WebContents the URL