| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h" | 5 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h" |
| 6 | 6 |
| 7 #include "base/prefs/pref_service.h" | 7 #include "base/prefs/pref_service.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "chrome/browser/browser_process.h" | 9 #include "chrome/browser/browser_process.h" |
| 10 #include "chrome/browser/lifetime/application_lifetime.h" | 10 #include "chrome/browser/lifetime/application_lifetime.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 #include "ui/views/controls/button/image_button.h" | 61 #include "ui/views/controls/button/image_button.h" |
| 62 #include "ui/views/controls/button/label_button.h" | 62 #include "ui/views/controls/button/label_button.h" |
| 63 #include "ui/views/controls/button/label_button_border.h" | 63 #include "ui/views/controls/button/label_button_border.h" |
| 64 #include "ui/views/controls/button/menu_button.h" | 64 #include "ui/views/controls/button/menu_button.h" |
| 65 #include "ui/views/controls/label.h" | 65 #include "ui/views/controls/label.h" |
| 66 #include "ui/views/controls/link.h" | 66 #include "ui/views/controls/link.h" |
| 67 #include "ui/views/controls/separator.h" | 67 #include "ui/views/controls/separator.h" |
| 68 #include "ui/views/controls/styled_label.h" | 68 #include "ui/views/controls/styled_label.h" |
| 69 #include "ui/views/controls/textfield/textfield.h" | 69 #include "ui/views/controls/textfield/textfield.h" |
| 70 #include "ui/views/controls/webview/webview.h" | 70 #include "ui/views/controls/webview/webview.h" |
| 71 #include "ui/views/layout/fill_layout.h" |
| 71 #include "ui/views/layout/grid_layout.h" | 72 #include "ui/views/layout/grid_layout.h" |
| 72 #include "ui/views/layout/layout_constants.h" | 73 #include "ui/views/layout/layout_constants.h" |
| 73 #include "ui/views/widget/widget.h" | 74 #include "ui/views/widget/widget.h" |
| 74 | 75 |
| 75 namespace { | 76 namespace { |
| 76 | 77 |
| 77 // Helpers -------------------------------------------------------------------- | 78 // Helpers -------------------------------------------------------------------- |
| 78 | 79 |
| 79 const int kFixedMenuWidth = 250; | 80 const int kFixedMenuWidth = 250; |
| 80 const int kButtonHeight = 32; | 81 const int kButtonHeight = 32; |
| 81 const int kFixedGaiaViewHeight = 440; | 82 const int kPasswordCombinedFixedGaiaViewHeight = 440; |
| 82 const int kFixedGaiaViewWidth = 360; | 83 const int kPasswordCombinedFixedGaiaViewWidth = 360; |
| 84 const int kFixedGaiaViewHeight = 512; |
| 85 const int kFixedGaiaViewWidth = 448; |
| 83 const int kFixedAccountRemovalViewWidth = 280; | 86 const int kFixedAccountRemovalViewWidth = 280; |
| 84 const int kFixedSwitchUserViewWidth = 320; | 87 const int kFixedSwitchUserViewWidth = 320; |
| 85 const int kLargeImageSide = 88; | 88 const int kLargeImageSide = 88; |
| 86 | 89 |
| 87 const int kVerticalSpacing = 16; | 90 const int kVerticalSpacing = 16; |
| 88 | 91 |
| 92 const int kTitleViewNativeWidgetOffset = 8; |
| 93 |
| 89 bool IsProfileChooser(profiles::BubbleViewMode mode) { | 94 bool IsProfileChooser(profiles::BubbleViewMode mode) { |
| 90 return mode == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER || | 95 return mode == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER || |
| 91 mode == profiles::BUBBLE_VIEW_MODE_FAST_PROFILE_CHOOSER; | 96 mode == profiles::BUBBLE_VIEW_MODE_FAST_PROFILE_CHOOSER; |
| 92 } | 97 } |
| 93 | 98 |
| 94 // Creates a GridLayout with a single column. This ensures that all the child | 99 // Creates a GridLayout with a single column. This ensures that all the child |
| 95 // views added get auto-expanded to fill the full width of the bubble. | 100 // views added get auto-expanded to fill the full width of the bubble. |
| 96 views::GridLayout* CreateSingleColumnLayout(views::View* view, int width) { | 101 views::GridLayout* CreateSingleColumnLayout(views::View* view, int width) { |
| 97 views::GridLayout* layout = new views::GridLayout(view); | 102 views::GridLayout* layout = new views::GridLayout(view); |
| 98 view->SetLayoutManager(layout); | 103 view->SetLayoutManager(layout); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 127 | 132 |
| 128 std::string GetAuthErrorAccountId(Profile* profile) { | 133 std::string GetAuthErrorAccountId(Profile* profile) { |
| 129 const SigninErrorController* error = | 134 const SigninErrorController* error = |
| 130 SigninErrorControllerFactory::GetForProfile(profile); | 135 SigninErrorControllerFactory::GetForProfile(profile); |
| 131 if (!error) | 136 if (!error) |
| 132 return std::string(); | 137 return std::string(); |
| 133 | 138 |
| 134 return error->error_account_id(); | 139 return error->error_account_id(); |
| 135 } | 140 } |
| 136 | 141 |
| 142 views::ImageButton* CreateBackButton(views::ButtonListener* listener) { |
| 143 views::ImageButton* back_button = new views::ImageButton(listener); |
| 144 back_button->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
| 145 views::ImageButton::ALIGN_MIDDLE); |
| 146 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); |
| 147 back_button->SetImage(views::ImageButton::STATE_NORMAL, |
| 148 rb->GetImageSkiaNamed(IDR_BACK)); |
| 149 back_button->SetImage(views::ImageButton::STATE_HOVERED, |
| 150 rb->GetImageSkiaNamed(IDR_BACK_H)); |
| 151 back_button->SetImage(views::ImageButton::STATE_PRESSED, |
| 152 rb->GetImageSkiaNamed(IDR_BACK_P)); |
| 153 back_button->SetImage(views::ImageButton::STATE_DISABLED, |
| 154 rb->GetImageSkiaNamed(IDR_BACK_D)); |
| 155 back_button->SetFocusable(true); |
| 156 return back_button; |
| 157 } |
| 158 |
| 137 // BackgroundColorHoverButton ------------------------------------------------- | 159 // BackgroundColorHoverButton ------------------------------------------------- |
| 138 | 160 |
| 139 // A custom button that allows for setting a background color when hovered over. | 161 // A custom button that allows for setting a background color when hovered over. |
| 140 class BackgroundColorHoverButton : public views::LabelButton { | 162 class BackgroundColorHoverButton : public views::LabelButton { |
| 141 public: | 163 public: |
| 142 BackgroundColorHoverButton(views::ButtonListener* listener, | 164 BackgroundColorHoverButton(views::ButtonListener* listener, |
| 143 const base::string16& text, | 165 const base::string16& text, |
| 144 const gfx::ImageSkia& icon) | 166 const gfx::ImageSkia& icon) |
| 145 : views::LabelButton(listener, text) { | 167 : views::LabelButton(listener, text) { |
| 146 SetImageLabelSpacing(views::kItemLabelSpacing); | 168 SetImageLabelSpacing(views::kItemLabelSpacing); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 175 public: | 197 public: |
| 176 explicit SizedContainer(const gfx::Size& preferred_size) | 198 explicit SizedContainer(const gfx::Size& preferred_size) |
| 177 : preferred_size_(preferred_size) {} | 199 : preferred_size_(preferred_size) {} |
| 178 | 200 |
| 179 gfx::Size GetPreferredSize() const override { return preferred_size_; } | 201 gfx::Size GetPreferredSize() const override { return preferred_size_; } |
| 180 | 202 |
| 181 private: | 203 private: |
| 182 gfx::Size preferred_size_; | 204 gfx::Size preferred_size_; |
| 183 }; | 205 }; |
| 184 | 206 |
| 207 // A view to host the GAIA webview overlapped with a back button. This class |
| 208 // is needed to reparent the back button inside a native view so that on |
| 209 // windows, user input can be be properly routed to the button. |
| 210 class HostView : public views::View { |
| 211 public: |
| 212 HostView() {} |
| 213 |
| 214 void Initialize(views::View* title_view, views::View* main_view); |
| 215 |
| 216 private: |
| 217 // views::View: |
| 218 void ViewHierarchyChanged( |
| 219 const ViewHierarchyChangedDetails& details) override; |
| 220 |
| 221 // The title itself and the overlaped widget that contains it. |
| 222 views::View* title_view_ = nullptr; // Not owned. |
| 223 scoped_ptr<views::Widget> title_widget_; |
| 224 |
| 225 DISALLOW_COPY_AND_ASSIGN(HostView); |
| 226 }; |
| 227 |
| 228 void HostView::Initialize(views::View* title_view, views::View* main_view) { |
| 229 title_view_ = title_view; |
| 230 AddChildView(main_view); |
| 231 SetLayoutManager(new views::FillLayout()); |
| 232 } |
| 233 |
| 234 void HostView::ViewHierarchyChanged( |
| 235 const ViewHierarchyChangedDetails& details) { |
| 236 if (title_widget_ != nullptr || GetWidget() == nullptr) |
| 237 return; |
| 238 |
| 239 // The title view must be placed within its own widget so that it can |
| 240 // properly receive user input when overlapped on another view. |
| 241 views::Widget::InitParams params( |
| 242 views::Widget::InitParams::TYPE_CONTROL); |
| 243 params.parent = GetWidget()->GetNativeView(); |
| 244 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
| 245 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 246 title_widget_.reset(new views::Widget); |
| 247 title_widget_->Init(params); |
| 248 title_widget_->SetContentsView(title_view_); |
| 249 |
| 250 gfx::Rect bounds(title_view_->GetPreferredSize()); |
| 251 title_view_->SetBoundsRect(bounds); |
| 252 bounds.Offset(kTitleViewNativeWidgetOffset, kTitleViewNativeWidgetOffset); |
| 253 title_widget_->SetBounds(bounds); |
| 254 } |
| 255 |
| 185 } // namespace | 256 } // namespace |
| 186 | 257 |
| 187 // RightAlignedIconLabelButton ------------------------------------------------- | 258 // RightAlignedIconLabelButton ------------------------------------------------- |
| 188 | 259 |
| 189 // A custom LabelButton that has a centered text and right aligned icon. | 260 // A custom LabelButton that has a centered text and right aligned icon. |
| 190 class RightAlignedIconLabelButton : public views::LabelButton { | 261 class RightAlignedIconLabelButton : public views::LabelButton { |
| 191 public: | 262 public: |
| 192 RightAlignedIconLabelButton(views::ButtonListener* listener, | 263 RightAlignedIconLabelButton(views::ButtonListener* listener, |
| 193 const base::string16& text) | 264 const base::string16& text) |
| 194 : views::LabelButton(listener, text) { | 265 : views::LabelButton(listener, text) { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 views::Textfield* profile_name_textfield_; | 465 views::Textfield* profile_name_textfield_; |
| 395 | 466 |
| 396 DISALLOW_COPY_AND_ASSIGN(EditableProfileName); | 467 DISALLOW_COPY_AND_ASSIGN(EditableProfileName); |
| 397 }; | 468 }; |
| 398 | 469 |
| 399 // A title card with one back button right aligned and one label center aligned. | 470 // A title card with one back button right aligned and one label center aligned. |
| 400 class TitleCard : public views::View { | 471 class TitleCard : public views::View { |
| 401 public: | 472 public: |
| 402 TitleCard(const base::string16& message, views::ButtonListener* listener, | 473 TitleCard(const base::string16& message, views::ButtonListener* listener, |
| 403 views::ImageButton** back_button) { | 474 views::ImageButton** back_button) { |
| 404 back_button_ = new views::ImageButton(listener); | 475 back_button_ = CreateBackButton(listener); |
| 405 back_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | |
| 406 views::ImageButton::ALIGN_MIDDLE); | |
| 407 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); | |
| 408 back_button_->SetImage(views::ImageButton::STATE_NORMAL, | |
| 409 rb->GetImageSkiaNamed(IDR_BACK)); | |
| 410 back_button_->SetImage(views::ImageButton::STATE_HOVERED, | |
| 411 rb->GetImageSkiaNamed(IDR_BACK_H)); | |
| 412 back_button_->SetImage(views::ImageButton::STATE_PRESSED, | |
| 413 rb->GetImageSkiaNamed(IDR_BACK_P)); | |
| 414 back_button_->SetImage(views::ImageButton::STATE_DISABLED, | |
| 415 rb->GetImageSkiaNamed(IDR_BACK_D)); | |
| 416 back_button_->SetFocusable(true); | |
| 417 *back_button = back_button_; | 476 *back_button = back_button_; |
| 418 | 477 |
| 419 title_label_ = new views::Label(message); | 478 title_label_ = new views::Label(message); |
| 420 title_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER); | 479 title_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER); |
| 480 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); |
| 421 const gfx::FontList& medium_font_list = | 481 const gfx::FontList& medium_font_list = |
| 422 rb->GetFontList(ui::ResourceBundle::MediumFont); | 482 rb->GetFontList(ui::ResourceBundle::MediumFont); |
| 423 title_label_->SetFontList(medium_font_list); | 483 title_label_->SetFontList(medium_font_list); |
| 424 | 484 |
| 425 AddChildView(back_button_); | 485 AddChildView(back_button_); |
| 426 AddChildView(title_label_); | 486 AddChildView(title_label_); |
| 427 } | 487 } |
| 428 | 488 |
| 429 // Creates a new view that has the |title_card| with horizontal padding at the | 489 // Creates a new view that has the |title_card| with horizontal padding at the |
| 430 // top, an edge-to-edge separator below, and the specified |view| at the | 490 // top, an edge-to-edge separator below, and the specified |view| at the |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 ResetView(); | 777 ResetView(); |
| 718 RemoveAllChildViews(true); | 778 RemoveAllChildViews(true); |
| 719 view_mode_ = view_to_display; | 779 view_mode_ = view_to_display; |
| 720 | 780 |
| 721 views::GridLayout* layout = nullptr; | 781 views::GridLayout* layout = nullptr; |
| 722 views::View* sub_view = nullptr; | 782 views::View* sub_view = nullptr; |
| 723 views::View* view_to_focus = nullptr; | 783 views::View* view_to_focus = nullptr; |
| 724 switch (view_mode_) { | 784 switch (view_mode_) { |
| 725 case profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN: | 785 case profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN: |
| 726 case profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT: | 786 case profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT: |
| 727 case profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH: | 787 case profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH: { |
| 728 layout = CreateSingleColumnLayout(this, kFixedGaiaViewWidth); | 788 const int width = switches::UsePasswordSeparatedSigninFlow() |
| 789 ? kFixedGaiaViewWidth : kPasswordCombinedFixedGaiaViewWidth; |
| 790 layout = CreateSingleColumnLayout(this, width); |
| 729 sub_view = CreateGaiaSigninView(&view_to_focus); | 791 sub_view = CreateGaiaSigninView(&view_to_focus); |
| 730 break; | 792 break; |
| 793 } |
| 731 case profiles::BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL: | 794 case profiles::BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL: |
| 732 layout = CreateSingleColumnLayout(this, kFixedAccountRemovalViewWidth); | 795 layout = CreateSingleColumnLayout(this, kFixedAccountRemovalViewWidth); |
| 733 sub_view = CreateAccountRemovalView(); | 796 sub_view = CreateAccountRemovalView(); |
| 734 break; | 797 break; |
| 735 case profiles::BUBBLE_VIEW_MODE_SWITCH_USER: | 798 case profiles::BUBBLE_VIEW_MODE_SWITCH_USER: |
| 736 layout = CreateSingleColumnLayout(this, kFixedSwitchUserViewWidth); | 799 layout = CreateSingleColumnLayout(this, kFixedSwitchUserViewWidth); |
| 737 sub_view = CreateSwitchUserView(); | 800 sub_view = CreateSwitchUserView(); |
| 738 ProfileMetrics::LogProfileNewAvatarMenuNotYou( | 801 ProfileMetrics::LogProfileNewAvatarMenuNotYou( |
| 739 ProfileMetrics::PROFILE_AVATAR_MENU_NOT_YOU_VIEW); | 802 ProfileMetrics::PROFILE_AVATAR_MENU_NOT_YOU_VIEW); |
| 740 break; | 803 break; |
| (...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1572 url = signin::GetReauthURL(browser_->profile(), | 1635 url = signin::GetReauthURL(browser_->profile(), |
| 1573 GetAuthErrorAccountId(browser_->profile())); | 1636 GetAuthErrorAccountId(browser_->profile())); |
| 1574 message_id = IDS_PROFILES_GAIA_REAUTH_TITLE; | 1637 message_id = IDS_PROFILES_GAIA_REAUTH_TITLE; |
| 1575 break; | 1638 break; |
| 1576 } | 1639 } |
| 1577 default: | 1640 default: |
| 1578 NOTREACHED() << "Called with invalid mode=" << view_mode_; | 1641 NOTREACHED() << "Called with invalid mode=" << view_mode_; |
| 1579 return NULL; | 1642 return NULL; |
| 1580 } | 1643 } |
| 1581 | 1644 |
| 1582 // Adds Gaia signin webview | 1645 // Adds Gaia signin webview. |
| 1646 const gfx::Size pref_size = switches::UsePasswordSeparatedSigninFlow() |
| 1647 ? gfx::Size(kFixedGaiaViewWidth, kFixedGaiaViewHeight) |
| 1648 : gfx::Size(kPasswordCombinedFixedGaiaViewWidth, |
| 1649 kPasswordCombinedFixedGaiaViewHeight); |
| 1583 Profile* profile = browser_->profile(); | 1650 Profile* profile = browser_->profile(); |
| 1584 views::WebView* web_view = new views::WebView(profile); | 1651 views::WebView* web_view = new views::WebView(profile); |
| 1585 web_view->LoadInitialURL(url); | 1652 web_view->LoadInitialURL(url); |
| 1586 web_view->GetWebContents()->SetDelegate(this); | 1653 web_view->GetWebContents()->SetDelegate(this); |
| 1587 web_view->SetPreferredSize( | 1654 web_view->SetPreferredSize(pref_size); |
| 1588 gfx::Size(kFixedGaiaViewWidth, kFixedGaiaViewHeight)); | |
| 1589 content::RenderWidgetHostView* rwhv = | 1655 content::RenderWidgetHostView* rwhv = |
| 1590 web_view->GetWebContents()->GetRenderWidgetHostView(); | 1656 web_view->GetWebContents()->GetRenderWidgetHostView(); |
| 1591 if (rwhv) | 1657 if (rwhv) |
| 1592 rwhv->SetBackgroundColor(profiles::kAvatarBubbleGaiaBackgroundColor); | 1658 rwhv->SetBackgroundColor(profiles::kAvatarBubbleGaiaBackgroundColor); |
| 1659 |
| 1660 if (signin_content_view) |
| 1661 *signin_content_view = web_view; |
| 1662 |
| 1663 if (switches::UsePasswordSeparatedSigninFlow()) { |
| 1664 gaia_signin_cancel_button_ = CreateBackButton(this); |
| 1665 HostView* host = new HostView(); |
| 1666 host->Initialize(gaia_signin_cancel_button_, web_view); |
| 1667 return host; |
| 1668 } |
| 1669 |
| 1593 TitleCard* title_card = new TitleCard(l10n_util::GetStringUTF16(message_id), | 1670 TitleCard* title_card = new TitleCard(l10n_util::GetStringUTF16(message_id), |
| 1594 this, | 1671 this, |
| 1595 &gaia_signin_cancel_button_); | 1672 &gaia_signin_cancel_button_); |
| 1596 if (signin_content_view) | |
| 1597 *signin_content_view = web_view; | |
| 1598 return TitleCard::AddPaddedTitleCard( | 1673 return TitleCard::AddPaddedTitleCard( |
| 1599 web_view, title_card, kFixedGaiaViewWidth); | 1674 web_view, title_card, kPasswordCombinedFixedGaiaViewWidth); |
| 1600 } | 1675 } |
| 1601 | 1676 |
| 1602 views::View* ProfileChooserView::CreateAccountRemovalView() { | 1677 views::View* ProfileChooserView::CreateAccountRemovalView() { |
| 1603 views::View* view = new views::View(); | 1678 views::View* view = new views::View(); |
| 1604 views::GridLayout* layout = CreateSingleColumnLayout( | 1679 views::GridLayout* layout = CreateSingleColumnLayout( |
| 1605 view, kFixedAccountRemovalViewWidth - 2 * views::kButtonHEdgeMarginNew); | 1680 view, kFixedAccountRemovalViewWidth - 2 * views::kButtonHEdgeMarginNew); |
| 1606 layout->SetInsets(0, | 1681 layout->SetInsets(0, |
| 1607 views::kButtonHEdgeMarginNew, | 1682 views::kButtonHEdgeMarginNew, |
| 1608 views::kButtonVEdgeMarginNew, | 1683 views::kButtonVEdgeMarginNew, |
| 1609 views::kButtonHEdgeMarginNew); | 1684 views::kButtonHEdgeMarginNew); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 IncognitoModePrefs::GetAvailability(browser_->profile()->GetPrefs()) != | 1870 IncognitoModePrefs::GetAvailability(browser_->profile()->GetPrefs()) != |
| 1796 IncognitoModePrefs::DISABLED; | 1871 IncognitoModePrefs::DISABLED; |
| 1797 return incognito_available && !browser_->profile()->IsGuestSession(); | 1872 return incognito_available && !browser_->profile()->IsGuestSession(); |
| 1798 } | 1873 } |
| 1799 | 1874 |
| 1800 void ProfileChooserView::PostActionPerformed( | 1875 void ProfileChooserView::PostActionPerformed( |
| 1801 ProfileMetrics::ProfileDesktopMenu action_performed) { | 1876 ProfileMetrics::ProfileDesktopMenu action_performed) { |
| 1802 ProfileMetrics::LogProfileDesktopMenu(action_performed, gaia_service_type_); | 1877 ProfileMetrics::LogProfileDesktopMenu(action_performed, gaia_service_type_); |
| 1803 gaia_service_type_ = signin::GAIA_SERVICE_TYPE_NONE; | 1878 gaia_service_type_ = signin::GAIA_SERVICE_TYPE_NONE; |
| 1804 } | 1879 } |
| OLD | NEW |