Commit c153e317 authored by David Black's avatar David Black Committed by Commit Bot

Fix crash due to destruction order.

We have dependencies on TabletModeController and need to be destroyed
before it.

Previously we assumed that the view hierarchy would be destroyed before
our Assistant controllers. This will not actually be the case since I
am moving our reset above destruction of the view hierarchy.

As such, we now destroy our view hierarchy at the beginning of our
controller destruction sequence.

Also fixes some outdated comments.

Bug: b:112781572
Change-Id: Iecdce642790c0c8278d489734ea735370e98912c
Reviewed-on: https://chromium-review.googlesource.com/1180656
Commit-Queue: David Black <dmblack@google.com>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584831}
parent c3878671
...@@ -252,11 +252,6 @@ void AssistantController::OpenUrl(const GURL& url) { ...@@ -252,11 +252,6 @@ void AssistantController::OpenUrl(const GURL& url) {
NotifyUrlOpened(url); NotifyUrlOpened(url);
} }
void AssistantController::ShutDown() {
// Controllers can be added to handle this event as needed.
assistant_ui_controller_->ShutDown();
}
void AssistantController::NotifyConstructed() { void AssistantController::NotifyConstructed() {
for (AssistantControllerObserver& observer : observers_) for (AssistantControllerObserver& observer : observers_)
observer.OnAssistantControllerConstructed(); observer.OnAssistantControllerConstructed();
......
...@@ -123,9 +123,6 @@ class ASH_EXPORT AssistantController ...@@ -123,9 +123,6 @@ class ASH_EXPORT AssistantController
// TODO(dmblack): Support opening specific URLs in the Assistant container. // TODO(dmblack): Support opening specific URLs in the Assistant container.
void OpenUrl(const GURL& url); void OpenUrl(const GURL& url);
// Called before dtor to deregister services and avoid life cycle issues.
void ShutDown();
AssistantCacheController* cache_controller() { AssistantCacheController* cache_controller() {
DCHECK(assistant_cache_controller_); DCHECK(assistant_cache_controller_);
return assistant_cache_controller_.get(); return assistant_cache_controller_.get();
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "ash/system/toast/toast_data.h" #include "ash/system/toast/toast_data.h"
#include "ash/system/toast/toast_manager.h" #include "ash/system/toast/toast_manager.h"
#include "ash/voice_interaction/voice_interaction_controller.h" #include "ash/voice_interaction/voice_interaction_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/optional.h" #include "base/optional.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h" #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
...@@ -45,16 +44,12 @@ AssistantUiController::AssistantUiController( ...@@ -45,16 +44,12 @@ AssistantUiController::AssistantUiController(
AddModelObserver(this); AddModelObserver(this);
assistant_controller_->AddObserver(this); assistant_controller_->AddObserver(this);
Shell::Get()->highlighter_controller()->AddObserver(this); Shell::Get()->highlighter_controller()->AddObserver(this);
Shell::Get()->tablet_mode_controller()->AddObserver(this);
} }
AssistantUiController::~AssistantUiController() { AssistantUiController::~AssistantUiController() {
Shell::Get()->highlighter_controller()->RemoveObserver(this); Shell::Get()->highlighter_controller()->RemoveObserver(this);
assistant_controller_->RemoveObserver(this); assistant_controller_->RemoveObserver(this);
RemoveModelObserver(this); RemoveModelObserver(this);
if (container_view_)
container_view_->GetWidget()->RemoveObserver(this);
} }
void AssistantUiController::SetAssistant( void AssistantUiController::SetAssistant(
...@@ -93,16 +88,6 @@ void AssistantUiController::OnWidgetDestroying(views::Widget* widget) { ...@@ -93,16 +88,6 @@ void AssistantUiController::OnWidgetDestroying(views::Widget* widget) {
container_view_ = nullptr; container_view_ = nullptr;
} }
void AssistantUiController::OnAssistantControllerConstructed() {
assistant_controller_->interaction_controller()->AddModelObserver(this);
assistant_controller_->screen_context_controller()->AddModelObserver(this);
}
void AssistantUiController::OnAssistantControllerDestroying() {
assistant_controller_->screen_context_controller()->RemoveModelObserver(this);
assistant_controller_->interaction_controller()->RemoveModelObserver(this);
}
void AssistantUiController::OnInputModalityChanged( void AssistantUiController::OnInputModalityChanged(
InputModality input_modality) { InputModality input_modality) {
UpdateUiMode(); UpdateUiMode();
...@@ -188,6 +173,22 @@ void AssistantUiController::OnHighlighterEnabledChanged( ...@@ -188,6 +173,22 @@ void AssistantUiController::OnHighlighterEnabledChanged(
} }
} }
void AssistantUiController::OnAssistantControllerConstructed() {
assistant_controller_->interaction_controller()->AddModelObserver(this);
assistant_controller_->screen_context_controller()->AddModelObserver(this);
}
void AssistantUiController::OnAssistantControllerDestroying() {
assistant_controller_->screen_context_controller()->RemoveModelObserver(this);
assistant_controller_->interaction_controller()->RemoveModelObserver(this);
if (container_view_) {
// Our view hierarchy should not outlive our controllers.
container_view_->GetWidget()->CloseNow();
DCHECK_EQ(nullptr, container_view_);
}
}
void AssistantUiController::OnDeepLinkReceived( void AssistantUiController::OnDeepLinkReceived(
assistant::util::DeepLinkType type, assistant::util::DeepLinkType type,
const std::map<std::string, std::string>& params) { const std::map<std::string, std::string>& params) {
...@@ -265,20 +266,6 @@ void AssistantUiController::ToggleUi(AssistantSource source) { ...@@ -265,20 +266,6 @@ void AssistantUiController::ToggleUi(AssistantSource source) {
ShowUi(source); ShowUi(source);
} }
void AssistantUiController::OnTabletModeStarted() {
if (container_view_)
container_view_->OnTabletModeChanged();
}
void AssistantUiController::OnTabletModeEnded() {
if (container_view_)
container_view_->OnTabletModeChanged();
}
void AssistantUiController::ShutDown() {
Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
}
void AssistantUiController::UpdateUiMode( void AssistantUiController::UpdateUiMode(
base::Optional<AssistantUiMode> ui_mode) { base::Optional<AssistantUiMode> ui_mode) {
// If a UI mode is provided, we will use it in lieu of updating UI mode on the // If a UI mode is provided, we will use it in lieu of updating UI mode on the
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "ash/assistant/ui/caption_bar.h" #include "ash/assistant/ui/caption_bar.h"
#include "ash/assistant/ui/dialog_plate/dialog_plate.h" #include "ash/assistant/ui/dialog_plate/dialog_plate.h"
#include "ash/highlighter/highlighter_controller.h" #include "ash/highlighter/highlighter_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_observer.h"
#include "base/macros.h" #include "base/macros.h"
#include "ui/views/widget/widget_observer.h" #include "ui/views/widget/widget_observer.h"
...@@ -45,8 +44,7 @@ class ASH_EXPORT AssistantUiController ...@@ -45,8 +44,7 @@ class ASH_EXPORT AssistantUiController
public AssistantMiniViewDelegate, public AssistantMiniViewDelegate,
public CaptionBarDelegate, public CaptionBarDelegate,
public DialogPlateObserver, public DialogPlateObserver,
public HighlighterController::Observer, public HighlighterController::Observer {
public TabletModeObserver {
public: public:
explicit AssistantUiController(AssistantController* assistant_controller); explicit AssistantUiController(AssistantController* assistant_controller);
~AssistantUiController() override; ~AssistantUiController() override;
...@@ -102,13 +100,6 @@ class ASH_EXPORT AssistantUiController ...@@ -102,13 +100,6 @@ class ASH_EXPORT AssistantUiController
void HideUi(AssistantSource source); void HideUi(AssistantSource source);
void ToggleUi(AssistantSource source); void ToggleUi(AssistantSource source);
// TabletModeObserver:
void OnTabletModeStarted() override;
void OnTabletModeEnded() override;
// Called before dtor to clean up service dependencies.
void ShutDown();
AssistantContainerView* GetViewForTest(); AssistantContainerView* GetViewForTest();
private: private:
......
...@@ -32,12 +32,11 @@ namespace ash { ...@@ -32,12 +32,11 @@ namespace ash {
namespace { namespace {
constexpr int kClamshellMarginBottomDip = 8; // Margin in clamshell mode.
constexpr int kTabletMarginTopDip = 24; // Margin in tablet mode.
// Appearance. // Appearance.
constexpr SkColor kBackgroundColor = SK_ColorWHITE; constexpr SkColor kBackgroundColor = SK_ColorWHITE;
constexpr int kCornerRadiusDip = 20; constexpr int kCornerRadiusDip = 20;
constexpr int kClamshellMarginBottomDip = 8; // Margin in clamshell mode.
constexpr int kTabletMarginTopDip = 24; // Margin in tablet mode.
// Animation. // Animation.
constexpr int kResizeAnimationDurationMs = 250; constexpr int kResizeAnimationDurationMs = 250;
...@@ -163,9 +162,11 @@ AssistantContainerView::AssistantContainerView( ...@@ -163,9 +162,11 @@ AssistantContainerView::AssistantContainerView(
// AssistantContainerView belongs so is guaranteed to outlive it. // AssistantContainerView belongs so is guaranteed to outlive it.
assistant_controller_->ui_controller()->AddModelObserver(this); assistant_controller_->ui_controller()->AddModelObserver(this);
display::Screen::GetScreen()->AddObserver(this); display::Screen::GetScreen()->AddObserver(this);
Shell::Get()->tablet_mode_controller()->AddObserver(this);
} }
AssistantContainerView::~AssistantContainerView() { AssistantContainerView::~AssistantContainerView() {
Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
display::Screen::GetScreen()->RemoveObserver(this); display::Screen::GetScreen()->RemoveObserver(this);
assistant_controller_->ui_controller()->RemoveModelObserver(this); assistant_controller_->ui_controller()->RemoveModelObserver(this);
} }
...@@ -281,9 +282,12 @@ void AssistantContainerView::RequestFocus() { ...@@ -281,9 +282,12 @@ void AssistantContainerView::RequestFocus() {
} }
void AssistantContainerView::SetAnchor(aura::Window* root_window) { void AssistantContainerView::SetAnchor(aura::Window* root_window) {
// If |root_window| is not specified, we'll use the root window corresponding
// to where new windows will be opened.
if (!root_window) if (!root_window)
root_window = Shell::Get()->GetRootWindowForNewWindows(); root_window = Shell::Get()->GetRootWindowForNewWindows();
// Anchor to the display matching where new windows will be opened.
// Anchor to the display matching |root_window|.
display::Display display = display::Screen::GetScreen()->GetDisplayMatching( display::Display display = display::Screen::GetScreen()->GetDisplayMatching(
root_window->GetBoundsInScreen()); root_window->GetBoundsInScreen());
...@@ -291,7 +295,8 @@ void AssistantContainerView::SetAnchor(aura::Window* root_window) { ...@@ -291,7 +295,8 @@ void AssistantContainerView::SetAnchor(aura::Window* root_window) {
->tablet_mode_controller() ->tablet_mode_controller()
->IsTabletModeWindowManagerEnabled(); ->IsTabletModeWindowManagerEnabled();
// Anchor to the bottom center of the work area. // Align to the horizontal center of the work area. We are top aligned in
// tablet mode, bottom aligned in clamshell.
gfx::Rect work_area = display.work_area(); gfx::Rect work_area = display.work_area();
gfx::Rect anchor = gfx::Rect anchor =
gfx::Rect(work_area.x(), gfx::Rect(work_area.x(),
...@@ -335,8 +340,9 @@ void AssistantContainerView::AnimationProgressed( ...@@ -335,8 +340,9 @@ void AssistantContainerView::AnimationProgressed(
// Retrieve current bounds. // Retrieve current bounds.
gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen(); gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen();
// Our view is horizontally centered and bottom aligned. As such, we should // Our view is horizontally centered. As such, we should retain the same
// retain the same |bottom| and |center_x| position after resizing. // |center_x| position after resizing. In clamshell mode, we are bottom
// aligned so we cache |bottom| position here as well.
const int bottom = bounds.bottom(); const int bottom = bounds.bottom();
const int center_x = bounds.CenterPoint().x(); const int center_x = bounds.CenterPoint().x();
...@@ -350,21 +356,17 @@ void AssistantContainerView::AnimationProgressed( ...@@ -350,21 +356,17 @@ void AssistantContainerView::AnimationProgressed(
if (!Shell::Get() if (!Shell::Get()
->tablet_mode_controller() ->tablet_mode_controller()
->IsTabletModeWindowManagerEnabled()) { ->IsTabletModeWindowManagerEnabled()) {
// Maintain our original |bottom| positions in clamshell mode. In tablet // Maintain our original |bottom| position in clamshell mode. In tablet
// mode, they should grow downwards, which is the default behavior. // mode we grow downwards which is the default behavior.
bounds.set_y(bottom - bounds.height()); bounds.set_y(bottom - bounds.height());
} }
// Maintain |center_x| position. // Maintain |center_x| position.
bounds.set_x(center_x - (bounds.width() / 2)); bounds.set_x(center_x - (bounds.width() / 2));
GetWidget()->SetBounds(bounds); GetWidget()->SetBounds(bounds);
} }
void AssistantContainerView::OnTabletModeChanged() {
DCHECK(GetWidget());
SetAnchor(GetWidget()->GetNativeWindow()->GetRootWindow());
}
void AssistantContainerView::OnDisplayMetricsChanged( void AssistantContainerView::OnDisplayMetricsChanged(
const display::Display& display, const display::Display& display,
uint32_t changed_metrics) { uint32_t changed_metrics) {
...@@ -373,4 +375,14 @@ void AssistantContainerView::OnDisplayMetricsChanged( ...@@ -373,4 +375,14 @@ void AssistantContainerView::OnDisplayMetricsChanged(
SetAnchor(root_window); SetAnchor(root_window);
} }
void AssistantContainerView::OnTabletModeStarted() {
DCHECK(GetWidget());
SetAnchor(GetWidget()->GetNativeWindow()->GetRootWindow());
}
void AssistantContainerView::OnTabletModeEnded() {
DCHECK(GetWidget());
SetAnchor(GetWidget()->GetNativeWindow()->GetRootWindow());
}
} // namespace ash } // namespace ash
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define ASH_ASSISTANT_UI_ASSISTANT_CONTAINER_VIEW_H_ #define ASH_ASSISTANT_UI_ASSISTANT_CONTAINER_VIEW_H_
#include "ash/assistant/model/assistant_ui_model_observer.h" #include "ash/assistant/model/assistant_ui_model_observer.h"
#include "ash/wm/tablet_mode/tablet_mode_observer.h"
#include "base/macros.h" #include "base/macros.h"
#include "ui/display/display_observer.h" #include "ui/display/display_observer.h"
#include "ui/gfx/animation/animation_delegate.h" #include "ui/gfx/animation/animation_delegate.h"
...@@ -29,7 +30,8 @@ class AssistantWebView; ...@@ -29,7 +30,8 @@ class AssistantWebView;
class AssistantContainerView : public views::BubbleDialogDelegateView, class AssistantContainerView : public views::BubbleDialogDelegateView,
public AssistantUiModelObserver, public AssistantUiModelObserver,
public display::DisplayObserver, public display::DisplayObserver,
public gfx::AnimationDelegate { public gfx::AnimationDelegate,
public TabletModeObserver {
public: public:
explicit AssistantContainerView(AssistantController* assistant_controller); explicit AssistantContainerView(AssistantController* assistant_controller);
~AssistantContainerView() override; ~AssistantContainerView() override;
...@@ -57,14 +59,12 @@ class AssistantContainerView : public views::BubbleDialogDelegateView, ...@@ -57,14 +59,12 @@ class AssistantContainerView : public views::BubbleDialogDelegateView,
void AnimationProgressed(const gfx::Animation* animation) override; void AnimationProgressed(const gfx::Animation* animation) override;
// display::DisplayObserver: // display::DisplayObserver:
void OnWillProcessDisplayChanges() override {}
void OnDidProcessDisplayChanges() override {}
void OnDisplayAdded(const display::Display& new_display) override {}
void OnDisplayRemoved(const display::Display& old_display) override {}
void OnDisplayMetricsChanged(const display::Display& display, void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override; uint32_t changed_metrics) override;
void OnTabletModeChanged(); // TabletModeObserver:
void OnTabletModeStarted() override;
void OnTabletModeEnded() override;
private: private:
// Sets anchor rect to |root_window|. If it's null, // Sets anchor rect to |root_window|. If it's null,
......
...@@ -792,10 +792,11 @@ Shell::~Shell() { ...@@ -792,10 +792,11 @@ Shell::~Shell() {
// the former may use the latter before destruction. // the former may use the latter before destruction.
app_list_controller_.reset(); app_list_controller_.reset();
// Shutdown |assistant_controller_| to properly remove observer on // Destroy |assistant_controller_| earlier than |tablet_mode_controller_| so
// |tablet_mode_controller_|. // that the former will destroy the Assistant view hierarchy which has a
// dependency on the latter.
if (chromeos::switches::IsAssistantEnabled()) if (chromeos::switches::IsAssistantEnabled())
assistant_controller_->ShutDown(); assistant_controller_.reset();
// Destroy tablet mode controller early on since it has some observers which // Destroy tablet mode controller early on since it has some observers which
// need to be removed. // need to be removed.
...@@ -860,7 +861,6 @@ Shell::~Shell() { ...@@ -860,7 +861,6 @@ Shell::~Shell() {
// These need a valid Shell instance to clean up properly, so explicitly // These need a valid Shell instance to clean up properly, so explicitly
// delete them before invalidating the instance. // delete them before invalidating the instance.
// Alphabetical. TODO(oshima): sort. // Alphabetical. TODO(oshima): sort.
assistant_controller_.reset();
magnification_controller_.reset(); magnification_controller_.reset();
tooltip_controller_.reset(); tooltip_controller_.reset();
event_client_.reset(); event_client_.reset();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment