diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-15 14:18:00 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-15 14:00:37 +0000 |
commit | 66a2147d838e293f4a5db7711c8eba4e6faaaf0f (patch) | |
tree | 61ad99912355f5b6cc603d9b1dfadd77b950ce98 /chromium/components | |
parent | da51f56cc21233c2d30f0fe0d171727c3102b2e0 (diff) | |
download | qtwebengine-chromium-66a2147d838e293f4a5db7711c8eba4e6faaaf0f.tar.gz |
BASELINE: Update Chromium to 65.0.3325.75
Change-Id: I5485bc5c111539356276457516584fa5737f07d8
Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/components')
29 files changed, 221 insertions, 1027 deletions
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc index 4347194e254..3319035130c 100644 --- a/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc +++ b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc @@ -610,7 +610,7 @@ void GpuArcVideoDecodeAccelerator::ImportBufferForPicture( base::FileDescriptor(handle_fd.release(), true)); for (const auto& plane : planes) { gmb_handle.native_pixmap_handle.planes.emplace_back(plane.stride, - plane.offset, 0, 0); + plane.offset, 0); } } diff --git a/chromium/components/autofill/content/renderer/page_passwords_analyser.cc b/chromium/components/autofill/content/renderer/page_passwords_analyser.cc index 141d40e521c..f45a6caa4ad 100644 --- a/chromium/components/autofill/content/renderer/page_passwords_analyser.cc +++ b/chromium/components/autofill/content/renderer/page_passwords_analyser.cc @@ -371,8 +371,9 @@ void AnalyseForm(const FormInputCollection& form_input_collection, } else { // By default (if the other heuristics fail), the first text field // preceding a password field will be considered the username field. - for (username_field_guess = password_inputs[0] - 1;; + for (username_field_guess = explicit_password_inputs[0] - 1;; --username_field_guess) { + DCHECK(username_field_guess < signature.size()); if (signature[username_field_guess] == kTextFieldSignature) break; } diff --git a/chromium/components/data_use_measurement/core/data_use_ascriber.h b/chromium/components/data_use_measurement/core/data_use_ascriber.h index 9d903aea015..5ead8d7d0f8 100644 --- a/chromium/components/data_use_measurement/core/data_use_ascriber.h +++ b/chromium/components/data_use_measurement/core/data_use_ascriber.h @@ -102,6 +102,7 @@ class DataUseAscriber { } // Methods called by DataUseNetworkDelegate to propagate data use information: + // OnBeforeUrlRequest may be called twice. e.g., in case of redirects. virtual void OnBeforeUrlRequest(net::URLRequest* request); virtual void OnNetworkBytesSent(net::URLRequest* request, int64_t bytes_sent); virtual void OnNetworkBytesReceived(net::URLRequest* request, diff --git a/chromium/components/exo/client_controlled_shell_surface.cc b/chromium/components/exo/client_controlled_shell_surface.cc index 348a3168631..7139392ef6e 100644 --- a/chromium/components/exo/client_controlled_shell_surface.cc +++ b/chromium/components/exo/client_controlled_shell_surface.cc @@ -474,14 +474,15 @@ void ClientControlledShellSurface::OnSurfaceCommit() { orientation_compositor_lock_.reset(); } -bool ClientControlledShellSurface::IsTouchEnabled(Surface* surface) const { - // The target for input events is selected by recursively hit-testing surfaces - // in the surface tree. During client-driven dragging/resizing, capture is set - // on the root surface. When capture is reset to a different target, mouse - // events are redirected from the old to the new target, but touch/gesture - // events are cancelled. To avoid prematurely ending the drag/resize, ensure - // that the target and capture windows are the same by disabling touch input - // for all but the root surface. +bool ClientControlledShellSurface::IsInputEnabled(Surface* surface) const { + // Client-driven dragging/resizing relies on implicit grab, which ensures that + // mouse/touch events are delivered to the focused surface until release, even + // if they fall outside surface bounds. However, if the client destroys the + // surface with implicit grab, the drag/resize is prematurely ended. Prevent + // this by delivering all input events to the root surface, which shares the + // lifetime of the shell surface. + // TODO(domlaskowski): Remove once the client is provided with an API to hook + // into server-driven dragging/resizing. return surface == root_surface(); } @@ -670,8 +671,9 @@ void ClientControlledShellSurface::InitializeWindowState( // Allow the client to request bounds that do not fill the entire work area // when maximized, or the entire display when fullscreen. window_state->set_allow_set_bounds_direct(true); - widget_->set_movement_disabled(true); window_state->set_ignore_keyboard_bounds_change(true); + if (container_ == ash::kShellWindowId_SystemModalContainer) + DisableMovement(); } float ClientControlledShellSurface::GetScale() const { diff --git a/chromium/components/exo/client_controlled_shell_surface.h b/chromium/components/exo/client_controlled_shell_surface.h index 7c9349db058..3fda1e29f85 100644 --- a/chromium/components/exo/client_controlled_shell_surface.h +++ b/chromium/components/exo/client_controlled_shell_surface.h @@ -150,7 +150,7 @@ class ClientControlledShellSurface // Overridden from SurfaceDelegate: void OnSurfaceCommit() override; - bool IsTouchEnabled(Surface* surface) const override; + bool IsInputEnabled(Surface* surface) const override; // Overridden from views::WidgetDelegate: bool CanMaximize() const override; diff --git a/chromium/components/exo/client_controlled_shell_surface_unittest.cc b/chromium/components/exo/client_controlled_shell_surface_unittest.cc index 78da5c0e8af..68ff31e7c4b 100644 --- a/chromium/components/exo/client_controlled_shell_surface_unittest.cc +++ b/chromium/components/exo/client_controlled_shell_surface_unittest.cc @@ -754,4 +754,51 @@ TEST_F(ClientControlledShellSurfaceTest, MouseAndTouchTarget) { targeter->FindTargetForEvent(root, &no_touch)))); } +// The shell surface in SystemModal container should be unresizable. +TEST_F(ClientControlledShellSurfaceTest, + ShellSurfaceInSystemModalIsUnresizable) { + gfx::Size buffer_size(256, 256); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get(), + /*is_modal=*/true); + surface->Attach(buffer.get()); + surface->Commit(); + + EXPECT_FALSE(shell_surface->GetWidget()->widget_delegate()->CanResize()); +} + +// The shell surface in SystemModal container should not become target +// at the edge. +TEST_F(ClientControlledShellSurfaceTest, ShellSurfaceInSystemModalHitTest) { + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get(), + /*is_modal=*/true); + shell_surface->set_client_controlled_move_resize(false); + + display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay(); + + gfx::Size desktop_size(640, 480); + std::unique_ptr<Buffer> desktop_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(desktop_size))); + surface->Attach(desktop_buffer.get()); + surface->SetInputRegion(gfx::Rect(0, 0, 0, 0)); + shell_surface->SetGeometry(display.bounds()); + surface->Commit(); + + EXPECT_FALSE(shell_surface->GetWidget()->widget_delegate()->CanResize()); + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + aura::Window* root = window->GetRootWindow(); + + ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(100, 0), + gfx::Point(100, 0), ui::EventTimeForNow(), 0, 0); + aura::WindowTargeter targeter; + aura::Window* found = + static_cast<aura::Window*>(targeter.FindTargetForEvent(root, &event)); + EXPECT_FALSE(window->Contains(found)); +} + } // namespace exo diff --git a/chromium/components/exo/pointer.cc b/chromium/components/exo/pointer.cc index 5d278bbe7b9..62ccbe27047 100644 --- a/chromium/components/exo/pointer.cc +++ b/chromium/components/exo/pointer.cc @@ -23,6 +23,7 @@ #include "ui/events/event.h" #include "ui/gfx/geometry/vector2d_conversions.h" #include "ui/gfx/transform_util.h" +#include "ui/views/widget/widget.h" #if defined(USE_OZONE) #include "ui/ozone/public/cursor_factory_ozone.h" @@ -478,7 +479,22 @@ void Pointer::UpdateCursor() { #endif } - cursor_client->SetCursor(cursor_); + // If there is a focused surface, update its widget as the views framework + // expect that Widget knows the current cursor. Otherwise update the + // cursor directly on CursorClient. + if (focus_surface_) { + aura::Window* window = focus_surface_->window(); + do { + views::Widget* widget = views::Widget::GetWidgetForNativeView(window); + if (widget) { + widget->SetCursor(cursor_); + return; + } + window = window->parent(); + } while (window); + } else { + cursor_client->SetCursor(cursor_); + } } } // namespace exo diff --git a/chromium/components/exo/shell_surface.cc b/chromium/components/exo/shell_surface.cc index 1bcfad83e97..b14d7aafd1f 100644 --- a/chromium/components/exo/shell_surface.cc +++ b/chromium/components/exo/shell_surface.cc @@ -140,13 +140,6 @@ void ShellSurface::SetFullscreen(bool fullscreen) { widget_->SetFullscreen(fullscreen); } -void ShellSurface::DisableMovement() { - movement_disabled_ = true; - - if (widget_) - widget_->set_movement_disabled(true); -} - void ShellSurface::Resize(int component) { TRACE_EVENT1("exo", "ShellSurface::Resize", "component", component); diff --git a/chromium/components/exo/shell_surface.h b/chromium/components/exo/shell_surface.h index 589e27bf2f1..10e753899f0 100644 --- a/chromium/components/exo/shell_surface.h +++ b/chromium/components/exo/shell_surface.h @@ -43,9 +43,6 @@ class ShellSurface : public ShellSurfaceBase, // Set fullscreen state for shell surface. void SetFullscreen(bool fullscreen); - // Prevents shell surface from being moved. - void DisableMovement(); - // Start an interactive resize of surface. |component| is one of the windows // HT constants (see ui/base/hit_test.h) and describes in what direction the // surface should be resized. diff --git a/chromium/components/exo/shell_surface_base.cc b/chromium/components/exo/shell_surface_base.cc index 3a189d58e7c..7023369b1d4 100644 --- a/chromium/components/exo/shell_surface_base.cc +++ b/chromium/components/exo/shell_surface_base.cc @@ -210,8 +210,10 @@ class CustomWindowTargeter : public aura::WindowTargeter { return false; int component = widget_->non_client_view()->NonClientHitTest(local_point); - if (component != HTNOWHERE && component != HTCLIENT) + if (component != HTNOWHERE && component != HTCLIENT && + component != HTBORDER) { return true; + } aura::Window::ConvertPointToTarget(window, surface->window(), &local_point); return surface->HitTest(local_point); @@ -567,6 +569,13 @@ void ShellSurfaceBase::SetCanMinimize(bool can_minimize) { can_minimize_ = can_minimize; } +void ShellSurfaceBase::DisableMovement() { + movement_disabled_ = true; + + if (widget_) + widget_->set_movement_disabled(true); +} + // static void ShellSurfaceBase::SetMainSurface(aura::Window* window, Surface* surface) { window->SetProperty(kMainSurfaceKey, surface); @@ -675,7 +684,7 @@ void ShellSurfaceBase::OnSurfaceCommit() { widget_->OnSizeConstraintsChanged(); } -bool ShellSurfaceBase::IsTouchEnabled(Surface*) const { +bool ShellSurfaceBase::IsInputEnabled(Surface*) const { return true; } diff --git a/chromium/components/exo/shell_surface_base.h b/chromium/components/exo/shell_surface_base.h index 58d91216f18..defeb662aba 100644 --- a/chromium/components/exo/shell_surface_base.h +++ b/chromium/components/exo/shell_surface_base.h @@ -146,6 +146,9 @@ class ShellSurfaceBase : public SurfaceTreeHost, void SetCanMinimize(bool can_minimize); + // Prevents shell surface from being moved. + void DisableMovement(); + // Sets the main surface for the window. static void SetMainSurface(aura::Window* window, Surface* surface); @@ -158,7 +161,7 @@ class ShellSurfaceBase : public SurfaceTreeHost, // Overridden from SurfaceDelegate: void OnSurfaceCommit() override; - bool IsTouchEnabled(Surface* surface) const override; + bool IsInputEnabled(Surface* surface) const override; void OnSetFrame(SurfaceFrameType type) override; void OnSetFrameColors(SkColor active_color, SkColor inactive_color) override; void OnSetParent(Surface* parent, const gfx::Point& position) override; diff --git a/chromium/components/exo/sub_surface.cc b/chromium/components/exo/sub_surface.cc index 871899143c9..27592e55850 100644 --- a/chromium/components/exo/sub_surface.cc +++ b/chromium/components/exo/sub_surface.cc @@ -109,8 +109,8 @@ bool SubSurface::IsSurfaceSynchronized() const { return parent_ && parent_->IsSynchronized(); } -bool SubSurface::IsTouchEnabled(Surface* surface) const { - return !parent_ || parent_->IsTouchEnabled(surface); +bool SubSurface::IsInputEnabled(Surface* surface) const { + return !parent_ || parent_->IsInputEnabled(surface); } //////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/components/exo/sub_surface.h b/chromium/components/exo/sub_surface.h index e0a11185c20..acd775eac0e 100644 --- a/chromium/components/exo/sub_surface.h +++ b/chromium/components/exo/sub_surface.h @@ -51,7 +51,7 @@ class SubSurface : public SurfaceDelegate, public SurfaceObserver { // Overridden from SurfaceDelegate: void OnSurfaceCommit() override; bool IsSurfaceSynchronized() const override; - bool IsTouchEnabled(Surface* surface) const override; + bool IsInputEnabled(Surface* surface) const override; void OnSetFrame(SurfaceFrameType type) override {} void OnSetFrameColors(SkColor active_color, SkColor inactive_color) override { } diff --git a/chromium/components/exo/surface.cc b/chromium/components/exo/surface.cc index 6b9d48ab3f4..be321c416bf 100644 --- a/chromium/components/exo/surface.cc +++ b/chromium/components/exo/surface.cc @@ -163,10 +163,7 @@ class CustomWindowTargeter : public aura::WindowTargeter { bool EventLocationInsideBounds(aura::Window* window, const ui::LocatedEvent& event) const override { Surface* surface = Surface::AsSurface(window); - if (!surface) - return false; - - if (event.IsTouchEvent() && !surface->IsTouchEnabled(surface)) + if (!surface || !surface->IsInputEnabled(surface)) return false; gfx::Point local_point = event.location(); @@ -629,8 +626,8 @@ bool Surface::IsSynchronized() const { return delegate_ && delegate_->IsSurfaceSynchronized(); } -bool Surface::IsTouchEnabled(Surface* surface) const { - return !delegate_ || delegate_->IsTouchEnabled(surface); +bool Surface::IsInputEnabled(Surface* surface) const { + return !delegate_ || delegate_->IsInputEnabled(surface); } bool Surface::HasHitTestRegion() const { diff --git a/chromium/components/exo/surface.h b/chromium/components/exo/surface.h index 888a518a9b9..efac96f8a68 100644 --- a/chromium/components/exo/surface.h +++ b/chromium/components/exo/surface.h @@ -181,8 +181,8 @@ class Surface final : public ui::PropertyHandler { // Returns true if surface is in synchronized mode. bool IsSynchronized() const; - // Returns true if surface should receive touch events. - bool IsTouchEnabled(Surface* surface) const; + // Returns true if surface should receive input events. + bool IsInputEnabled(Surface* surface) const; // Returns false if the hit test region is empty. bool HasHitTestRegion() const; diff --git a/chromium/components/exo/surface_delegate.h b/chromium/components/exo/surface_delegate.h index a1895815d07..4b5ed492e2f 100644 --- a/chromium/components/exo/surface_delegate.h +++ b/chromium/components/exo/surface_delegate.h @@ -24,10 +24,8 @@ class SurfaceDelegate { // double-buffered state should be synchronized with parent surface. virtual bool IsSurfaceSynchronized() const = 0; - // Returns true if surface should receive touch events. - // TODO(domlaskowski): Remove once client-driven dragging/resizing is removed - // in crbug.com/795119. - virtual bool IsTouchEnabled(Surface* surface) const = 0; + // Returns true if surface should receive input events. + virtual bool IsInputEnabled(Surface* surface) const = 0; // Called when surface was requested to use a specific frame type. virtual void OnSetFrame(SurfaceFrameType type) = 0; diff --git a/chromium/components/exo/surface_tree_host.cc b/chromium/components/exo/surface_tree_host.cc index 23b8131f6fa..f796cf48285 100644 --- a/chromium/components/exo/surface_tree_host.cc +++ b/chromium/components/exo/surface_tree_host.cc @@ -152,10 +152,6 @@ void SurfaceTreeHost::GetHitTestMask(gfx::Path* mask) const { root_surface_->GetHitTestMask(mask); } -gfx::NativeCursor SurfaceTreeHost::GetCursor(const gfx::Point& point) const { - return root_surface_ ? root_surface_->GetCursor() : ui::CursorType::kNull; -} - void SurfaceTreeHost::DidReceiveCompositorFrameAck() { active_frame_callbacks_.splice(active_frame_callbacks_.end(), frame_callbacks_); @@ -217,7 +213,7 @@ bool SurfaceTreeHost::IsSurfaceSynchronized() const { return false; } -bool SurfaceTreeHost::IsTouchEnabled(Surface*) const { +bool SurfaceTreeHost::IsInputEnabled(Surface*) const { return true; } diff --git a/chromium/components/exo/surface_tree_host.h b/chromium/components/exo/surface_tree_host.h index 0cfff8f0dd5..51c0dad364c 100644 --- a/chromium/components/exo/surface_tree_host.h +++ b/chromium/components/exo/surface_tree_host.h @@ -49,10 +49,6 @@ class SurfaceTreeHost : public SurfaceDelegate, // surface tree. void GetHitTestMask(gfx::Path* mask) const; - // Returns the cursor for the given position. If no cursor provider is - // registered then CursorType::kNull is returned. - gfx::NativeCursor GetCursor(const gfx::Point& point) const; - // Call this to indicate that the previous CompositorFrame is processed and // the surface is being scheduled for a draw. void DidReceiveCompositorFrameAck(); @@ -90,7 +86,7 @@ class SurfaceTreeHost : public SurfaceDelegate, // Overridden from SurfaceDelegate: void OnSurfaceCommit() override; bool IsSurfaceSynchronized() const override; - bool IsTouchEnabled(Surface* surface) const override; + bool IsInputEnabled(Surface* surface) const override; void OnSetFrame(SurfaceFrameType type) override {} void OnSetFrameColors(SkColor active_color, SkColor inactive_color) override { } diff --git a/chromium/components/exo/wayland/server.cc b/chromium/components/exo/wayland/server.cc index c60295e8c97..d9feec46565 100644 --- a/chromium/components/exo/wayland/server.cc +++ b/chromium/components/exo/wayland/server.cc @@ -745,7 +745,7 @@ void linux_buffer_params_create(wl_client* client, for (uint32_t i = 0; i < num_planes; ++i) { auto plane_it = linux_buffer_params->planes.find(i); LinuxBufferParams::Plane& plane = plane_it->second; - planes.emplace_back(plane.stride, plane.offset, 0, 0); + planes.emplace_back(plane.stride, plane.offset, 0); fds.push_back(std::move(plane.fd)); } @@ -804,7 +804,7 @@ void linux_buffer_params_create_immed(wl_client* client, for (uint32_t i = 0; i < num_planes; ++i) { auto plane_it = linux_buffer_params->planes.find(i); LinuxBufferParams::Plane& plane = plane_it->second; - planes.emplace_back(plane.stride, plane.offset, 0, 0); + planes.emplace_back(plane.stride, plane.offset, 0); fds.push_back(std::move(plane.fd)); } diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc index d33d3f03224..1150c058052 100644 --- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc +++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc @@ -15,9 +15,9 @@ #include "components/ntp_snippets/category.h" #include "components/ntp_snippets/ntp_snippets_constants.h" #include "components/ntp_snippets/user_classifier.h" +#include "components/signin/core/browser/signin_manager_base.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_status.h" -#include "services/identity/public/cpp/identity_manager.h" #include "services/identity/public/cpp/primary_account_access_token_fetcher.h" using language::UrlLanguageHistogram; @@ -124,7 +124,8 @@ void FilterCategories(FetchedCategoriesVector* categories, } // namespace RemoteSuggestionsFetcherImpl::RemoteSuggestionsFetcherImpl( - identity::IdentityManager* identity_manager, + SigninManagerBase* signin_manager, + OAuth2TokenService* token_service, scoped_refptr<URLRequestContextGetter> url_request_context_getter, PrefService* pref_service, UrlLanguageHistogram* language_histogram, @@ -132,7 +133,8 @@ RemoteSuggestionsFetcherImpl::RemoteSuggestionsFetcherImpl( const GURL& api_endpoint, const std::string& api_key, const UserClassifier* user_classifier) - : identity_manager_(identity_manager), + : signin_manager_(signin_manager), + token_service_(token_service), url_request_context_getter_(std::move(url_request_context_getter)), language_histogram_(language_histogram), parse_json_callback_(parse_json_callback), @@ -177,7 +179,7 @@ void RemoteSuggestionsFetcherImpl::FetchSnippets( .SetUrlRequestContextGetter(url_request_context_getter_) .SetUserClassifier(*user_classifier_); - if (identity_manager_->HasPrimaryAccount()) { + if (signin_manager_->IsAuthenticated()) { // Signed-in: get OAuth token --> fetch suggestions. pending_requests_.emplace(std::move(builder), std::move(callback)); StartTokenRequest(); @@ -209,7 +211,7 @@ void RemoteSuggestionsFetcherImpl::FetchSnippetsAuthenticated( const std::string& oauth_access_token) { // TODO(jkrcal, treib): Add unit-tests for authenticated fetches. builder.SetUrl(fetch_url_) - .SetAuthentication(identity_manager_->GetPrimaryAccountInfo().account_id, + .SetAuthentication(signin_manager_->GetAuthenticatedAccountId(), base::StringPrintf(kAuthorizationRequestHeaderFormat, oauth_access_token.c_str())); StartRequest(std::move(builder), std::move(callback)); @@ -232,8 +234,8 @@ void RemoteSuggestionsFetcherImpl::StartTokenRequest() { } OAuth2TokenService::ScopeSet scopes{kContentSuggestionsApiScope}; - token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForPrimaryAccount( - "ntp_snippets", scopes, + token_fetcher_ = std::make_unique<identity::PrimaryAccountAccessTokenFetcher>( + "ntp_snippets", signin_manager_, token_service_, scopes, base::BindOnce(&RemoteSuggestionsFetcherImpl::AccessTokenFetchFinished, base::Unretained(this)), identity::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable); diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h index f5a33841bb3..0d95ca461e0 100644 --- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h +++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h @@ -20,14 +20,15 @@ #include "components/ntp_snippets/remote/request_params.h" #include "net/url_request/url_request_context_getter.h" +class OAuth2TokenService; class PrefService; +class SigninManagerBase; namespace base { class Value; } // namespace base namespace identity { -class IdentityManager; class PrimaryAccountAccessTokenFetcher; } @@ -42,7 +43,8 @@ class UserClassifier; class RemoteSuggestionsFetcherImpl : public RemoteSuggestionsFetcher { public: RemoteSuggestionsFetcherImpl( - identity::IdentityManager* identity_manager, + SigninManagerBase* signin_manager, + OAuth2TokenService* token_service, scoped_refptr<net::URLRequestContextGetter> url_request_context_getter, PrefService* pref_service, language::UrlLanguageHistogram* language_histogram, @@ -88,7 +90,8 @@ class RemoteSuggestionsFetcherImpl : public RemoteSuggestionsFetcher { const std::string& error_details); // Authentication for signed-in users. - identity::IdentityManager* identity_manager_; + SigninManagerBase* signin_manager_; + OAuth2TokenService* token_service_; std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> token_fetcher_; diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc index 3df8a732140..67d205ba0a5 100644 --- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc +++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc @@ -10,7 +10,6 @@ #include "base/containers/circular_deque.h" #include "base/json/json_reader.h" -#include "base/message_loop/message_loop.h" #include "base/optional.h" #include "base/test/histogram_tester.h" #include "base/test/test_mock_time_task_runner.h" @@ -35,7 +34,6 @@ #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/url_request_test_util.h" -#include "services/identity/public/cpp/identity_manager.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -61,7 +59,7 @@ const char kTestChromeContentSuggestionsSignedOutUrl[] = const char kTestChromeContentSuggestionsSignedInUrl[] = "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/fetch"; -const char kTestAccount[] = "foo@bar.com"; +const char kTestEmail[] = "foo@bar.com"; // Artificial time delay for JSON parsing. const int64_t kTestJsonParsingLatencyMs = 20; @@ -293,25 +291,18 @@ class RemoteSuggestionsFetcherImplTestBase scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = new net::TestURLRequestContextGetter(mock_task_runner_.get()); - if (fake_token_service_) { + if (fake_token_service_) fake_token_service_->RemoveDiagnosticsObserver(this); - identity_manager_.reset(); - } - fake_token_service_ = std::make_unique<FakeProfileOAuth2TokenService>( std::make_unique<FakeOAuth2TokenServiceDelegate>( request_context_getter.get())); fake_token_service_->AddDiagnosticsObserver(this); - // TODO(blundell): Convert this test to use IdentityTestEnvironment once - // that infrastructure lands in the codebase. - identity_manager_ = std::make_unique<identity::IdentityManager>( - utils_.fake_signin_manager(), fake_token_service_.get()); - fetcher_ = std::make_unique<RemoteSuggestionsFetcherImpl>( - identity_manager_.get(), std::move(request_context_getter), - utils_.pref_service(), nullptr, base::BindRepeating(&ParseJsonDelayed), + utils_.fake_signin_manager(), fake_token_service_.get(), + std::move(request_context_getter), utils_.pref_service(), nullptr, + base::BindRepeating(&ParseJsonDelayed), GetFetchEndpoint(version_info::Channel::STABLE), api_key, user_classifier_.get()); @@ -320,24 +311,26 @@ class RemoteSuggestionsFetcherImplTestBase } void SignIn() { - identity_manager_->SetPrimaryAccountSynchronouslyForTests(kTestAccount, - kTestAccount, ""); +#if defined(OS_CHROMEOS) + utils_.fake_signin_manager()->SignIn(kTestEmail); +#else + utils_.fake_signin_manager()->SignIn(kTestEmail, "user", "password"); +#endif } void IssueRefreshToken() { - fake_token_service_->GetDelegate()->UpdateCredentials(kTestAccount, - "token"); + fake_token_service_->GetDelegate()->UpdateCredentials(kTestEmail, "token"); } void IssueOAuth2Token() { - fake_token_service_->IssueAllTokensForAccount(kTestAccount, "access_token", + fake_token_service_->IssueAllTokensForAccount(kTestEmail, "access_token", base::Time::Max()); } void CancelOAuth2TokenRequests() { fake_token_service_->IssueErrorForAllPendingRequestsForAccount( - kTestAccount, GoogleServiceAuthError( - GoogleServiceAuthError::State::REQUEST_CANCELED)); + kTestEmail, GoogleServiceAuthError( + GoogleServiceAuthError::State::REQUEST_CANCELED)); } RemoteSuggestionsFetcher::SnippetsAvailableCallback @@ -415,7 +408,6 @@ class RemoteSuggestionsFetcherImplTestBase // Initialized lazily in SetFakeResponse(). std::unique_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_; std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_; - std::unique_ptr<identity::IdentityManager> identity_manager_; std::unique_ptr<RemoteSuggestionsFetcherImpl> fetcher_; std::unique_ptr<UserClassifier> user_classifier_; MockSnippetsAvailableCallback mock_callback_; diff --git a/chromium/components/password_manager/core/browser/password_syncable_service.cc b/chromium/components/password_manager/core/browser/password_syncable_service.cc index 4653ac0cf8b..4f959a6ba44 100644 --- a/chromium/components/password_manager/core/browser/password_syncable_service.cc +++ b/chromium/components/password_manager/core/browser/password_syncable_service.cc @@ -12,12 +12,8 @@ #include "base/auto_reset.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" -#include "base/optional.h" -#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/time/default_clock.h" #include "components/autofill/core/common/password_form.h" -#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_store_sync.h" #include "components/sync/model/sync_error_factory.h" @@ -40,12 +36,20 @@ std::string MakePasswordSyncTag(const autofill::PasswordForm& password); namespace { // Returns true iff |password_specifics| and |password_specifics| are equal -// in the fields which don't comprise the sync tag. -bool AreLocalAndSyncPasswordsNonSyncTagEqual( +// memberwise. +bool AreLocalAndSyncPasswordsEqual( const sync_pb::PasswordSpecificsData& password_specifics, const autofill::PasswordForm& password_form) { return (password_form.scheme == password_specifics.scheme() && + password_form.signon_realm == password_specifics.signon_realm() && + password_form.origin.spec() == password_specifics.origin() && password_form.action.spec() == password_specifics.action() && + base::UTF16ToUTF8(password_form.username_element) == + password_specifics.username_element() && + base::UTF16ToUTF8(password_form.password_element) == + password_specifics.password_element() && + base::UTF16ToUTF8(password_form.username_value) == + password_specifics.username_value() && base::UTF16ToUTF8(password_form.password_value) == password_specifics.password_value() && password_form.preferred == password_specifics.preferred() && @@ -62,38 +66,6 @@ bool AreLocalAndSyncPasswordsNonSyncTagEqual( .Serialize() == password_form.federation_origin.Serialize()); } -// Returns true iff |password_specifics| and |password_specifics| are equal -// memberwise. -bool AreLocalAndSyncPasswordsEqual( - const sync_pb::PasswordSpecificsData& password_specifics, - const autofill::PasswordForm& password_form) { - return (password_form.signon_realm == password_specifics.signon_realm() && - password_form.origin.spec() == password_specifics.origin() && - base::UTF16ToUTF8(password_form.username_element) == - password_specifics.username_element() && - base::UTF16ToUTF8(password_form.password_element) == - password_specifics.password_element() && - base::UTF16ToUTF8(password_form.username_value) == - password_specifics.username_value() && - AreLocalAndSyncPasswordsNonSyncTagEqual(password_specifics, - password_form)); -} - -// Compares the fields which are not part of the sync tag. -bool AreNonSyncTagFieldsEqual(const sync_pb::PasswordSpecificsData& left, - const sync_pb::PasswordSpecificsData& right) { - return (left.scheme() == right.scheme() && left.action() == right.action() && - left.password_value() == right.password_value() && - left.preferred() == right.preferred() && - left.date_created() == right.date_created() && - left.blacklisted() == right.blacklisted() && - left.type() == right.type() && - left.times_used() == right.times_used() && - left.display_name() == right.display_name() && - left.avatar_url() == right.avatar_url() && - left.federation_url() == right.federation_url()); -} - syncer::SyncChange::SyncChangeType GetSyncChangeType( PasswordStoreChange::Type type) { switch (type) { @@ -119,190 +91,6 @@ void AppendPasswordFromSpecifics( entries->back()->date_synced = sync_time; } -// Android autofill saves credential in a different format without trailing '/'. -std::string GetIncorrectAndroidSignonRealm(std::string android_autofill_realm) { - if (base::EndsWith(android_autofill_realm, "/", base::CompareCase::SENSITIVE)) - android_autofill_realm.erase(android_autofill_realm.size() - 1); - return android_autofill_realm; -} - -// The correct Android signon_realm should have a trailing '/'. -std::string GetCorrectAndroidSignonRealm(std::string android_realm) { - if (!base::EndsWith(android_realm, "/", base::CompareCase::SENSITIVE)) - android_realm += '/'; - return android_realm; -} - -// Android autofill saves credentials in a different format without trailing -// '/'. Return a sync tag for the style used by Android Autofill in GMS Core -// v12. -std::string AndroidAutofillSyncTag( - const sync_pb::PasswordSpecificsData& password) { - // realm has the same value as the origin. - std::string origin = GetIncorrectAndroidSignonRealm(password.origin()); - std::string signon_realm = - GetIncorrectAndroidSignonRealm(password.signon_realm()); - return (net::EscapePath(origin) + "|" + - net::EscapePath(password.username_element()) + "|" + - net::EscapePath(password.username_value()) + "|" + - net::EscapePath(password.password_element()) + "|" + - net::EscapePath(signon_realm)); -} - -// Return a sync tag for the correct format used by Android. -std::string AndroidCorrectSyncTag( - const sync_pb::PasswordSpecificsData& password) { - // realm has the same value as the origin. - std::string origin = GetCorrectAndroidSignonRealm(password.origin()); - std::string signon_realm = - GetCorrectAndroidSignonRealm(password.signon_realm()); - return (net::EscapePath(origin) + "|" + - net::EscapePath(password.username_element()) + "|" + - net::EscapePath(password.username_value()) + "|" + - net::EscapePath(password.password_element()) + "|" + - net::EscapePath(signon_realm)); -} - -void PasswordSpecificsFromPassword( - const autofill::PasswordForm& password_form, - sync_pb::PasswordSpecificsData* password_specifics) { -#define CopyField(field) password_specifics->set_##field(password_form.field) -#define CopyStringField(field) \ - password_specifics->set_##field(base::UTF16ToUTF8(password_form.field)) - CopyField(scheme); - CopyField(signon_realm); - password_specifics->set_origin(password_form.origin.spec()); - password_specifics->set_action(password_form.action.spec()); - CopyStringField(username_element); - CopyStringField(password_element); - CopyStringField(username_value); - CopyStringField(password_value); - CopyField(preferred); - password_specifics->set_date_created( - password_form.date_created.ToInternalValue()); - password_specifics->set_blacklisted(password_form.blacklisted_by_user); - CopyField(type); - CopyField(times_used); - CopyStringField(display_name); - password_specifics->set_avatar_url(password_form.icon_url.spec()); - password_specifics->set_federation_url( - password_form.federation_origin.unique() - ? std::string() - : password_form.federation_origin.Serialize()); -#undef CopyStringField -#undef CopyField -} - -struct AndroidMergeResult { - // New value for Android entry in the correct format. - base::Optional<syncer::SyncData> new_android_correct; - // New value for Android autofill entry. - base::Optional<syncer::SyncData> new_android_incorrect; - // New value for local entry in the correct format. - base::Optional<autofill::PasswordForm> new_local_correct; - // New value for local entry in the Android autofill format. - base::Optional<autofill::PasswordForm> new_local_incorrect; -}; - -// Perform deduplication of Android credentials saved in the wrong format. As -// the result all the four entries should be created and have the same value. -AndroidMergeResult Perform4WayMergeAndroidCredentials( - const sync_pb::PasswordSpecificsData* correct_android, - const sync_pb::PasswordSpecificsData* incorrect_android, - const autofill::PasswordForm* correct_local, - const autofill::PasswordForm* incorrect_local) { - AndroidMergeResult result; - - base::Optional<sync_pb::PasswordSpecificsData> local_correct_ps; - if (correct_local) { - local_correct_ps = sync_pb::PasswordSpecificsData(); - PasswordSpecificsFromPassword(*correct_local, &local_correct_ps.value()); - } - - base::Optional<sync_pb::PasswordSpecificsData> local_incorrect_ps; - if (incorrect_local) { - local_incorrect_ps = sync_pb::PasswordSpecificsData(); - PasswordSpecificsFromPassword(*incorrect_local, - &local_incorrect_ps.value()); - } - - const sync_pb::PasswordSpecificsData* all_data[4] = { - correct_android, incorrect_android, - local_correct_ps ? &local_correct_ps.value() : nullptr, - local_incorrect_ps ? &local_incorrect_ps.value() : nullptr}; - - // |newest_data| will point to the newest entry out of all 4. - const sync_pb::PasswordSpecificsData* newest_data = nullptr; - for (int i = 0; i < 4; ++i) { - if (newest_data && all_data[i]) { - if (all_data[i]->date_created() > newest_data->date_created()) - newest_data = all_data[i]; - } else if (all_data[i]) { - newest_data = all_data[i]; - } - } - DCHECK(newest_data); - - const std::string correct_tag = AndroidCorrectSyncTag(*newest_data); - const std::string incorrect_tag = AndroidAutofillSyncTag(*newest_data); - const std::string correct_signon_realm = - GetCorrectAndroidSignonRealm(newest_data->signon_realm()); - const std::string incorrect_signon_realm = - GetIncorrectAndroidSignonRealm(newest_data->signon_realm()); - const std::string correct_origin = - GetCorrectAndroidSignonRealm(newest_data->origin()); - const std::string incorrect_origin = - GetIncorrectAndroidSignonRealm(newest_data->origin()); - DCHECK_EQ(GURL(incorrect_origin).spec(), incorrect_origin); - - // Set the correct Sync entry if needed. - if (newest_data != correct_android && - (!correct_android || - !AreNonSyncTagFieldsEqual(*correct_android, *newest_data))) { - sync_pb::EntitySpecifics password_data; - sync_pb::PasswordSpecificsData* password_specifics = - password_data.mutable_password()->mutable_client_only_encrypted_data(); - *password_specifics = *newest_data; - password_specifics->set_origin(correct_origin); - password_specifics->set_signon_realm(correct_signon_realm); - result.new_android_correct = syncer::SyncData::CreateLocalData( - correct_tag, correct_tag, password_data); - } - - // Set the Andoroid Autofill Sync entry if needed. - if (newest_data != incorrect_android && - (!incorrect_android || - !AreNonSyncTagFieldsEqual(*incorrect_android, *newest_data))) { - sync_pb::EntitySpecifics password_data; - sync_pb::PasswordSpecificsData* password_specifics = - password_data.mutable_password()->mutable_client_only_encrypted_data(); - *password_specifics = *newest_data; - password_specifics->set_origin(incorrect_origin); - password_specifics->set_signon_realm(incorrect_signon_realm); - result.new_android_incorrect = syncer::SyncData::CreateLocalData( - incorrect_tag, incorrect_tag, password_data); - } - - // Set the correct local entry if needed. - if (!local_correct_ps || - (newest_data != &local_correct_ps.value() && - !AreNonSyncTagFieldsEqual(local_correct_ps.value(), *newest_data))) { - result.new_local_correct = PasswordFromSpecifics(*newest_data); - result.new_local_correct.value().origin = GURL(correct_origin); - result.new_local_correct.value().signon_realm = correct_signon_realm; - } - - // Set the incorrect local entry if needed. - if (!local_incorrect_ps || - (newest_data != &local_incorrect_ps.value() && - !AreNonSyncTagFieldsEqual(local_incorrect_ps.value(), *newest_data))) { - result.new_local_incorrect = PasswordFromSpecifics(*newest_data); - result.new_local_incorrect.value().origin = GURL(incorrect_origin); - result.new_local_incorrect.value().signon_realm = incorrect_signon_realm; - } - return result; -} - } // namespace struct PasswordSyncableService::SyncEntries { @@ -336,9 +124,8 @@ struct PasswordSyncableService::SyncEntries { PasswordSyncableService::PasswordSyncableService( PasswordStoreSync* password_store) - : password_store_(password_store), - clock_(new base::DefaultClock), - is_processing_sync_changes_(false) {} + : password_store_(password_store), is_processing_sync_changes_(false) { +} PasswordSyncableService::~PasswordSyncableService() = default; @@ -374,12 +161,17 @@ syncer::SyncMergeResult PasswordSyncableService::MergeDataAndStartSyncing( } merge_result.set_num_items_before_association(new_local_entries.size()); - // Changes from Sync to be applied locally. SyncEntries sync_entries; // Changes from password db that need to be propagated to sync. syncer::SyncChangeList updated_db_entries; - MergeSyncDataWithLocalData(initial_sync_data, &new_local_entries, - &sync_entries, &updated_db_entries); + for (syncer::SyncDataList::const_iterator sync_iter = + initial_sync_data.begin(); + sync_iter != initial_sync_data.end(); ++sync_iter) { + CreateOrUpdateEntry(*sync_iter, + &new_local_entries, + &sync_entries, + &updated_db_entries); + } for (PasswordEntryMap::iterator it = new_local_entries.begin(); it != new_local_entries.end(); ++it) { @@ -443,7 +235,7 @@ syncer::SyncError PasswordSyncableService::ProcessSyncChanges( DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::AutoReset<bool> processing_changes(&is_processing_sync_changes_, true); SyncEntries sync_entries; - base::Time time_now = clock_->Now(); + base::Time time_now = base::Time::Now(); for (syncer::SyncChangeList::const_iterator it = change_list.begin(); it != change_list.end(); ++it) { @@ -456,13 +248,6 @@ syncer::SyncError PasswordSyncableService::ProcessSyncChanges( } AppendPasswordFromSpecifics( specifics.password().client_only_encrypted_data(), time_now, entries); - if (IsValidAndroidFacetURI(entries->back()->signon_realm)) { - // Fix the Android Autofill credentials if needed. - entries->back()->signon_realm = - GetCorrectAndroidSignonRealm(entries->back()->signon_realm); - entries->back()->origin = - GURL(GetCorrectAndroidSignonRealm(entries->back()->origin.spec())); - } } WriteToPasswordStore(sync_entries); @@ -553,132 +338,21 @@ void PasswordSyncableService::WriteToPasswordStore(const SyncEntries& entries) { password_store_->NotifyLoginsChanged(changes); } -void PasswordSyncableService::MergeSyncDataWithLocalData( - const syncer::SyncDataList& sync_data, - PasswordEntryMap* unmatched_data_from_password_db, - SyncEntries* sync_entries, - syncer::SyncChangeList* updated_db_entries) { - std::map<std::string, const sync_pb::PasswordSpecificsData*> sync_data_map; - for (const auto& data : sync_data) { - const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); - const sync_pb::PasswordSpecificsData* password_specifics = - &specifics.password().client_only_encrypted_data(); - sync_data_map[MakePasswordSyncTag(*password_specifics)] = - password_specifics; - } - DCHECK_EQ(sync_data_map.size(), sync_data.size()); - - for (auto it = sync_data_map.begin(); it != sync_data_map.end();) { - if (IsValidAndroidFacetURI(it->second->signon_realm())) { - // Perform deduplication of Android credentials saved in the wrong format. - // For each incorrect entry, a duplicate of it is created in the correct - // format, so Chrome can make use of it. The incorrect sync entries are - // not deleted for now. - std::string incorrect_tag = AndroidAutofillSyncTag(*it->second); - std::string correct_tag = AndroidCorrectSyncTag(*it->second); - auto it_sync_incorrect = sync_data_map.find(incorrect_tag); - auto it_sync_correct = sync_data_map.find(correct_tag); - auto it_local_data_correct = - unmatched_data_from_password_db->find(correct_tag); - auto it_local_data_incorrect = - unmatched_data_from_password_db->find(incorrect_tag); - if ((it != it_sync_incorrect && it != it_sync_correct) || - (it_sync_incorrect == sync_data_map.end() && - it_local_data_incorrect == unmatched_data_from_password_db->end())) { - // The current credential is in an unexpected format or incorrect - // credential don't exist. Just do what Sync would normally do. - CreateOrUpdateEntry(*it->second, unmatched_data_from_password_db, - sync_entries, updated_db_entries); - ++it; - } else { - AndroidMergeResult result = Perform4WayMergeAndroidCredentials( - it_sync_correct == sync_data_map.end() ? nullptr - : it_sync_correct->second, - it_sync_incorrect == sync_data_map.end() - ? nullptr - : it_sync_incorrect->second, - it_local_data_correct == unmatched_data_from_password_db->end() - ? nullptr - : it_local_data_correct->second, - it_local_data_incorrect == unmatched_data_from_password_db->end() - ? nullptr - : it_local_data_incorrect->second); - // Add or update the correct local entry. - if (result.new_local_correct) { - auto* local_changes = sync_entries->EntriesForChangeType( - it_local_data_correct == unmatched_data_from_password_db->end() - ? syncer::SyncChange::ACTION_ADD - : syncer::SyncChange::ACTION_UPDATE); - local_changes->push_back(std::make_unique<autofill::PasswordForm>( - result.new_local_correct.value())); - local_changes->back()->date_synced = clock_->Now(); - } - // Add or update the incorrect local entry. - if (result.new_local_incorrect) { - auto* local_changes = sync_entries->EntriesForChangeType( - it_local_data_incorrect == unmatched_data_from_password_db->end() - ? syncer::SyncChange::ACTION_ADD - : syncer::SyncChange::ACTION_UPDATE); - local_changes->push_back(std::make_unique<autofill::PasswordForm>( - result.new_local_incorrect.value())); - local_changes->back()->date_synced = clock_->Now(); - } - if (it_local_data_correct != unmatched_data_from_password_db->end()) - unmatched_data_from_password_db->erase(it_local_data_correct); - if (it_local_data_incorrect != unmatched_data_from_password_db->end()) - unmatched_data_from_password_db->erase(it_local_data_incorrect); - // Add or update the correct sync entry. - if (result.new_android_correct) { - updated_db_entries->push_back( - syncer::SyncChange(FROM_HERE, - it_sync_correct == sync_data_map.end() - ? syncer::SyncChange::ACTION_ADD - : syncer::SyncChange::ACTION_UPDATE, - result.new_android_correct.value())); - } - // Add or update the Android Autofill sync entry. - if (result.new_android_incorrect) { - updated_db_entries->push_back( - syncer::SyncChange(FROM_HERE, - it_sync_incorrect == sync_data_map.end() - ? syncer::SyncChange::ACTION_ADD - : syncer::SyncChange::ACTION_UPDATE, - result.new_android_incorrect.value())); - } - bool increment = true; - for (auto sync_data_it : {it_sync_incorrect, it_sync_correct}) { - if (sync_data_it != sync_data_map.end()) { - if (sync_data_it == it) { - it = sync_data_map.erase(it); - increment = false; - } else { - sync_data_map.erase(sync_data_it); - } - } - } - if (increment) - ++it; - } - } else { - // Not Android. - CreateOrUpdateEntry(*it->second, unmatched_data_from_password_db, - sync_entries, updated_db_entries); - ++it; - } - } -} - +// static void PasswordSyncableService::CreateOrUpdateEntry( - const sync_pb::PasswordSpecificsData& password_specifics, + const syncer::SyncData& data, PasswordEntryMap* unmatched_data_from_password_db, SyncEntries* sync_entries, syncer::SyncChangeList* updated_db_entries) { + const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); + const sync_pb::PasswordSpecificsData& password_specifics( + specifics.password().client_only_encrypted_data()); std::string tag = MakePasswordSyncTag(password_specifics); // Check whether the data from sync is already in the password store. PasswordEntryMap::iterator existing_local_entry_iter = unmatched_data_from_password_db->find(tag); - base::Time time_now = clock_->Now(); + base::Time time_now = base::Time::Now(); if (existing_local_entry_iter == unmatched_data_from_password_db->end()) { // The sync data is not in the password store, so we need to create it in // the password store. Add the entry to the new_entries list. @@ -726,7 +400,31 @@ syncer::SyncData SyncDataFromPassword( sync_pb::EntitySpecifics password_data; sync_pb::PasswordSpecificsData* password_specifics = password_data.mutable_password()->mutable_client_only_encrypted_data(); - PasswordSpecificsFromPassword(password_form, password_specifics); +#define CopyField(field) password_specifics->set_##field(password_form.field) +#define CopyStringField(field) \ + password_specifics->set_##field(base::UTF16ToUTF8(password_form.field)) + CopyField(scheme); + CopyField(signon_realm); + password_specifics->set_origin(password_form.origin.spec()); + password_specifics->set_action(password_form.action.spec()); + CopyStringField(username_element); + CopyStringField(password_element); + CopyStringField(username_value); + CopyStringField(password_value); + CopyField(preferred); + password_specifics->set_date_created( + password_form.date_created.ToInternalValue()); + password_specifics->set_blacklisted(password_form.blacklisted_by_user); + CopyField(type); + CopyField(times_used); + CopyStringField(display_name); + password_specifics->set_avatar_url(password_form.icon_url.spec()); + password_specifics->set_federation_url( + password_form.federation_origin.unique() + ? std::string() + : password_form.federation_origin.Serialize()); +#undef CopyStringField +#undef CopyField std::string tag = MakePasswordSyncTag(*password_specifics); return syncer::SyncData::CreateLocalData(tag, tag, password_data); diff --git a/chromium/components/password_manager/core/browser/password_syncable_service.h b/chromium/components/password_manager/core/browser/password_syncable_service.h index e2fd572c4fb..d86daac1974 100644 --- a/chromium/components/password_manager/core/browser/password_syncable_service.h +++ b/chromium/components/password_manager/core/browser/password_syncable_service.h @@ -11,7 +11,6 @@ #include "base/macros.h" #include "base/sequence_checker.h" -#include "base/time/clock.h" #include "components/password_manager/core/browser/password_store_change.h" #include "components/sync/model/sync_change.h" #include "components/sync/model/sync_data.h" @@ -61,12 +60,6 @@ class PasswordSyncableService : public syncer::SyncableService { void InjectStartSyncFlare( const syncer::SyncableService::StartSyncFlare& flare); -#if defined(UNIT_TEST) - void set_clock(std::unique_ptr<base::Clock> clock) { - clock_ = std::move(clock); - } -#endif - private: // Map from password sync tag to password form. typedef std::map<std::string, autofill::PasswordForm*> PasswordEntryMap; @@ -87,23 +80,14 @@ class PasswordSyncableService : public syncer::SyncableService { // Uses the |PasswordStore| APIs to change entries. void WriteToPasswordStore(const SyncEntries& entries); - // Goes through |sync_data| and for each entry merges the data with - // |unmatched_data_from_password_db|. The result of merge is recorded in - // |sync_entries| or |updated_db_entries|. Successfully merged elements are - // removed from |unmatched_data_from_password_db|. - void MergeSyncDataWithLocalData( - const syncer::SyncDataList& sync_data, - PasswordEntryMap* unmatched_data_from_password_db, - SyncEntries* sync_entries, - syncer::SyncChangeList* updated_db_entries); - // Examines |data|, an entry in sync db, and updates |sync_entries| or // |updated_db_entries| accordingly. An element is removed from // |unmatched_data_from_password_db| if its tag is identical to |data|'s. - void CreateOrUpdateEntry(const sync_pb::PasswordSpecificsData& data, - PasswordEntryMap* unmatched_data_from_password_db, - SyncEntries* sync_entries, - syncer::SyncChangeList* updated_db_entries); + static void CreateOrUpdateEntry( + const syncer::SyncData& data, + PasswordEntryMap* unmatched_data_from_password_db, + SyncEntries* sync_entries, + syncer::SyncChangeList* updated_db_entries); // Calls |operation| for each element in |entries| and appends the changes to // |all_changes|. @@ -125,9 +109,6 @@ class PasswordSyncableService : public syncer::SyncableService { // A signal activated by this class to start sync as soon as possible. syncer::SyncableService::StartSyncFlare flare_; - // Clock for date_synced updates. - std::unique_ptr<base::Clock> clock_; - // True if processing sync changes is in progress. bool is_processing_sync_changes_; diff --git a/chromium/components/password_manager/core/browser/password_syncable_service_unittest.cc b/chromium/components/password_manager/core/browser/password_syncable_service_unittest.cc index 9f1975d0895..39c4499a730 100644 --- a/chromium/components/password_manager/core/browser/password_syncable_service_unittest.cc +++ b/chromium/components/password_manager/core/browser/password_syncable_service_unittest.cc @@ -15,9 +15,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_task_environment.h" -#include "base/test/simple_test_clock.h" #include "components/password_manager/core/browser/mock_password_store.h" -#include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/sync/model/sync_change_processor.h" #include "components/sync/model/sync_error.h" #include "components/sync/model/sync_error_factory_mock.h" @@ -54,8 +52,6 @@ namespace { // PasswordForm values for tests. constexpr autofill::PasswordForm::Type kArbitraryType = autofill::PasswordForm::TYPE_GENERATED; -constexpr char kAndroidAutofillRealm[] = "android://hash@com.magisto"; -constexpr char kAndroidCorrectRealm[] = "android://hash@com.magisto/"; constexpr char kIconUrl[] = "https://fb.com/Icon"; constexpr char kDisplayName[] = "Agent Smith"; constexpr char kFederationUrl[] = "https://fb.com/"; @@ -73,8 +69,8 @@ const sync_pb::PasswordSpecificsData& GetPasswordSpecifics( return sync_data.GetSpecifics().password().client_only_encrypted_data(); } -MATCHER_P(HasDateSynced, time, "") { - return arg.date_synced == time; +MATCHER(HasDateSynced, "") { + return !arg.date_synced.is_null() && !arg.date_synced.is_max(); } MATCHER_P(PasswordIs, form, "") { @@ -127,14 +123,6 @@ ACTION_P(AppendForm, form) { return true; } -// The argument is std::vector<autofill::PasswordForm*>*. The caller is -// responsible for the lifetime of all the password forms. -ACTION_P(AppendForms, forms) { - for (const autofill::PasswordForm& form : forms) - arg0->push_back(std::make_unique<autofill::PasswordForm>(form)); - return true; -} - // Creates a sync data consisting of password specifics. The sign on realm is // set to |signon_realm|. SyncData CreateSyncData(const std::string& signon_realm) { @@ -185,14 +173,12 @@ class PasswordSyncableServiceWrapper { password_store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr); service_.reset( new PasswordSyncableService(password_store_->GetSyncInterface())); - auto clock = std::make_unique<base::SimpleTestClock>(); - clock->SetNow(time()); - service_->set_clock(std::move(clock)); - ON_CALL(*password_store_, AddLoginImpl(HasDateSynced(time()))) + + ON_CALL(*password_store_, AddLoginImpl(HasDateSynced())) .WillByDefault(Return(PasswordStoreChangeList())); ON_CALL(*password_store_, RemoveLoginImpl(_)) .WillByDefault(Return(PasswordStoreChangeList())); - ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced(time()))) + ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced())) .WillByDefault(Return(PasswordStoreChangeList())); EXPECT_CALL(*password_store(), NotifyLoginsChanged(_)).Times(AnyNumber()); } @@ -203,8 +189,6 @@ class PasswordSyncableServiceWrapper { PasswordSyncableService* service() { return service_.get(); } - static base::Time time() { return base::Time::FromInternalValue(100000); } - // Returnes the scoped_ptr to |service_| thus NULLing out it. std::unique_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() { return std::move(service_); @@ -233,6 +217,7 @@ class PasswordSyncableServiceTest : public testing::Test { std::unique_ptr<MockSyncChangeProcessor> processor_; private: + // Used by the password store. base::test::ScopedTaskEnvironment scoped_task_environment_; PasswordSyncableServiceWrapper wrapper_; }; @@ -677,546 +662,6 @@ TEST_F(PasswordSyncableServiceTest, SerializeNonEmptyPasswordForm) { EXPECT_EQ("https://google.com", specifics.federation_url()); } -// Tests for Android Autofill credentials. Those are saved in the wrong format -// without trailing '/'. Nevertheless, password store should always contain the -// correct values. -class PasswordSyncableServiceAndroidAutofillTest : public testing::Test { - public: - PasswordSyncableServiceAndroidAutofillTest() = default; - - static PasswordFormData android_incorrect(double creation_time) { - PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML, - kAndroidAutofillRealm, - kAndroidAutofillRealm, - "", - L"", - L"", - L"", - L"username_value_1", - L"11111", - true, - creation_time}; - return data; - } - - static PasswordFormData android_correct(double creation_time) { - PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML, - kAndroidCorrectRealm, - kAndroidCorrectRealm, - "", - L"", - L"", - L"", - L"username_value_1", - L"22222", - true, - creation_time}; - return data; - } - - static PasswordFormData android_incorrect2(double creation_time) { - PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML, - kAndroidAutofillRealm, - kAndroidAutofillRealm, - "", - L"", - L"", - L"", - L"username_value_1", - L"33333", - false, - creation_time}; - return data; - } - - static PasswordFormData android_correct2(double creation_time) { - PasswordFormData data = {autofill::PasswordForm::SCHEME_HTML, - kAndroidCorrectRealm, - kAndroidCorrectRealm, - "", - L"", - L"", - L"", - L"username_value_1", - L"444444", - false, - creation_time}; - return data; - } - - static autofill::PasswordForm FormWithCorrectTag(PasswordFormData data) { - autofill::PasswordForm form = *FillPasswordFormWithData(data); - form.signon_realm = kAndroidCorrectRealm; - form.origin = GURL(kAndroidCorrectRealm); - form.date_synced = PasswordSyncableServiceWrapper::time(); - return form; - } - - static autofill::PasswordForm FormWithAndroidAutofillTag( - PasswordFormData data) { - autofill::PasswordForm form = *FillPasswordFormWithData(data); - form.signon_realm = kAndroidAutofillRealm; - form.origin = GURL(kAndroidAutofillRealm); - form.date_synced = PasswordSyncableServiceWrapper::time(); - return form; - } - - // Transforms |val| into |count| numbers from 1 to |count| inclusive. - static std::vector<unsigned> ExtractTimestamps(unsigned val, unsigned count) { - std::vector<unsigned> result; - for (unsigned i = 0; i < count; ++i) { - result.push_back(val % count + 1); - val /= count; - } - return result; - } - - static testing::Message FormDataMessage(const std::string& prefix, - const PasswordFormData* data) { - testing::Message message; - message << prefix; - if (data) - message << *FillPasswordFormWithData(*data); - else - message << "NULL"; - return message; - } - - protected: - base::test::ScopedTaskEnvironment scoped_task_environment_; -}; - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, FourWayMerge) { - for (unsigned val = 0; val < 4 * 4 * 4 * 4; ++val) { - // Generate 4 creation timestamps for all the entries. - std::vector<unsigned> dates = ExtractTimestamps(val, 4); - ASSERT_EQ(4u, dates.size()); - const unsigned latest = *std::max_element(dates.begin(), dates.end()); - // Sync correct, Sync Android autofill, local correct, local incorrect. - const PasswordFormData data[4] = { - android_correct(dates[0]), android_incorrect(dates[1]), - android_correct2(dates[2]), android_incorrect2(dates[3])}; - const PasswordFormData* latest_data = - std::find_if(data, data + 4, [latest](const PasswordFormData& data) { - return data.creation_time == latest; - }); - ASSERT_TRUE(latest_data); - std::vector<autofill::PasswordForm> expected_sync_updates; - if (latest_data != &data[0]) - expected_sync_updates.push_back(FormWithCorrectTag(*latest_data)); - if (latest_data != &data[1]) - expected_sync_updates.push_back(FormWithAndroidAutofillTag(*latest_data)); - autofill::PasswordForm local_correct = *FillPasswordFormWithData(data[2]); - autofill::PasswordForm local_incorrect = *FillPasswordFormWithData(data[3]); - syncer::SyncData sync_correct = - SyncDataFromPassword(*FillPasswordFormWithData(data[0])); - syncer::SyncData sync_incorrect = - SyncDataFromPassword(*FillPasswordFormWithData(data[1])); - - SCOPED_TRACE(*FillPasswordFormWithData(data[0])); - SCOPED_TRACE(*FillPasswordFormWithData(data[1])); - SCOPED_TRACE(*FillPasswordFormWithData(data[2])); - SCOPED_TRACE(*FillPasswordFormWithData(data[3])); - - for (bool correct_sync_first : {true, false}) { - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - std::vector<autofill::PasswordForm> stored_forms = {local_correct, - local_incorrect}; - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForms(stored_forms)); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - if (latest_data != &data[2]) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(FormWithCorrectTag(*latest_data))); - } - if (latest_data != &data[3]) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(FormWithAndroidAutofillTag(*latest_data))); - } - - if (expected_sync_updates.size() == 1) { - EXPECT_CALL(*processor, - ProcessSyncChanges(_, ElementsAre(SyncChangeIs( - SyncChange::ACTION_UPDATE, - expected_sync_updates[0])))); - } else { - EXPECT_CALL( - *processor, - ProcessSyncChanges(_, UnorderedElementsAre( - SyncChangeIs(SyncChange::ACTION_UPDATE, - expected_sync_updates[0]), - SyncChangeIs(SyncChange::ACTION_UPDATE, - expected_sync_updates[1])))); - } - - SyncDataList sync_list = {sync_correct, sync_incorrect}; - if (!correct_sync_first) - std::swap(sync_list[0], sync_list[1]); - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); - } - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, ThreeWayMerge) { - for (int j = 0; j < 4; ++j) { - // Whether the entry exists: Sync correct, Sync Android autofill, - // local correct, local incorrect. - bool entry_present[4] = {true, true, true, true}; - entry_present[j] = false; - for (unsigned val = 0; val < 3 * 3 * 3; ++val) { - // Generate 3 creation timestamps for all the entries. - std::vector<unsigned> dates = ExtractTimestamps(val, 3); - ASSERT_EQ(3u, dates.size()); - const unsigned latest = *std::max_element(dates.begin(), dates.end()); - - // Sync correct, Sync Android autofill, local correct, local incorrect. - std::vector<std::unique_ptr<PasswordFormData>> data; - int date_index = 0; - data.push_back(entry_present[0] - ? std::make_unique<PasswordFormData>( - android_correct(dates[date_index++])) - : nullptr); - data.push_back(entry_present[1] - ? std::make_unique<PasswordFormData>( - android_incorrect(dates[date_index++])) - : nullptr); - data.push_back(entry_present[2] - ? std::make_unique<PasswordFormData>( - android_correct2(dates[date_index++])) - : nullptr); - data.push_back(entry_present[3] - ? std::make_unique<PasswordFormData>( - android_incorrect2(dates[date_index++])) - : nullptr); - - SCOPED_TRACE(val); - SCOPED_TRACE(j); - SCOPED_TRACE(FormDataMessage("data[0]=", data[0].get())); - SCOPED_TRACE(FormDataMessage("data[1]=", data[1].get())); - SCOPED_TRACE(FormDataMessage("data[2]=", data[2].get())); - SCOPED_TRACE(FormDataMessage("data[3]=", data[3].get())); - - const PasswordFormData* latest_data = - std::find_if(data.begin(), data.end(), - [latest](const std::unique_ptr<PasswordFormData>& data) { - return data && data->creation_time == latest; - }) - ->get(); - ASSERT_TRUE(latest_data); - std::vector<std::pair<SyncChange::SyncChangeType, autofill::PasswordForm>> - expected_sync_updates; - for (int i = 0; i < 2; ++i) { - if (latest_data != data[i].get()) { - expected_sync_updates.push_back(std::make_pair( - data[i] ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD, - i == 0 ? FormWithCorrectTag(*latest_data) - : FormWithAndroidAutofillTag(*latest_data))); - } - } - - std::vector<autofill::PasswordForm> stored_forms; - for (int i = 2; i < 4; ++i) { - if (data[i]) - stored_forms.push_back(*FillPasswordFormWithData(*data[i])); - } - - SyncDataList sync_list; - for (int i = 0; i < 2; ++i) { - if (data[i]) { - sync_list.push_back( - SyncDataFromPassword(*FillPasswordFormWithData(*data[i]))); - } - } - - for (bool swap_sync_list : {false, true}) { - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForms(stored_forms)); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - for (int i = 2; i < 4; ++i) { - if (latest_data != data[i].get()) { - autofill::PasswordForm latest_form = - i == 2 ? FormWithCorrectTag(*latest_data) - : FormWithAndroidAutofillTag(*latest_data); - if (data[i]) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(latest_form)); - } else { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(latest_form)); - } - } - } - - if (expected_sync_updates.size() == 0) { - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - } else if (expected_sync_updates.size() == 1) { - EXPECT_CALL( - *processor, - ProcessSyncChanges(_, ElementsAre(SyncChangeIs( - expected_sync_updates[0].first, - expected_sync_updates[0].second)))); - } else if (expected_sync_updates.size() == 2) { - EXPECT_CALL( - *processor, - ProcessSyncChanges( - _, UnorderedElementsAre( - SyncChangeIs(expected_sync_updates[0].first, - expected_sync_updates[0].second), - SyncChangeIs(expected_sync_updates[1].first, - expected_sync_updates[1].second)))); - } - - if (swap_sync_list && sync_list.size() == 2) - std::swap(sync_list[0], sync_list[1]); - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations - // on it are checked. - scoped_task_environment_.RunUntilIdle(); - } - } - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, TwoWayServerAndLocalMerge) { - for (unsigned i = 0; i < 2 * 2; ++i) { - // Generate 4 different combinations for local/server entries. - std::vector<unsigned> combination = ExtractTimestamps(i, 2); - ASSERT_EQ(2u, combination.size()); - const bool sync_data_correct = !!combination[0]; - const bool local_data_correct = !!combination[1]; - - for (unsigned val = 0; val < 2 * 2; ++val) { - std::vector<unsigned> dates = ExtractTimestamps(val, 2); - ASSERT_EQ(2u, dates.size()); - - const PasswordFormData sync_data = sync_data_correct - ? android_correct(dates[0]) - : android_incorrect(dates[0]); - const PasswordFormData local_data = local_data_correct - ? android_correct2(dates[1]) - : android_incorrect2(dates[1]); - - const PasswordFormData* latest_data = - dates[1] > dates[0] ? &local_data : &sync_data; - - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForm(*FillPasswordFormWithData(local_data))); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - if (!local_data_correct || latest_data == &sync_data) { - if (local_data_correct) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(FormWithCorrectTag(*latest_data))); - } else { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(FormWithCorrectTag(*latest_data))); - } - } - if (!local_data_correct && latest_data == &sync_data) { - EXPECT_CALL(*wrapper->password_store(), - UpdateLoginImpl(FormWithAndroidAutofillTag(*latest_data))); - } else if (local_data_correct && !sync_data_correct) { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(FormWithAndroidAutofillTag(*latest_data))); - } - - std::vector<std::pair<SyncChange::SyncChangeType, autofill::PasswordForm>> - expected_sync_updates; - // Deal with the correct sync entry and incorrect one. - if (sync_data_correct) { - if (latest_data != &sync_data) { - expected_sync_updates.push_back(std::make_pair( - SyncChange::ACTION_UPDATE, FormWithCorrectTag(*latest_data))); - } - if (!local_data_correct) { - expected_sync_updates.push_back( - std::make_pair(SyncChange::ACTION_ADD, - FormWithAndroidAutofillTag(*latest_data))); - } - } else { - expected_sync_updates.push_back(std::make_pair( - SyncChange::ACTION_ADD, FormWithCorrectTag(*latest_data))); - if (latest_data != &sync_data) { - expected_sync_updates.push_back( - std::make_pair(SyncChange::ACTION_UPDATE, - FormWithAndroidAutofillTag(*latest_data))); - } - } - - // Set expectation on |processor|. - if (expected_sync_updates.size() == 0) { - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - } else if (expected_sync_updates.size() == 1) { - EXPECT_CALL( - *processor, - ProcessSyncChanges( - _, ElementsAre(SyncChangeIs(expected_sync_updates[0].first, - expected_sync_updates[0].second)))); - } else if (expected_sync_updates.size() == 2) { - EXPECT_CALL(*processor, - ProcessSyncChanges( - _, UnorderedElementsAre( - SyncChangeIs(expected_sync_updates[0].first, - expected_sync_updates[0].second), - SyncChangeIs(expected_sync_updates[1].first, - expected_sync_updates[1].second)))); - } - - SyncDataList sync_list = { - SyncDataFromPassword(*FillPasswordFormWithData(sync_data))}; - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); - } - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, OneEntryOnly) { - for (int i = 0; i < 3; ++i) { - // The case when only local incorrect entry exists is excluded. It's very - // exotic because a local incorrect entry can come only from the server. - // In such a case a copy will be uploaded to the server and next - // MergeDataAndStartSyncing will do a proper migration. - SCOPED_TRACE(i); - // Whether the entry exists: Sync correct, Sync Android autofill, - // local correct, local incorrect. - const bool entry_is_correct = i == 0 || i == 2; - const bool entry_is_local = i >= 2; - PasswordFormData data = - entry_is_correct ? android_correct(100) : android_incorrect(100); - - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - if (entry_is_local) { - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForm(*FillPasswordFormWithData(data))); - } else { - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(Return(true)); - } - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - if (!entry_is_local && !entry_is_correct) { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(FormWithAndroidAutofillTag(data))); - } - if (!entry_is_local) { - EXPECT_CALL(*wrapper->password_store(), - AddLoginImpl(FormWithCorrectTag(data))); - } - - if (entry_is_correct && !entry_is_local) { - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - } else { - EXPECT_CALL(*processor, - ProcessSyncChanges( - _, ElementsAre(SyncChangeIs(SyncChange::ACTION_ADD, - FormWithCorrectTag(data))))); - } - - SyncDataList sync_list; - if (!entry_is_local) { - sync_list.push_back( - SyncDataFromPassword(*FillPasswordFormWithData(data))); - } - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, FourEqualEntries) { - // Sync correct, Sync Android autofill, local correct, local incorrect with - // the same content. Nothing should happen. - const PasswordFormData data = android_correct(100); - autofill::PasswordForm local_correct = FormWithCorrectTag(data); - autofill::PasswordForm local_incorrect = FormWithAndroidAutofillTag(data); - syncer::SyncData sync_correct = SyncDataFromPassword(local_correct); - syncer::SyncData sync_incorrect = SyncDataFromPassword(local_incorrect); - - for (bool correct_sync_first : {true, false}) { - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - std::vector<autofill::PasswordForm> stored_forms = {local_correct, - local_incorrect}; - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForms(stored_forms)); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - - SyncDataList sync_list = {sync_correct, sync_incorrect}; - if (!correct_sync_first) - std::swap(sync_list[0], sync_list[1]); - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, sync_list, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); - } -} - -TEST_F(PasswordSyncableServiceAndroidAutofillTest, AndroidCorrectEqualEntries) { - // Sync correct, local correct with the same content. Nothing should happen. - const PasswordFormData data = android_correct(100); - autofill::PasswordForm local_correct = FormWithCorrectTag(data); - syncer::SyncData sync_correct = SyncDataFromPassword(local_correct); - - auto wrapper = std::make_unique<PasswordSyncableServiceWrapper>(); - auto processor = - std::make_unique<testing::StrictMock<MockSyncChangeProcessor>>(); - - EXPECT_CALL(*wrapper->password_store(), FillAutofillableLogins(_)) - .WillOnce(AppendForm(local_correct)); - EXPECT_CALL(*wrapper->password_store(), FillBlacklistLogins(_)) - .WillOnce(Return(true)); - EXPECT_CALL(*processor, ProcessSyncChanges(_, IsEmpty())); - - wrapper->service()->MergeDataAndStartSyncing( - syncer::PASSWORDS, {sync_correct}, std::move(processor), - std::unique_ptr<syncer::SyncErrorFactory>()); - wrapper.reset(); - // Wait til PasswordStore is destroy end therefore all the expectations on - // it are checked. - scoped_task_environment_.RunUntilIdle(); -} - } // namespace } // namespace password_manager diff --git a/chromium/components/safe_browsing/proto/csd.proto b/chromium/components/safe_browsing/proto/csd.proto index 842637175ae..f84453864fa 100644 --- a/chromium/components/safe_browsing/proto/csd.proto +++ b/chromium/components/safe_browsing/proto/csd.proto @@ -1146,3 +1146,18 @@ message NotificationImageReportRequest { // (even if the image URL is cross-origin). Otherwise a website could mislead // Safe Browsing into associating phishing image bitmaps with safe image URLs. } + +// Protobuf for Chrome extension webstore install request. +message ExtensionWebStoreInstallRequest { + // If we can find the complete referrer chain, this field will contain URL + // transitions from landing referrer to event in reverse chronological + // order, i.e. event url comes first in this list, and landing referrer + // comes last. + // For Safe Browsing Extended Reporting or Scout users, if the referrer + // chain is empty or partially missing, we will add/append recent navigation + // events to this list. The type of these entries will be RECENT_NAVIGATION. + repeated ReferrerChainEntry referrer_chain = 1; + + // Options and metadata about the above referrer chain. + optional ReferrerChainOptions referrer_chain_options = 2; +} diff --git a/chromium/components/strings/components_strings_mr.xtb b/chromium/components/strings/components_strings_mr.xtb index 7d8cef25840..67145b8dfcd 100644 --- a/chromium/components/strings/components_strings_mr.xtb +++ b/chromium/components/strings/components_strings_mr.xtb @@ -647,7 +647,7 @@ <translation id="5719499550583120431">प्रीपेड कार्डे स्वीकारली जातात.</translation> <translation id="5720705177508910913">वर्तमान वापरकर्ता</translation> <translation id="5732392974455271431">आपले पालक तुमच्यासाठी ती अनावरोधित करू शकतात</translation> -<translation id="5763042198335101085">वैध ईमेल पत्ता एंटर करा</translation> +<translation id="5763042198335101085">वैध ईमेल अॅड्रेस एंटर करा</translation> <translation id="5765072501007116331">वितरण पद्धती आणि आवश्यकता पाहण्यासाठी, एक पत्ता निवडा</translation> <translation id="5770114862687765385">फाइल करप्ट आहे असे दिसते. सेशन रीसेट करण्यासाठी 'रीसेट करा' बटणावर क्लिक करा.</translation> <translation id="5778550464785688721">MIDI डिव्हाइसेस पूर्ण नियंत्रण</translation> diff --git a/chromium/components/strings/components_strings_no.xtb b/chromium/components/strings/components_strings_no.xtb index 3e8755086b2..df9d93ba04b 100644 --- a/chromium/components/strings/components_strings_no.xtb +++ b/chromium/components/strings/components_strings_no.xtb @@ -259,6 +259,7 @@ <translation id="2835170189407361413">Slett skjemaet</translation> <translation id="2851634818064021665">Du trenger tillatelse for å besøke dette nettstedet</translation> <translation id="2856444702002559011">Det kan hende at angripere prøver å stjele informasjonen din fra <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (for eksempel passord, meldinger og kredittkortinformasjon). <ph name="BEGIN_LEARN_MORE_LINK" />Finn ut mer<ph name="END_LEARN_MORE_LINK" /></translation> +<translation id="2881276955470682203">Vil du lagre kortet?</translation> <translation id="2909946352844186028">En nettverksendring ble oppdaget.</translation> <translation id="2916038427272391327">Lukk andre programmer</translation> <translation id="2922350208395188000">Tjenerens sertifikat kan ikke kontrolleres.</translation> @@ -1073,4 +1074,5 @@ <li>Prøv å avinstallere eller slå av «<ph name="SOFTWARE_NAME" />»</li> <li>Prøv å koble til et annet nettverk</li> </ul></translation> +<translation id="997986563973421916">Fra Google Pay</translation> </translationbundle>
\ No newline at end of file diff --git a/chromium/components/viz/service/display/gl_renderer.cc b/chromium/components/viz/service/display/gl_renderer.cc index 66a93a56b75..345f72d6684 100644 --- a/chromium/components/viz/service/display/gl_renderer.cc +++ b/chromium/components/viz/service/display/gl_renderer.cc @@ -2128,7 +2128,7 @@ void GLRenderer::DrawContentQuadNoAA(const ContentDrawQuadBase* quad, // clamping to tex_coord_rect in all cases would cause these border // texels to not be sampled. Therefore, only clamp texture coordinates // for external edge bottom/right tiles that don't have content all - // the way to the edge. + // the way to the edge and are using bilinear filtering. gfx::Size texture_size = quad->texture_size; bool fills_right_edge = quad->shared_quad_state->quad_layer_rect.right() != quad->rect.right() || @@ -2137,7 +2137,7 @@ void GLRenderer::DrawContentQuadNoAA(const ContentDrawQuadBase* quad, quad->rect.bottom() || texture_size.height() == tex_coord_rect.bottom(); bool has_tex_clamp_rect = - (!fills_right_edge || !fills_bottom_edge) && !quad->nearest_neighbor; + filter == GL_LINEAR && (!fills_right_edge || !fills_bottom_edge); gfx::SizeF tex_clamp_size(texture_size); // Clamp from the original tex coord rect, instead of the one that has // been adjusted by the visible rect. |