| OLD | NEW |
| (Empty) |
| 1 // Copyright 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/ui/gtk/location_bar_view_gtk.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <string> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/basictypes.h" | |
| 12 #include "base/bind.h" | |
| 13 #include "base/command_line.h" | |
| 14 #include "base/debug/trace_event.h" | |
| 15 #include "base/i18n/rtl.h" | |
| 16 #include "base/logging.h" | |
| 17 #include "base/message_loop/message_loop.h" | |
| 18 #include "base/prefs/pref_service.h" | |
| 19 #include "base/strings/string_number_conversions.h" | |
| 20 #include "base/strings/string_util.h" | |
| 21 #include "base/strings/utf_string_conversions.h" | |
| 22 #include "chrome/app/chrome_command_ids.h" | |
| 23 #include "chrome/browser/accessibility/accessibility_events.h" | |
| 24 #include "chrome/browser/accessibility/accessibility_extension_api.h" | |
| 25 #include "chrome/browser/chrome_notification_types.h" | |
| 26 #include "chrome/browser/command_updater.h" | |
| 27 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | |
| 28 #include "chrome/browser/defaults.h" | |
| 29 #include "chrome/browser/extensions/api/commands/command_service.h" | |
| 30 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h" | |
| 31 #include "chrome/browser/extensions/extension_action.h" | |
| 32 #include "chrome/browser/extensions/extension_service.h" | |
| 33 #include "chrome/browser/extensions/extension_tab_util.h" | |
| 34 #include "chrome/browser/extensions/location_bar_controller.h" | |
| 35 #include "chrome/browser/extensions/tab_helper.h" | |
| 36 #include "chrome/browser/favicon/favicon_tab_helper.h" | |
| 37 #include "chrome/browser/profiles/profile.h" | |
| 38 #include "chrome/browser/search/instant_service.h" | |
| 39 #include "chrome/browser/search/instant_service_factory.h" | |
| 40 #include "chrome/browser/search_engines/template_url.h" | |
| 41 #include "chrome/browser/search_engines/template_url_service.h" | |
| 42 #include "chrome/browser/search_engines/template_url_service_factory.h" | |
| 43 #include "chrome/browser/themes/theme_properties.h" | |
| 44 #include "chrome/browser/ui/browser.h" | |
| 45 #include "chrome/browser/ui/browser_command_controller.h" | |
| 46 #include "chrome/browser/ui/browser_commands.h" | |
| 47 #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h" | |
| 48 #include "chrome/browser/ui/browser_instant_controller.h" | |
| 49 #include "chrome/browser/ui/browser_list.h" | |
| 50 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h" | |
| 51 #include "chrome/browser/ui/content_settings/content_setting_image_model.h" | |
| 52 #include "chrome/browser/ui/gtk/bookmarks/bookmark_bubble_gtk.h" | |
| 53 #include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h" | |
| 54 #include "chrome/browser/ui/gtk/browser_window_gtk.h" | |
| 55 #include "chrome/browser/ui/gtk/content_setting_bubble_gtk.h" | |
| 56 #include "chrome/browser/ui/gtk/extensions/extension_popup_gtk.h" | |
| 57 #include "chrome/browser/ui/gtk/first_run_bubble.h" | |
| 58 #include "chrome/browser/ui/gtk/gtk_theme_service.h" | |
| 59 #include "chrome/browser/ui/gtk/gtk_util.h" | |
| 60 #include "chrome/browser/ui/gtk/manage_passwords_bubble_gtk.h" | |
| 61 #include "chrome/browser/ui/gtk/nine_box.h" | |
| 62 #include "chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h" | |
| 63 #include "chrome/browser/ui/gtk/rounded_window.h" | |
| 64 #include "chrome/browser/ui/gtk/view_id_util.h" | |
| 65 #include "chrome/browser/ui/gtk/zoom_bubble_gtk.h" | |
| 66 #include "chrome/browser/ui/omnibox/location_bar_util.h" | |
| 67 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" | |
| 68 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" | |
| 69 #include "chrome/browser/ui/passwords/manage_passwords_bubble_ui_controller.h" | |
| 70 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
| 71 #include "chrome/browser/ui/webui/extensions/extension_info_ui.h" | |
| 72 #include "chrome/browser/ui/zoom/zoom_controller.h" | |
| 73 #include "chrome/common/badge_util.h" | |
| 74 #include "chrome/common/chrome_switches.h" | |
| 75 #include "chrome/common/pref_names.h" | |
| 76 #include "content/public/browser/navigation_entry.h" | |
| 77 #include "content/public/browser/notification_service.h" | |
| 78 #include "content/public/browser/web_contents.h" | |
| 79 #include "extensions/common/extension.h" | |
| 80 #include "extensions/common/feature_switch.h" | |
| 81 #include "extensions/common/manifest_handlers/icons_handler.h" | |
| 82 #include "grit/generated_resources.h" | |
| 83 #include "grit/theme_resources.h" | |
| 84 #include "net/base/net_util.h" | |
| 85 #include "ui/accessibility/ax_enums.h" | |
| 86 #include "ui/base/accelerators/platform_accelerator_gtk.h" | |
| 87 #include "ui/base/dragdrop/gtk_dnd_util.h" | |
| 88 #include "ui/base/gtk/gtk_hig_constants.h" | |
| 89 #include "ui/base/gtk/gtk_signal_registrar.h" | |
| 90 #include "ui/base/l10n/l10n_util.h" | |
| 91 #include "ui/base/resource/resource_bundle.h" | |
| 92 #include "ui/base/window_open_disposition.h" | |
| 93 #include "ui/gfx/canvas_skia_paint.h" | |
| 94 #include "ui/gfx/font.h" | |
| 95 #include "ui/gfx/gtk_util.h" | |
| 96 #include "ui/gfx/image/image.h" | |
| 97 | |
| 98 using content::NavigationEntry; | |
| 99 using content::OpenURLParams; | |
| 100 using content::WebContents; | |
| 101 using extensions::LocationBarController; | |
| 102 using extensions::Extension; | |
| 103 | |
| 104 namespace { | |
| 105 | |
| 106 // We draw a border on the top and bottom (but not on left or right). | |
| 107 const int kBorderThickness = 1; | |
| 108 | |
| 109 const int kPopupEdgeThickness = 1; | |
| 110 const int kNormalEdgeThickness = 2; | |
| 111 | |
| 112 // Spacing needed to align the bubble with the left side of the omnibox. | |
| 113 const int kFirstRunBubbleLeftSpacing = 4; | |
| 114 | |
| 115 // The padding around the top, bottom, and sides of the location bar hbox. | |
| 116 // We don't want to edit control's text to be right against the edge, | |
| 117 // as well the tab to search box and other widgets need to have the padding on | |
| 118 // top and bottom to avoid drawing larger than the location bar space. | |
| 119 const int kHboxBorder = 2; | |
| 120 | |
| 121 // Padding between the elements in the bar. | |
| 122 const int kInnerPadding = 2; | |
| 123 | |
| 124 // Colors used to draw the EV certificate rounded bubble. | |
| 125 const GdkColor kEvSecureTextColor = GDK_COLOR_RGB(0x07, 0x95, 0x00); | |
| 126 const GdkColor kEvSecureBackgroundColor = GDK_COLOR_RGB(0xef, 0xfc, 0xef); | |
| 127 const GdkColor kEvSecureBorderColor = GDK_COLOR_RGB(0x90, 0xc3, 0x90); | |
| 128 | |
| 129 // Colors used to draw the Tab to Search rounded bubble. | |
| 130 const GdkColor kKeywordBackgroundColor = GDK_COLOR_RGB(0xf0, 0xf4, 0xfa); | |
| 131 const GdkColor kKeywordBorderColor = GDK_COLOR_RGB(0xcb, 0xde, 0xf7); | |
| 132 | |
| 133 // Use weak gray for showing search and keyword hint text. | |
| 134 const GdkColor kHintTextColor = GDK_COLOR_RGB(0x75, 0x75, 0x75); | |
| 135 | |
| 136 // Size of the rounding of the "Search site for:" box. | |
| 137 const int kCornerSize = 3; | |
| 138 | |
| 139 // Default page tool animation time (open and close). In ms. | |
| 140 const int kPageToolAnimationTime = 150; | |
| 141 | |
| 142 // The time, in ms, that the content setting label is fully displayed, for the | |
| 143 // cases where we animate it into and out of view. | |
| 144 const int kContentSettingImageDisplayTime = 3200; | |
| 145 // The time, in ms, of the animation (open and close). | |
| 146 const int kContentSettingImageAnimationTime = 150; | |
| 147 | |
| 148 // Color of border of content setting area (icon/label). | |
| 149 const GdkColor kContentSettingBorderColor = GDK_COLOR_RGB(0xe9, 0xb9, 0x66); | |
| 150 // Colors for the background gradient. | |
| 151 const GdkColor kContentSettingTopColor = GDK_COLOR_RGB(0xff, 0xf8, 0xd4); | |
| 152 const GdkColor kContentSettingBottomColor = GDK_COLOR_RGB(0xff, 0xe6, 0xaf); | |
| 153 | |
| 154 // If widget is visible, increment the int pointed to by count. | |
| 155 // Suitible for use with gtk_container_foreach. | |
| 156 void CountVisibleWidgets(GtkWidget* widget, gpointer count) { | |
| 157 if (gtk_widget_get_visible(widget)) | |
| 158 *static_cast<int*>(count) += 1; | |
| 159 } | |
| 160 | |
| 161 class ContentSettingImageViewGtk : public LocationBarViewGtk::PageToolViewGtk, | |
| 162 public BubbleDelegateGtk { | |
| 163 public: | |
| 164 ContentSettingImageViewGtk(ContentSettingsType content_type, | |
| 165 LocationBarViewGtk* parent); | |
| 166 virtual ~ContentSettingImageViewGtk(); | |
| 167 | |
| 168 // PageToolViewGtk | |
| 169 virtual void Update(WebContents* web_contents) OVERRIDE; | |
| 170 | |
| 171 // gfx::AnimationDelegate | |
| 172 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; | |
| 173 | |
| 174 private: | |
| 175 // PageToolViewGtk | |
| 176 virtual GdkColor GetButtonBorderColor() const OVERRIDE; | |
| 177 virtual GdkColor GetGradientTopColor() const OVERRIDE; | |
| 178 virtual GdkColor GetGradientBottomColor() const OVERRIDE; | |
| 179 virtual void OnClick(GtkWidget* sender) OVERRIDE; | |
| 180 | |
| 181 // BubbleDelegateGtk | |
| 182 virtual void BubbleClosing(BubbleGtk* bubble, | |
| 183 bool closed_by_escape) OVERRIDE; | |
| 184 | |
| 185 // The owning LocationBarViewGtk. | |
| 186 LocationBarViewGtk* parent_; | |
| 187 | |
| 188 scoped_ptr<ContentSettingImageModel> content_setting_image_model_; | |
| 189 | |
| 190 // The currently shown bubble if any. | |
| 191 ContentSettingBubbleGtk* content_setting_bubble_; | |
| 192 | |
| 193 DISALLOW_COPY_AND_ASSIGN(ContentSettingImageViewGtk); | |
| 194 }; | |
| 195 | |
| 196 ContentSettingImageViewGtk::ContentSettingImageViewGtk( | |
| 197 ContentSettingsType content_type, | |
| 198 LocationBarViewGtk* parent) | |
| 199 : PageToolViewGtk(), | |
| 200 parent_(parent), | |
| 201 content_setting_image_model_( | |
| 202 ContentSettingImageModel::CreateContentSettingImageModel( | |
| 203 content_type)), | |
| 204 content_setting_bubble_(NULL) { | |
| 205 animation_.SetSlideDuration(kContentSettingImageAnimationTime); | |
| 206 } | |
| 207 | |
| 208 ContentSettingImageViewGtk::~ContentSettingImageViewGtk() { | |
| 209 if (content_setting_bubble_) | |
| 210 content_setting_bubble_->Close(); | |
| 211 } | |
| 212 | |
| 213 void ContentSettingImageViewGtk::Update(WebContents* web_contents) { | |
| 214 if (web_contents) | |
| 215 content_setting_image_model_->UpdateFromWebContents(web_contents); | |
| 216 | |
| 217 if (!content_setting_image_model_->is_visible()) { | |
| 218 gtk_widget_hide(widget()); | |
| 219 return; | |
| 220 } | |
| 221 | |
| 222 gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()), | |
| 223 GtkThemeService::GetFrom(parent_->browser()->profile())->GetImageNamed( | |
| 224 content_setting_image_model_->get_icon()).ToGdkPixbuf()); | |
| 225 | |
| 226 gtk_widget_set_tooltip_text(widget(), | |
| 227 content_setting_image_model_->get_tooltip().c_str()); | |
| 228 gtk_widget_show_all(widget()); | |
| 229 | |
| 230 if (!web_contents) | |
| 231 return; | |
| 232 | |
| 233 TabSpecificContentSettings* content_settings = | |
| 234 TabSpecificContentSettings::FromWebContents(web_contents); | |
| 235 if (!content_settings || content_settings->IsBlockageIndicated( | |
| 236 content_setting_image_model_->get_content_settings_type())) | |
| 237 return; | |
| 238 | |
| 239 // The content blockage was not yet indicated to the user. Start indication | |
| 240 // animation and clear "not yet shown" flag. | |
| 241 content_settings->SetBlockageHasBeenIndicated( | |
| 242 content_setting_image_model_->get_content_settings_type()); | |
| 243 | |
| 244 int label_string_id = | |
| 245 content_setting_image_model_->explanatory_string_id(); | |
| 246 // If there's no string for the content type, we don't animate. | |
| 247 if (!label_string_id) | |
| 248 return; | |
| 249 | |
| 250 gtk_label_set_text(GTK_LABEL(label_.get()), | |
| 251 l10n_util::GetStringUTF8(label_string_id).c_str()); | |
| 252 StartAnimating(); | |
| 253 } | |
| 254 | |
| 255 void ContentSettingImageViewGtk::AnimationEnded( | |
| 256 const gfx::Animation* animation) { | |
| 257 if (animation_.IsShowing()) { | |
| 258 base::MessageLoop::current()->PostDelayedTask( | |
| 259 FROM_HERE, | |
| 260 base::Bind(&ContentSettingImageViewGtk::CloseAnimation, | |
| 261 weak_factory_.GetWeakPtr()), | |
| 262 base::TimeDelta::FromMilliseconds(kContentSettingImageDisplayTime)); | |
| 263 } else { | |
| 264 gtk_widget_hide(label_.get()); | |
| 265 gtk_util::StopActingAsRoundedWindow(event_box_.get()); | |
| 266 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE); | |
| 267 } | |
| 268 } | |
| 269 | |
| 270 GdkColor ContentSettingImageViewGtk::GetButtonBorderColor() const { | |
| 271 return kContentSettingBorderColor; | |
| 272 } | |
| 273 | |
| 274 GdkColor ContentSettingImageViewGtk::GetGradientTopColor() const { | |
| 275 return kContentSettingTopColor; | |
| 276 } | |
| 277 | |
| 278 GdkColor ContentSettingImageViewGtk::GetGradientBottomColor() const { | |
| 279 return kContentSettingBottomColor; | |
| 280 } | |
| 281 | |
| 282 void ContentSettingImageViewGtk::OnClick( | |
| 283 GtkWidget* sender) { | |
| 284 WebContents* web_contents = parent_->GetWebContents(); | |
| 285 if (!web_contents) | |
| 286 return; | |
| 287 Profile* profile = parent_->browser()->profile(); | |
| 288 content_setting_bubble_ = new ContentSettingBubbleGtk( | |
| 289 sender, this, | |
| 290 ContentSettingBubbleModel::CreateContentSettingBubbleModel( | |
| 291 parent_->browser()->content_setting_bubble_model_delegate(), | |
| 292 web_contents, | |
| 293 profile, | |
| 294 content_setting_image_model_->get_content_settings_type()), | |
| 295 profile); | |
| 296 return; | |
| 297 } | |
| 298 | |
| 299 void ContentSettingImageViewGtk::BubbleClosing( | |
| 300 BubbleGtk* bubble, | |
| 301 bool closed_by_escape) { | |
| 302 content_setting_bubble_ = NULL; | |
| 303 } | |
| 304 | |
| 305 gfx::Rect AllocationToRect(const GtkAllocation& allocation) { | |
| 306 return gfx::Rect(allocation.x, allocation.y, | |
| 307 allocation.width, allocation.height); | |
| 308 } | |
| 309 | |
| 310 } // namespace | |
| 311 | |
| 312 //////////////////////////////////////////////////////////////////////////////// | |
| 313 // LocationBarViewGtk | |
| 314 | |
| 315 // static | |
| 316 const GdkColor LocationBarViewGtk::kBackgroundColor = | |
| 317 GDK_COLOR_RGB(255, 255, 255); | |
| 318 | |
| 319 LocationBarViewGtk::LocationBarViewGtk(Browser* browser) | |
| 320 : OmniboxEditController(browser->command_controller()->command_updater()), | |
| 321 LocationBar(browser->profile()), | |
| 322 zoom_image_(NULL), | |
| 323 manage_passwords_icon_image_(NULL), | |
| 324 star_image_(NULL), | |
| 325 starred_(false), | |
| 326 star_sized_(false), | |
| 327 site_type_alignment_(NULL), | |
| 328 site_type_event_box_(NULL), | |
| 329 location_icon_image_(NULL), | |
| 330 drag_icon_(NULL), | |
| 331 enable_location_drag_(false), | |
| 332 security_info_label_(NULL), | |
| 333 tab_to_search_alignment_(NULL), | |
| 334 tab_to_search_box_(NULL), | |
| 335 tab_to_search_full_label_(NULL), | |
| 336 tab_to_search_partial_label_(NULL), | |
| 337 tab_to_search_hint_(NULL), | |
| 338 tab_to_search_hint_leading_label_(NULL), | |
| 339 tab_to_search_hint_icon_(NULL), | |
| 340 tab_to_search_hint_trailing_label_(NULL), | |
| 341 browser_(browser), | |
| 342 popup_window_mode_(false), | |
| 343 theme_service_(NULL), | |
| 344 hbox_width_(0), | |
| 345 entry_box_width_(0), | |
| 346 show_selected_keyword_(false), | |
| 347 show_keyword_hint_(false), | |
| 348 weak_ptr_factory_(this) { | |
| 349 } | |
| 350 | |
| 351 LocationBarViewGtk::~LocationBarViewGtk() { | |
| 352 // All of our widgets should be children of / owned by the alignment. | |
| 353 zoom_.Destroy(); | |
| 354 manage_passwords_icon_.Destroy(); | |
| 355 star_.Destroy(); | |
| 356 hbox_.Destroy(); | |
| 357 content_setting_hbox_.Destroy(); | |
| 358 page_action_hbox_.Destroy(); | |
| 359 } | |
| 360 | |
| 361 void LocationBarViewGtk::Init(bool popup_window_mode) { | |
| 362 popup_window_mode_ = popup_window_mode; | |
| 363 | |
| 364 theme_service_ = GtkThemeService::GetFrom(profile()); | |
| 365 | |
| 366 // Create the widget first, so we can pass it to the OmniboxViewGtk. | |
| 367 hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding)); | |
| 368 gtk_container_set_border_width(GTK_CONTAINER(hbox_.get()), kHboxBorder); | |
| 369 // We will paint for the alignment, to paint the background and border. | |
| 370 gtk_widget_set_app_paintable(hbox_.get(), TRUE); | |
| 371 // Redraw the whole location bar when it changes size (e.g., when toggling | |
| 372 // the home button on/off. | |
| 373 gtk_widget_set_redraw_on_allocate(hbox_.get(), TRUE); | |
| 374 | |
| 375 // Now initialize the OmniboxViewGtk. | |
| 376 omnibox_view_.reset(new OmniboxViewGtk(this, browser_, profile(), | |
| 377 command_updater(), | |
| 378 popup_window_mode_, hbox_.get())); | |
| 379 omnibox_view_->Init(); | |
| 380 | |
| 381 g_signal_connect(hbox_.get(), "expose-event", | |
| 382 G_CALLBACK(&HandleExposeThunk), this); | |
| 383 | |
| 384 BuildSiteTypeArea(); | |
| 385 | |
| 386 // Put |tab_to_search_box_|, |omnibox_view_|, and |tab_to_search_hint_| into | |
| 387 // a sub hbox, so that we can make this part horizontally shrinkable without | |
| 388 // affecting other elements in the location bar. | |
| 389 entry_box_ = gtk_hbox_new(FALSE, kInnerPadding); | |
| 390 gtk_widget_show(entry_box_); | |
| 391 gtk_widget_set_size_request(entry_box_, 0, -1); | |
| 392 gtk_box_pack_start(GTK_BOX(hbox_.get()), entry_box_, TRUE, TRUE, 0); | |
| 393 | |
| 394 // We need to adjust the visibility of the search hint widgets according to | |
| 395 // the horizontal space in the |entry_box_|. | |
| 396 g_signal_connect(entry_box_, "size-allocate", | |
| 397 G_CALLBACK(&OnEntryBoxSizeAllocateThunk), this); | |
| 398 | |
| 399 // Tab to search (the keyword box on the left hand side). | |
| 400 tab_to_search_full_label_ = | |
| 401 theme_service_->BuildLabel(std::string(), ui::kGdkBlack); | |
| 402 tab_to_search_partial_label_ = | |
| 403 theme_service_->BuildLabel(std::string(), ui::kGdkBlack); | |
| 404 GtkWidget* tab_to_search_label_hbox = gtk_hbox_new(FALSE, 0); | |
| 405 gtk_box_pack_start(GTK_BOX(tab_to_search_label_hbox), | |
| 406 tab_to_search_full_label_, FALSE, FALSE, 0); | |
| 407 gtk_box_pack_start(GTK_BOX(tab_to_search_label_hbox), | |
| 408 tab_to_search_partial_label_, FALSE, FALSE, 0); | |
| 409 GtkWidget* tab_to_search_hbox = gtk_hbox_new(FALSE, 0); | |
| 410 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 411 tab_to_search_magnifier_ = gtk_image_new_from_pixbuf( | |
| 412 rb.GetNativeImageNamed(IDR_KEYWORD_SEARCH_MAGNIFIER).ToGdkPixbuf()); | |
| 413 gtk_box_pack_start(GTK_BOX(tab_to_search_hbox), tab_to_search_magnifier_, | |
| 414 FALSE, FALSE, 0); | |
| 415 gtk_util::CenterWidgetInHBox(tab_to_search_hbox, tab_to_search_label_hbox, | |
| 416 false, 0); | |
| 417 | |
| 418 // This creates a box around the keyword text with a border, background color, | |
| 419 // and padding around the text. | |
| 420 tab_to_search_box_ = gtk_util::CreateGtkBorderBin( | |
| 421 tab_to_search_hbox, NULL, 1, 1, 1, 3); | |
| 422 gtk_widget_set_name(tab_to_search_box_, "chrome-tab-to-search-box"); | |
| 423 gtk_util::ActAsRoundedWindow(tab_to_search_box_, kKeywordBorderColor, | |
| 424 kCornerSize, | |
| 425 gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL); | |
| 426 | |
| 427 // Put the event box in an alignment to get the padding correct. | |
| 428 tab_to_search_alignment_ = gtk_alignment_new(0, 0, 1, 1); | |
| 429 gtk_container_add(GTK_CONTAINER(tab_to_search_alignment_), | |
| 430 tab_to_search_box_); | |
| 431 gtk_box_pack_start(GTK_BOX(entry_box_), tab_to_search_alignment_, | |
| 432 FALSE, FALSE, 0); | |
| 433 | |
| 434 // Show all children widgets of |tab_to_search_box_| initially, except | |
| 435 // |tab_to_search_partial_label_|. | |
| 436 gtk_widget_show_all(tab_to_search_box_); | |
| 437 gtk_widget_hide(tab_to_search_partial_label_); | |
| 438 | |
| 439 omnibox_view_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); | |
| 440 gtk_container_add(GTK_CONTAINER(omnibox_view_alignment_), | |
| 441 omnibox_view_->GetNativeView()); | |
| 442 gtk_box_pack_start(GTK_BOX(entry_box_), omnibox_view_alignment_, | |
| 443 TRUE, TRUE, 0); | |
| 444 | |
| 445 // Tab to search notification (the hint on the right hand side). | |
| 446 tab_to_search_hint_ = gtk_hbox_new(FALSE, 0); | |
| 447 gtk_widget_set_name(tab_to_search_hint_, "chrome-tab-to-search-hint"); | |
| 448 tab_to_search_hint_leading_label_ = | |
| 449 theme_service_->BuildLabel(std::string(), kHintTextColor); | |
| 450 gtk_widget_set_sensitive(tab_to_search_hint_leading_label_, FALSE); | |
| 451 tab_to_search_hint_icon_ = gtk_image_new_from_pixbuf( | |
| 452 rb.GetNativeImageNamed(IDR_OMNIBOX_KEYWORD_HINT_TAB).ToGdkPixbuf()); | |
| 453 tab_to_search_hint_trailing_label_ = | |
| 454 theme_service_->BuildLabel(std::string(), kHintTextColor); | |
| 455 gtk_widget_set_sensitive(tab_to_search_hint_trailing_label_, FALSE); | |
| 456 gtk_box_pack_start(GTK_BOX(tab_to_search_hint_), | |
| 457 tab_to_search_hint_leading_label_, | |
| 458 FALSE, FALSE, 0); | |
| 459 gtk_box_pack_start(GTK_BOX(tab_to_search_hint_), | |
| 460 tab_to_search_hint_icon_, | |
| 461 FALSE, FALSE, 0); | |
| 462 gtk_box_pack_start(GTK_BOX(tab_to_search_hint_), | |
| 463 tab_to_search_hint_trailing_label_, | |
| 464 FALSE, FALSE, 0); | |
| 465 // Show all children widgets of |tab_to_search_hint_| initially. | |
| 466 gtk_widget_show_all(tab_to_search_hint_); | |
| 467 gtk_widget_hide(tab_to_search_hint_); | |
| 468 // tab_to_search_hint_ gets hidden initially in OnChanged. Hiding it here | |
| 469 // doesn't work, someone is probably calling show_all on our parent box. | |
| 470 gtk_box_pack_end(GTK_BOX(entry_box_), tab_to_search_hint_, FALSE, FALSE, 0); | |
| 471 | |
| 472 if (browser_defaults::bookmarks_enabled && !ShouldOnlyShowLocation()) { | |
| 473 // Hide the star icon in popups, app windows, etc. | |
| 474 CreateStarButton(); | |
| 475 gtk_box_pack_end(GTK_BOX(hbox_.get()), star_.get(), FALSE, FALSE, 0); | |
| 476 } | |
| 477 | |
| 478 CreateZoomButton(); | |
| 479 gtk_box_pack_end(GTK_BOX(hbox_.get()), zoom_.get(), FALSE, FALSE, 0); | |
| 480 | |
| 481 CreateManagePasswordsIconButton(); | |
| 482 gtk_box_pack_end(GTK_BOX(hbox_.get()), manage_passwords_icon_.get(), FALSE, | |
| 483 FALSE, 0); | |
| 484 | |
| 485 content_setting_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding + 1)); | |
| 486 gtk_widget_set_name(content_setting_hbox_.get(), | |
| 487 "chrome-content-setting-hbox"); | |
| 488 gtk_box_pack_end(GTK_BOX(hbox_.get()), content_setting_hbox_.get(), | |
| 489 FALSE, FALSE, 1); | |
| 490 | |
| 491 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { | |
| 492 ContentSettingImageViewGtk* content_setting_view = | |
| 493 new ContentSettingImageViewGtk( | |
| 494 static_cast<ContentSettingsType>(i), this); | |
| 495 content_setting_views_.push_back(content_setting_view); | |
| 496 gtk_box_pack_end(GTK_BOX(content_setting_hbox_.get()), | |
| 497 content_setting_view->widget(), FALSE, FALSE, 0); | |
| 498 } | |
| 499 | |
| 500 page_action_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding)); | |
| 501 gtk_widget_set_name(page_action_hbox_.get(), | |
| 502 "chrome-page-action-hbox"); | |
| 503 gtk_box_pack_end(GTK_BOX(hbox_.get()), page_action_hbox_.get(), | |
| 504 FALSE, FALSE, 0); | |
| 505 | |
| 506 // Now that we've created the widget hierarchy, connect to the main |hbox_|'s | |
| 507 // size-allocate so we can do proper resizing and eliding on | |
| 508 // |security_info_label_|. | |
| 509 g_signal_connect(hbox_.get(), "size-allocate", | |
| 510 G_CALLBACK(&OnHboxSizeAllocateThunk), this); | |
| 511 | |
| 512 registrar_.Add(this, | |
| 513 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | |
| 514 content::Source<ThemeService>(theme_service_)); | |
| 515 registrar_.Add(this, | |
| 516 chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED, | |
| 517 content::Source<Profile>(profile())); | |
| 518 edit_bookmarks_enabled_.Init(prefs::kEditBookmarksEnabled, | |
| 519 profile()->GetPrefs(), | |
| 520 base::Bind(&LocationBarViewGtk::UpdateStarIcon, | |
| 521 base::Unretained(this))); | |
| 522 | |
| 523 theme_service_->InitThemesFor(this); | |
| 524 } | |
| 525 | |
| 526 void LocationBarViewGtk::SetPreviewEnabledPageAction( | |
| 527 ExtensionAction* page_action, | |
| 528 bool preview_enabled) { | |
| 529 DCHECK(page_action); | |
| 530 for (ScopedVector<PageActionViewGtk>::iterator iter = | |
| 531 page_action_views_.begin(); iter != page_action_views_.end(); | |
| 532 ++iter) { | |
| 533 if ((*iter)->page_action() == page_action) { | |
| 534 (*iter)->set_preview_enabled(preview_enabled); | |
| 535 UpdatePageActions(); | |
| 536 return; | |
| 537 } | |
| 538 } | |
| 539 } | |
| 540 | |
| 541 GtkWidget* LocationBarViewGtk::GetPageActionWidget( | |
| 542 ExtensionAction* page_action) { | |
| 543 DCHECK(page_action); | |
| 544 for (ScopedVector<PageActionViewGtk>::iterator iter = | |
| 545 page_action_views_.begin(); | |
| 546 iter != page_action_views_.end(); | |
| 547 ++iter) { | |
| 548 if ((*iter)->page_action() == page_action) | |
| 549 return (*iter)->widget(); | |
| 550 } | |
| 551 return NULL; | |
| 552 } | |
| 553 | |
| 554 void LocationBarViewGtk::ShowStarBubble(const GURL& url, | |
| 555 bool newly_bookmarked) { | |
| 556 if (!star_.get()) | |
| 557 return; | |
| 558 | |
| 559 if (star_sized_) { | |
| 560 BookmarkBubbleGtk::Show(star_.get(), profile(), url, newly_bookmarked); | |
| 561 } else { | |
| 562 on_star_sized_ = base::Bind(&BookmarkBubbleGtk::Show, star_.get(), | |
| 563 profile(), url, newly_bookmarked); | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 void LocationBarViewGtk::ShowManagePasswordsBubble() { | |
| 568 if (GetToolbarModel()->input_in_progress() || !GetWebContents()) | |
| 569 return; | |
| 570 | |
| 571 ManagePasswordsBubbleGtk::ShowBubble(GetWebContents()); | |
| 572 } | |
| 573 | |
| 574 void LocationBarViewGtk::ZoomChangedForActiveTab(bool can_show_bubble) { | |
| 575 UpdateZoomIcon(); | |
| 576 | |
| 577 if (can_show_bubble && gtk_widget_get_visible(zoom_.get())) | |
| 578 ShowZoomBubble(); | |
| 579 } | |
| 580 | |
| 581 void LocationBarViewGtk::SetStarred(bool starred) { | |
| 582 if (starred == starred_) | |
| 583 return; | |
| 584 | |
| 585 starred_ = starred; | |
| 586 UpdateStarIcon(); | |
| 587 } | |
| 588 | |
| 589 void LocationBarViewGtk::Update(const WebContents* contents) { | |
| 590 UpdateZoomIcon(); | |
| 591 UpdateStarIcon(); | |
| 592 UpdateSiteTypeArea(); | |
| 593 UpdateContentSettingsIcons(); | |
| 594 UpdatePageActions(); | |
| 595 if (contents) | |
| 596 omnibox_view_->OnTabChanged(contents); | |
| 597 else | |
| 598 omnibox_view_->Update(); | |
| 599 // The security level (background color) could have changed, etc. | |
| 600 if (theme_service_->UsingNativeTheme()) { | |
| 601 // In GTK mode, we need our parent to redraw, as it draws the text entry | |
| 602 // border. | |
| 603 gtk_widget_queue_draw(gtk_widget_get_parent(widget())); | |
| 604 } else { | |
| 605 gtk_widget_queue_draw(widget()); | |
| 606 } | |
| 607 ZoomBubbleGtk::CloseBubble(); | |
| 608 } | |
| 609 | |
| 610 void LocationBarViewGtk::OnChanged() { | |
| 611 UpdateSiteTypeArea(); | |
| 612 | |
| 613 const base::string16 keyword(omnibox_view_->model()->keyword()); | |
| 614 const bool is_keyword_hint = omnibox_view_->model()->is_keyword_hint(); | |
| 615 show_selected_keyword_ = !keyword.empty() && !is_keyword_hint; | |
| 616 show_keyword_hint_ = !keyword.empty() && is_keyword_hint; | |
| 617 | |
| 618 if (show_selected_keyword_) | |
| 619 SetKeywordLabel(keyword); | |
| 620 | |
| 621 if (show_keyword_hint_) | |
| 622 SetKeywordHintLabel(keyword); | |
| 623 | |
| 624 AdjustChildrenVisibility(); | |
| 625 } | |
| 626 | |
| 627 void LocationBarViewGtk::OnSetFocus() { | |
| 628 AccessibilityTextBoxInfo info(profile(), | |
| 629 l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION), | |
| 630 std::string(), false); | |
| 631 ExtensionAccessibilityEventRouter::GetInstance()->HandleControlEvent( | |
| 632 ui::AX_EVENT_FOCUS, &info); | |
| 633 | |
| 634 // Update the keyword and search hint states. | |
| 635 OnChanged(); | |
| 636 } | |
| 637 | |
| 638 void LocationBarViewGtk::ShowURL() { | |
| 639 omnibox_view_->ShowURL(); | |
| 640 } | |
| 641 | |
| 642 InstantController* LocationBarViewGtk::GetInstant() { | |
| 643 return browser_->instant_controller() ? | |
| 644 browser_->instant_controller()->instant() : NULL; | |
| 645 } | |
| 646 | |
| 647 WebContents* LocationBarViewGtk::GetWebContents() { | |
| 648 return browser_->tab_strip_model()->GetActiveWebContents(); | |
| 649 } | |
| 650 | |
| 651 ToolbarModel* LocationBarViewGtk::GetToolbarModel() { | |
| 652 return browser_->toolbar_model(); | |
| 653 } | |
| 654 | |
| 655 const ToolbarModel* LocationBarViewGtk::GetToolbarModel() const { | |
| 656 return browser_->toolbar_model(); | |
| 657 } | |
| 658 | |
| 659 void LocationBarViewGtk::ShowFirstRunBubble() { | |
| 660 // We need the browser window to be shown before we can show the bubble, but | |
| 661 // we get called before that's happened. | |
| 662 base::MessageLoop::current()->PostTask( | |
| 663 FROM_HERE, | |
| 664 base::Bind(&LocationBarViewGtk::ShowFirstRunBubbleInternal, | |
| 665 weak_ptr_factory_.GetWeakPtr())); | |
| 666 } | |
| 667 | |
| 668 GURL LocationBarViewGtk::GetDestinationURL() const { | |
| 669 return destination_url(); | |
| 670 } | |
| 671 | |
| 672 WindowOpenDisposition LocationBarViewGtk::GetWindowOpenDisposition() const { | |
| 673 return disposition(); | |
| 674 } | |
| 675 | |
| 676 content::PageTransition LocationBarViewGtk::GetPageTransition() const { | |
| 677 return transition(); | |
| 678 } | |
| 679 | |
| 680 void LocationBarViewGtk::AcceptInput() { | |
| 681 omnibox_view_->model()->AcceptInput(CURRENT_TAB, false); | |
| 682 } | |
| 683 | |
| 684 void LocationBarViewGtk::FocusLocation(bool select_all) { | |
| 685 omnibox_view_->SetFocus(); | |
| 686 if (select_all) | |
| 687 omnibox_view_->SelectAll(true); | |
| 688 } | |
| 689 | |
| 690 void LocationBarViewGtk::FocusSearch() { | |
| 691 omnibox_view_->SetFocus(); | |
| 692 omnibox_view_->SetForcedQuery(); | |
| 693 } | |
| 694 | |
| 695 void LocationBarViewGtk::UpdateContentSettingsIcons() { | |
| 696 bool any_visible = false; | |
| 697 for (ScopedVector<PageToolViewGtk>::iterator i( | |
| 698 content_setting_views_.begin()); | |
| 699 i != content_setting_views_.end(); ++i) { | |
| 700 (*i)->Update(GetToolbarModel()->input_in_progress() ? | |
| 701 NULL : GetWebContents()); | |
| 702 any_visible = (*i)->IsVisible() || any_visible; | |
| 703 } | |
| 704 // If there are no visible content things, hide the top level box so it | |
| 705 // doesn't mess with padding. | |
| 706 gtk_widget_set_visible(content_setting_hbox_.get(), any_visible); | |
| 707 } | |
| 708 | |
| 709 void LocationBarViewGtk::UpdateManagePasswordsIconAndBubble() { | |
| 710 UpdateManagePasswordsIcon(); | |
| 711 } | |
| 712 | |
| 713 void LocationBarViewGtk::UpdatePageActions() { | |
| 714 std::vector<ExtensionAction*> new_page_actions; | |
| 715 | |
| 716 WebContents* contents = GetWebContents(); | |
| 717 if (contents) { | |
| 718 LocationBarController* location_bar_controller = | |
| 719 extensions::TabHelper::FromWebContents(contents)-> | |
| 720 location_bar_controller(); | |
| 721 new_page_actions = location_bar_controller->GetCurrentActions(); | |
| 722 } | |
| 723 | |
| 724 // Initialize on the first call, or re-initialize if more extensions have been | |
| 725 // loaded or added after startup. | |
| 726 if (new_page_actions != page_actions_) { | |
| 727 page_actions_.swap(new_page_actions); | |
| 728 page_action_views_.clear(); | |
| 729 | |
| 730 for (size_t i = 0; i < page_actions_.size(); ++i) { | |
| 731 page_action_views_.push_back( | |
| 732 new PageActionViewGtk(this, page_actions_[i])); | |
| 733 gtk_box_pack_end(GTK_BOX(page_action_hbox_.get()), | |
| 734 page_action_views_[i]->widget(), FALSE, FALSE, 0); | |
| 735 } | |
| 736 content::NotificationService::current()->Notify( | |
| 737 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED, | |
| 738 content::Source<LocationBar>(this), | |
| 739 content::NotificationService::NoDetails()); | |
| 740 } | |
| 741 | |
| 742 if (!page_action_views_.empty() && contents) { | |
| 743 GURL url = GetWebContents()->GetURL(); | |
| 744 | |
| 745 for (size_t i = 0; i < page_action_views_.size(); i++) { | |
| 746 page_action_views_[i]->UpdateVisibility( | |
| 747 GetToolbarModel()->input_in_progress() ? NULL : contents, url); | |
| 748 } | |
| 749 gtk_widget_queue_draw(hbox_.get()); | |
| 750 } | |
| 751 | |
| 752 // If there are no visible page actions, hide the hbox too, so that it does | |
| 753 // not affect the padding in the location bar. | |
| 754 gtk_widget_set_visible(page_action_hbox_.get(), | |
| 755 PageActionVisibleCount() && !ShouldOnlyShowLocation()); | |
| 756 } | |
| 757 | |
| 758 void LocationBarViewGtk::InvalidatePageActions() { | |
| 759 size_t count_before = page_action_views_.size(); | |
| 760 page_action_views_.clear(); | |
| 761 if (page_action_views_.size() != count_before) { | |
| 762 content::NotificationService::current()->Notify( | |
| 763 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED, | |
| 764 content::Source<LocationBar>(this), | |
| 765 content::NotificationService::NoDetails()); | |
| 766 } | |
| 767 } | |
| 768 | |
| 769 void LocationBarViewGtk::UpdateOpenPDFInReaderPrompt() { | |
| 770 // Not implemented on Gtk. | |
| 771 } | |
| 772 | |
| 773 void LocationBarViewGtk::UpdateGeneratedCreditCardView() { | |
| 774 NOTIMPLEMENTED(); | |
| 775 } | |
| 776 | |
| 777 void LocationBarViewGtk::SaveStateToContents(WebContents* contents) { | |
| 778 omnibox_view_->SaveStateToTab(contents); | |
| 779 } | |
| 780 | |
| 781 void LocationBarViewGtk::Revert() { | |
| 782 omnibox_view_->RevertAll(); | |
| 783 } | |
| 784 | |
| 785 const OmniboxView* LocationBarViewGtk::GetOmniboxView() const { | |
| 786 return omnibox_view_.get(); | |
| 787 } | |
| 788 | |
| 789 OmniboxView* LocationBarViewGtk::GetOmniboxView() { | |
| 790 return omnibox_view_.get(); | |
| 791 } | |
| 792 | |
| 793 LocationBarTesting* LocationBarViewGtk::GetLocationBarForTesting() { | |
| 794 return this; | |
| 795 } | |
| 796 | |
| 797 int LocationBarViewGtk::PageActionCount() { | |
| 798 return page_action_views_.size(); | |
| 799 } | |
| 800 | |
| 801 int LocationBarViewGtk::PageActionVisibleCount() { | |
| 802 int count = 0; | |
| 803 gtk_container_foreach(GTK_CONTAINER(page_action_hbox_.get()), | |
| 804 CountVisibleWidgets, &count); | |
| 805 return count; | |
| 806 } | |
| 807 | |
| 808 ExtensionAction* LocationBarViewGtk::GetPageAction(size_t index) { | |
| 809 if (index >= page_action_views_.size()) { | |
| 810 NOTREACHED(); | |
| 811 return NULL; | |
| 812 } | |
| 813 | |
| 814 return page_action_views_[index]->page_action(); | |
| 815 } | |
| 816 | |
| 817 ExtensionAction* LocationBarViewGtk::GetVisiblePageAction(size_t index) { | |
| 818 size_t visible_index = 0; | |
| 819 for (size_t i = 0; i < page_action_views_.size(); ++i) { | |
| 820 if (page_action_views_[i]->IsVisible()) { | |
| 821 if (index == visible_index++) | |
| 822 return page_action_views_[i]->page_action(); | |
| 823 } | |
| 824 } | |
| 825 | |
| 826 NOTREACHED(); | |
| 827 return NULL; | |
| 828 } | |
| 829 | |
| 830 void LocationBarViewGtk::TestPageActionPressed(size_t index) { | |
| 831 if (index >= page_action_views_.size()) { | |
| 832 NOTREACHED(); | |
| 833 return; | |
| 834 } | |
| 835 | |
| 836 page_action_views_[index]->TestActivatePageAction(); | |
| 837 } | |
| 838 | |
| 839 bool LocationBarViewGtk::GetBookmarkStarVisibility() { | |
| 840 return starred_; | |
| 841 } | |
| 842 | |
| 843 void LocationBarViewGtk::Observe(int type, | |
| 844 const content::NotificationSource& source, | |
| 845 const content::NotificationDetails& details) { | |
| 846 switch (type) { | |
| 847 case chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED: { | |
| 848 // Only update if the updated action box was for the active tab contents. | |
| 849 WebContents* target_tab = content::Details<WebContents>(details).ptr(); | |
| 850 if (target_tab == GetWebContents()) | |
| 851 UpdatePageActions(); | |
| 852 break; | |
| 853 } | |
| 854 | |
| 855 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: { | |
| 856 if (theme_service_->UsingNativeTheme()) { | |
| 857 gtk_widget_modify_bg(tab_to_search_box_, GTK_STATE_NORMAL, NULL); | |
| 858 | |
| 859 GdkColor border_color = theme_service_->GetGdkColor( | |
| 860 ThemeProperties::COLOR_FRAME); | |
| 861 gtk_util::SetRoundedWindowBorderColor(tab_to_search_box_, border_color); | |
| 862 | |
| 863 gtk_util::UndoForceFontSize(security_info_label_); | |
| 864 gtk_util::UndoForceFontSize(tab_to_search_full_label_); | |
| 865 gtk_util::UndoForceFontSize(tab_to_search_partial_label_); | |
| 866 gtk_util::UndoForceFontSize(tab_to_search_hint_leading_label_); | |
| 867 gtk_util::UndoForceFontSize(tab_to_search_hint_trailing_label_); | |
| 868 | |
| 869 gtk_alignment_set_padding(GTK_ALIGNMENT(omnibox_view_alignment_), | |
| 870 0, 0, 0, 0); | |
| 871 gtk_alignment_set_padding(GTK_ALIGNMENT(tab_to_search_alignment_), | |
| 872 1, 1, 1, 0); | |
| 873 gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_), | |
| 874 1, 1, 1, 0); | |
| 875 } else { | |
| 876 gtk_widget_modify_bg(tab_to_search_box_, GTK_STATE_NORMAL, | |
| 877 &kKeywordBackgroundColor); | |
| 878 gtk_util::SetRoundedWindowBorderColor(tab_to_search_box_, | |
| 879 kKeywordBorderColor); | |
| 880 | |
| 881 // Until we switch to vector graphics, force the font size of labels. | |
| 882 // 12.1px = 9pt @ 96dpi | |
| 883 gtk_util::ForceFontSizePixels(security_info_label_, 12.1); | |
| 884 gtk_util::ForceFontSizePixels(tab_to_search_full_label_, | |
| 885 browser_defaults::kOmniboxFontPixelSize); | |
| 886 gtk_util::ForceFontSizePixels(tab_to_search_partial_label_, | |
| 887 browser_defaults::kOmniboxFontPixelSize); | |
| 888 gtk_util::ForceFontSizePixels(tab_to_search_hint_leading_label_, | |
| 889 browser_defaults::kOmniboxFontPixelSize); | |
| 890 gtk_util::ForceFontSizePixels(tab_to_search_hint_trailing_label_, | |
| 891 browser_defaults::kOmniboxFontPixelSize); | |
| 892 | |
| 893 const int left_right = popup_window_mode_ ? kPopupEdgeThickness : 0; | |
| 894 gtk_alignment_set_padding(GTK_ALIGNMENT(omnibox_view_alignment_), | |
| 895 kBorderThickness, kBorderThickness, | |
| 896 left_right, left_right); | |
| 897 gtk_alignment_set_padding(GTK_ALIGNMENT(tab_to_search_alignment_), | |
| 898 1, 1, 0, 0); | |
| 899 gtk_alignment_set_padding(GTK_ALIGNMENT(site_type_alignment_), | |
| 900 1, 1, 0, 0); | |
| 901 } | |
| 902 | |
| 903 UpdateZoomIcon(); | |
| 904 UpdateManagePasswordsIcon(); | |
| 905 UpdateStarIcon(); | |
| 906 UpdateSiteTypeArea(); | |
| 907 UpdateContentSettingsIcons(); | |
| 908 break; | |
| 909 } | |
| 910 | |
| 911 default: | |
| 912 NOTREACHED(); | |
| 913 } | |
| 914 } | |
| 915 | |
| 916 void LocationBarViewGtk::BuildSiteTypeArea() { | |
| 917 location_icon_image_ = gtk_image_new(); | |
| 918 gtk_widget_set_name(location_icon_image_, "chrome-location-icon"); | |
| 919 | |
| 920 GtkWidget* icon_alignment = gtk_alignment_new(0, 0, 1, 1); | |
| 921 gtk_alignment_set_padding(GTK_ALIGNMENT(icon_alignment), 0, 0, 2, 0); | |
| 922 gtk_container_add(GTK_CONTAINER(icon_alignment), location_icon_image_); | |
| 923 gtk_widget_show_all(icon_alignment); | |
| 924 | |
| 925 security_info_label_ = gtk_label_new(NULL); | |
| 926 gtk_label_set_ellipsize(GTK_LABEL(security_info_label_), | |
| 927 PANGO_ELLIPSIZE_MIDDLE); | |
| 928 gtk_widget_modify_fg(GTK_WIDGET(security_info_label_), GTK_STATE_NORMAL, | |
| 929 &kEvSecureTextColor); | |
| 930 gtk_widget_set_name(security_info_label_, | |
| 931 "chrome-location-bar-security-info-label"); | |
| 932 | |
| 933 GtkWidget* site_type_hbox = gtk_hbox_new(FALSE, 1); | |
| 934 gtk_box_pack_start(GTK_BOX(site_type_hbox), icon_alignment, | |
| 935 FALSE, FALSE, 0); | |
| 936 gtk_box_pack_start(GTK_BOX(site_type_hbox), security_info_label_, | |
| 937 FALSE, FALSE, 2); | |
| 938 | |
| 939 site_type_event_box_ = gtk_event_box_new(); | |
| 940 gtk_widget_modify_bg(site_type_event_box_, GTK_STATE_NORMAL, | |
| 941 &kEvSecureBackgroundColor); | |
| 942 g_signal_connect(site_type_event_box_, "drag-data-get", | |
| 943 G_CALLBACK(&OnIconDragDataThunk), this); | |
| 944 g_signal_connect(site_type_event_box_, "drag-begin", | |
| 945 G_CALLBACK(&OnIconDragBeginThunk), this); | |
| 946 g_signal_connect(site_type_event_box_, "drag-end", | |
| 947 G_CALLBACK(&OnIconDragEndThunk), this); | |
| 948 | |
| 949 // Make the event box not visible so it does not paint a background. | |
| 950 gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_), | |
| 951 FALSE); | |
| 952 gtk_widget_set_name(site_type_event_box_, | |
| 953 "chrome-location-icon-eventbox"); | |
| 954 gtk_container_add(GTK_CONTAINER(site_type_event_box_), | |
| 955 site_type_hbox); | |
| 956 | |
| 957 // Put the event box in an alignment to get the padding correct. | |
| 958 site_type_alignment_ = gtk_alignment_new(0, 0, 1, 1); | |
| 959 gtk_container_add(GTK_CONTAINER(site_type_alignment_), | |
| 960 site_type_event_box_); | |
| 961 gtk_box_pack_start(GTK_BOX(hbox_.get()), site_type_alignment_, | |
| 962 FALSE, FALSE, 0); | |
| 963 | |
| 964 gtk_widget_set_tooltip_text(location_icon_image_, | |
| 965 l10n_util::GetStringUTF8(IDS_TOOLTIP_LOCATION_ICON).c_str()); | |
| 966 | |
| 967 g_signal_connect(site_type_event_box_, "button-release-event", | |
| 968 G_CALLBACK(&OnIconReleasedThunk), this); | |
| 969 } | |
| 970 | |
| 971 void LocationBarViewGtk::SetSiteTypeDragSource() { | |
| 972 bool enable = !GetOmniboxView()->IsEditingOrEmpty(); | |
| 973 if (enable_location_drag_ == enable) | |
| 974 return; | |
| 975 enable_location_drag_ = enable; | |
| 976 | |
| 977 if (!enable) { | |
| 978 gtk_drag_source_unset(site_type_event_box_); | |
| 979 return; | |
| 980 } | |
| 981 | |
| 982 gtk_drag_source_set(site_type_event_box_, GDK_BUTTON1_MASK, | |
| 983 NULL, 0, GDK_ACTION_COPY); | |
| 984 ui::SetSourceTargetListFromCodeMask(site_type_event_box_, | |
| 985 ui::TEXT_PLAIN | | |
| 986 ui::TEXT_URI_LIST | | |
| 987 ui::CHROME_NAMED_URL); | |
| 988 } | |
| 989 | |
| 990 gboolean LocationBarViewGtk::HandleExpose(GtkWidget* widget, | |
| 991 GdkEventExpose* event) { | |
| 992 // If we're not using GTK theming, draw our own border over the edge pixels | |
| 993 // of the background. | |
| 994 GtkThemeService* theme_service = GtkThemeService::GetFrom(profile()); | |
| 995 if (!theme_service->UsingNativeTheme()) { | |
| 996 // Perform a scoped paint to fill in the background color. | |
| 997 { | |
| 998 gfx::CanvasSkiaPaint canvas(event, /*opaque=*/false); | |
| 999 | |
| 1000 GtkAllocation allocation; | |
| 1001 gtk_widget_get_allocation(widget, &allocation); | |
| 1002 | |
| 1003 int thickness = popup_window_mode_ ? | |
| 1004 kPopupEdgeThickness : kNormalEdgeThickness; | |
| 1005 gfx::Rect bounds(allocation); | |
| 1006 bounds.Inset(thickness, thickness); | |
| 1007 | |
| 1008 const SkColor color = SK_ColorWHITE; | |
| 1009 if (popup_window_mode_) { | |
| 1010 canvas.FillRect(bounds, color); | |
| 1011 } else { | |
| 1012 SkPaint paint; | |
| 1013 paint.setStyle(SkPaint::kFill_Style); | |
| 1014 paint.setColor(color); | |
| 1015 const int kBorderCornerRadius = 2; | |
| 1016 canvas.DrawRoundRect(bounds, kBorderCornerRadius, paint); | |
| 1017 } | |
| 1018 } | |
| 1019 | |
| 1020 if (popup_window_mode_) { | |
| 1021 NineBox(IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP_LEFT, | |
| 1022 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP, | |
| 1023 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP_RIGHT, | |
| 1024 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_LEFT, | |
| 1025 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_CENTER, | |
| 1026 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_RIGHT, | |
| 1027 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_BOTTOM_LEFT, | |
| 1028 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_BOTTOM, | |
| 1029 IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_BOTTOM_RIGHT). | |
| 1030 RenderToWidget(widget); | |
| 1031 } else { | |
| 1032 NineBox(IDR_TEXTFIELD_TOP_LEFT, | |
| 1033 IDR_TEXTFIELD_TOP, | |
| 1034 IDR_TEXTFIELD_TOP_RIGHT, | |
| 1035 IDR_TEXTFIELD_LEFT, | |
| 1036 IDR_TEXTFIELD_CENTER, | |
| 1037 IDR_TEXTFIELD_RIGHT, | |
| 1038 IDR_TEXTFIELD_BOTTOM_LEFT, | |
| 1039 IDR_TEXTFIELD_BOTTOM, | |
| 1040 IDR_TEXTFIELD_BOTTOM_RIGHT). | |
| 1041 RenderToWidget(widget); | |
| 1042 } | |
| 1043 } | |
| 1044 | |
| 1045 return FALSE; // Continue propagating the expose. | |
| 1046 } | |
| 1047 | |
| 1048 gboolean LocationBarViewGtk::OnIconReleased(GtkWidget* sender, | |
| 1049 GdkEventButton* event) { | |
| 1050 WebContents* tab = GetWebContents(); | |
| 1051 | |
| 1052 if (event->button == 1) { | |
| 1053 // Do not show page info if the user has been editing the location | |
| 1054 // bar, or the location bar is at the NTP. | |
| 1055 if (GetOmniboxView()->IsEditingOrEmpty()) | |
| 1056 return FALSE; | |
| 1057 | |
| 1058 // (0,0) event coordinates indicates that the release came at the end of | |
| 1059 // a drag. | |
| 1060 if (event->x == 0 && event->y == 0) | |
| 1061 return FALSE; | |
| 1062 | |
| 1063 // Important to use GetVisibleEntry to match what's showing in the omnibox. | |
| 1064 NavigationEntry* nav_entry = tab->GetController().GetVisibleEntry(); | |
| 1065 if (!nav_entry) { | |
| 1066 NOTREACHED(); | |
| 1067 return FALSE; | |
| 1068 } | |
| 1069 chrome::ShowWebsiteSettings(browser_, tab, nav_entry->GetURL(), | |
| 1070 nav_entry->GetSSL()); | |
| 1071 return TRUE; | |
| 1072 } else if (event->button == 2) { | |
| 1073 // When the user middle clicks on the location icon, try to open the | |
| 1074 // contents of the PRIMARY selection in the current tab. | |
| 1075 // If the click was outside our bounds, do nothing. | |
| 1076 if (!gtk_util::WidgetBounds(sender).Contains( | |
| 1077 gfx::Point(event->x, event->y))) { | |
| 1078 return FALSE; | |
| 1079 } | |
| 1080 | |
| 1081 GURL url; | |
| 1082 if (!gtk_util::URLFromPrimarySelection(profile(), &url)) | |
| 1083 return FALSE; | |
| 1084 | |
| 1085 tab->OpenURL(OpenURLParams( | |
| 1086 url, content::Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, | |
| 1087 false)); | |
| 1088 return TRUE; | |
| 1089 } | |
| 1090 | |
| 1091 return FALSE; | |
| 1092 } | |
| 1093 | |
| 1094 void LocationBarViewGtk::OnIconDragData(GtkWidget* sender, | |
| 1095 GdkDragContext* context, | |
| 1096 GtkSelectionData* data, | |
| 1097 guint info, guint time) { | |
| 1098 ui::WriteURLWithName(data, drag_url_, drag_title_, info); | |
| 1099 } | |
| 1100 | |
| 1101 void LocationBarViewGtk::OnIconDragBegin(GtkWidget* sender, | |
| 1102 GdkDragContext* context) { | |
| 1103 content::WebContents* web_contents = GetWebContents(); | |
| 1104 gfx::Image favicon = | |
| 1105 FaviconTabHelper::FromWebContents(web_contents)->GetFavicon(); | |
| 1106 if (favicon.IsEmpty()) | |
| 1107 return; | |
| 1108 drag_url_ = web_contents->GetURL(); | |
| 1109 drag_title_ = web_contents->GetTitle(); | |
| 1110 drag_icon_ = GetDragRepresentation(favicon.ToGdkPixbuf(), drag_title_, | |
| 1111 theme_service_); | |
| 1112 gtk_drag_set_icon_widget(context, drag_icon_, 0, 0); | |
| 1113 } | |
| 1114 | |
| 1115 void LocationBarViewGtk::OnIconDragEnd(GtkWidget* sender, | |
| 1116 GdkDragContext* context) { | |
| 1117 DCHECK(drag_icon_); | |
| 1118 gtk_widget_destroy(drag_icon_); | |
| 1119 drag_icon_ = NULL; | |
| 1120 drag_url_ = GURL::EmptyGURL(); | |
| 1121 drag_title_.clear(); | |
| 1122 } | |
| 1123 | |
| 1124 void LocationBarViewGtk::OnHboxSizeAllocate(GtkWidget* sender, | |
| 1125 GtkAllocation* allocation) { | |
| 1126 if (hbox_width_ != allocation->width) { | |
| 1127 hbox_width_ = allocation->width; | |
| 1128 UpdateEVCertificateLabelSize(); | |
| 1129 } | |
| 1130 InstantService* instant_service = | |
| 1131 InstantServiceFactory::GetForProfile(profile()); | |
| 1132 if (instant_service) { | |
| 1133 instant_service->OnOmniboxStartMarginChanged( | |
| 1134 AllocationToRect(*allocation).x()); | |
| 1135 } | |
| 1136 } | |
| 1137 | |
| 1138 void LocationBarViewGtk::OnEntryBoxSizeAllocate(GtkWidget* sender, | |
| 1139 GtkAllocation* allocation) { | |
| 1140 if (entry_box_width_ != allocation->width) { | |
| 1141 entry_box_width_ = allocation->width; | |
| 1142 AdjustChildrenVisibility(); | |
| 1143 } | |
| 1144 } | |
| 1145 | |
| 1146 gboolean LocationBarViewGtk::OnZoomButtonPress(GtkWidget* widget, | |
| 1147 GdkEventButton* event) { | |
| 1148 if (event->button == 1 && GetWebContents()) { | |
| 1149 // If the zoom icon is clicked, show the zoom bubble and keep it open until | |
| 1150 // it loses focus. | |
| 1151 ZoomBubbleGtk::ShowBubble(GetWebContents(), false); | |
| 1152 return TRUE; | |
| 1153 } | |
| 1154 return FALSE; | |
| 1155 } | |
| 1156 | |
| 1157 gboolean LocationBarViewGtk::OnManagePasswordsIconButtonPress( | |
| 1158 GtkWidget* widget, GdkEventButton* event) { | |
| 1159 if (event->button == 1 && GetWebContents()) { | |
| 1160 // If the manage passwords icon is clicked, show the manage passwords bubble | |
| 1161 // and keep it open until the user makes a choice or clicks outside the | |
| 1162 // bubble. | |
| 1163 ManagePasswordsBubbleGtk::ShowBubble(GetWebContents()); | |
| 1164 return TRUE; | |
| 1165 } | |
| 1166 return FALSE; | |
| 1167 } | |
| 1168 | |
| 1169 void LocationBarViewGtk::OnStarButtonSizeAllocate(GtkWidget* sender, | |
| 1170 GtkAllocation* allocation) { | |
| 1171 if (!on_star_sized_.is_null()) { | |
| 1172 on_star_sized_.Run(); | |
| 1173 on_star_sized_.Reset(); | |
| 1174 } | |
| 1175 star_sized_ = true; | |
| 1176 } | |
| 1177 | |
| 1178 gboolean LocationBarViewGtk::OnStarButtonPress(GtkWidget* widget, | |
| 1179 GdkEventButton* event) { | |
| 1180 if (event->button != 1) | |
| 1181 return FALSE; | |
| 1182 chrome::ExecuteCommand(browser_, IDC_BOOKMARK_PAGE_FROM_STAR); | |
| 1183 return TRUE; | |
| 1184 } | |
| 1185 | |
| 1186 void LocationBarViewGtk::UpdateSiteTypeArea() { | |
| 1187 // The icon is always visible except when the |tab_to_search_alignment_| is | |
| 1188 // visible. | |
| 1189 if (!omnibox_view_->model()->keyword().empty() && | |
| 1190 !omnibox_view_->model()->is_keyword_hint()) { | |
| 1191 gtk_widget_hide(site_type_area()); | |
| 1192 return; | |
| 1193 } | |
| 1194 | |
| 1195 int resource_id = omnibox_view_->GetIcon(); | |
| 1196 gtk_image_set_from_pixbuf( | |
| 1197 GTK_IMAGE(location_icon_image_), | |
| 1198 theme_service_->GetImageNamed(resource_id).ToGdkPixbuf()); | |
| 1199 | |
| 1200 if (GetToolbarModel()->GetSecurityLevel(false) == ToolbarModel::EV_SECURE) { | |
| 1201 if (!gtk_util::IsActingAsRoundedWindow(site_type_event_box_)) { | |
| 1202 // Fun fact: If wee try to make |site_type_event_box_| act as a | |
| 1203 // rounded window while it doesn't have a visible window, GTK interprets | |
| 1204 // this as a sign that it should paint the skyline texture into the | |
| 1205 // omnibox. | |
| 1206 gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_), | |
| 1207 TRUE); | |
| 1208 | |
| 1209 gtk_util::ActAsRoundedWindow(site_type_event_box_, | |
| 1210 kEvSecureBorderColor, | |
| 1211 kCornerSize, | |
| 1212 gtk_util::ROUNDED_ALL, | |
| 1213 gtk_util::BORDER_ALL); | |
| 1214 } | |
| 1215 | |
| 1216 base::string16 info_text = GetToolbarModel()->GetEVCertName(); | |
| 1217 gtk_label_set_text(GTK_LABEL(security_info_label_), | |
| 1218 base::UTF16ToUTF8(info_text).c_str()); | |
| 1219 | |
| 1220 UpdateEVCertificateLabelSize(); | |
| 1221 | |
| 1222 gtk_widget_show(GTK_WIDGET(security_info_label_)); | |
| 1223 } else { | |
| 1224 if (gtk_util::IsActingAsRoundedWindow(site_type_event_box_)) { | |
| 1225 gtk_util::StopActingAsRoundedWindow(site_type_event_box_); | |
| 1226 | |
| 1227 gtk_event_box_set_visible_window(GTK_EVENT_BOX(site_type_event_box_), | |
| 1228 FALSE); | |
| 1229 } | |
| 1230 | |
| 1231 gtk_widget_hide(GTK_WIDGET(security_info_label_)); | |
| 1232 } | |
| 1233 | |
| 1234 if (GetOmniboxView()->IsEditingOrEmpty()) { | |
| 1235 // Do not show the tooltip if the user has been editing the location | |
| 1236 // bar, or the location bar is at the NTP. | |
| 1237 gtk_widget_set_tooltip_text(location_icon_image_, ""); | |
| 1238 } else { | |
| 1239 gtk_widget_set_tooltip_text(location_icon_image_, | |
| 1240 l10n_util::GetStringUTF8(IDS_TOOLTIP_LOCATION_ICON).c_str()); | |
| 1241 } | |
| 1242 | |
| 1243 gtk_widget_show(site_type_area()); | |
| 1244 | |
| 1245 SetSiteTypeDragSource(); | |
| 1246 } | |
| 1247 | |
| 1248 void LocationBarViewGtk::UpdateEVCertificateLabelSize() { | |
| 1249 // Figure out the width of the average character. | |
| 1250 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(security_info_label_)); | |
| 1251 PangoContext* context = pango_layout_get_context(layout); | |
| 1252 PangoFontMetrics* metrics = pango_context_get_metrics( | |
| 1253 context, | |
| 1254 gtk_widget_get_style(security_info_label_)->font_desc, | |
| 1255 pango_context_get_language(context)); | |
| 1256 int char_width = | |
| 1257 pango_font_metrics_get_approximate_char_width(metrics) / PANGO_SCALE; | |
| 1258 | |
| 1259 // The EV label should never take up more than half the hbox. We try to | |
| 1260 // correct our inaccurate measurement units ("the average character width") | |
| 1261 // by dividing more than an even 2. | |
| 1262 GtkAllocation security_label_allocation; | |
| 1263 gtk_widget_get_allocation(security_info_label_, &security_label_allocation); | |
| 1264 GtkAllocation entry_box_allocation; | |
| 1265 gtk_widget_get_allocation(entry_box_, &entry_box_allocation); | |
| 1266 int text_area = security_label_allocation.width + | |
| 1267 entry_box_allocation.width; | |
| 1268 int max_chars = static_cast<int>(static_cast<float>(text_area) / | |
| 1269 static_cast<float>(char_width) / 2.75); | |
| 1270 // Don't let the label be smaller than 10 characters so that the country | |
| 1271 // code is always visible. | |
| 1272 gtk_label_set_max_width_chars(GTK_LABEL(security_info_label_), | |
| 1273 std::max(10, max_chars)); | |
| 1274 | |
| 1275 pango_font_metrics_unref(metrics); | |
| 1276 } | |
| 1277 | |
| 1278 void LocationBarViewGtk::SetKeywordLabel(const base::string16& keyword) { | |
| 1279 if (keyword.empty()) | |
| 1280 return; | |
| 1281 | |
| 1282 TemplateURLService* template_url_service = | |
| 1283 TemplateURLServiceFactory::GetForProfile(profile()); | |
| 1284 if (!template_url_service) | |
| 1285 return; | |
| 1286 | |
| 1287 bool is_extension_keyword; | |
| 1288 const base::string16 short_name = template_url_service->GetKeywordShortName( | |
| 1289 keyword, &is_extension_keyword); | |
| 1290 const base::string16 min_string = | |
| 1291 location_bar_util::CalculateMinString(short_name); | |
| 1292 const base::string16 full_name = is_extension_keyword ? | |
| 1293 short_name : | |
| 1294 l10n_util::GetStringFUTF16(IDS_OMNIBOX_KEYWORD_TEXT, short_name); | |
| 1295 const base::string16 partial_name = is_extension_keyword ? | |
| 1296 min_string : | |
| 1297 l10n_util::GetStringFUTF16(IDS_OMNIBOX_KEYWORD_TEXT, min_string); | |
| 1298 gtk_label_set_text(GTK_LABEL(tab_to_search_full_label_), | |
| 1299 base::UTF16ToUTF8(full_name).c_str()); | |
| 1300 gtk_label_set_text(GTK_LABEL(tab_to_search_partial_label_), | |
| 1301 base::UTF16ToUTF8(partial_name).c_str()); | |
| 1302 | |
| 1303 if (last_keyword_ != keyword) { | |
| 1304 last_keyword_ = keyword; | |
| 1305 | |
| 1306 if (is_extension_keyword) { | |
| 1307 const TemplateURL* template_url = | |
| 1308 template_url_service->GetTemplateURLForKeyword(keyword); | |
| 1309 gfx::Image image = extensions::OmniboxAPI::Get(profile())-> | |
| 1310 GetOmniboxIcon(template_url->GetExtensionId()); | |
| 1311 gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_), | |
| 1312 image.ToGdkPixbuf()); | |
| 1313 } else { | |
| 1314 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 1315 gtk_image_set_from_pixbuf(GTK_IMAGE(tab_to_search_magnifier_), | |
| 1316 rb.GetNativeImageNamed(IDR_OMNIBOX_SEARCH).ToGdkPixbuf()); | |
| 1317 } | |
| 1318 } | |
| 1319 } | |
| 1320 | |
| 1321 void LocationBarViewGtk::SetKeywordHintLabel(const base::string16& keyword) { | |
| 1322 if (keyword.empty()) | |
| 1323 return; | |
| 1324 | |
| 1325 TemplateURLService* template_url_service = | |
| 1326 TemplateURLServiceFactory::GetForProfile(profile()); | |
| 1327 if (!template_url_service) | |
| 1328 return; | |
| 1329 | |
| 1330 bool is_extension_keyword; | |
| 1331 const base::string16 short_name = template_url_service-> | |
| 1332 GetKeywordShortName(keyword, &is_extension_keyword); | |
| 1333 int message_id = is_extension_keyword ? | |
| 1334 IDS_OMNIBOX_EXTENSION_KEYWORD_HINT : IDS_OMNIBOX_KEYWORD_HINT; | |
| 1335 std::vector<size_t> content_param_offsets; | |
| 1336 const base::string16 keyword_hint = l10n_util::GetStringFUTF16( | |
| 1337 message_id, | |
| 1338 base::string16(), | |
| 1339 short_name, | |
| 1340 &content_param_offsets); | |
| 1341 if (content_param_offsets.size() != 2) { | |
| 1342 // See comments on an identical NOTREACHED() in search_provider.cc. | |
| 1343 NOTREACHED(); | |
| 1344 return; | |
| 1345 } | |
| 1346 | |
| 1347 std::string leading(base::UTF16ToUTF8( | |
| 1348 keyword_hint.substr(0, content_param_offsets.front()))); | |
| 1349 std::string trailing(base::UTF16ToUTF8( | |
| 1350 keyword_hint.substr(content_param_offsets.front()))); | |
| 1351 gtk_label_set_text(GTK_LABEL(tab_to_search_hint_leading_label_), | |
| 1352 leading.c_str()); | |
| 1353 gtk_label_set_text(GTK_LABEL(tab_to_search_hint_trailing_label_), | |
| 1354 trailing.c_str()); | |
| 1355 } | |
| 1356 | |
| 1357 void LocationBarViewGtk::ShowFirstRunBubbleInternal() { | |
| 1358 if (!omnibox_view_.get() || !gtk_widget_get_window(widget())) | |
| 1359 return; | |
| 1360 | |
| 1361 gfx::Rect bounds = gtk_util::WidgetBounds(location_icon_image_); | |
| 1362 bounds.set_x(bounds.x() + kFirstRunBubbleLeftSpacing); | |
| 1363 FirstRunBubble::Show(browser_, location_icon_image_, bounds); | |
| 1364 } | |
| 1365 | |
| 1366 void LocationBarViewGtk::ShowZoomBubble() { | |
| 1367 if (GetToolbarModel()->input_in_progress() || !GetWebContents()) | |
| 1368 return; | |
| 1369 | |
| 1370 ZoomBubbleGtk::ShowBubble(GetWebContents(), true); | |
| 1371 } | |
| 1372 | |
| 1373 void LocationBarViewGtk::AdjustChildrenVisibility() { | |
| 1374 int text_width = omnibox_view_->GetTextWidth(); | |
| 1375 int available_width = entry_box_width_ - text_width - kInnerPadding; | |
| 1376 | |
| 1377 // Only one of |tab_to_search_alignment_| and |tab_to_search_hint_| can be | |
| 1378 // visible at the same time. | |
| 1379 if (!show_selected_keyword_ && | |
| 1380 gtk_widget_get_visible(tab_to_search_alignment_)) { | |
| 1381 gtk_widget_hide(tab_to_search_alignment_); | |
| 1382 } else if (!show_keyword_hint_ && | |
| 1383 gtk_widget_get_visible(tab_to_search_hint_)) { | |
| 1384 gtk_widget_hide(tab_to_search_hint_); | |
| 1385 } | |
| 1386 | |
| 1387 if (show_selected_keyword_) { | |
| 1388 GtkRequisition box, full_label, partial_label; | |
| 1389 gtk_widget_size_request(tab_to_search_box_, &box); | |
| 1390 gtk_widget_size_request(tab_to_search_full_label_, &full_label); | |
| 1391 gtk_widget_size_request(tab_to_search_partial_label_, &partial_label); | |
| 1392 int full_partial_width_diff = full_label.width - partial_label.width; | |
| 1393 int full_box_width; | |
| 1394 int partial_box_width; | |
| 1395 if (gtk_widget_get_visible(tab_to_search_full_label_)) { | |
| 1396 full_box_width = box.width; | |
| 1397 partial_box_width = full_box_width - full_partial_width_diff; | |
| 1398 } else { | |
| 1399 partial_box_width = box.width; | |
| 1400 full_box_width = partial_box_width + full_partial_width_diff; | |
| 1401 } | |
| 1402 | |
| 1403 if (partial_box_width >= entry_box_width_ - kInnerPadding) { | |
| 1404 gtk_widget_hide(tab_to_search_alignment_); | |
| 1405 } else if (full_box_width >= available_width) { | |
| 1406 gtk_widget_hide(tab_to_search_full_label_); | |
| 1407 gtk_widget_show(tab_to_search_partial_label_); | |
| 1408 gtk_widget_show(tab_to_search_alignment_); | |
| 1409 } else if (full_box_width < available_width) { | |
| 1410 gtk_widget_hide(tab_to_search_partial_label_); | |
| 1411 gtk_widget_show(tab_to_search_full_label_); | |
| 1412 gtk_widget_show(tab_to_search_alignment_); | |
| 1413 } | |
| 1414 } else if (show_keyword_hint_) { | |
| 1415 GtkRequisition leading, icon, trailing; | |
| 1416 gtk_widget_size_request(tab_to_search_hint_leading_label_, &leading); | |
| 1417 gtk_widget_size_request(tab_to_search_hint_icon_, &icon); | |
| 1418 gtk_widget_size_request(tab_to_search_hint_trailing_label_, &trailing); | |
| 1419 int full_width = leading.width + icon.width + trailing.width; | |
| 1420 | |
| 1421 if (icon.width >= entry_box_width_ - kInnerPadding) { | |
| 1422 gtk_widget_hide(tab_to_search_hint_); | |
| 1423 } else if (full_width >= available_width) { | |
| 1424 gtk_widget_hide(tab_to_search_hint_leading_label_); | |
| 1425 gtk_widget_hide(tab_to_search_hint_trailing_label_); | |
| 1426 gtk_widget_show(tab_to_search_hint_); | |
| 1427 } else if (full_width < available_width) { | |
| 1428 gtk_widget_show(tab_to_search_hint_leading_label_); | |
| 1429 gtk_widget_show(tab_to_search_hint_trailing_label_); | |
| 1430 gtk_widget_show(tab_to_search_hint_); | |
| 1431 } | |
| 1432 } | |
| 1433 } | |
| 1434 | |
| 1435 GtkWidget* LocationBarViewGtk::CreateIconButton( | |
| 1436 GtkWidget** image, | |
| 1437 int image_id, | |
| 1438 ViewID debug_id, | |
| 1439 int tooltip_id, | |
| 1440 gboolean (click_callback)(GtkWidget*, GdkEventButton*, gpointer)) { | |
| 1441 *image = image_id ? | |
| 1442 gtk_image_new_from_pixbuf( | |
| 1443 theme_service_->GetImageNamed(image_id).ToGdkPixbuf()) : | |
| 1444 gtk_image_new(); | |
| 1445 | |
| 1446 GtkWidget* alignment = gtk_alignment_new(0, 0, 1, 1); | |
| 1447 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, | |
| 1448 0, kInnerPadding); | |
| 1449 gtk_container_add(GTK_CONTAINER(alignment), *image); | |
| 1450 | |
| 1451 GtkWidget* result = gtk_event_box_new(); | |
| 1452 gtk_event_box_set_visible_window(GTK_EVENT_BOX(result), FALSE); | |
| 1453 gtk_container_add(GTK_CONTAINER(result), alignment); | |
| 1454 gtk_widget_show_all(result); | |
| 1455 | |
| 1456 if (debug_id != VIEW_ID_NONE) | |
| 1457 ViewIDUtil::SetID(result, debug_id); | |
| 1458 | |
| 1459 if (tooltip_id) { | |
| 1460 gtk_widget_set_tooltip_text(result, | |
| 1461 l10n_util::GetStringUTF8(tooltip_id).c_str()); | |
| 1462 } | |
| 1463 | |
| 1464 g_signal_connect(result, "button-press-event", | |
| 1465 G_CALLBACK(click_callback), this); | |
| 1466 | |
| 1467 return result; | |
| 1468 } | |
| 1469 | |
| 1470 void LocationBarViewGtk::CreateZoomButton() { | |
| 1471 zoom_.Own(CreateIconButton(&zoom_image_, | |
| 1472 0, | |
| 1473 VIEW_ID_ZOOM_BUTTON, | |
| 1474 0, | |
| 1475 OnZoomButtonPressThunk)); | |
| 1476 } | |
| 1477 | |
| 1478 void LocationBarViewGtk::CreateManagePasswordsIconButton() { | |
| 1479 manage_passwords_icon_.Own(CreateIconButton( | |
| 1480 &manage_passwords_icon_image_, 0, VIEW_ID_MANAGE_PASSWORDS_ICON_BUTTON, 0, | |
| 1481 OnManagePasswordsIconButtonPressThunk)); | |
| 1482 } | |
| 1483 | |
| 1484 void LocationBarViewGtk::CreateStarButton() { | |
| 1485 star_.Own(CreateIconButton(&star_image_, | |
| 1486 0, | |
| 1487 VIEW_ID_STAR_BUTTON, | |
| 1488 IDS_TOOLTIP_STAR, | |
| 1489 OnStarButtonPressThunk)); | |
| 1490 // We need to track when the star button is resized to show any bubble | |
| 1491 // attached to it at this time. | |
| 1492 g_signal_connect(star_image_, "size-allocate", | |
| 1493 G_CALLBACK(&OnStarButtonSizeAllocateThunk), this); | |
| 1494 } | |
| 1495 | |
| 1496 void LocationBarViewGtk::UpdateZoomIcon() { | |
| 1497 WebContents* web_contents = GetWebContents(); | |
| 1498 if (!zoom_.get() || !web_contents) | |
| 1499 return; | |
| 1500 | |
| 1501 ZoomController* zoom_controller = | |
| 1502 ZoomController::FromWebContents(web_contents); | |
| 1503 if (!zoom_controller || zoom_controller->IsAtDefaultZoom() || | |
| 1504 GetToolbarModel()->input_in_progress()) { | |
| 1505 gtk_widget_hide(zoom_.get()); | |
| 1506 ZoomBubbleGtk::CloseBubble(); | |
| 1507 return; | |
| 1508 } | |
| 1509 | |
| 1510 const int zoom_resource = zoom_controller->GetResourceForZoomLevel(); | |
| 1511 gtk_image_set_from_pixbuf(GTK_IMAGE(zoom_image_), | |
| 1512 theme_service_->GetImageNamed(zoom_resource).ToGdkPixbuf()); | |
| 1513 | |
| 1514 base::string16 tooltip = l10n_util::GetStringFUTF16Int( | |
| 1515 IDS_TOOLTIP_ZOOM, zoom_controller->zoom_percent()); | |
| 1516 gtk_widget_set_tooltip_text(zoom_.get(), base::UTF16ToUTF8(tooltip).c_str()); | |
| 1517 | |
| 1518 gtk_widget_show(zoom_.get()); | |
| 1519 } | |
| 1520 | |
| 1521 void LocationBarViewGtk::UpdateManagePasswordsIcon() { | |
| 1522 WebContents* web_contents = GetWebContents(); | |
| 1523 if (!manage_passwords_icon_.get() || !web_contents) | |
| 1524 return; | |
| 1525 | |
| 1526 ManagePasswordsBubbleUIController* manage_passwords_bubble_ui_controller = | |
| 1527 ManagePasswordsBubbleUIController::FromWebContents(web_contents); | |
| 1528 if (!manage_passwords_bubble_ui_controller || | |
| 1529 !manage_passwords_bubble_ui_controller->password_to_be_saved() || | |
| 1530 GetToolbarModel()->input_in_progress()) { | |
| 1531 gtk_widget_hide(manage_passwords_icon_.get()); | |
| 1532 ManagePasswordsBubbleGtk::CloseBubble(); | |
| 1533 return; | |
| 1534 } | |
| 1535 | |
| 1536 gtk_image_set_from_pixbuf( | |
| 1537 GTK_IMAGE(manage_passwords_icon_image_), | |
| 1538 theme_service_->GetImageNamed(IDR_SAVE_PASSWORD).ToGdkPixbuf()); | |
| 1539 | |
| 1540 base::string16 tooltip = | |
| 1541 l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_TOOLTIP_SAVE); | |
| 1542 gtk_widget_set_tooltip_text(manage_passwords_icon_.get(), | |
| 1543 base::UTF16ToUTF8(tooltip).c_str()); | |
| 1544 | |
| 1545 gtk_widget_show(manage_passwords_icon_.get()); | |
| 1546 if (manage_passwords_bubble_ui_controller-> | |
| 1547 manage_passwords_bubble_needs_showing()) { | |
| 1548 ShowManagePasswordsBubble(); | |
| 1549 manage_passwords_bubble_ui_controller->OnBubbleShown(); | |
| 1550 } | |
| 1551 } | |
| 1552 | |
| 1553 void LocationBarViewGtk::UpdateStarIcon() { | |
| 1554 if (!star_.get()) | |
| 1555 return; | |
| 1556 // Indicate the star icon is not correctly sized. It will be marked as sized | |
| 1557 // when the next size-allocate signal is received by the star widget. | |
| 1558 star_sized_ = false; | |
| 1559 if (browser_defaults::bookmarks_enabled && !popup_window_mode_ && | |
| 1560 !GetToolbarModel()->input_in_progress() && | |
| 1561 edit_bookmarks_enabled_.GetValue() && | |
| 1562 !IsBookmarkStarHiddenByExtension()) { | |
| 1563 gtk_widget_show_all(star_.get()); | |
| 1564 int id = starred_ ? IDR_STAR_LIT : IDR_STAR; | |
| 1565 gtk_image_set_from_pixbuf(GTK_IMAGE(star_image_), | |
| 1566 theme_service_->GetImageNamed(id).ToGdkPixbuf()); | |
| 1567 gtk_widget_set_tooltip_text(star_.get(), l10n_util::GetStringUTF8( | |
| 1568 starred_ ? IDS_TOOLTIP_STARRED : IDS_TOOLTIP_STAR).c_str()); | |
| 1569 } else { | |
| 1570 gtk_widget_hide_all(star_.get()); | |
| 1571 } | |
| 1572 } | |
| 1573 | |
| 1574 bool LocationBarViewGtk::ShouldOnlyShowLocation() { | |
| 1575 return !browser_->is_type_tabbed(); | |
| 1576 } | |
| 1577 | |
| 1578 void LocationBarViewGtk::HideURL() { | |
| 1579 omnibox_view_->HideURL(); | |
| 1580 } | |
| 1581 | |
| 1582 //////////////////////////////////////////////////////////////////////////////// | |
| 1583 // LocationBarViewGtk::PageToolViewGtk | |
| 1584 | |
| 1585 LocationBarViewGtk::PageToolViewGtk::PageToolViewGtk() | |
| 1586 : alignment_(gtk_alignment_new(0, 0, 1, 1)), | |
| 1587 event_box_(gtk_event_box_new()), | |
| 1588 hbox_(gtk_hbox_new(FALSE, kInnerPadding)), | |
| 1589 image_(gtk_image_new()), | |
| 1590 label_(gtk_label_new(NULL)), | |
| 1591 animation_(this), | |
| 1592 weak_factory_(this) { | |
| 1593 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_.get()), 1, 1, 0, 0); | |
| 1594 gtk_container_add(GTK_CONTAINER(alignment_.get()), event_box_.get()); | |
| 1595 | |
| 1596 // Make the event box not visible so it does not paint a background. | |
| 1597 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE); | |
| 1598 g_signal_connect(event_box_.get(), "button-press-event", | |
| 1599 G_CALLBACK(&OnButtonPressedThunk), this); | |
| 1600 g_signal_connect(event_box_.get(), "expose-event", | |
| 1601 G_CALLBACK(&OnExposeThunk), this); | |
| 1602 | |
| 1603 gtk_widget_set_no_show_all(label_.get(), TRUE); | |
| 1604 gtk_label_set_line_wrap(GTK_LABEL(label_.get()), FALSE); | |
| 1605 | |
| 1606 gtk_box_pack_start(GTK_BOX(hbox_), image_.get(), FALSE, FALSE, 0); | |
| 1607 gtk_box_pack_start(GTK_BOX(hbox_), label_.get(), FALSE, FALSE, 0); | |
| 1608 | |
| 1609 gtk_container_set_border_width(GTK_CONTAINER(hbox_), kHboxBorder); | |
| 1610 | |
| 1611 gtk_container_add(GTK_CONTAINER(event_box_.get()), hbox_); | |
| 1612 gtk_widget_hide(widget()); | |
| 1613 | |
| 1614 animation_.SetSlideDuration(kPageToolAnimationTime); | |
| 1615 } | |
| 1616 | |
| 1617 LocationBarViewGtk::PageToolViewGtk::~PageToolViewGtk() { | |
| 1618 image_.Destroy(); | |
| 1619 label_.Destroy(); | |
| 1620 event_box_.Destroy(); | |
| 1621 alignment_.Destroy(); | |
| 1622 } | |
| 1623 | |
| 1624 bool LocationBarViewGtk::PageToolViewGtk::IsVisible() { | |
| 1625 return gtk_widget_get_visible(widget()); | |
| 1626 } | |
| 1627 | |
| 1628 void LocationBarViewGtk::PageToolViewGtk::AnimationProgressed( | |
| 1629 const gfx::Animation* animation) { | |
| 1630 gtk_widget_set_size_request( | |
| 1631 label_.get(), | |
| 1632 animation->GetCurrentValue() * label_req_.width, | |
| 1633 -1); | |
| 1634 } | |
| 1635 | |
| 1636 void LocationBarViewGtk::PageToolViewGtk::AnimationEnded( | |
| 1637 const gfx::Animation* animation) { | |
| 1638 } | |
| 1639 | |
| 1640 void LocationBarViewGtk::PageToolViewGtk::AnimationCanceled( | |
| 1641 const gfx::Animation* animation) { | |
| 1642 } | |
| 1643 | |
| 1644 void LocationBarViewGtk::PageToolViewGtk::StartAnimating() { | |
| 1645 if (animation_.IsShowing() || animation_.IsClosing()) | |
| 1646 return; | |
| 1647 | |
| 1648 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), TRUE); | |
| 1649 GdkColor border_color = GetButtonBorderColor(); | |
| 1650 gtk_util::ActAsRoundedWindow(event_box_.get(), border_color, | |
| 1651 kCornerSize, | |
| 1652 gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL); | |
| 1653 | |
| 1654 gtk_widget_set_size_request(label_.get(), -1, -1); | |
| 1655 gtk_widget_size_request(label_.get(), &label_req_); | |
| 1656 gtk_widget_set_size_request(label_.get(), 0, -1); | |
| 1657 gtk_widget_show(label_.get()); | |
| 1658 | |
| 1659 animation_.Show(); | |
| 1660 } | |
| 1661 | |
| 1662 void LocationBarViewGtk::PageToolViewGtk::CloseAnimation() { | |
| 1663 animation_.Hide(); | |
| 1664 } | |
| 1665 | |
| 1666 gboolean LocationBarViewGtk::PageToolViewGtk::OnButtonPressed( | |
| 1667 GtkWidget* sender, GdkEvent* event) { | |
| 1668 OnClick(sender); | |
| 1669 return TRUE; | |
| 1670 } | |
| 1671 | |
| 1672 gboolean LocationBarViewGtk::PageToolViewGtk::OnExpose( | |
| 1673 GtkWidget* sender, GdkEventExpose* event) { | |
| 1674 TRACE_EVENT0("ui::gtk", "LocationBarViewGtk::PageToolViewGtk::OnExpose"); | |
| 1675 | |
| 1676 if (!(animation_.IsShowing() || animation_.IsClosing())) | |
| 1677 return FALSE; | |
| 1678 | |
| 1679 GtkAllocation allocation; | |
| 1680 gtk_widget_get_allocation(sender, &allocation); | |
| 1681 const int height = allocation.height; | |
| 1682 | |
| 1683 cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(sender)); | |
| 1684 gdk_cairo_rectangle(cr, &event->area); | |
| 1685 cairo_clip(cr); | |
| 1686 | |
| 1687 cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height); | |
| 1688 | |
| 1689 const GdkColor top_color = GetGradientTopColor(); | |
| 1690 const GdkColor bottom_color = GetGradientBottomColor(); | |
| 1691 cairo_pattern_add_color_stop_rgb( | |
| 1692 pattern, 0.0, | |
| 1693 top_color.red/255.0, | |
| 1694 top_color.blue/255.0, | |
| 1695 top_color.green/255.0); | |
| 1696 cairo_pattern_add_color_stop_rgb( | |
| 1697 pattern, 1.0, | |
| 1698 bottom_color.red/255.0, | |
| 1699 bottom_color.blue/255.0, | |
| 1700 bottom_color.green/255.0); | |
| 1701 | |
| 1702 cairo_set_source(cr, pattern); | |
| 1703 cairo_paint(cr); | |
| 1704 cairo_pattern_destroy(pattern); | |
| 1705 cairo_destroy(cr); | |
| 1706 | |
| 1707 return FALSE; | |
| 1708 } | |
| 1709 | |
| 1710 //////////////////////////////////////////////////////////////////////////////// | |
| 1711 // LocationBarViewGtk::PageActionViewGtk | |
| 1712 | |
| 1713 LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk( | |
| 1714 LocationBarViewGtk* owner, | |
| 1715 ExtensionAction* page_action) | |
| 1716 : owner_(NULL), | |
| 1717 page_action_(page_action), | |
| 1718 current_tab_id_(-1), | |
| 1719 window_(NULL), | |
| 1720 accel_group_(NULL), | |
| 1721 preview_enabled_(false) { | |
| 1722 event_box_.Own(gtk_event_box_new()); | |
| 1723 gtk_widget_set_size_request(event_box_.get(), | |
| 1724 ExtensionAction::kPageActionIconMaxSize, | |
| 1725 ExtensionAction::kPageActionIconMaxSize); | |
| 1726 | |
| 1727 // Make the event box not visible so it does not paint a background. | |
| 1728 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE); | |
| 1729 g_signal_connect(event_box_.get(), "button-press-event", | |
| 1730 G_CALLBACK(&OnButtonPressedThunk), this); | |
| 1731 g_signal_connect_after(event_box_.get(), "expose-event", | |
| 1732 G_CALLBACK(OnExposeEventThunk), this); | |
| 1733 g_signal_connect(event_box_.get(), "realize", | |
| 1734 G_CALLBACK(OnRealizeThunk), this); | |
| 1735 | |
| 1736 image_.Own(gtk_image_new()); | |
| 1737 gtk_container_add(GTK_CONTAINER(event_box_.get()), image_.get()); | |
| 1738 | |
| 1739 const Extension* extension = | |
| 1740 owner->profile()->GetExtensionService()->GetExtensionById( | |
| 1741 page_action->extension_id(), false); | |
| 1742 DCHECK(extension); | |
| 1743 | |
| 1744 icon_factory_.reset(new ExtensionActionIconFactory( | |
| 1745 owner->profile(), extension, page_action, this)); | |
| 1746 | |
| 1747 // We set the owner last of all so that we can determine whether we are in | |
| 1748 // the process of initializing this class or not. | |
| 1749 owner_ = owner; | |
| 1750 } | |
| 1751 | |
| 1752 LocationBarViewGtk::PageActionViewGtk::~PageActionViewGtk() { | |
| 1753 DisconnectPageActionAccelerator(); | |
| 1754 | |
| 1755 image_.Destroy(); | |
| 1756 event_box_.Destroy(); | |
| 1757 } | |
| 1758 | |
| 1759 bool LocationBarViewGtk::PageActionViewGtk::IsVisible() { | |
| 1760 return gtk_widget_get_visible(widget()); | |
| 1761 } | |
| 1762 | |
| 1763 void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility( | |
| 1764 WebContents* contents, const GURL& url) { | |
| 1765 // Save this off so we can pass it back to the extension when the action gets | |
| 1766 // executed. See PageActionImageView::OnMousePressed. | |
| 1767 current_tab_id_ = | |
| 1768 contents ? extensions::ExtensionTabUtil::GetTabId(contents) : -1; | |
| 1769 current_url_ = url; | |
| 1770 | |
| 1771 bool visible = contents && | |
| 1772 (preview_enabled_ || page_action_->GetIsVisible(current_tab_id_)); | |
| 1773 if (visible) { | |
| 1774 // Set the tooltip. | |
| 1775 gtk_widget_set_tooltip_text(event_box_.get(), | |
| 1776 page_action_->GetTitle(current_tab_id_).c_str()); | |
| 1777 | |
| 1778 // Set the image. | |
| 1779 gfx::Image icon = icon_factory_->GetIcon(current_tab_id_); | |
| 1780 if (!icon.IsEmpty()) { | |
| 1781 GdkPixbuf* pixbuf = icon.ToGdkPixbuf(); | |
| 1782 DCHECK(pixbuf); | |
| 1783 gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()), pixbuf); | |
| 1784 } | |
| 1785 } | |
| 1786 | |
| 1787 bool old_visible = IsVisible(); | |
| 1788 if (visible) | |
| 1789 gtk_widget_show_all(event_box_.get()); | |
| 1790 else | |
| 1791 gtk_widget_hide_all(event_box_.get()); | |
| 1792 | |
| 1793 if (visible != old_visible) { | |
| 1794 content::NotificationService::current()->Notify( | |
| 1795 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, | |
| 1796 content::Source<ExtensionAction>(page_action_), | |
| 1797 content::Details<WebContents>(contents)); | |
| 1798 } | |
| 1799 } | |
| 1800 | |
| 1801 void LocationBarViewGtk::PageActionViewGtk::OnIconUpdated() { | |
| 1802 // If we have no owner, that means this class is still being constructed. | |
| 1803 WebContents* web_contents = owner_ ? owner_->GetWebContents() : NULL; | |
| 1804 if (web_contents) | |
| 1805 UpdateVisibility(web_contents, current_url_); | |
| 1806 } | |
| 1807 | |
| 1808 void LocationBarViewGtk::PageActionViewGtk::TestActivatePageAction() { | |
| 1809 GdkEventButton event = {}; | |
| 1810 event.type = GDK_BUTTON_PRESS; | |
| 1811 event.button = 1; | |
| 1812 OnButtonPressed(widget(), &event); | |
| 1813 } | |
| 1814 | |
| 1815 void LocationBarViewGtk::PageActionViewGtk::Observe( | |
| 1816 int type, | |
| 1817 const content::NotificationSource& source, | |
| 1818 const content::NotificationDetails& details) { | |
| 1819 DCHECK_EQ(type, chrome::NOTIFICATION_WINDOW_CLOSED); | |
| 1820 DisconnectPageActionAccelerator(); | |
| 1821 } | |
| 1822 | |
| 1823 void LocationBarViewGtk::PageActionViewGtk::InspectPopup( | |
| 1824 ExtensionAction* action) { | |
| 1825 ExtensionPopupGtk::Show( | |
| 1826 action->GetPopupUrl(current_tab_id_), | |
| 1827 owner_->browser_, | |
| 1828 event_box_.get(), | |
| 1829 ExtensionPopupGtk::SHOW_AND_INSPECT); | |
| 1830 } | |
| 1831 | |
| 1832 void LocationBarViewGtk::PageActionViewGtk::ConnectPageActionAccelerator() { | |
| 1833 const extensions::ExtensionSet* extensions = | |
| 1834 owner_->profile()->GetExtensionService()->extensions(); | |
| 1835 const Extension* extension = | |
| 1836 extensions->GetByID(page_action_->extension_id()); | |
| 1837 window_ = owner_->browser()->window()->GetNativeWindow(); | |
| 1838 | |
| 1839 extensions::CommandService* command_service = | |
| 1840 extensions::CommandService::Get(owner_->profile()); | |
| 1841 | |
| 1842 extensions::Command command_page_action; | |
| 1843 if (command_service->GetPageActionCommand( | |
| 1844 extension->id(), | |
| 1845 extensions::CommandService::ACTIVE_ONLY, | |
| 1846 &command_page_action, | |
| 1847 NULL)) { | |
| 1848 // Found the page action shortcut command, register it. | |
| 1849 page_action_keybinding_.reset( | |
| 1850 new ui::Accelerator(command_page_action.accelerator())); | |
| 1851 } | |
| 1852 | |
| 1853 if (page_action_keybinding_.get()) { | |
| 1854 accel_group_ = gtk_accel_group_new(); | |
| 1855 gtk_window_add_accel_group(window_, accel_group_); | |
| 1856 | |
| 1857 gtk_accel_group_connect( | |
| 1858 accel_group_, | |
| 1859 ui::GetGdkKeyCodeForAccelerator(*page_action_keybinding_), | |
| 1860 ui::GetGdkModifierForAccelerator(*page_action_keybinding_), | |
| 1861 GtkAccelFlags(0), | |
| 1862 g_cclosure_new(G_CALLBACK(OnGtkAccelerator), this, NULL)); | |
| 1863 | |
| 1864 // Since we've added an accelerator, we'll need to unregister it before | |
| 1865 // the window is closed, so we listen for the window being closed. | |
| 1866 registrar_.Add(this, | |
| 1867 chrome::NOTIFICATION_WINDOW_CLOSED, | |
| 1868 content::Source<GtkWindow>(window_)); | |
| 1869 } | |
| 1870 } | |
| 1871 | |
| 1872 void LocationBarViewGtk::PageActionViewGtk::DisconnectPageActionAccelerator() { | |
| 1873 if (accel_group_) { | |
| 1874 if (page_action_keybinding_.get()) { | |
| 1875 gtk_accel_group_disconnect_key( | |
| 1876 accel_group_, | |
| 1877 ui::GetGdkKeyCodeForAccelerator(*page_action_keybinding_), | |
| 1878 ui::GetGdkModifierForAccelerator(*page_action_keybinding_)); | |
| 1879 } | |
| 1880 gtk_window_remove_accel_group(window_, accel_group_); | |
| 1881 g_object_unref(accel_group_); | |
| 1882 accel_group_ = NULL; | |
| 1883 page_action_keybinding_.reset(NULL); | |
| 1884 } | |
| 1885 } | |
| 1886 | |
| 1887 gboolean LocationBarViewGtk::PageActionViewGtk::OnButtonPressed( | |
| 1888 GtkWidget* sender, | |
| 1889 GdkEventButton* event) { | |
| 1890 // Double and triple-clicks generate both a GDK_BUTTON_PRESS and a | |
| 1891 // GDK_[23]BUTTON_PRESS event. We don't want to double-trigger by acting on | |
| 1892 // both. | |
| 1893 if (event->type != GDK_BUTTON_PRESS) | |
| 1894 return TRUE; | |
| 1895 | |
| 1896 WebContents* web_contents = owner_->GetWebContents(); | |
| 1897 if (!web_contents) | |
| 1898 return TRUE; | |
| 1899 | |
| 1900 ExtensionService* extension_service = | |
| 1901 owner_->profile()->GetExtensionService(); | |
| 1902 if (!extension_service) | |
| 1903 return TRUE; | |
| 1904 | |
| 1905 const Extension* extension = | |
| 1906 extension_service->extensions()->GetByID(page_action()->extension_id()); | |
| 1907 if (!extension) | |
| 1908 return TRUE; | |
| 1909 | |
| 1910 LocationBarController* controller = | |
| 1911 extensions::TabHelper::FromWebContents(web_contents)-> | |
| 1912 location_bar_controller(); | |
| 1913 | |
| 1914 switch (controller->OnClicked(extension->id(), event->button)) { | |
| 1915 case LocationBarController::ACTION_NONE: | |
| 1916 break; | |
| 1917 | |
| 1918 case LocationBarController::ACTION_SHOW_POPUP: | |
| 1919 ExtensionPopupGtk::Show( | |
| 1920 page_action_->GetPopupUrl(current_tab_id_), | |
| 1921 owner_->browser_, | |
| 1922 event_box_.get(), | |
| 1923 ExtensionPopupGtk::SHOW); | |
| 1924 break; | |
| 1925 | |
| 1926 case LocationBarController::ACTION_SHOW_CONTEXT_MENU: | |
| 1927 context_menu_model_ = | |
| 1928 new ExtensionContextMenuModel(extension, owner_->browser_, this); | |
| 1929 context_menu_.reset( | |
| 1930 new MenuGtk(NULL, context_menu_model_.get())); | |
| 1931 context_menu_->PopupForWidget(sender, event->button, event->time); | |
| 1932 break; | |
| 1933 } | |
| 1934 | |
| 1935 return TRUE; | |
| 1936 } | |
| 1937 | |
| 1938 gboolean LocationBarViewGtk::PageActionViewGtk::OnExposeEvent( | |
| 1939 GtkWidget* widget, | |
| 1940 GdkEventExpose* event) { | |
| 1941 TRACE_EVENT0("ui::gtk", "LocationBarViewGtk::PageActionViewGtk::OnExpose"); | |
| 1942 WebContents* contents = owner_->GetWebContents(); | |
| 1943 if (!contents) | |
| 1944 return FALSE; | |
| 1945 | |
| 1946 int tab_id = extensions::ExtensionTabUtil::GetTabId(contents); | |
| 1947 if (tab_id < 0) | |
| 1948 return FALSE; | |
| 1949 | |
| 1950 std::string badge_text = page_action_->GetBadgeText(tab_id); | |
| 1951 if (badge_text.empty()) | |
| 1952 return FALSE; | |
| 1953 | |
| 1954 gfx::CanvasSkiaPaint canvas(event, false); | |
| 1955 GtkAllocation allocation; | |
| 1956 gtk_widget_get_allocation(widget, &allocation); | |
| 1957 page_action_->PaintBadge(&canvas, gfx::Rect(allocation), tab_id); | |
| 1958 return FALSE; | |
| 1959 } | |
| 1960 | |
| 1961 void LocationBarViewGtk::PageActionViewGtk::OnRealize(GtkWidget* widget) { | |
| 1962 ConnectPageActionAccelerator(); | |
| 1963 } | |
| 1964 | |
| 1965 // static | |
| 1966 gboolean LocationBarViewGtk::PageActionViewGtk::OnGtkAccelerator( | |
| 1967 GtkAccelGroup* accel_group, | |
| 1968 GObject* acceleratable, | |
| 1969 guint keyval, | |
| 1970 GdkModifierType modifier, | |
| 1971 void* user_data) { | |
| 1972 PageActionViewGtk* view = static_cast<PageActionViewGtk*>(user_data); | |
| 1973 if (!gtk_widget_get_visible(view->widget())) | |
| 1974 return FALSE; | |
| 1975 | |
| 1976 GdkEventButton event = {}; | |
| 1977 event.type = GDK_BUTTON_PRESS; | |
| 1978 event.button = 1; | |
| 1979 return view->OnButtonPressed(view->widget(), &event); | |
| 1980 } | |
| OLD | NEW |