1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/login/ui/captive_portal_window_proxy.h"
6
7#include "chrome/browser/chromeos/login/ui/captive_portal_view.h"
8#include "chrome/browser/chromeos/login/ui/proxy_settings_dialog.h"
9#include "chrome/browser/chromeos/profiles/profile_helper.h"
10#include "components/web_modal/popup_manager.h"
11#include "ui/views/widget/widget.h"
12
13namespace {
14
15// The captive portal dialog is system-modal, but uses the web-content-modal
16// dialog manager (odd) and requires this atypical dialog widget initialization.
17views::Widget* CreateWindowAsFramelessChild(views::WidgetDelegate* delegate,
18                                            gfx::NativeView parent) {
19  views::Widget* widget = new views::Widget;
20
21  views::Widget::InitParams params;
22  params.delegate = delegate;
23  params.child = true;
24  params.parent = parent;
25  params.remove_standard_frame = true;
26  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
27
28  widget->Init(params);
29  return widget;
30}
31
32}  // namespace
33
34namespace chromeos {
35
36CaptivePortalWindowProxy::CaptivePortalWindowProxy(
37    Delegate* delegate,
38    content::WebContents* web_contents)
39    : delegate_(delegate),
40      widget_(NULL),
41      web_contents_(web_contents),
42      captive_portal_view_for_testing_(NULL) {
43  DCHECK(GetState() == STATE_IDLE);
44}
45
46CaptivePortalWindowProxy::~CaptivePortalWindowProxy() {
47  if (!widget_)
48    return;
49  DCHECK(GetState() == STATE_DISPLAYED);
50  widget_->RemoveObserver(this);
51  widget_->Close();
52}
53
54void CaptivePortalWindowProxy::ShowIfRedirected() {
55  if (GetState() != STATE_IDLE)
56    return;
57  InitCaptivePortalView();
58  DCHECK(GetState() == STATE_WAITING_FOR_REDIRECTION);
59}
60
61void CaptivePortalWindowProxy::Show() {
62  if (ProxySettingsDialog::IsShown()) {
63    // ProxySettingsDialog is being shown, don't cover it.
64    Close();
65    return;
66  }
67
68  if (GetState() == STATE_DISPLAYED)  // Dialog is already shown, do nothing.
69    return;
70
71  InitCaptivePortalView();
72
73  CaptivePortalView* portal = captive_portal_view_.release();
74  web_modal::PopupManager* popup_manager =
75      web_modal::PopupManager::FromWebContents(web_contents_);
76  if (popup_manager) {
77    widget_ =
78        CreateWindowAsFramelessChild(portal, popup_manager->GetHostView());
79    portal->Init();
80    widget_->AddObserver(this);
81    popup_manager->ShowModalDialog(widget_->GetNativeView(), web_contents_);
82  }
83}
84
85void CaptivePortalWindowProxy::Close() {
86  if (GetState() == STATE_DISPLAYED)
87    widget_->Close();
88  captive_portal_view_.reset();
89  captive_portal_view_for_testing_ = NULL;
90}
91
92void CaptivePortalWindowProxy::OnRedirected() {
93  if (GetState() == STATE_WAITING_FOR_REDIRECTION)
94    Show();
95  delegate_->OnPortalDetected();
96}
97
98void CaptivePortalWindowProxy::OnOriginalURLLoaded() {
99  Close();
100}
101
102void CaptivePortalWindowProxy::OnWidgetClosing(views::Widget* widget) {
103  DCHECK(GetState() == STATE_DISPLAYED);
104  DCHECK(widget == widget_);
105
106  DetachFromWidget(widget);
107
108  DCHECK(GetState() == STATE_IDLE);
109}
110
111void CaptivePortalWindowProxy::OnWidgetDestroying(views::Widget* widget) {
112  DetachFromWidget(widget);
113}
114
115void CaptivePortalWindowProxy::OnWidgetDestroyed(views::Widget* widget) {
116  DetachFromWidget(widget);
117}
118
119void CaptivePortalWindowProxy::InitCaptivePortalView() {
120  DCHECK(GetState() == STATE_IDLE ||
121         GetState() == STATE_WAITING_FOR_REDIRECTION);
122  if (!captive_portal_view_.get()) {
123    captive_portal_view_.reset(
124        new CaptivePortalView(ProfileHelper::GetSigninProfile(), this));
125    captive_portal_view_for_testing_ = captive_portal_view_.get();
126  }
127  captive_portal_view_->StartLoad();
128}
129
130CaptivePortalWindowProxy::State CaptivePortalWindowProxy::GetState() const {
131  if (widget_ == NULL) {
132    if (captive_portal_view_.get() == NULL)
133      return STATE_IDLE;
134    else
135      return STATE_WAITING_FOR_REDIRECTION;
136  } else {
137    if (captive_portal_view_.get() == NULL)
138      return STATE_DISPLAYED;
139    else
140      NOTREACHED();
141  }
142  return STATE_UNKNOWN;
143}
144
145void CaptivePortalWindowProxy::DetachFromWidget(views::Widget* widget) {
146  if (!widget_ || widget_ != widget)
147    return;
148  widget_->RemoveObserver(this);
149  widget_ = NULL;
150}
151
152}  // namespace chromeos
153