Home | History | Annotate | Download | only in chromeos
      1 // Copyright (c) 2012 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/enrollment_dialog_view.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "chrome/browser/extensions/extension_host.h"
     10 #include "chrome/browser/profiles/profile.h"
     11 #include "chrome/browser/profiles/profile_manager.h"
     12 #include "chrome/browser/ui/browser_finder.h"
     13 #include "chrome/browser/ui/browser_navigator.h"
     14 #include "chromeos/network/network_event_log.h"
     15 #include "chromeos/network/network_state.h"
     16 #include "chromeos/network/network_state_handler.h"
     17 #include "content/public/common/page_transition_types.h"
     18 #include "extensions/common/constants.h"
     19 #include "grit/generated_resources.h"
     20 #include "ui/base/l10n/l10n_util.h"
     21 #include "ui/base/resource/resource_bundle.h"
     22 #include "ui/views/controls/label.h"
     23 #include "ui/views/layout/grid_layout.h"
     24 #include "ui/views/layout/layout_constants.h"
     25 #include "ui/views/widget/widget.h"
     26 #include "ui/views/window/dialog_delegate.h"
     27 
     28 namespace chromeos {
     29 
     30 namespace {
     31 
     32 // Default width/height of the dialog.
     33 const int kDefaultWidth = 350;
     34 const int kDefaultHeight = 100;
     35 
     36 ////////////////////////////////////////////////////////////////////////////////
     37 // Dialog for certificate enrollment. This displays the content from the
     38 // certificate enrollment URI.
     39 class EnrollmentDialogView : public views::DialogDelegateView {
     40  public:
     41   virtual ~EnrollmentDialogView();
     42 
     43   static void ShowDialog(gfx::NativeWindow owning_window,
     44                          const std::string& network_name,
     45                          Profile* profile,
     46                          const GURL& target_uri,
     47                          const base::Closure& connect);
     48 
     49   // views::DialogDelegateView overrides
     50   virtual int GetDialogButtons() const OVERRIDE;
     51   virtual bool Accept() OVERRIDE;
     52   virtual void OnClosed() OVERRIDE;
     53   virtual base::string16 GetDialogButtonLabel(
     54       ui::DialogButton button) const OVERRIDE;
     55 
     56   // views::WidgetDelegate overrides
     57   virtual ui::ModalType GetModalType() const OVERRIDE;
     58   virtual base::string16 GetWindowTitle() const OVERRIDE;
     59 
     60   // views::View overrides
     61   virtual gfx::Size GetPreferredSize() OVERRIDE;
     62 
     63  private:
     64   EnrollmentDialogView(const std::string& network_name,
     65                        Profile* profile,
     66                        const GURL& target_uri,
     67                        const base::Closure& connect);
     68   void InitDialog();
     69 
     70   bool accepted_;
     71   std::string network_name_;
     72   Profile* profile_;
     73   GURL target_uri_;
     74   base::Closure connect_;
     75   bool added_cert_;
     76 };
     77 
     78 ////////////////////////////////////////////////////////////////////////////////
     79 // EnrollmentDialogView implementation.
     80 
     81 EnrollmentDialogView::EnrollmentDialogView(const std::string& network_name,
     82                                            Profile* profile,
     83                                            const GURL& target_uri,
     84                                            const base::Closure& connect)
     85     : accepted_(false),
     86       network_name_(network_name),
     87       profile_(profile),
     88       target_uri_(target_uri),
     89       connect_(connect),
     90       added_cert_(false) {
     91 }
     92 
     93 EnrollmentDialogView::~EnrollmentDialogView() {
     94 }
     95 
     96 // static
     97 void EnrollmentDialogView::ShowDialog(gfx::NativeWindow owning_window,
     98                                       const std::string& network_name,
     99                                       Profile* profile,
    100                                       const GURL& target_uri,
    101                                       const base::Closure& connect) {
    102   EnrollmentDialogView* dialog_view =
    103       new EnrollmentDialogView(network_name, profile, target_uri, connect);
    104   views::DialogDelegate::CreateDialogWidget(dialog_view, NULL, owning_window);
    105   dialog_view->InitDialog();
    106   views::Widget* widget = dialog_view->GetWidget();
    107   DCHECK(widget);
    108   widget->Show();
    109 }
    110 
    111 int EnrollmentDialogView::GetDialogButtons() const {
    112   return ui::DIALOG_BUTTON_CANCEL | ui::DIALOG_BUTTON_OK;
    113 }
    114 
    115 bool EnrollmentDialogView::Accept() {
    116   accepted_ = true;
    117   return true;
    118 }
    119 
    120 void EnrollmentDialogView::OnClosed() {
    121   if (!accepted_)
    122     return;
    123   chrome::NavigateParams params(profile_,
    124                                 GURL(target_uri_),
    125                                 content::PAGE_TRANSITION_LINK);
    126   params.disposition = NEW_FOREGROUND_TAB;
    127   params.window_action = chrome::NavigateParams::SHOW_WINDOW;
    128   chrome::Navigate(&params);
    129 }
    130 
    131 base::string16 EnrollmentDialogView::GetDialogButtonLabel(
    132     ui::DialogButton button) const {
    133   if (button == ui::DIALOG_BUTTON_OK)
    134     return l10n_util::GetStringUTF16(IDS_NETWORK_ENROLLMENT_HANDLER_BUTTON);
    135   return views::DialogDelegateView::GetDialogButtonLabel(button);
    136 }
    137 
    138 ui::ModalType EnrollmentDialogView::GetModalType() const {
    139   return ui::MODAL_TYPE_SYSTEM;
    140 }
    141 
    142 base::string16 EnrollmentDialogView::GetWindowTitle() const {
    143   return l10n_util::GetStringUTF16(IDS_NETWORK_ENROLLMENT_HANDLER_TITLE);
    144 }
    145 
    146 gfx::Size EnrollmentDialogView::GetPreferredSize() {
    147   return gfx::Size(kDefaultWidth, kDefaultHeight);
    148 }
    149 
    150 void EnrollmentDialogView::InitDialog() {
    151   added_cert_ = false;
    152   // Create the views and layout manager and set them up.
    153   views::Label* label = new views::Label(
    154       l10n_util::GetStringFUTF16(IDS_NETWORK_ENROLLMENT_HANDLER_INSTRUCTIONS,
    155                                  UTF8ToUTF16(network_name_)));
    156   label->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
    157       ui::ResourceBundle::BaseFont));
    158   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    159   label->SetMultiLine(true);
    160   label->SetAllowCharacterBreak(true);
    161 
    162   views::GridLayout* grid_layout = views::GridLayout::CreatePanel(this);
    163   SetLayoutManager(grid_layout);
    164 
    165   views::ColumnSet* columns = grid_layout->AddColumnSet(0);
    166   columns->AddColumn(views::GridLayout::FILL,  // Horizontal resize.
    167                      views::GridLayout::FILL,  // Vertical resize.
    168                      1,   // Resize weight.
    169                      views::GridLayout::USE_PREF,  // Size type.
    170                      0,   // Ignored for USE_PREF.
    171                      0);  // Minimum size.
    172   columns = grid_layout->AddColumnSet(1);
    173   columns->AddPaddingColumn(
    174       0, views::kUnrelatedControlHorizontalSpacing);
    175   columns->AddColumn(views::GridLayout::LEADING,  // Horizontal leading.
    176                      views::GridLayout::FILL,     // Vertical resize.
    177                      1,   // Resize weight.
    178                      views::GridLayout::USE_PREF,  // Size type.
    179                      0,   // Ignored for USE_PREF.
    180                      0);  // Minimum size.
    181 
    182   grid_layout->StartRow(0, 0);
    183   grid_layout->AddView(label);
    184   grid_layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
    185   grid_layout->Layout(this);
    186 }
    187 
    188 ////////////////////////////////////////////////////////////////////////////////
    189 // Handler for certificate enrollment.
    190 
    191 class DialogEnrollmentDelegate {
    192  public:
    193   // |owning_window| is the window that will own the dialog.
    194   DialogEnrollmentDelegate(gfx::NativeWindow owning_window,
    195                            const std::string& network_name,
    196                            Profile* profile);
    197   ~DialogEnrollmentDelegate();
    198 
    199   // EnrollmentDelegate overrides
    200   bool Enroll(const std::vector<std::string>& uri_list,
    201               const base::Closure& connect);
    202 
    203  private:
    204   gfx::NativeWindow owning_window_;
    205   std::string network_name_;
    206   Profile* profile_;
    207 
    208   DISALLOW_COPY_AND_ASSIGN(DialogEnrollmentDelegate);
    209 };
    210 
    211 DialogEnrollmentDelegate::DialogEnrollmentDelegate(
    212     gfx::NativeWindow owning_window,
    213     const std::string& network_name,
    214     Profile* profile) : owning_window_(owning_window),
    215                         network_name_(network_name),
    216                         profile_(profile) {}
    217 
    218 DialogEnrollmentDelegate::~DialogEnrollmentDelegate() {}
    219 
    220 bool DialogEnrollmentDelegate::Enroll(const std::vector<std::string>& uri_list,
    221                                       const base::Closure& post_action) {
    222   if (uri_list.empty()) {
    223     NET_LOG_EVENT("No enrollment URIs", network_name_);
    224     return false;
    225   }
    226 
    227   // Keep the closure for later activation if we notice that
    228   // a certificate has been added.
    229 
    230   // TODO(gspencer): Do something smart with the closure.  At the moment it is
    231   // being ignored because we don't know when the enrollment tab is closed.
    232   // http://crosbug.com/30422
    233   for (std::vector<std::string>::const_iterator iter = uri_list.begin();
    234        iter != uri_list.end(); ++iter) {
    235     GURL uri(*iter);
    236     if (uri.IsStandard() || uri.scheme() == extensions::kExtensionScheme) {
    237       // If this is a "standard" scheme, like http, ftp, etc., then open that in
    238       // the enrollment dialog.
    239       NET_LOG_EVENT("Showing enrollment dialog", network_name_);
    240       EnrollmentDialogView::ShowDialog(owning_window_,
    241                                        network_name_,
    242                                        profile_,
    243                                        uri, post_action);
    244       return true;
    245     }
    246     NET_LOG_DEBUG("Nonstandard URI: " + uri.spec(), network_name_);
    247   }
    248 
    249   // No appropriate scheme was found.
    250   NET_LOG_ERROR("No usable enrollment URI", network_name_);
    251   return false;
    252 }
    253 
    254 void EnrollmentComplete(const std::string& service_path) {
    255   NET_LOG_USER("Enrollment Complete", service_path);
    256 }
    257 
    258 }  // namespace
    259 
    260 ////////////////////////////////////////////////////////////////////////////////
    261 // Factory function.
    262 
    263 namespace enrollment {
    264 
    265 bool CreateDialog(const std::string& service_path,
    266                   gfx::NativeWindow owning_window) {
    267   const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
    268       GetNetworkState(service_path);
    269   if (!network) {
    270     NET_LOG_ERROR("Enrolling Unknown network", service_path);
    271     return false;
    272   }
    273   // We skip certificate patterns for device policy ONC so that an unmanaged
    274   // user can't get to the place where a cert is presented for them
    275   // involuntarily.
    276   if (network->ui_data().onc_source() == onc::ONC_SOURCE_DEVICE_POLICY)
    277     return false;
    278 
    279   const CertificatePattern& certificate_pattern =
    280       network->ui_data().certificate_pattern();
    281   if (certificate_pattern.Empty()) {
    282     NET_LOG_EVENT("No certificate pattern found", service_path);
    283     return false;
    284   }
    285 
    286   NET_LOG_USER("Enrolling", service_path);
    287 
    288   Browser* browser = chrome::FindBrowserWithWindow(owning_window);
    289   Profile* profile = browser ? browser->profile() :
    290       ProfileManager::GetPrimaryUserProfileOrOffTheRecord();
    291   DialogEnrollmentDelegate* enrollment =
    292       new DialogEnrollmentDelegate(owning_window, network->name(), profile);
    293   return enrollment->Enroll(certificate_pattern.enrollment_uri_list(),
    294                             base::Bind(&EnrollmentComplete, service_path));
    295 }
    296 
    297 }  // namespace enrollment
    298 
    299 }  // namespace chromeos
    300