summaryrefslogtreecommitdiff
path: root/chromium/components
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components')
-rw-r--r--chromium/components/arc/common/notifications.mojom12
-rw-r--r--chromium/components/autofill/content/browser/BUILD.gn3
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.cc27
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.h17
-rw-r--r--chromium/components/autofill/content/browser/key_press_handler_manager.cc37
-rw-r--r--chromium/components/autofill/content/browser/key_press_handler_manager.h47
-rw-r--r--chromium/components/autofill/content/browser/key_press_handler_manager_unittest.cc113
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.h1
-rw-r--r--chromium/components/autofill/core/browser/autofill_popup_delegate.h5
-rw-r--r--chromium/components/display_compositor/buffer_queue.cc21
-rw-r--r--chromium/components/display_compositor/buffer_queue.h5
-rw-r--r--chromium/components/exo/pointer.cc6
-rw-r--r--chromium/components/exo/shell_surface.cc83
-rw-r--r--chromium/components/exo/shell_surface.h14
-rw-r--r--chromium/components/exo/shell_surface_unittest.cc50
-rw-r--r--chromium/components/exo/touch.cc9
-rw-r--r--chromium/components/exo/touch_unittest.cc9
-rw-r--r--chromium/components/exo/wayland/server.cc20
-rw-r--r--chromium/components/offline_pages/core/downloads/download_notifying_observer.cc5
-rw-r--r--chromium/components/password_manager/content/browser/content_password_manager_driver.cc5
-rw-r--r--chromium/components/password_manager/content/browser/content_password_manager_driver.h1
-rw-r--r--chromium/components/password_manager/core/browser/password_autofill_manager.cc9
-rw-r--r--chromium/components/password_manager/core/browser/password_autofill_manager.h1
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_driver.h4
-rw-r--r--chromium/components/password_manager/core/browser/stub_password_manager_driver.cc4
-rw-r--r--chromium/components/password_manager/core/browser/stub_password_manager_driver.h1
-rw-r--r--chromium/components/ssl_errors/error_classification.cc57
-rw-r--r--chromium/components/ssl_errors/error_classification.h38
-rw-r--r--chromium/components/ssl_errors/error_classification_unittest.cc140
-rw-r--r--chromium/components/ssl_errors/error_info.cc34
-rw-r--r--chromium/components/strings/components_strings_es.xtb8
-rw-r--r--chromium/components/url_formatter/url_formatter.cc79
-rw-r--r--chromium/components/url_formatter/url_formatter_unittest.cc30
-rw-r--r--chromium/components/user_manager/user_manager_base.cc17
-rw-r--r--chromium/components/user_manager/user_manager_base.h7
36 files changed, 716 insertions, 207 deletions
diff --git a/chromium/components/arc/common/notifications.mojom b/chromium/components/arc/common/notifications.mojom
index 563ee775d83..50621f101b0 100644
--- a/chromium/components/arc/common/notifications.mojom
+++ b/chromium/components/arc/common/notifications.mojom
@@ -45,6 +45,15 @@ enum ArcNotificationExpandState {
EXPANDED = 2,
};
+// These values represent what shows in an ARC custom notification.
+[Extensible, MinVersion=11]
+enum ArcNotificationShownContents {
+ // The normal notification contents are shown.
+ CONTENTS_SHOWN = 0,
+ // The notification settings view is shown.
+ SETTINGS_SHOWN = 1,
+};
+
struct ArcNotificationData {
// Identifier of notification
string key;
@@ -98,6 +107,9 @@ struct ArcNotificationData {
// Flag if the notification is expandable
[MinVersion=10]
ArcNotificationExpandState expand_state;
+ // Flag for what shows in a notification.
+ [MinVersion=11]
+ ArcNotificationShownContents shown_contents;
};
[MinVersion=2]
diff --git a/chromium/components/autofill/content/browser/BUILD.gn b/chromium/components/autofill/content/browser/BUILD.gn
index 88576886284..5fa6ea67efd 100644
--- a/chromium/components/autofill/content/browser/BUILD.gn
+++ b/chromium/components/autofill/content/browser/BUILD.gn
@@ -10,6 +10,8 @@ static_library("browser") {
"content_autofill_driver.h",
"content_autofill_driver_factory.cc",
"content_autofill_driver_factory.h",
+ "key_press_handler_manager.cc",
+ "key_press_handler_manager.h",
"risk/fingerprint.cc",
"risk/fingerprint.h",
]
@@ -61,6 +63,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"content_autofill_driver_unittest.cc",
+ "key_press_handler_manager_unittest.cc",
"payments/payments_client_unittest.cc",
]
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.cc b/chromium/components/autofill/content/browser/content_autofill_driver.cc
index 710a1e74c9a..38bf3070fd2 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.cc
@@ -20,6 +20,7 @@
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
@@ -41,6 +42,7 @@ ContentAutofillDriver::ContentAutofillDriver(
app_locale,
enable_download_manager)),
autofill_external_delegate_(autofill_manager_.get(), this),
+ key_press_handler_manager_(this),
binding_(this) {
autofill_manager_->SetExternalDelegate(&autofill_external_delegate_);
}
@@ -265,4 +267,29 @@ const mojom::AutofillAgentPtr& ContentAutofillDriver::GetAutofillAgent() {
return autofill_agent_;
}
+void ContentAutofillDriver::RegisterKeyPressHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler) {
+ key_press_handler_manager_.RegisterKeyPressHandler(handler);
+}
+
+void ContentAutofillDriver::RemoveKeyPressHandler() {
+ key_press_handler_manager_.RemoveKeyPressHandler();
+}
+
+void ContentAutofillDriver::AddHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler) {
+ content::RenderWidgetHostView* view = render_frame_host_->GetView();
+ if (!view)
+ return;
+ view->GetRenderWidgetHost()->AddKeyPressEventCallback(handler);
+}
+
+void ContentAutofillDriver::RemoveHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler) {
+ content::RenderWidgetHostView* view = render_frame_host_->GetView();
+ if (!view)
+ return;
+ view->GetRenderWidgetHost()->RemoveKeyPressEventCallback(handler);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.h b/chromium/components/autofill/content/browser/content_autofill_driver.h
index 0f6fb084027..f038f76f89c 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/supports_user_data.h"
+#include "components/autofill/content/browser/key_press_handler_manager.h"
#include "components/autofill/content/common/autofill_agent.mojom.h"
#include "components/autofill/content/common/autofill_driver.mojom.h"
#include "components/autofill/core/browser/autofill_driver.h"
@@ -29,7 +30,8 @@ class AutofillClient;
// communication from the renderer and from the external world. There is one
// instance per RenderFrameHost.
class ContentAutofillDriver : public AutofillDriver,
- public mojom::AutofillDriver {
+ public mojom::AutofillDriver,
+ public KeyPressHandlerManager::Delegate {
public:
ContentAutofillDriver(
content::RenderFrameHost* render_frame_host,
@@ -103,12 +105,23 @@ class ContentAutofillDriver : public AutofillDriver,
const mojom::AutofillAgentPtr& GetAutofillAgent();
+ // Methods forwarded to key_press_handler_manager_.
+ void RegisterKeyPressHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler);
+ void RemoveKeyPressHandler();
+
protected:
// Sets the manager to |manager| and sets |manager|'s external delegate
// to |autofill_external_delegate_|. Takes ownership of |manager|.
void SetAutofillManager(std::unique_ptr<AutofillManager> manager);
private:
+ // KeyPressHandlerManager::Delegate:
+ void AddHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler) override;
+ void RemoveHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler) override;
+
// Weak ref to the RenderFrameHost the driver is associated with. Should
// always be non-NULL and valid for lifetime of |this|.
content::RenderFrameHost* const render_frame_host_;
@@ -124,6 +137,8 @@ class ContentAutofillDriver : public AutofillDriver,
// case where the Autofill native UI is enabled.
AutofillExternalDelegate autofill_external_delegate_;
+ KeyPressHandlerManager key_press_handler_manager_;
+
mojo::Binding<mojom::AutofillDriver> binding_;
mojom::AutofillAgentPtr autofill_agent_;
diff --git a/chromium/components/autofill/content/browser/key_press_handler_manager.cc b/chromium/components/autofill/content/browser/key_press_handler_manager.cc
new file mode 100644
index 00000000000..96b463bc5d4
--- /dev/null
+++ b/chromium/components/autofill/content/browser/key_press_handler_manager.cc
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/content/browser/key_press_handler_manager.h"
+
+namespace autofill {
+
+KeyPressHandlerManager::KeyPressHandlerManager(Delegate* delegate)
+ : delegate_(delegate) {}
+
+KeyPressHandlerManager::~KeyPressHandlerManager() = default;
+
+void KeyPressHandlerManager::RegisterKeyPressHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler) {
+ // It would have been nice to be able to tell if two callbacks are just the
+ // same function with the same bound arguments. That's not what Equals() does
+ // (they have to have the same BindState), but it's the closest approximation
+ // available.
+ if (handler.is_null() || handler.Equals(handler_))
+ return;
+
+ if (!handler_.is_null())
+ delegate_->RemoveHandler(handler_);
+ handler_ = handler;
+ delegate_->AddHandler(handler_);
+}
+
+void KeyPressHandlerManager::RemoveKeyPressHandler() {
+ if (handler_.is_null())
+ return;
+
+ delegate_->RemoveHandler(handler_);
+ handler_.Reset();
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/content/browser/key_press_handler_manager.h b/chromium/components/autofill/content/browser/key_press_handler_manager.h
new file mode 100644
index 00000000000..916ca9df3bb
--- /dev/null
+++ b/chromium/components/autofill/content/browser/key_press_handler_manager.h
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CONTENT_BROWSER_KEY_PRESS_HANDLER_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CONTENT_BROWSER_KEY_PRESS_HANDLER_MANAGER_H_
+
+#include "base/macros.h"
+#include "content/public/browser/render_widget_host.h"
+
+namespace autofill {
+
+// KeyPressHandlerManager allows registering a key press handler and ensuring
+// its unregistering in case of destruction of the manager or request for
+// registration of another handler. It still needs a Delegate implementation to
+// use the low-level handler registration API.
+
+class KeyPressHandlerManager {
+ public:
+ class Delegate {
+ public:
+ virtual void AddHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler) = 0;
+ virtual void RemoveHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler) = 0;
+ };
+
+ explicit KeyPressHandlerManager(Delegate* delegate);
+
+ virtual ~KeyPressHandlerManager();
+
+ void RegisterKeyPressHandler(
+ const content::RenderWidgetHost::KeyPressEventCallback& handler);
+
+ void RemoveKeyPressHandler(); // Unregisters previous handler.
+
+ private:
+ Delegate* const delegate_;
+
+ content::RenderWidgetHost::KeyPressEventCallback handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyPressHandlerManager);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CONTENT_BROWSER_KEY_PRESS_HANDLER_MANAGER_H_
diff --git a/chromium/components/autofill/content/browser/key_press_handler_manager_unittest.cc b/chromium/components/autofill/content/browser/key_press_handler_manager_unittest.cc
new file mode 100644
index 00000000000..e839b3d2b2e
--- /dev/null
+++ b/chromium/components/autofill/content/browser/key_press_handler_manager_unittest.cc
@@ -0,0 +1,113 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/content/browser/key_press_handler_manager.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "content/public/browser/native_web_keyboard_event.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+namespace {
+
+const content::NativeWebKeyboardEvent
+ kDummyEvent(blink::WebInputEvent::Undefined, 0, 0);
+
+// Dummy keyboard event handler: ignores the event, but appends the given |name|
+// to a logging |target|.
+bool DummyHandler(const char* name,
+ std::string* target,
+ const content::NativeWebKeyboardEvent& /*event*/) {
+ target->append(name);
+ return false;
+}
+
+// A delegate which logs the handlers instead of adding and removing them.
+class LoggingDelegate : public KeyPressHandlerManager::Delegate {
+ public:
+ explicit LoggingDelegate(std::string* target) : target_(target) {}
+
+ // KeyPressHandlerManager::Delegate:
+ void AddHandler(const content::RenderWidgetHost::KeyPressEventCallback&
+ handler) override {
+ target_->append("A");
+ handler.Run(kDummyEvent);
+ }
+ void RemoveHandler(const content::RenderWidgetHost::KeyPressEventCallback&
+ handler) override {
+ target_->append("R");
+ handler.Run(kDummyEvent);
+ }
+
+ private:
+ std::string* const target_;
+};
+
+} // namespace
+
+class KeyPressHandlerManagerTest : public testing::Test {
+ public:
+ KeyPressHandlerManagerTest() : delegate_(&callback_trace_) {}
+
+ protected:
+ content::RenderWidgetHost::KeyPressEventCallback CallbackForName(
+ const char* name) {
+ return base::Bind(DummyHandler, name, &callback_trace_);
+ }
+
+ // String encoding the events related to adding and removing callbacks. For
+ // example, "A1R1A2R2" means that callback "1" was added, then removed, and
+ // then callback "2" was added and removed.
+ std::string callback_trace_;
+
+ LoggingDelegate delegate_;
+};
+
+// Removing should remove the previously added callback.
+TEST_F(KeyPressHandlerManagerTest, AddRemove) {
+ KeyPressHandlerManager manager(&delegate_);
+ manager.RegisterKeyPressHandler(CallbackForName("1"));
+ manager.RemoveKeyPressHandler();
+ EXPECT_EQ("A1R1", callback_trace_);
+}
+
+// Registering a new callback should remove the old one.
+TEST_F(KeyPressHandlerManagerTest, AddReplace) {
+ KeyPressHandlerManager manager(&delegate_);
+ manager.RegisterKeyPressHandler(CallbackForName("1"));
+ manager.RegisterKeyPressHandler(CallbackForName("2"));
+ manager.RemoveKeyPressHandler();
+ EXPECT_EQ("A1R1A2R2", callback_trace_);
+}
+
+// Without registering a callback first, none should be removed.
+TEST_F(KeyPressHandlerManagerTest, NoRemove) {
+ KeyPressHandlerManager manager(&delegate_);
+ manager.RemoveKeyPressHandler();
+ EXPECT_EQ(std::string(), callback_trace_);
+}
+
+// Adding one callback twice should be a no-op.
+TEST_F(KeyPressHandlerManagerTest, AddTwice) {
+ KeyPressHandlerManager manager(&delegate_);
+ auto callback = CallbackForName("1");
+ manager.RegisterKeyPressHandler(callback);
+ manager.RegisterKeyPressHandler(callback);
+ manager.RemoveKeyPressHandler();
+ EXPECT_EQ("A1R1", callback_trace_);
+}
+
+// Removing one callback twice should be a no-op.
+TEST_F(KeyPressHandlerManagerTest, RemoveTwice) {
+ KeyPressHandlerManager manager(&delegate_);
+ manager.RegisterKeyPressHandler(CallbackForName("1"));
+ manager.RemoveKeyPressHandler();
+ manager.RemoveKeyPressHandler();
+ EXPECT_EQ("A1R1", callback_trace_);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index 5853a8de1d7..3db7f0fd00b 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -285,6 +285,10 @@ bool AutofillExternalDelegate::IsCreditCardPopup() {
return is_credit_card_popup_;
}
+AutofillDriver* AutofillExternalDelegate::GetAutofillDriver() {
+ return driver_;
+}
+
void AutofillExternalDelegate::Reset() {
manager_->client()->HideAutofillPopup();
}
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.h b/chromium/components/autofill/core/browser/autofill_external_delegate.h
index 6a9807a0505..a5984209fa9 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.h
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.h
@@ -54,6 +54,7 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// Returns false for all popups prior to |onQuery|, true for credit card
// popups after call to |onQuery|.
bool IsCreditCardPopup() override;
+ AutofillDriver* GetAutofillDriver() override;
// Records and associates a query_id with web form data. Called
// when the renderer posts an Autofill query to the browser. |bounds|
diff --git a/chromium/components/autofill/core/browser/autofill_popup_delegate.h b/chromium/components/autofill/core/browser/autofill_popup_delegate.h
index 5a864242755..6febbf91cfc 100644
--- a/chromium/components/autofill/core/browser/autofill_popup_delegate.h
+++ b/chromium/components/autofill/core/browser/autofill_popup_delegate.h
@@ -9,6 +9,8 @@
namespace autofill {
+class AutofillDriver;
+
// An interface for interaction with AutofillPopupController. Will be notified
// of events by the controller.
class AutofillPopupDelegate {
@@ -46,6 +48,9 @@ class AutofillPopupDelegate {
// Returns true if popup is for credit card.
virtual bool IsCreditCardPopup() = 0;
+
+ // Returns the associated AutofillDriver.
+ virtual AutofillDriver* GetAutofillDriver() = 0;
};
} // namespace autofill
diff --git a/chromium/components/display_compositor/buffer_queue.cc b/chromium/components/display_compositor/buffer_queue.cc
index afb40e1a491..60b50d7a8bb 100644
--- a/chromium/components/display_compositor/buffer_queue.cc
+++ b/chromium/components/display_compositor/buffer_queue.cc
@@ -183,13 +183,32 @@ std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
}
void BufferQueue::PageFlipComplete() {
- DCHECK(!in_flight_surfaces_.empty());
+ // Early out when no surface is in-flight. This can happen when using
+ // overlays and page flipping without changing the primary plane.
+ if (in_flight_surfaces_.empty())
+ return;
if (displayed_surface_)
available_surfaces_.push_back(std::move(displayed_surface_));
displayed_surface_ = std::move(in_flight_surfaces_.front());
in_flight_surfaces_.pop_front();
}
+uint32_t BufferQueue::GetCurrentTextureId() const {
+ // Return current surface texture if bound.
+ if (current_surface_)
+ return current_surface_->texture;
+
+ // Return in-flight or displayed surface texture if no surface is
+ // currently bound. This can happen when using overlays and surface
+ // damage is empty.
+ if (!in_flight_surfaces_.empty())
+ return in_flight_surfaces_.back()->texture;
+ if (displayed_surface_)
+ return displayed_surface_->texture;
+
+ return 0;
+}
+
void BufferQueue::FreeAllSurfaces() {
displayed_surface_.reset();
current_surface_.reset();
diff --git a/chromium/components/display_compositor/buffer_queue.h b/chromium/components/display_compositor/buffer_queue.h
index 7ac212e1be7..c6bedbb1757 100644
--- a/chromium/components/display_compositor/buffer_queue.h
+++ b/chromium/components/display_compositor/buffer_queue.h
@@ -60,12 +60,9 @@ class DISPLAY_COMPOSITOR_EXPORT BufferQueue {
float scale_factor,
const gfx::ColorSpace& color_space,
bool use_stencil);
-
void RecreateBuffers();
+ uint32_t GetCurrentTextureId() const;
- uint32_t current_texture_id() const {
- return current_surface_ ? current_surface_->texture : 0;
- }
uint32_t fbo() const { return fbo_; }
uint32_t internal_format() const { return internal_format_; }
diff --git a/chromium/components/exo/pointer.cc b/chromium/components/exo/pointer.cc
index 61442ed0608..1697f5c34dc 100644
--- a/chromium/components/exo/pointer.cc
+++ b/chromium/components/exo/pointer.cc
@@ -380,8 +380,12 @@ void Pointer::OnCursorCaptured(const gfx::Point& hotspot,
void Pointer::UpdateCursor() {
DCHECK(focus_);
+ aura::Window* root_window = focus_->window()->GetRootWindow();
+ if (!root_window)
+ return;
+
aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(focus_->window()->GetRootWindow());
+ aura::client::GetCursorClient(root_window);
if (cursor_client)
cursor_client->SetCursor(cursor_);
}
diff --git a/chromium/components/exo/shell_surface.cc b/chromium/components/exo/shell_surface.cc
index 97c18fee52e..57460ab9654 100644
--- a/chromium/components/exo/shell_surface.cc
+++ b/chromium/components/exo/shell_surface.cc
@@ -596,7 +596,7 @@ void ShellSurface::SetGeometry(const gfx::Rect& geometry) {
void ShellSurface::SetRectangularShadowEnabled(bool enabled) {
TRACE_EVENT1("exo", "ShellSurface::SetRectangularShadowEnabled", "enabled",
enabled);
- shadow_underlay_in_surface_ = false;
+ pending_shadow_underlay_in_surface_ = false;
shadow_enabled_ = enabled;
}
@@ -604,7 +604,7 @@ void ShellSurface::SetRectangularShadow_DEPRECATED(
const gfx::Rect& content_bounds) {
TRACE_EVENT1("exo", "ShellSurface::SetRectangularShadow_DEPRECATED",
"content_bounds", content_bounds.ToString());
- shadow_underlay_in_surface_ = false;
+ pending_shadow_underlay_in_surface_ = false;
shadow_content_bounds_ = content_bounds;
shadow_enabled_ = !content_bounds.IsEmpty();
}
@@ -613,7 +613,7 @@ void ShellSurface::SetRectangularSurfaceShadow(
const gfx::Rect& content_bounds) {
TRACE_EVENT1("exo", "ShellSurface::SetRectangularSurfaceShadow",
"content_bounds", content_bounds.ToString());
- shadow_underlay_in_surface_ = true;
+ pending_shadow_underlay_in_surface_ = true;
shadow_content_bounds_ = content_bounds;
shadow_enabled_ = !content_bounds.IsEmpty();
}
@@ -847,13 +847,26 @@ base::string16 ShellSurface::GetWindowTitle() const {
return title_;
}
+void ShellSurface::SaveWindowPlacement(const gfx::Rect& bounds,
+ ui::WindowShowState show_state) {
+ if (bounds_mode_ != BoundsMode::CLIENT)
+ WidgetDelegate::SaveWindowPlacement(bounds, show_state);
+}
+
+bool ShellSurface::GetSavedWindowPlacement(
+ const views::Widget* widget,
+ gfx::Rect* bounds,
+ ui::WindowShowState* show_state) const {
+ if (bounds_mode_ != BoundsMode::CLIENT)
+ return WidgetDelegate::GetSavedWindowPlacement(widget, bounds, show_state);
+ return false;
+}
+
void ShellSurface::WindowClosing() {
if (resizer_)
EndDrag(true /* revert */);
SetEnabled(false);
widget_ = nullptr;
- shadow_overlay_ = nullptr;
- shadow_underlay_ = nullptr;
}
views::Widget* ShellSurface::GetWidget() {
@@ -1143,8 +1156,7 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) {
// 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_in_maximized(
- bounds_mode_ == BoundsMode::CLIENT);
+ window_state->set_allow_set_bounds_direct(bounds_mode_ == BoundsMode::CLIENT);
// Notify client of initial state if different than normal.
if (window_state->GetStateType() != ash::wm::WINDOW_STATE_TYPE_NORMAL &&
@@ -1388,7 +1400,7 @@ void ShellSurface::UpdateWidgetBounds() {
ash::wm::WindowState* window_state =
ash::wm::GetWindowState(widget_->GetNativeWindow());
if (window_state->IsMaximizedOrFullscreenOrPinned() &&
- !window_state->allow_set_bounds_in_maximized()) {
+ !window_state->allow_set_bounds_direct()) {
return;
}
@@ -1449,8 +1461,23 @@ void ShellSurface::UpdateSurfaceBounds() {
void ShellSurface::UpdateShadow() {
if (!widget_ || !surface_)
return;
+ if (shadow_underlay_in_surface_ != pending_shadow_underlay_in_surface_) {
+ shadow_underlay_in_surface_ = pending_shadow_underlay_in_surface_;
+ shadow_overlay_.reset();
+ shadow_underlay_.reset();
+ }
+
aura::Window* window = widget_->GetNativeWindow();
- if (!shadow_enabled_) {
+
+ bool underlay_capture_events =
+ WMHelper::GetInstance()->IsSpokenFeedbackEnabled() && widget_->IsActive();
+ bool black_background_enabled =
+ ((widget_->IsFullscreen() || widget_->IsMaximized()) ||
+ underlay_capture_events) &&
+ ash::wm::GetWindowState(window)->allow_set_bounds_direct() &&
+ window->layer()->GetTargetTransform().IsIdentity();
+
+ if (!shadow_enabled_ && !black_background_enabled) {
wm::SetShadowElevation(window, wm::ShadowElevation::NONE);
if (shadow_underlay_)
shadow_underlay_->Hide();
@@ -1497,11 +1524,12 @@ void ShellSurface::UpdateShadow() {
// Always create and show the underlay, even in maximized/fullscreen.
if (!shadow_underlay_) {
- shadow_underlay_ = new aura::Window(nullptr);
+ shadow_underlay_ = base::MakeUnique<aura::Window>(nullptr);
+ shadow_underlay_->set_owned_by_parent(false);
shadow_underlay_event_handler_ =
base::MakeUnique<ShadowUnderlayEventHandler>();
shadow_underlay_->SetTargetHandler(shadow_underlay_event_handler_.get());
- DCHECK(shadow_underlay_->owned_by_parent());
+ DCHECK(!shadow_underlay_->owned_by_parent());
// Ensure the background area inside the shadow is solid black.
// Clients that provide translucent contents should not be using
// rectangular shadows as this method requires opaque contents to
@@ -1510,18 +1538,14 @@ void ShellSurface::UpdateShadow() {
shadow_underlay_->layer()->SetColor(SK_ColorBLACK);
DCHECK(shadow_underlay_->layer()->fills_bounds_opaquely());
if (shadow_underlay_in_surface_) {
- surface_->window()->AddChild(shadow_underlay_);
- surface_->window()->StackChildAtBottom(shadow_underlay_);
+ surface_->window()->AddChild(shadow_underlay());
+ surface_->window()->StackChildAtBottom(shadow_underlay());
} else {
- window->AddChild(shadow_underlay_);
- window->StackChildAtBottom(shadow_underlay_);
+ window->AddChild(shadow_underlay());
+ window->StackChildAtBottom(shadow_underlay());
}
}
- bool underlay_capture_events =
- WMHelper::GetInstance()->IsSpokenFeedbackEnabled() &&
- widget_->IsActive();
-
float shadow_underlay_opacity = shadow_background_opacity_;
// Put the black background layer behind the window if
@@ -1531,10 +1555,7 @@ void ShellSurface::UpdateShadow() {
// thus the background can be visible).
// 3) the window has no transform (the transformed background may
// not cover the entire background, e.g. overview mode).
- if ((widget_->IsFullscreen() || widget_->IsMaximized() ||
- underlay_capture_events) &&
- ash::wm::GetWindowState(window)->allow_set_bounds_in_maximized() &&
- window->layer()->GetTargetTransform().IsIdentity()) {
+ if (black_background_enabled) {
if (shadow_underlay_in_surface_) {
shadow_underlay_bounds = gfx::Rect(surface_->window()->bounds().size());
} else {
@@ -1558,6 +1579,9 @@ void ShellSurface::UpdateShadow() {
shadow_underlay_->SetBounds(shadow_underlay_bounds);
+ if (!shadow_underlay_->IsVisible())
+ shadow_underlay_->Show();
+
// TODO(oshima): Setting to the same value should be no-op.
// crbug.com/642223.
if (shadow_underlay_opacity !=
@@ -1565,25 +1589,24 @@ void ShellSurface::UpdateShadow() {
shadow_underlay_->layer()->SetOpacity(shadow_underlay_opacity);
}
- shadow_underlay_->Show();
-
wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window);
// Maximized/Fullscreen window does not create a shadow.
if (!shadow)
return;
if (!shadow_overlay_) {
- shadow_overlay_ = new aura::Window(nullptr);
- DCHECK(shadow_overlay_->owned_by_parent());
+ shadow_overlay_ = base::MakeUnique<aura::Window>(nullptr);
+ shadow_overlay_->set_owned_by_parent(false);
+ DCHECK(!shadow_overlay_->owned_by_parent());
shadow_overlay_->set_ignore_events(true);
shadow_overlay_->Init(ui::LAYER_NOT_DRAWN);
shadow_overlay_->layer()->Add(shadow->layer());
- window->AddChild(shadow_overlay_);
+ window->AddChild(shadow_overlay());
if (shadow_underlay_in_surface_) {
- window->StackChildBelow(shadow_overlay_, surface_->window());
+ window->StackChildBelow(shadow_overlay(), surface_->window());
} else {
- window->StackChildAbove(shadow_overlay_, shadow_underlay_);
+ window->StackChildAbove(shadow_overlay(), shadow_underlay());
}
shadow_overlay_->Show();
}
diff --git a/chromium/components/exo/shell_surface.h b/chromium/components/exo/shell_surface.h
index d621a988607..0bf2b7e916f 100644
--- a/chromium/components/exo/shell_surface.h
+++ b/chromium/components/exo/shell_surface.h
@@ -220,6 +220,11 @@ class ShellSurface : public SurfaceDelegate,
bool CanMaximize() const override;
bool CanMinimize() const override;
base::string16 GetWindowTitle() const override;
+ void SaveWindowPlacement(const gfx::Rect& bounds,
+ ui::WindowShowState show_state) override;
+ bool GetSavedWindowPlacement(const views::Widget* widget,
+ gfx::Rect* bounds,
+ ui::WindowShowState* show_state) const override;
void WindowClosing() override;
views::Widget* GetWidget() override;
const views::Widget* GetWidget() const override;
@@ -260,8 +265,8 @@ class ShellSurface : public SurfaceDelegate,
// Overridden from ui::AcceleratorTarget:
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
- aura::Window* shadow_overlay() { return shadow_overlay_; }
- aura::Window* shadow_underlay() { return shadow_underlay_; }
+ aura::Window* shadow_overlay() { return shadow_overlay_.get(); }
+ aura::Window* shadow_underlay() { return shadow_underlay_.get(); }
Surface* surface_for_testing() { return surface_; }
@@ -342,8 +347,8 @@ class ShellSurface : public SurfaceDelegate,
gfx::Vector2d pending_origin_offset_accumulator_;
int resize_component_ = HTCAPTION; // HT constant (see ui/base/hit_test.h)
int pending_resize_component_ = HTCAPTION;
- aura::Window* shadow_overlay_ = nullptr;
- aura::Window* shadow_underlay_ = nullptr;
+ std::unique_ptr<aura::Window> shadow_overlay_;
+ std::unique_ptr<aura::Window> shadow_underlay_;
std::unique_ptr<ui::EventHandler> shadow_underlay_event_handler_;
gfx::Rect shadow_content_bounds_;
float shadow_background_opacity_ = 1.0;
@@ -353,6 +358,7 @@ class ShellSurface : public SurfaceDelegate,
int top_inset_height_ = 0;
int pending_top_inset_height_ = 0;
bool shadow_underlay_in_surface_ = true;
+ bool pending_shadow_underlay_in_surface_ = true;
bool system_modal_ = false;
DISALLOW_COPY_AND_ASSIGN(ShellSurface);
diff --git a/chromium/components/exo/shell_surface_unittest.cc b/chromium/components/exo/shell_surface_unittest.cc
index 5e300222acb..b8dbca007cd 100644
--- a/chromium/components/exo/shell_surface_unittest.cc
+++ b/chromium/components/exo/shell_surface_unittest.cc
@@ -829,6 +829,20 @@ TEST_F(ShellSurfaceTest, ShadowStartMaximized) {
ASSERT_TRUE(shell_surface->shadow_underlay());
EXPECT_TRUE(shell_surface->shadow_underlay()->IsVisible());
+ shell_surface->SetRectangularSurfaceShadow(gfx::Rect(0, 0, 0, 0));
+ // Underlay should be created even without shadow.
+ ASSERT_TRUE(shell_surface->shadow_underlay());
+ EXPECT_TRUE(shell_surface->shadow_underlay()->IsVisible());
+ shell_surface->SetRectangularShadowEnabled(false);
+ surface->Commit();
+ // Underlay should be created even without shadow.
+ ASSERT_TRUE(shell_surface->shadow_underlay());
+ EXPECT_TRUE(shell_surface->shadow_underlay()->IsVisible());
+
+ shell_surface->SetRectangularShadowEnabled(true);
+ shell_surface->SetRectangularSurfaceShadow(gfx::Rect(10, 10, 100, 100));
+ surface->Commit();
+
// Restore the window and make sure the shadow is created, visible and
// has the latest bounds.
widget->Restore();
@@ -1011,5 +1025,41 @@ TEST_F(ShellSurfaceTest, SpokenFeedbackFullscreenBackground) {
EXPECT_EQ(shadow_bounds, shell_surface2.shadow_underlay()->bounds());
}
+// Make sure that a surface shell started in maximize creates deprecated
+// shadow correctly.
+TEST_F(ShellSurfaceTest,
+ StartMaximizedThenMinimizeWithSetRectangularShadow_DEPRECATED) {
+ const gfx::Size display_size =
+ display::Screen::GetScreen()->GetPrimaryDisplay().size();
+ const gfx::Size buffer_size(display_size);
+ std::unique_ptr<Buffer> buffer(
+ new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+ std::unique_ptr<Surface> surface(new Surface);
+ std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(
+ surface.get(), nullptr, ShellSurface::BoundsMode::CLIENT, gfx::Point(),
+ true, false, ash::kShellWindowId_DefaultContainer));
+
+ // Start in maximized.
+ shell_surface->Maximize();
+ surface->Attach(buffer.get());
+ surface->Commit();
+
+ gfx::Rect shadow_bounds =
+ display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
+ shell_surface->SetGeometry(shadow_bounds);
+ shell_surface->SetRectangularShadow_DEPRECATED(shadow_bounds);
+ surface->Commit();
+ EXPECT_EQ(shadow_bounds,
+ shell_surface->GetWidget()->GetWindowBoundsInScreen());
+ ASSERT_EQ(shadow_bounds, shell_surface->shadow_underlay()->bounds());
+ EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().size(),
+ shell_surface->surface_for_testing()->window()->bounds().size());
+
+ ash::wm::WMEvent minimize_event(ash::wm::WM_EVENT_MINIMIZE);
+ ash::WmWindow* window =
+ ash::WmWindow::Get(shell_surface->GetWidget()->GetNativeWindow());
+ window->GetWindowState()->OnWMEvent(&minimize_event);
+}
+
} // namespace
} // namespace exo
diff --git a/chromium/components/exo/touch.cc b/chromium/components/exo/touch.cc
index fa2de6dd507..2ebdbb5950d 100644
--- a/chromium/components/exo/touch.cc
+++ b/chromium/components/exo/touch.cc
@@ -147,8 +147,13 @@ void Touch::OnTouchEvent(ui::TouchEvent* event) {
return;
}
if (send_details) {
- delegate_->OnTouchShape(touch_pointer_id, event->pointer_details().radius_x,
- event->pointer_details().radius_y);
+ // Some devices do not report radius_y/minor. We assume a circular shape
+ // in that case.
+ float major = event->pointer_details().radius_x * 2.0f;
+ float minor = event->pointer_details().radius_y * 2.0f;
+ if (!minor)
+ minor = major;
+ delegate_->OnTouchShape(touch_pointer_id, major, minor);
if (stylus_delegate_ &&
event->pointer_details().pointer_type !=
diff --git a/chromium/components/exo/touch_unittest.cc b/chromium/components/exo/touch_unittest.cc
index 18917fb7544..1384229ac62 100644
--- a/chromium/components/exo/touch_unittest.cc
+++ b/chromium/components/exo/touch_unittest.cc
@@ -164,23 +164,24 @@ TEST_F(TouchTest, OnTouchShape) {
testing::InSequence sequence;
EXPECT_CALL(delegate, OnTouchDown(window.surface(), testing::_, testing::_,
gfx::PointF()));
- EXPECT_CALL(delegate, OnTouchShape(testing::_, 1, 1));
+ EXPECT_CALL(delegate, OnTouchShape(testing::_, 20, 10));
EXPECT_CALL(delegate, OnTouchFrame());
EXPECT_CALL(delegate,
OnTouchMotion(testing::_, testing::_, gfx::PointF(5, 5)));
- EXPECT_CALL(delegate, OnTouchShape(testing::_, 1, 1));
+ EXPECT_CALL(delegate, OnTouchShape(testing::_, 20, 10));
EXPECT_CALL(delegate, OnTouchFrame());
EXPECT_CALL(delegate,
OnTouchMotion(testing::_, testing::_, gfx::PointF(10, 10)));
- EXPECT_CALL(delegate, OnTouchShape(testing::_, 20, 10));
+ EXPECT_CALL(delegate, OnTouchShape(testing::_, 20, 20));
EXPECT_CALL(delegate, OnTouchFrame());
EXPECT_CALL(delegate, OnTouchUp(testing::_, testing::_));
EXPECT_CALL(delegate, OnTouchFrame());
}
generator.set_current_location(window.origin());
+ generator.SetTouchRadius(10, 5);
generator.PressTouch();
generator.MoveTouchBy(5, 5);
- generator.SetTouchRadius(20, 10);
+ generator.SetTouchRadius(10, 0); // Minor not supported
generator.MoveTouchBy(5, 5);
generator.ReleaseTouch();
EXPECT_CALL(delegate, OnTouchDestroying(touch.get()));
diff --git a/chromium/components/exo/wayland/server.cc b/chromium/components/exo/wayland/server.cc
index 0abc727db2a..0faf554a77f 100644
--- a/chromium/components/exo/wayland/server.cc
+++ b/chromium/components/exo/wayland/server.cc
@@ -157,6 +157,10 @@ DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasSecurityKey, false);
// associated with window.
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasBlendingKey, false);
+// A property key containing a boolean set to true whether the current
+// OnWindowActivated invocation should be ignored.
+DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIgnoreWindowActivated, false);
+
wl_resource* GetSurfaceResource(Surface* surface) {
return surface->GetProperty(kSurfaceResourceKey);
}
@@ -1925,7 +1929,14 @@ void remote_surface_set_top_inset(wl_client* client,
void remote_surface_activate(wl_client* client,
wl_resource* resource,
uint32_t serial) {
+ ShellSurface* shell_surface = GetUserDataAs<ShellSurface>(resource);
+ aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
+
+ // Activation on Aura is synchronous, so activation callbacks will be called
+ // before the flag is reset.
+ window->SetProperty(kIgnoreWindowActivated, true);
GetUserDataAs<ShellSurface>(resource)->Activate();
+ window->ClearProperty(kIgnoreWindowActivated);
}
void remote_surface_maximize(wl_client* client, wl_resource* resource) {
@@ -2106,6 +2117,13 @@ class WaylandRemoteShell : public WMHelper::MaximizeModeObserver,
// Overridden from WMHelper::ActivationObserver:
void OnWindowActivated(aura::Window* gained_active,
aura::Window* lost_active) override {
+ // If the origin of activation is Wayland client, then assume it's been
+ // already activated on the client side, so do not notify about the
+ // activation. It means that zcr_remote_shell_v1_send_activated is used
+ // only to notify about activations originating in Aura.
+ if (gained_active && gained_active->GetProperty(kIgnoreWindowActivated))
+ return;
+
SendActivated(gained_active, lost_active);
}
@@ -2934,7 +2952,7 @@ void seat_release(wl_client* client, wl_resource* resource) {
const struct wl_seat_interface seat_implementation = {
seat_get_pointer, seat_get_keyboard, seat_get_touch, seat_release};
-const uint32_t seat_version = 5;
+const uint32_t seat_version = 6;
void bind_seat(wl_client* client, void* data, uint32_t version, uint32_t id) {
wl_resource* resource = wl_resource_create(
diff --git a/chromium/components/offline_pages/core/downloads/download_notifying_observer.cc b/chromium/components/offline_pages/core/downloads/download_notifying_observer.cc
index 37836088129..00cc67daf40 100644
--- a/chromium/components/offline_pages/core/downloads/download_notifying_observer.cc
+++ b/chromium/components/offline_pages/core/downloads/download_notifying_observer.cc
@@ -67,9 +67,8 @@ void DownloadNotifyingObserver::OnChanged(const SavePageRequest& request) {
void DownloadNotifyingObserver::OnNetworkProgress(
const SavePageRequest& request,
int64_t received_bytes) {
- DownloadUIItem item(request);
- item.download_progress_bytes = received_bytes;
- notifier_->NotifyDownloadProgress(item);
+ // TODO(dimich): Enable this back in M59. See bug 704049 for more info and
+ // what was temporarily (for M58) reverted.
}
void DownloadNotifyingObserver::OnCompleted(
diff --git a/chromium/components/password_manager/content/browser/content_password_manager_driver.cc b/chromium/components/password_manager/content/browser/content_password_manager_driver.cc
index 0c26839db26..26695612a11 100644
--- a/chromium/components/password_manager/content/browser/content_password_manager_driver.cc
+++ b/chromium/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -155,6 +155,11 @@ void ContentPasswordManagerDriver::AllowToRunFormClassifier() {
GetPasswordGenerationAgent()->AllowToRunFormClassifier();
}
+autofill::AutofillDriver* ContentPasswordManagerDriver::GetAutofillDriver() {
+ return autofill::ContentAutofillDriver::GetForRenderFrameHost(
+ render_frame_host_);
+}
+
PasswordGenerationManager*
ContentPasswordManagerDriver::GetPasswordGenerationManager() {
return &password_generation_manager_;
diff --git a/chromium/components/password_manager/content/browser/content_password_manager_driver.h b/chromium/components/password_manager/content/browser/content_password_manager_driver.h
index eb6d2881dcf..a1c2168995b 100644
--- a/chromium/components/password_manager/content/browser/content_password_manager_driver.h
+++ b/chromium/components/password_manager/content/browser/content_password_manager_driver.h
@@ -77,6 +77,7 @@ class ContentPasswordManagerDriver
void GeneratePassword() override;
void SendLoggingAvailability() override;
void AllowToRunFormClassifier() override;
+ autofill::AutofillDriver* GetAutofillDriver() override;
PasswordGenerationManager* GetPasswordGenerationManager() override;
PasswordManager* GetPasswordManager() override;
diff --git a/chromium/components/password_manager/core/browser/password_autofill_manager.cc b/chromium/components/password_manager/core/browser/password_autofill_manager.cc
index 091b2062c2e..a242d655fc0 100644
--- a/chromium/components/password_manager/core/browser/password_autofill_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_autofill_manager.cc
@@ -17,7 +17,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_driver.h"
+#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/popup_item_ids.h"
#include "components/autofill/core/browser/suggestion.h"
@@ -138,8 +138,7 @@ PasswordAutofillManager::PasswordAutofillManager(
autofill::AutofillClient* autofill_client)
: password_manager_driver_(password_manager_driver),
autofill_client_(autofill_client),
- weak_ptr_factory_(this) {
-}
+ weak_ptr_factory_(this) {}
PasswordAutofillManager::~PasswordAutofillManager() {
}
@@ -353,6 +352,10 @@ bool PasswordAutofillManager::IsCreditCardPopup() {
return false;
}
+autofill::AutofillDriver* PasswordAutofillManager::GetAutofillDriver() {
+ return password_manager_driver_->GetAutofillDriver();
+}
+
////////////////////////////////////////////////////////////////////////////////
// PasswordAutofillManager, private:
diff --git a/chromium/components/password_manager/core/browser/password_autofill_manager.h b/chromium/components/password_manager/core/browser/password_autofill_manager.h
index 56a5b5c62ba..737bc926e3a 100644
--- a/chromium/components/password_manager/core/browser/password_autofill_manager.h
+++ b/chromium/components/password_manager/core/browser/password_autofill_manager.h
@@ -43,6 +43,7 @@ class PasswordAutofillManager : public autofill::AutofillPopupDelegate {
bool RemoveSuggestion(const base::string16& value, int identifier) override;
void ClearPreviewedForm() override;
bool IsCreditCardPopup() override;
+ autofill::AutofillDriver* GetAutofillDriver() override;
// Invoked when a password mapping is added.
void OnAddPasswordFormMapping(
diff --git a/chromium/components/password_manager/core/browser/password_manager_driver.h b/chromium/components/password_manager/core/browser/password_manager_driver.h
index 8ec6b5e8261..028bf7273ac 100644
--- a/chromium/components/password_manager/core/browser/password_manager_driver.h
+++ b/chromium/components/password_manager/core/browser/password_manager_driver.h
@@ -14,6 +14,7 @@
#include "components/autofill/core/common/password_form_field_prediction_map.h"
namespace autofill {
+class AutofillDriver;
struct FormData;
struct PasswordForm;
struct PasswordFormGenerationData;
@@ -97,6 +98,9 @@ class PasswordManagerDriver
// Allows the form classifier to find generation fields.
virtual void AllowToRunFormClassifier() {}
+ // Return the associated AutofillDriver.
+ virtual autofill::AutofillDriver* GetAutofillDriver() = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(PasswordManagerDriver);
};
diff --git a/chromium/components/password_manager/core/browser/stub_password_manager_driver.cc b/chromium/components/password_manager/core/browser/stub_password_manager_driver.cc
index ba19e68c086..18b7dc56a7c 100644
--- a/chromium/components/password_manager/core/browser/stub_password_manager_driver.cc
+++ b/chromium/components/password_manager/core/browser/stub_password_manager_driver.cc
@@ -56,4 +56,8 @@ StubPasswordManagerDriver::GetPasswordAutofillManager() {
return nullptr;
}
+autofill::AutofillDriver* StubPasswordManagerDriver::GetAutofillDriver() {
+ return nullptr;
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/stub_password_manager_driver.h b/chromium/components/password_manager/core/browser/stub_password_manager_driver.h
index 88d1ff38b28..f7a1703d1d9 100644
--- a/chromium/components/password_manager/core/browser/stub_password_manager_driver.h
+++ b/chromium/components/password_manager/core/browser/stub_password_manager_driver.h
@@ -36,6 +36,7 @@ class StubPasswordManagerDriver : public PasswordManagerDriver {
PasswordGenerationManager* GetPasswordGenerationManager() override;
PasswordManager* GetPasswordManager() override;
PasswordAutofillManager* GetPasswordAutofillManager() override;
+ autofill::AutofillDriver* GetAutofillDriver() override;
private:
DISALLOW_COPY_AND_ASSIGN(StubPasswordManagerDriver);
diff --git a/chromium/components/ssl_errors/error_classification.cc b/chromium/components/ssl_errors/error_classification.cc
index 572b5729528..52827fe1565 100644
--- a/chromium/components/ssl_errors/error_classification.cc
+++ b/chromium/components/ssl_errors/error_classification.cc
@@ -38,32 +38,13 @@ using base::TimeDelta;
namespace ssl_errors {
namespace {
-// Events for UMA. Do not reorder or change!
-enum SSLInterstitialCause {
- CLOCK_PAST,
- CLOCK_FUTURE,
- WWW_SUBDOMAIN_MATCH,
- SUBDOMAIN_MATCH,
- SUBDOMAIN_INVERSE_MATCH,
- SUBDOMAIN_OUTSIDE_WILDCARD,
- HOST_NAME_NOT_KNOWN_TLD,
- LIKELY_MULTI_TENANT_HOSTING,
- LOCALHOST,
- PRIVATE_URL,
- AUTHORITY_ERROR_CAPTIVE_PORTAL, // Deprecated in M47.
- SELF_SIGNED,
- EXPIRED_RECENTLY,
- LIKELY_SAME_DOMAIN,
- UNUSED_INTERSTITIAL_CAUSE_ENTRY,
-};
-
void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) {
if (overridable) {
UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event,
- UNUSED_INTERSTITIAL_CAUSE_ENTRY);
+ SSL_INTERSTITIAL_CAUSE_MAX);
} else {
UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event,
- UNUSED_INTERSTITIAL_CAUSE_ENTRY);
+ SSL_INTERSTITIAL_CAUSE_MAX);
}
}
@@ -109,7 +90,7 @@ bool IsWWWSubDomainMatch(const GURL& request_url,
const net::X509Certificate& cert) {
std::string www_host;
std::vector<std::string> dns_names;
- cert.GetDNSNames(&dns_names);
+ cert.GetSubjectAltName(&dns_names, nullptr);
return GetWWWSubDomainMatch(request_url, dns_names, &www_host);
}
@@ -148,24 +129,28 @@ void RecordUMAStatistics(bool overridable,
}
case ssl_errors::ErrorInfo::CERT_COMMON_NAME_INVALID: {
std::string host_name = request_url.host();
+ std::vector<std::string> dns_names;
+ cert.GetSubjectAltName(&dns_names, nullptr);
+ std::vector<HostnameTokens> dns_name_tokens =
+ GetTokenizedDNSNames(dns_names);
+
+ if (dns_names.empty())
+ RecordSSLInterstitialCause(overridable, NO_SUBJECT_ALT_NAME);
+
if (HostNameHasKnownTLD(host_name)) {
HostnameTokens host_name_tokens = Tokenize(host_name);
if (IsWWWSubDomainMatch(request_url, cert))
- RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH);
+ RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH2);
if (IsSubDomainOutsideWildcard(request_url, cert))
- RecordSSLInterstitialCause(overridable, SUBDOMAIN_OUTSIDE_WILDCARD);
- std::vector<std::string> dns_names;
- cert.GetDNSNames(&dns_names);
- std::vector<HostnameTokens> dns_name_tokens =
- GetTokenizedDNSNames(dns_names);
+ RecordSSLInterstitialCause(overridable, SUBDOMAIN_OUTSIDE_WILDCARD2);
if (NameUnderAnyNames(host_name_tokens, dns_name_tokens))
- RecordSSLInterstitialCause(overridable, SUBDOMAIN_MATCH);
+ RecordSSLInterstitialCause(overridable, SUBDOMAIN_MATCH2);
if (AnyNamesUnderName(dns_name_tokens, host_name_tokens))
- RecordSSLInterstitialCause(overridable, SUBDOMAIN_INVERSE_MATCH);
+ RecordSSLInterstitialCause(overridable, SUBDOMAIN_INVERSE_MATCH2);
if (IsCertLikelyFromMultiTenantHosting(request_url, cert))
- RecordSSLInterstitialCause(overridable, LIKELY_MULTI_TENANT_HOSTING);
+ RecordSSLInterstitialCause(overridable, LIKELY_MULTI_TENANT_HOSTING2);
if (IsCertLikelyFromSameDomain(request_url, cert))
- RecordSSLInterstitialCause(overridable, LIKELY_SAME_DOMAIN);
+ RecordSSLInterstitialCause(overridable, LIKELY_SAME_DOMAIN2);
} else {
RecordSSLInterstitialCause(overridable, HOST_NAME_NOT_KNOWN_TLD);
}
@@ -382,7 +367,7 @@ bool IsSubDomainOutsideWildcard(const GURL& request_url,
std::string host_name = request_url.host();
HostnameTokens host_name_tokens = Tokenize(host_name);
std::vector<std::string> dns_names;
- cert.GetDNSNames(&dns_names);
+ cert.GetSubjectAltName(&dns_names, nullptr);
bool result = false;
// This method requires that the host name be longer than the dns name on
@@ -410,7 +395,7 @@ bool IsCertLikelyFromMultiTenantHosting(const GURL& request_url,
std::string host_name = request_url.host();
std::vector<std::string> dns_names;
std::vector<std::string> dns_names_domain;
- cert.GetDNSNames(&dns_names);
+ cert.GetSubjectAltName(&dns_names, nullptr);
size_t dns_names_size = dns_names.size();
// If there is only 1 DNS name then it is definitely not a shared certificate.
@@ -457,7 +442,9 @@ bool IsCertLikelyFromSameDomain(const GURL& request_url,
const net::X509Certificate& cert) {
std::string host_name = request_url.host();
std::vector<std::string> dns_names;
- cert.GetDNSNames(&dns_names);
+ cert.GetSubjectAltName(&dns_names, nullptr);
+ if (dns_names.empty())
+ return false;
dns_names.push_back(host_name);
std::vector<std::string> dns_names_domain;
diff --git a/chromium/components/ssl_errors/error_classification.h b/chromium/components/ssl_errors/error_classification.h
index b8c472df669..0dea46560cc 100644
--- a/chromium/components/ssl_errors/error_classification.h
+++ b/chromium/components/ssl_errors/error_classification.h
@@ -28,6 +28,33 @@ typedef std::vector<std::string> HostnameTokens;
// Methods for identifying specific error causes. ------------------------------
+// These values are written to logs. New enum values can be added, but existing
+// enums must never be renumbered or deleted and reused.
+enum SSLInterstitialCause {
+ CLOCK_PAST = 0,
+ CLOCK_FUTURE = 1,
+ WWW_SUBDOMAIN_MATCH = 2, // Deprecated in M59.
+ SUBDOMAIN_MATCH = 3, // Deprecated in M59.
+ SUBDOMAIN_INVERSE_MATCH = 4, // Deprecated in M59.
+ SUBDOMAIN_OUTSIDE_WILDCARD = 5, // Deprecated in M59.
+ HOST_NAME_NOT_KNOWN_TLD = 6,
+ LIKELY_MULTI_TENANT_HOSTING = 7, // Deprecated in M59.
+ LOCALHOST = 8,
+ PRIVATE_URL = 9,
+ AUTHORITY_ERROR_CAPTIVE_PORTAL = 10, // Deprecated in M47.
+ SELF_SIGNED = 11,
+ EXPIRED_RECENTLY = 12,
+ LIKELY_SAME_DOMAIN = 13, // Deprecated in M59.
+ NO_SUBJECT_ALT_NAME = 14,
+ WWW_SUBDOMAIN_MATCH2 = 15,
+ SUBDOMAIN_MATCH2 = 16,
+ SUBDOMAIN_INVERSE_MATCH2 = 17,
+ SUBDOMAIN_OUTSIDE_WILDCARD2 = 18,
+ LIKELY_MULTI_TENANT_HOSTING2 = 19,
+ LIKELY_SAME_DOMAIN2 = 20,
+ SSL_INTERSTITIAL_CAUSE_MAX
+};
+
// What is known about the accuracy of system clock. Do not change or
// reorder; these values are used in an UMA histogram.
enum ClockState {
@@ -110,14 +137,9 @@ bool IsCertLikelyFromMultiTenantHosting(const GURL& request_url,
bool IsCertLikelyFromSameDomain(const GURL& request_url,
const net::X509Certificate& cert);
-// Returns true if the site's hostname differs from one of the DNS
-// names in the certificate (CN or SANs) only by the presence or
-// absence of the single-label prefix "www". E.g.: (The first domain
-// is hostname and the second domain is a DNS name in the certificate)
-// www.example.com ~ example.com -> true
-// example.com ~ www.example.com -> true
-// www.food.example.com ~ example.com -> false
-// mail.example.com ~ example.com -> false
+// Returns true if the site's hostname differs from one of the DNS names in
+// |dns_names| only by the presence or absence of the single-label prefix "www".
+// The matching name from the certificate is returned in |www_match_host_name|.
bool GetWWWSubDomainMatch(const GURL& request_url,
const std::vector<std::string>& dns_names,
std::string* www_match_host_name);
diff --git a/chromium/components/ssl_errors/error_classification_unittest.cc b/chromium/components/ssl_errors/error_classification_unittest.cc
index 1099181a6f4..c4c2c45e9ef 100644
--- a/chromium/components/ssl_errors/error_classification_unittest.cc
+++ b/chromium/components/ssl_errors/error_classification_unittest.cc
@@ -26,11 +26,15 @@
#include "net/test/test_certificate_data.h"
#include "net/test/test_data_directory.h"
#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+using testing::ElementsAre;
+
namespace {
const char kNetworkTimeHistogram[] = "interstitial.ssl.clockstate.network3";
+const char kSslErrorCauseHistogram[] = "interstitial.ssl.cause.overridable";
static std::unique_ptr<net::test_server::HttpResponse>
NetworkErrorResponseHandler(const net::test_server::HttpRequest& request) {
@@ -53,112 +57,132 @@ class SSLErrorClassificationTest : public ::testing::Test {
};
TEST_F(SSLErrorClassificationTest, TestNameMismatch) {
- scoped_refptr<net::X509Certificate> google_cert(
- net::X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der)));
- ASSERT_TRUE(google_cert.get());
- std::vector<std::string> dns_names_google;
- google_cert->GetDNSNames(&dns_names_google);
- ASSERT_EQ(1u, dns_names_google.size()); // ["www.google.com"]
- std::vector<std::string> hostname_tokens_google =
- ssl_errors::Tokenize(dns_names_google[0]);
- ASSERT_EQ(3u, hostname_tokens_google.size()); // ["www","google","com"]
- std::vector<std::vector<std::string>> dns_name_tokens_google;
- dns_name_tokens_google.push_back(hostname_tokens_google);
- ASSERT_EQ(1u, dns_name_tokens_google.size()); // [["www","google","com"]]
+ scoped_refptr<net::X509Certificate> example_cert = net::ImportCertFromFile(
+ net::GetTestCertsDirectory(), "subjectAltName_www_example_com.pem");
+ ASSERT_TRUE(example_cert);
+ std::vector<std::string> dns_names_example;
+ example_cert->GetSubjectAltName(&dns_names_example, nullptr);
+ ASSERT_THAT(dns_names_example, ElementsAre("www.example.com"));
+ std::vector<std::string> hostname_tokens_example =
+ ssl_errors::Tokenize(dns_names_example[0]);
+ ASSERT_THAT(hostname_tokens_example, ElementsAre("www", "example", "com"));
+ std::vector<std::vector<std::string>> dns_name_tokens_example;
+ dns_name_tokens_example.push_back(hostname_tokens_example);
+ ASSERT_EQ(1u, dns_name_tokens_example.size()); // [["www","example","com"]]
+ ASSERT_THAT(dns_name_tokens_example[0], ElementsAre("www", "example", "com"));
{
- GURL origin("https://google.com");
+ GURL origin("https://example.com");
std::string www_host;
std::vector<std::string> host_name_tokens = base::SplitString(
origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
EXPECT_TRUE(
- ssl_errors::GetWWWSubDomainMatch(origin, dns_names_google, &www_host));
- EXPECT_EQ("www.google.com", www_host);
+ ssl_errors::GetWWWSubDomainMatch(origin, dns_names_example, &www_host));
+ EXPECT_EQ("www.example.com", www_host);
EXPECT_FALSE(ssl_errors::NameUnderAnyNames(host_name_tokens,
- dns_name_tokens_google));
- EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_google,
+ dns_name_tokens_example));
+ EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_example,
host_name_tokens));
- EXPECT_FALSE(ssl_errors::IsSubDomainOutsideWildcard(origin, *google_cert));
+ EXPECT_FALSE(ssl_errors::IsSubDomainOutsideWildcard(origin, *example_cert));
EXPECT_FALSE(
- ssl_errors::IsCertLikelyFromMultiTenantHosting(origin, *google_cert));
- EXPECT_TRUE(ssl_errors::IsCertLikelyFromSameDomain(origin, *google_cert));
+ ssl_errors::IsCertLikelyFromMultiTenantHosting(origin, *example_cert));
+ EXPECT_TRUE(ssl_errors::IsCertLikelyFromSameDomain(origin, *example_cert));
}
{
- GURL origin("https://foo.blah.google.com");
+ GURL origin("https://foo.blah.example.com");
std::string www_host;
std::vector<std::string> host_name_tokens = base::SplitString(
origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
EXPECT_FALSE(
- ssl_errors::GetWWWSubDomainMatch(origin, dns_names_google, &www_host));
+ ssl_errors::GetWWWSubDomainMatch(origin, dns_names_example, &www_host));
EXPECT_FALSE(ssl_errors::NameUnderAnyNames(host_name_tokens,
- dns_name_tokens_google));
- EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_google,
+ dns_name_tokens_example));
+ EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_example,
host_name_tokens));
- EXPECT_TRUE(ssl_errors::IsCertLikelyFromSameDomain(origin, *google_cert));
+ EXPECT_TRUE(ssl_errors::IsCertLikelyFromSameDomain(origin, *example_cert));
}
{
- GURL origin("https://foo.www.google.com");
+ GURL origin("https://foo.www.example.com");
std::string www_host;
std::vector<std::string> host_name_tokens = base::SplitString(
origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
EXPECT_FALSE(
- ssl_errors::GetWWWSubDomainMatch(origin, dns_names_google, &www_host));
+ ssl_errors::GetWWWSubDomainMatch(origin, dns_names_example, &www_host));
EXPECT_TRUE(ssl_errors::NameUnderAnyNames(host_name_tokens,
- dns_name_tokens_google));
- EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_google,
+ dns_name_tokens_example));
+ EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_example,
host_name_tokens));
- EXPECT_TRUE(ssl_errors::IsCertLikelyFromSameDomain(origin, *google_cert));
+ EXPECT_TRUE(ssl_errors::IsCertLikelyFromSameDomain(origin, *example_cert));
}
{
- GURL origin("https://www.google.com.foo");
+ GURL origin("https://www.example.com.foo");
std::string www_host;
std::vector<std::string> host_name_tokens = base::SplitString(
origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
EXPECT_FALSE(
- ssl_errors::GetWWWSubDomainMatch(origin, dns_names_google, &www_host));
+ ssl_errors::GetWWWSubDomainMatch(origin, dns_names_example, &www_host));
EXPECT_FALSE(ssl_errors::NameUnderAnyNames(host_name_tokens,
- dns_name_tokens_google));
- EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_google,
+ dns_name_tokens_example));
+ EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_example,
host_name_tokens));
- EXPECT_FALSE(ssl_errors::IsCertLikelyFromSameDomain(origin, *google_cert));
+ EXPECT_FALSE(ssl_errors::IsCertLikelyFromSameDomain(origin, *example_cert));
}
{
- GURL origin("https://www.foogoogle.com.");
+ GURL origin("https://www.fooexample.com.");
std::string www_host;
std::vector<std::string> host_name_tokens = base::SplitString(
origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
EXPECT_FALSE(
- ssl_errors::GetWWWSubDomainMatch(origin, dns_names_google, &www_host));
+ ssl_errors::GetWWWSubDomainMatch(origin, dns_names_example, &www_host));
EXPECT_FALSE(ssl_errors::NameUnderAnyNames(host_name_tokens,
- dns_name_tokens_google));
- EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_google,
+ dns_name_tokens_example));
+ EXPECT_FALSE(ssl_errors::AnyNamesUnderName(dns_name_tokens_example,
host_name_tokens));
- EXPECT_FALSE(ssl_errors::IsCertLikelyFromSameDomain(origin, *google_cert));
+ EXPECT_FALSE(ssl_errors::IsCertLikelyFromSameDomain(origin, *example_cert));
+ }
+
+ // Ensure that a certificate with no SubjectAltName does not fall back to
+ // the Subject CN when evaluating hostnames.
+ {
+ scoped_refptr<net::X509Certificate> google_cert(
+ net::X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(google_der), sizeof(google_der)));
+ ASSERT_TRUE(google_cert);
+
+ GURL origin("https://google.com");
+
+ base::HistogramTester histograms;
+ ssl_errors::RecordUMAStatistics(true, base::Time::NowFromSystemTime(),
+ origin, net::ERR_CERT_COMMON_NAME_INVALID,
+ *google_cert);
+
+ // Verify that we recorded only NO_SUBJECT_ALT_NAME and no other causes.
+ histograms.ExpectUniqueSample(kSslErrorCauseHistogram,
+ ssl_errors::NO_SUBJECT_ALT_NAME, 1);
}
- scoped_refptr<net::X509Certificate> webkit_cert(
- net::X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)));
- ASSERT_TRUE(webkit_cert.get());
- std::vector<std::string> dns_names_webkit;
- webkit_cert->GetDNSNames(&dns_names_webkit);
- ASSERT_EQ(2u, dns_names_webkit.size()); // ["*.webkit.org", "webkit.org"]
- std::vector<std::string> hostname_tokens_webkit_0 =
- ssl_errors::Tokenize(dns_names_webkit[0]);
- ASSERT_EQ(3u, hostname_tokens_webkit_0.size()); // ["*", "webkit","org"]
- std::vector<std::string> hostname_tokens_webkit_1 =
- ssl_errors::Tokenize(dns_names_webkit[1]);
- ASSERT_EQ(2u, hostname_tokens_webkit_1.size()); // ["webkit","org"]
- std::vector<std::vector<std::string>> dns_name_tokens_webkit;
- dns_name_tokens_webkit.push_back(hostname_tokens_webkit_0);
- dns_name_tokens_webkit.push_back(hostname_tokens_webkit_1);
- ASSERT_EQ(2u, dns_name_tokens_webkit.size());
{
+ scoped_refptr<net::X509Certificate> webkit_cert(
+ net::X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)));
+ ASSERT_TRUE(webkit_cert);
+ std::vector<std::string> dns_names_webkit;
+ webkit_cert->GetSubjectAltName(&dns_names_webkit, nullptr);
+ ASSERT_THAT(dns_names_webkit, ElementsAre("*.webkit.org", "webkit.org"));
+ std::vector<std::string> hostname_tokens_webkit_0 =
+ ssl_errors::Tokenize(dns_names_webkit[0]);
+ ASSERT_THAT(hostname_tokens_webkit_0, ElementsAre("*", "webkit", "org"));
+ std::vector<std::string> hostname_tokens_webkit_1 =
+ ssl_errors::Tokenize(dns_names_webkit[1]);
+ ASSERT_THAT(hostname_tokens_webkit_1, ElementsAre("webkit", "org"));
+ std::vector<std::vector<std::string>> dns_name_tokens_webkit;
+ dns_name_tokens_webkit.push_back(hostname_tokens_webkit_0);
+ dns_name_tokens_webkit.push_back(hostname_tokens_webkit_1);
+ ASSERT_EQ(2u, dns_name_tokens_webkit.size());
GURL origin("https://a.b.webkit.org");
std::string www_host;
std::vector<std::string> host_name_tokens = base::SplitString(
diff --git a/chromium/components/ssl_errors/error_info.cc b/chromium/components/ssl_errors/error_info.cc
index 7ef291ebe4b..ab7afccb05c 100644
--- a/chromium/components/ssl_errors/error_info.cc
+++ b/chromium/components/ssl_errors/error_info.cc
@@ -32,22 +32,30 @@ ErrorInfo ErrorInfo::CreateError(ErrorType error_type,
base::string16 details, short_description;
switch (error_type) {
case CERT_COMMON_NAME_INVALID: {
- // If the certificate contains multiple DNS names, we choose the most
- // representative one -- either the DNS name that's also in the subject
- // field, or the first one. If this heuristic turns out to be
- // inadequate, we can consider choosing the DNS name that is the
- // "closest match" to the host name in the request URL, or listing all
- // the DNS names with an HTML <ul>.
std::vector<std::string> dns_names;
- cert->GetDNSNames(&dns_names);
- DCHECK(!dns_names.empty());
+ cert->GetSubjectAltName(&dns_names, nullptr);
+
size_t i = 0;
- for (; i < dns_names.size(); ++i) {
- if (dns_names[i] == cert->subject().common_name)
- break;
+ if (dns_names.empty()) {
+ // The certificate had no DNS names, display an explanatory string.
+ // TODO(elawrence): Change the error messsage instead of just the
+ // placeholder string; see https://crbug.com/708268
+ dns_names.push_back("[missing_subjectAltName]");
+ } else {
+ // If the certificate contains multiple DNS names, we choose the most
+ // representative one -- either the DNS name that's also in the subject
+ // field, or the first one. If this heuristic turns out to be
+ // inadequate, we can consider choosing the DNS name that is the
+ // "closest match" to the host name in the request URL, or listing all
+ // the DNS names with an HTML <ul>.
+ for (; i < dns_names.size(); ++i) {
+ if (dns_names[i] == cert->subject().common_name)
+ break;
+ }
+ if (i == dns_names.size())
+ i = 0;
}
- if (i == dns_names.size())
- i = 0;
+
details = l10n_util::GetStringFUTF16(
IDS_CERT_ERROR_COMMON_NAME_INVALID_DETAILS,
UTF8ToUTF16(request_url.host()),
diff --git a/chromium/components/strings/components_strings_es.xtb b/chromium/components/strings/components_strings_es.xtb
index 2096a445d92..262ea2fa385 100644
--- a/chromium/components/strings/components_strings_es.xtb
+++ b/chromium/components/strings/components_strings_es.xtb
@@ -89,7 +89,7 @@
<translation id="1787142507584202372">Las pestañas abiertas aparecen aquí</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1797835274315207060">Selecciona una dirección de envío para consultar los métodos de envío y los requisitos.</translation>
-<translation id="1803678881841855883">La función de navegación segura de Google <ph name="BEGIN_LINK" />detectó software malicioso<ph name="END_LINK" /> recientemente en <ph name="SITE" />. En ocasiones, los sitios web que suelen ser seguros contienen software malicioso. Este contenido procede de <ph name="SUBRESOURCE_HOST" />, un conocido distribuidor de este tipo de software. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="1803678881841855883">La función de Navegación Segura de Google <ph name="BEGIN_LINK" />detectó software malicioso<ph name="END_LINK" /> recientemente en <ph name="SITE" />. En ocasiones, los sitios web que suelen ser seguros contienen software malicioso. Este contenido procede de <ph name="SUBRESOURCE_HOST" />, un conocido distribuidor de este tipo de software. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="1806541873155184440">Añadida el <ph name="ADDED_TO_AUTOFILL_MONTH" /></translation>
<translation id="1821930232296380041">Parámetros de solicitud o solicitud no válidos</translation>
<translation id="1826516787628120939">Comprobando</translation>
@@ -157,7 +157,7 @@
<translation id="2386255080630008482">Se ha revocado el certificado de servidor.</translation>
<translation id="2392959068659972793">Mostrar políticas sin valores establecidos</translation>
<translation id="2396249848217231973">&amp;Deshacer eliminación</translation>
-<translation id="2460160116472764928">La función de navegación segura de Google <ph name="BEGIN_LINK" />detectó software malicioso<ph name="END_LINK" /> recientemente en <ph name="SITE" />. En ocasiones, los sitios web que suelen ser seguros contienen software malicioso. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="2460160116472764928">La función de Navegación Segura de Google <ph name="BEGIN_LINK" />detectó software malicioso<ph name="END_LINK" /> recientemente en <ph name="SITE" />. En ocasiones, los sitios web que suelen ser seguros contienen software malicioso. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2463739503403862330">Rellenar</translation>
<translation id="2467694685043708798"><ph name="BEGIN_LINK" />Ejecutar Diagnósticos de red<ph name="END_LINK" /></translation>
<translation id="2479410451996844060">La URL de búsqueda no es válida.</translation>
@@ -369,7 +369,7 @@
<translation id="4269787794583293679">(Ningún nombre de usuario)</translation>
<translation id="4275830172053184480">Reiniciar tu dispositivo</translation>
<translation id="4280429058323657511">Vcto. <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4295944351946828969">La función de navegación segura de Google <ph name="BEGIN_LINK" />encontró programas dañinos<ph name="END_LINK" /> recientemente en <ph name="SITE" />. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="4295944351946828969">La función de Navegación Segura de Google <ph name="BEGIN_LINK" />encontró programas dañinos<ph name="END_LINK" /> recientemente en <ph name="SITE" />. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="4300246636397505754">Sugerencias de padres</translation>
<translation id="4304224509867189079">Iniciar sesión</translation>
<translation id="432290197980158659">El servidor ha mostrado un certificado que no coincide con lo que se esperaba. Algunos sitios web tienen un alto nivel de seguridad para garantizar tu protección y esperan ciertas características de los certificados. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -745,7 +745,7 @@
<translation id="800218591365569300">Prueba a cerrar otros programas o pestañas para liberar memoria.</translation>
<translation id="8012647001091218357">No hemos podido contactar con tus padres. Vuelve a intentarlo.</translation>
<translation id="8025119109950072390">Es posible que los atacantes que se encuentren en este sitio web intenten engañarte para que realices una acción peligrosa, como instalar software o revelar tu información personal (por ejemplo, contraseñas, números de teléfono o tarjetas de crédito).</translation>
-<translation id="803030522067524905">La función de navegación segura de Google detectó phishing recientemente en <ph name="SITE" />. Los sitios web de phishing imitan el aspecto de otros sitios web para engañarte. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="803030522067524905">La función de Navegación Segura de Google detectó phishing recientemente en <ph name="SITE" />. Los sitios web de phishing imitan el aspecto de otros sitios web para engañarte. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="8034522405403831421">Esta página está escrita en <ph name="SOURCE_LANGUAGE" />. ¿Quieres traducirla al <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8041089156583427627">Enviar</translation>
<translation id="8088680233425245692">Se ha producido un error al ver el artículo.</translation>
diff --git a/chromium/components/url_formatter/url_formatter.cc b/chromium/components/url_formatter/url_formatter.cc
index a93bf1154c3..3d5740fd377 100644
--- a/chromium/components/url_formatter/url_formatter.cc
+++ b/chromium/components/url_formatter/url_formatter.cc
@@ -15,6 +15,7 @@
#include "base/strings/utf_offset_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_local_storage.h"
+#include "third_party/icu/source/common/unicode/schriter.h"
#include "third_party/icu/source/common/unicode/uidna.h"
#include "third_party/icu/source/common/unicode/uniset.h"
#include "third_party/icu/source/common/unicode/uscript.h"
@@ -33,6 +34,7 @@ base::string16 IDNToUnicodeWithAdjustments(
base::OffsetAdjuster::Adjustments* adjustments);
bool IDNToUnicodeOneComponent(const base::char16* comp,
size_t comp_len,
+ bool is_tld_ascii,
base::string16* out);
class AppendComponentTransform {
@@ -200,6 +202,13 @@ base::string16 IDNToUnicodeWithAdjustments(
input16.reserve(host.length());
input16.insert(input16.end(), host.begin(), host.end());
+ bool is_tld_ascii = true;
+ size_t last_dot = host.rfind('.');
+ if (last_dot != base::StringPiece::npos &&
+ host.substr(last_dot).starts_with(".xn--")) {
+ is_tld_ascii = false;
+ }
+
// Do each component of the host separately, since we enforce script matching
// on a per-component basis.
base::string16 out16;
@@ -217,7 +226,7 @@ base::string16 IDNToUnicodeWithAdjustments(
// Add the substring that we just found.
converted_idn =
IDNToUnicodeOneComponent(input16.data() + component_start,
- component_length, &out16);
+ component_length, is_tld_ascii, &out16);
}
size_t new_component_length = out16.length() - new_component_start;
@@ -241,17 +250,22 @@ class IDNSpoofChecker {
public:
IDNSpoofChecker();
- // Returns true if |label| is safe to display as Unicode. In the event of
- // library failure, all IDN inputs will be treated as unsafe.
- bool Check(base::StringPiece16 label);
+ // Returns true if |label| is safe to display as Unicode. When the TLD is
+ // ASCII, check if a label is entirely made of Cyrillic letters that look like
+ // Latin letters. In the event of library failure, all IDN inputs will be
+ // treated as unsafe.
+ bool Check(base::StringPiece16 label, bool is_tld_ascii);
private:
void SetAllowedUnicodeSet(UErrorCode* status);
+ bool IsMadeOfLatinAlikeCyrillic(const icu::UnicodeString& label_string);
USpoofChecker* checker_;
icu::UnicodeSet deviation_characters_;
icu::UnicodeSet non_ascii_latin_letters_;
icu::UnicodeSet kana_letters_exceptions_;
+ icu::UnicodeSet cyrillic_letters_;
+ icu::UnicodeSet cyrillic_letters_latin_alike_;
DISALLOW_COPY_AND_ASSIGN(IDNSpoofChecker);
};
@@ -314,10 +328,20 @@ IDNSpoofChecker::IDNSpoofChecker() {
"[\\u3078-\\u307a\\u30d8-\\u30da\\u30fb\\u30fc]"), status);
kana_letters_exceptions_.freeze();
+ // These Cyrillic letters look like Latin. A domain label entirely made of
+ // these letters is blocked as a simpliified whole-script-spoofable.
+ cyrillic_letters_latin_alike_ =
+ icu::UnicodeSet(icu::UnicodeString("[асԁеһіјӏорԛѕԝхуъЬҽпгѵѡ]"), status);
+ cyrillic_letters_latin_alike_.freeze();
+
+ cyrillic_letters_ =
+ icu::UnicodeSet(UNICODE_STRING_SIMPLE("[[:Cyrl:]]"), status);
+ cyrillic_letters_.freeze();
+
DCHECK(U_SUCCESS(status));
}
-bool IDNSpoofChecker::Check(base::StringPiece16 label) {
+bool IDNSpoofChecker::Check(base::StringPiece16 label, bool is_tld_ascii) {
UErrorCode status = U_ZERO_ERROR;
int32_t result = uspoof_check(checker_, label.data(),
base::checked_cast<int32_t>(label.size()),
@@ -345,17 +369,19 @@ bool IDNSpoofChecker::Check(base::StringPiece16 label) {
return false;
// If there's no script mixing, the input is regarded as safe without any
- // extra check unless it contains Kana letter exceptions. Note that
- // the following combinations of scripts are treated as a 'logical' single
- // script.
+ // extra check unless it contains Kana letter exceptions or it's made entirely
+ // of Cyrillic letters that look like Latin letters. Note that the following
+ // combinations of scripts are treated as a 'logical' single script.
// - Chinese: Han, Bopomofo, Common
// - Japanese: Han, Hiragana, Katakana, Common
// - Korean: Hangul, Han, Common
result &= USPOOF_RESTRICTION_LEVEL_MASK;
- if (result == USPOOF_ASCII ||
- (result == USPOOF_SINGLE_SCRIPT_RESTRICTIVE &&
- kana_letters_exceptions_.containsNone(label_string)))
- return true;
+ if (result == USPOOF_ASCII) return true;
+ if (result == USPOOF_SINGLE_SCRIPT_RESTRICTIVE &&
+ kana_letters_exceptions_.containsNone(label_string)) {
+ // Check Cyrillic confusable only for ASCII TLDs.
+ return !is_tld_ascii || !IsMadeOfLatinAlikeCyrillic(label_string);
+ }
// Additional checks for |label| with multiple scripts, one of which is Latin.
// Disallow non-ASCII Latin letters to mix with a non-Latin script.
@@ -407,6 +433,25 @@ bool IDNSpoofChecker::Check(base::StringPiece16 label) {
return !dangerous_pattern->find();
}
+bool IDNSpoofChecker::IsMadeOfLatinAlikeCyrillic(
+ const icu::UnicodeString& label_string) {
+ // Collect all the Cyrillic letters in |label_string| and see if they're
+ // a subset of |cyrillic_letters_latin_alike_|.
+ // A shortcut of defining cyrillic_letters_latin_alike_ to include [0-9] and
+ // [_-] and checking if the set contains all letters of |label_string|
+ // would work in most cases, but not if a label has non-letters outside
+ // ASCII.
+ icu::UnicodeSet cyrillic_in_label;
+ icu::StringCharacterIterator it(label_string);
+ for (it.setToStart(); it.hasNext();) {
+ const UChar32 c = it.next32PostInc();
+ if (cyrillic_letters_.contains(c))
+ cyrillic_in_label.add(c);
+ }
+ return !cyrillic_in_label.isEmpty() &&
+ cyrillic_letters_latin_alike_.containsAll(cyrillic_in_label);
+}
+
void IDNSpoofChecker::SetAllowedUnicodeSet(UErrorCode* status) {
if (U_FAILURE(*status))
return;
@@ -481,8 +526,8 @@ void IDNSpoofChecker::SetAllowedUnicodeSet(UErrorCode* status) {
// user. Note that this function does not deal with pure ASCII domain labels at
// all even though it's possible to make up look-alike labels with ASCII
// characters alone.
-bool IsIDNComponentSafe(base::StringPiece16 label) {
- return g_idn_spoof_checker.Get().Check(label);
+bool IsIDNComponentSafe(base::StringPiece16 label, bool is_tld_ascii) {
+ return g_idn_spoof_checker.Get().Check(label, is_tld_ascii);
}
// A wrapper to use LazyInstance<>::Leaky with ICU's UIDNA, a C pointer to
@@ -527,6 +572,7 @@ base::LazyInstance<UIDNAWrapper>::Leaky g_uidna = LAZY_INSTANCE_INITIALIZER;
// Returns whether any conversion was performed.
bool IDNToUnicodeOneComponent(const base::char16* comp,
size_t comp_len,
+ bool is_tld_ascii,
base::string16* out) {
DCHECK(out);
if (comp_len == 0)
@@ -558,8 +604,9 @@ bool IDNToUnicodeOneComponent(const base::char16* comp,
// can be safely displayed to the user.
out->resize(original_length + output_length);
if (IsIDNComponentSafe(
- base::StringPiece16(out->data() + original_length,
- base::checked_cast<size_t>(output_length))))
+ base::StringPiece16(out->data() + original_length,
+ base::checked_cast<size_t>(output_length)),
+ is_tld_ascii))
return true;
}
diff --git a/chromium/components/url_formatter/url_formatter_unittest.cc b/chromium/components/url_formatter/url_formatter_unittest.cc
index c0fe9509a6d..5b2646ce09c 100644
--- a/chromium/components/url_formatter/url_formatter_unittest.cc
+++ b/chromium/components/url_formatter/url_formatter_unittest.cc
@@ -32,6 +32,7 @@ struct IDNTestCase {
const bool unicode_allowed;
};
+// TODO(jshin): Replace L"..." with "..." in UTF-8 when it's easier to read.
const IDNTestCase idn_cases[] = {
// No IDN
{"www.google.com", L"www.google.com", true},
@@ -209,6 +210,35 @@ const IDNTestCase idn_cases[] = {
// U+30FB + Latin
{"xn--abc-os4b.jp", L"\x30fb" L"abc.jp", false},
+ // Cyrillic labels made of Latin-look-alike Cyrillic letters.
+ // ѕсоре.com with ѕсоре in Cyrillic
+ {"xn--e1argc3h.com", L"\x0455\x0441\x043e\x0440\x0435.com", false},
+ // ѕсоре123.com with ѕсоре in Cyrillic.
+ {"xn--123-qdd8bmf3n.com",
+ L"\x0455\x0441\x043e\x0440\x0435" L"123.com", false},
+ // ѕсоре-рау.com with ѕсоре and рау in Cyrillic.
+ {"xn----8sbn9akccw8m.com",
+ L"\x0455\x0441\x043e\x0440\x0435-\x0440\x0430\x0443.com", false},
+ // ѕсоре·рау.com with scope and pay in Cyrillic and U+00B7 between them.
+ {"xn--uba29ona9akccw8m.com",
+ L"\x0455\x0441\x043e\x0440\x0435\u00b7\x0440\x0430\x0443.com", false},
+
+ // The same as above three, but in IDN TLD.
+ {"xn--e1argc3h.xn--p1ai",
+ L"\x0455\x0441\x043e\x0440\x0435.\x0440\x0444", true},
+ {"xn--123-qdd8bmf3n.xn--p1ai",
+ L"\x0455\x0441\x043e\x0440\x0435" L"123.\x0440\x0444", true},
+ {"xn--uba29ona9akccw8m.xn--p1ai",
+ L"\x0455\x0441\x043e\x0440\x0435\u00b7\x0440\x0430\x0443.\x0440\x0444",
+ true},
+
+ // ѕсоре-рау.한국 with ѕсоре and рау in Cyrillic.
+ {"xn----8sbn9akccw8m.xn--3e0b707e",
+ L"\x0455\x0441\x043e\x0440\x0435-\x0440\x0430\x0443.\xd55c\xad6d", true},
+
+ // музей (museum in Russian) has characters without a Latin-look-alike.
+ {"xn--e1adhj9a.com", L"\x043c\x0443\x0437\x0435\x0439.com", true},
+
// Mixed digits: the first two will also fail mixed script test
// Latin + ASCII digit + Deva digit
{"xn--asc1deva-j0q.co.in", L"asc1deva\x0967.co.in", false},
diff --git a/chromium/components/user_manager/user_manager_base.cc b/chromium/components/user_manager/user_manager_base.cc
index 054949fff92..5805a9ca35b 100644
--- a/chromium/components/user_manager/user_manager_base.cc
+++ b/chromium/components/user_manager/user_manager_base.cc
@@ -242,6 +242,7 @@ void UserManagerBase::SwitchActiveUser(const AccountId& account_id) {
NotifyActiveUserHashChanged(active_user_->username_hash());
NotifyActiveUserChanged(active_user_);
+ CallUpdateLoginState();
}
void UserManagerBase::SwitchToLastActiveUser() {
@@ -508,17 +509,8 @@ void UserManagerBase::ParseUserList(const base::ListValue& users_list,
bool UserManagerBase::IsCurrentUserOwner() const {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
- base::AutoLock lk(is_current_user_owner_lock_);
- return is_current_user_owner_;
-}
-
-void UserManagerBase::SetCurrentUserIsOwner(bool is_current_user_owner) {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- {
- base::AutoLock lk(is_current_user_owner_lock_);
- is_current_user_owner_ = is_current_user_owner;
- }
- CallUpdateLoginState();
+ return !owner_account_id_.empty() && active_user_ &&
+ active_user_->GetAccountId() == owner_account_id_;
}
bool UserManagerBase::IsCurrentUserNew() const {
@@ -739,6 +731,7 @@ bool UserManagerBase::HasPendingBootstrap(const AccountId& account_id) const {
void UserManagerBase::SetOwnerId(const AccountId& owner_account_id) {
owner_account_id_ = owner_account_id;
+ CallUpdateLoginState();
}
const AccountId& UserManagerBase::GetPendingUserSwitchID() const {
@@ -1028,7 +1021,7 @@ void UserManagerBase::Initialize() {
}
void UserManagerBase::CallUpdateLoginState() {
- UpdateLoginState(active_user_, primary_user_, is_current_user_owner_);
+ UpdateLoginState(active_user_, primary_user_, IsCurrentUserOwner());
}
void UserManagerBase::SetLRUUser(User* user) {
diff --git a/chromium/components/user_manager/user_manager_base.h b/chromium/components/user_manager/user_manager_base.h
index b30015f0ecc..9e9fec63919 100644
--- a/chromium/components/user_manager/user_manager_base.h
+++ b/chromium/components/user_manager/user_manager_base.h
@@ -250,8 +250,6 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager {
// Getters/setters for private members.
- virtual void SetCurrentUserIsOwner(bool is_current_user_owner);
-
virtual bool GetEphemeralUsersEnabled() const;
virtual void SetEphemeralUsersEnabled(bool enabled);
@@ -340,11 +338,6 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager {
// Indicates stage of loading user from prefs.
UserLoadStage user_loading_stage_ = STAGE_NOT_LOADED;
- // Cached flag of whether currently logged-in user is owner or not.
- // May be accessed on different threads, requires locking.
- bool is_current_user_owner_ = false;
- mutable base::Lock is_current_user_owner_lock_;
-
// Cached flag of whether the currently logged-in user existed before this
// login.
bool is_current_user_new_ = false;