Commit 06ac889f authored by gbillock@chromium.org's avatar gbillock@chromium.org

Refactor location bar content setting image GTK classes to

support web intents picker button.

R=bauerb@chromium.org
BUG=None
TEST=None


Review URL: https://chromiumcodereview.appspot.com/10835020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148826 0039d316-1c4b-4281-b951-d872f2087c98
parent 51bc3846
...@@ -135,6 +135,9 @@ const GdkColor kHintTextColor = GDK_COLOR_RGB(0x75, 0x75, 0x75); ...@@ -135,6 +135,9 @@ const GdkColor kHintTextColor = GDK_COLOR_RGB(0x75, 0x75, 0x75);
// Size of the rounding of the "Search site for:" box. // Size of the rounding of the "Search site for:" box.
const int kCornerSize = 3; const int kCornerSize = 3;
// Default page tool animation time (open and close).
const int kPageToolAnimationTime = 150;
// The time, in ms, that the content setting label is fully displayed, for the // The time, in ms, that the content setting label is fully displayed, for the
// cases where we animate it into and out of view. // cases where we animate it into and out of view.
const int kContentSettingImageDisplayTime = 3200; const int kContentSettingImageDisplayTime = 3200;
...@@ -144,12 +147,8 @@ const int kContentSettingImageAnimationTime = 150; ...@@ -144,12 +147,8 @@ const int kContentSettingImageAnimationTime = 150;
// Color of border of content setting area (icon/label). // Color of border of content setting area (icon/label).
const GdkColor kContentSettingBorderColor = GDK_COLOR_RGB(0xe9, 0xb9, 0x66); const GdkColor kContentSettingBorderColor = GDK_COLOR_RGB(0xe9, 0xb9, 0x66);
// Colors for the background gradient. // Colors for the background gradient.
const double kContentSettingTopColor[] = { 0xff / 255.0, const GdkColor kContentSettingTopColor = GDK_COLOR_RGB(0xff, 0xf8, 0xd4);
0xf8 / 255.0, const GdkColor kContentSettingBottomColor = GDK_COLOR_RGB(0xff, 0xe6, 0xaf);
0xd4 / 255.0 };
const double kContentSettingBottomColor[] = { 0xff / 255.0,
0xe6 / 255.0,
0xaf / 255.0 };
// If widget is visible, increment the int pointed to by count. // If widget is visible, increment the int pointed to by count.
// Suitible for use with gtk_container_foreach. // Suitible for use with gtk_container_foreach.
...@@ -158,6 +157,153 @@ void CountVisibleWidgets(GtkWidget* widget, gpointer count) { ...@@ -158,6 +157,153 @@ void CountVisibleWidgets(GtkWidget* widget, gpointer count) {
*static_cast<int*>(count) += 1; *static_cast<int*>(count) += 1;
} }
class ContentSettingImageViewGtk : public LocationBarViewGtk::PageToolViewGtk,
public BubbleDelegateGtk {
public:
ContentSettingImageViewGtk(ContentSettingsType content_type,
const LocationBarViewGtk* parent);
virtual ~ContentSettingImageViewGtk();
// PageToolViewGtk
virtual void Update(TabContents* tab_contents) OVERRIDE;
// ui::AnimationDelegate
virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
private:
// PageToolViewGtk
virtual GdkColor button_border_color() const OVERRIDE;
virtual GdkColor gradient_top_color() const OVERRIDE;
virtual GdkColor gradient_bottom_color() const OVERRIDE;
virtual void OnClick(GtkWidget* sender) OVERRIDE;
// BubbleDelegateGtk
virtual void BubbleClosing(BubbleGtk* bubble,
bool closed_by_escape) OVERRIDE;
scoped_ptr<ContentSettingImageModel> content_setting_image_model_;
// The currently shown bubble if any.
ContentSettingBubbleGtk* content_setting_bubble_;
DISALLOW_COPY_AND_ASSIGN(ContentSettingImageViewGtk);
};
ContentSettingImageViewGtk::ContentSettingImageViewGtk(
ContentSettingsType content_type,
const LocationBarViewGtk* parent)
: PageToolViewGtk(parent),
content_setting_image_model_(
ContentSettingImageModel::CreateContentSettingImageModel(
content_type)),
content_setting_bubble_(NULL) {
animation_.SetSlideDuration(kContentSettingImageAnimationTime);
}
ContentSettingImageViewGtk::~ContentSettingImageViewGtk() {
if (content_setting_bubble_)
content_setting_bubble_->Close();
}
void ContentSettingImageViewGtk::Update(
TabContents* tab_contents) {
if (tab_contents) {
content_setting_image_model_->UpdateFromWebContents(
tab_contents->web_contents());
}
if (!content_setting_image_model_->is_visible()) {
gtk_widget_hide(widget());
return;
}
gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()),
GtkThemeService::GetFrom(parent_->browser()->profile())->GetImageNamed(
content_setting_image_model_->get_icon())->ToGdkPixbuf());
gtk_widget_set_tooltip_text(widget(),
content_setting_image_model_->get_tooltip().c_str());
gtk_widget_show_all(widget());
if (!tab_contents)
return;
TabSpecificContentSettings* content_settings =
tab_contents->content_settings();
if (!content_settings || content_settings->IsBlockageIndicated(
content_setting_image_model_->get_content_settings_type()))
return;
// The content blockage was not yet indicated to the user. Start indication
// animation and clear "not yet shown" flag.
content_settings->SetBlockageHasBeenIndicated(
content_setting_image_model_->get_content_settings_type());
int label_string_id =
content_setting_image_model_->explanatory_string_id();
// If there's no string for the content type, we don't animate.
if (!label_string_id)
return;
gtk_label_set_text(GTK_LABEL(label_.get()),
l10n_util::GetStringUTF8(label_string_id).c_str());
StartAnimating();
}
void ContentSettingImageViewGtk::AnimationEnded(
const ui::Animation* animation) {
if (animation_.IsShowing()) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&ContentSettingImageViewGtk::CloseAnimation,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kContentSettingImageDisplayTime));
} else {
gtk_widget_hide(label_.get());
gtk_util::StopActingAsRoundedWindow(event_box_.get());
gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE);
}
}
GdkColor ContentSettingImageViewGtk::
button_border_color() const {
return kContentSettingBorderColor;
}
GdkColor ContentSettingImageViewGtk::
gradient_top_color() const {
return kContentSettingTopColor;
}
GdkColor ContentSettingImageViewGtk::
gradient_bottom_color() const {
return kContentSettingBottomColor;
}
void ContentSettingImageViewGtk::OnClick(
GtkWidget* sender) {
TabContents* tab_contents = parent_->GetTabContents();
if (!tab_contents)
return;
Profile* profile = parent_->browser()->profile();
content_setting_bubble_ = new ContentSettingBubbleGtk(
sender, this,
ContentSettingBubbleModel::CreateContentSettingBubbleModel(
parent_->browser()->content_setting_bubble_model_delegate(),
tab_contents,
profile,
content_setting_image_model_->get_content_settings_type()),
profile, tab_contents->web_contents());
return;
}
void ContentSettingImageViewGtk::BubbleClosing(
BubbleGtk* bubble,
bool closed_by_escape) {
content_setting_bubble_ = NULL;
}
} // namespace } // namespace
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -709,13 +855,12 @@ void LocationBarViewGtk::FocusSearch() { ...@@ -709,13 +855,12 @@ void LocationBarViewGtk::FocusSearch() {
} }
void LocationBarViewGtk::UpdateContentSettingsIcons() { void LocationBarViewGtk::UpdateContentSettingsIcons() {
WebContents* web_contents = GetWebContents();
bool any_visible = false; bool any_visible = false;
for (ScopedVector<ContentSettingImageViewGtk>::iterator i( for (ScopedVector<PageToolViewGtk>::iterator i(
content_setting_views_.begin()); content_setting_views_.begin());
i != content_setting_views_.end(); ++i) { i != content_setting_views_.end(); ++i) {
(*i)->UpdateFromWebContents( (*i)->Update(
toolbar_model_->input_in_progress() ? NULL : web_contents); toolbar_model_->input_in_progress() ? NULL : GetTabContents());
any_visible = (*i)->IsVisible() || any_visible; any_visible = (*i)->IsVisible() || any_visible;
} }
...@@ -1413,20 +1558,16 @@ void LocationBarViewGtk::AdjustChildrenVisibility() { ...@@ -1413,20 +1558,16 @@ void LocationBarViewGtk::AdjustChildrenVisibility() {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// LocationBarViewGtk::ContentSettingImageViewGtk // LocationBarViewGtk::PageToolViewGtk
LocationBarViewGtk::ContentSettingImageViewGtk::ContentSettingImageViewGtk(
ContentSettingsType content_type, LocationBarViewGtk::PageToolViewGtk::PageToolViewGtk(
const LocationBarViewGtk* parent) const LocationBarViewGtk* parent)
: content_setting_image_model_( : alignment_(gtk_alignment_new(0, 0, 1, 1)),
ContentSettingImageModel::CreateContentSettingImageModel(
content_type)),
alignment_(gtk_alignment_new(0, 0, 1, 1)),
event_box_(gtk_event_box_new()), event_box_(gtk_event_box_new()),
hbox_(gtk_hbox_new(FALSE, kInnerPadding)), hbox_(gtk_hbox_new(FALSE, kInnerPadding)),
image_(gtk_image_new()), image_(gtk_image_new()),
label_(gtk_label_new(NULL)), label_(gtk_label_new(NULL)),
parent_(parent), parent_(parent),
content_setting_bubble_(NULL),
animation_(this), animation_(this),
weak_factory_(this) { weak_factory_(this) {
gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_.get()), 1, 1, 0, 0); gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_.get()), 1, 1, 0, 0);
...@@ -1450,70 +1591,31 @@ LocationBarViewGtk::ContentSettingImageViewGtk::ContentSettingImageViewGtk( ...@@ -1450,70 +1591,31 @@ LocationBarViewGtk::ContentSettingImageViewGtk::ContentSettingImageViewGtk(
gtk_container_add(GTK_CONTAINER(event_box_.get()), hbox_); gtk_container_add(GTK_CONTAINER(event_box_.get()), hbox_);
gtk_widget_hide(widget()); gtk_widget_hide(widget());
animation_.SetSlideDuration(kContentSettingImageAnimationTime); animation_.SetSlideDuration(kPageToolAnimationTime);
} }
LocationBarViewGtk::ContentSettingImageViewGtk::~ContentSettingImageViewGtk() { LocationBarViewGtk::PageToolViewGtk::~PageToolViewGtk() {
image_.Destroy(); image_.Destroy();
label_.Destroy(); label_.Destroy();
event_box_.Destroy(); event_box_.Destroy();
alignment_.Destroy(); alignment_.Destroy();
if (content_setting_bubble_)
content_setting_bubble_->Close();
} }
bool LocationBarViewGtk::ContentSettingImageViewGtk::IsVisible() { GtkWidget* LocationBarViewGtk::PageToolViewGtk::widget() {
return gtk_widget_get_visible(widget()); return alignment_.get();
} }
void LocationBarViewGtk::ContentSettingImageViewGtk::UpdateFromWebContents( bool LocationBarViewGtk::PageToolViewGtk::IsVisible() {
WebContents* web_contents) { return gtk_widget_get_visible(widget());
content_setting_image_model_->UpdateFromWebContents(web_contents);
if (!content_setting_image_model_->is_visible()) {
gtk_widget_hide(widget());
return;
}
gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()),
GtkThemeService::GetFrom(parent_->browser()->profile())->GetImageNamed(
content_setting_image_model_->get_icon())->ToGdkPixbuf());
gtk_widget_set_tooltip_text(widget(),
content_setting_image_model_->get_tooltip().c_str());
gtk_widget_show_all(widget());
TabSpecificContentSettings* content_settings = NULL;
if (web_contents) {
content_settings =
TabContents::FromWebContents(web_contents)->content_settings();
}
if (!content_settings || content_settings->IsBlockageIndicated(
content_setting_image_model_->get_content_settings_type()))
return;
// The content blockage was not yet indicated to the user. Start indication
// animation and clear "not yet shown" flag.
content_settings->SetBlockageHasBeenIndicated(
content_setting_image_model_->get_content_settings_type());
int label_string_id =
content_setting_image_model_->explanatory_string_id();
// If there's no string for the content type, we don't animate.
if (!label_string_id)
return;
gtk_label_set_text(GTK_LABEL(label_.get()),
l10n_util::GetStringUTF8(label_string_id).c_str());
StartAnimating();
} }
void LocationBarViewGtk::ContentSettingImageViewGtk::StartAnimating() { void LocationBarViewGtk::PageToolViewGtk::StartAnimating() {
if (animation_.IsShowing() || animation_.IsClosing()) if (animation_.IsShowing() || animation_.IsClosing())
return; return;
gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), TRUE); gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), TRUE);
gtk_util::ActAsRoundedWindow(event_box_.get(), kContentSettingBorderColor, GdkColor border_color = button_border_color();
gtk_util::ActAsRoundedWindow(event_box_.get(), border_color,
kCornerSize, kCornerSize,
gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL); gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);
...@@ -1525,11 +1627,11 @@ void LocationBarViewGtk::ContentSettingImageViewGtk::StartAnimating() { ...@@ -1525,11 +1627,11 @@ void LocationBarViewGtk::ContentSettingImageViewGtk::StartAnimating() {
animation_.Show(); animation_.Show();
} }
void LocationBarViewGtk::ContentSettingImageViewGtk::CloseAnimation() { void LocationBarViewGtk::PageToolViewGtk::CloseAnimation() {
animation_.Hide(); animation_.Hide();
} }
void LocationBarViewGtk::ContentSettingImageViewGtk::AnimationProgressed( void LocationBarViewGtk::PageToolViewGtk::AnimationProgressed(
const ui::Animation* animation) { const ui::Animation* animation) {
gtk_widget_set_size_request( gtk_widget_set_size_request(
label_.get(), label_.get(),
...@@ -1537,46 +1639,23 @@ void LocationBarViewGtk::ContentSettingImageViewGtk::AnimationProgressed( ...@@ -1537,46 +1639,23 @@ void LocationBarViewGtk::ContentSettingImageViewGtk::AnimationProgressed(
-1); -1);
} }
void LocationBarViewGtk::ContentSettingImageViewGtk::AnimationEnded( void LocationBarViewGtk::PageToolViewGtk::AnimationEnded(
const ui::Animation* animation) { const ui::Animation* animation) {
if (animation_.IsShowing()) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&ContentSettingImageViewGtk::CloseAnimation,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kContentSettingImageDisplayTime));
} else {
gtk_widget_hide(label_.get());
gtk_util::StopActingAsRoundedWindow(event_box_.get());
gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE);
}
} }
void LocationBarViewGtk::ContentSettingImageViewGtk::AnimationCanceled( void LocationBarViewGtk::PageToolViewGtk::AnimationCanceled(
const ui::Animation* animation) { const ui::Animation* animation) {
} }
gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnButtonPressed( gboolean LocationBarViewGtk::PageToolViewGtk::OnButtonPressed(
GtkWidget* sender, GdkEvent* event) { GtkWidget* sender, GdkEvent* event) {
TabContents* tab_contents = parent_->GetTabContents(); OnClick(sender);
if (!tab_contents)
return TRUE;
Profile* profile = parent_->browser()->profile();
content_setting_bubble_ = new ContentSettingBubbleGtk(
sender, this,
ContentSettingBubbleModel::CreateContentSettingBubbleModel(
parent_->browser()->content_setting_bubble_model_delegate(),
tab_contents,
profile,
content_setting_image_model_->get_content_settings_type()),
profile, tab_contents->web_contents());
return TRUE; return TRUE;
} }
gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnExpose( gboolean LocationBarViewGtk::PageToolViewGtk::OnExpose(
GtkWidget* sender, GdkEventExpose* event) { GtkWidget* sender, GdkEventExpose* event) {
TRACE_EVENT0("ui::gtk", TRACE_EVENT0("ui::gtk", "LocationBarViewGtk::PageToolViewGtk::OnExpose");
"LocationBarViewGtk::ContentSettingImageViewGtk::OnExpose");
if (!(animation_.IsShowing() || animation_.IsClosing())) if (!(animation_.IsShowing() || animation_.IsClosing()))
return FALSE; return FALSE;
...@@ -1591,14 +1670,19 @@ gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnExpose( ...@@ -1591,14 +1670,19 @@ gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnExpose(
cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height); cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height);
cairo_pattern_add_color_stop_rgb(pattern, 0.0, const GdkColor top_color = gradient_top_color();
kContentSettingTopColor[0], const GdkColor bottom_color = gradient_bottom_color();
kContentSettingTopColor[1], cairo_pattern_add_color_stop_rgb(
kContentSettingTopColor[2]); pattern, 0.0,
cairo_pattern_add_color_stop_rgb(pattern, 1.0, top_color.red/255.0,
kContentSettingBottomColor[0], top_color.blue/255.0,
kContentSettingBottomColor[1], top_color.green/255.0);
kContentSettingBottomColor[2]); cairo_pattern_add_color_stop_rgb(
pattern, 1.0,
bottom_color.red/255.0,
bottom_color.blue/255.0,
bottom_color.green/255.0);
cairo_set_source(cr, pattern); cairo_set_source(cr, pattern);
cairo_paint(cr); cairo_paint(cr);
cairo_pattern_destroy(pattern); cairo_pattern_destroy(pattern);
...@@ -1607,12 +1691,6 @@ gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnExpose( ...@@ -1607,12 +1691,6 @@ gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnExpose(
return FALSE; return FALSE;
} }
void LocationBarViewGtk::ContentSettingImageViewGtk::BubbleClosing(
BubbleGtk* bubble,
bool closed_by_escape) {
content_setting_bubble_ = NULL;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// LocationBarViewGtk::PageActionViewGtk // LocationBarViewGtk::PageActionViewGtk
......
...@@ -168,68 +168,66 @@ class LocationBarViewGtk : public OmniboxEditController, ...@@ -168,68 +168,66 @@ class LocationBarViewGtk : public OmniboxEditController,
// Edit background color. // Edit background color.
static const GdkColor kBackgroundColor; static const GdkColor kBackgroundColor;
private: // Superclass for content settings icons shown at the left side of the
class ContentSettingImageViewGtk : public BubbleDelegateGtk, // location bar.
public ui::AnimationDelegate { class PageToolViewGtk : public ui::AnimationDelegate {
public: public:
ContentSettingImageViewGtk(ContentSettingsType content_type, explicit PageToolViewGtk(const LocationBarViewGtk* parent);
const LocationBarViewGtk* parent); virtual ~PageToolViewGtk();
virtual ~ContentSettingImageViewGtk();
GtkWidget* widget() { return alignment_.get(); } GtkWidget* widget();
bool IsVisible(); bool IsVisible();
void UpdateFromWebContents(content::WebContents* web_contents); virtual void Update(TabContents* tab_contents) = 0;
// Overridden from ui::AnimationDelegate: // Overridden from ui::AnimationDelegate:
virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE; virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE;
private: protected:
// Theme constants for solid background elements.
virtual GdkColor button_border_color() const = 0;
virtual GdkColor gradient_top_color() const = 0;
virtual GdkColor gradient_bottom_color() const = 0;
// Delegate for ButtonPressed message.
virtual void OnClick(GtkWidget* sender) = 0;
// Start the process of showing the label. // Start the process of showing the label.
void StartAnimating(); void StartAnimating();
// Slide the label shut. // Slide the label shut.
void CloseAnimation(); void CloseAnimation();
CHROMEGTK_CALLBACK_1(ContentSettingImageViewGtk, gboolean, OnButtonPressed, CHROMEGTK_CALLBACK_1(PageToolViewGtk, gboolean, OnButtonPressed, GdkEvent*);
GdkEvent*); CHROMEGTK_CALLBACK_1(PageToolViewGtk, gboolean, OnExpose, GdkEventExpose*);
CHROMEGTK_CALLBACK_1(ContentSettingImageViewGtk, gboolean, OnExpose,
GdkEventExpose*);
// BubbleDelegateGtk overrides:
virtual void BubbleClosing(BubbleGtk* bubble,
bool closed_by_escape) OVERRIDE;
scoped_ptr<ContentSettingImageModel> content_setting_image_model_;
// The widgets for this content settings view. // The widgets for this view.
ui::OwnedWidgetGtk alignment_; ui::OwnedWidgetGtk alignment_;
ui::OwnedWidgetGtk event_box_; ui::OwnedWidgetGtk event_box_;
GtkWidget* hbox_; GtkWidget* hbox_;
ui::OwnedWidgetGtk image_; ui::OwnedWidgetGtk image_;
// Explanatory text ("popup blocked"). // Explanatory text (e.g. "popup blocked").
ui::OwnedWidgetGtk label_; ui::OwnedWidgetGtk label_;
// The owning LocationBarViewGtk. // The owning LocationBarViewGtk.
const LocationBarViewGtk* parent_; const LocationBarViewGtk* parent_;
// The currently shown bubble if any.
ContentSettingBubbleGtk* content_setting_bubble_;
// When we show explanatory text, we slide it in/out. // When we show explanatory text, we slide it in/out.
ui::SlideAnimation animation_; ui::SlideAnimation animation_;
// The label's default requisition (cached so we can animate accordingly). // The label's default requisition (cached so we can animate accordingly).
GtkRequisition label_req_; GtkRequisition label_req_;
base::WeakPtrFactory<ContentSettingImageViewGtk> weak_factory_; base::WeakPtrFactory<PageToolViewGtk> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ContentSettingImageViewGtk); private:
DISALLOW_COPY_AND_ASSIGN(PageToolViewGtk);
}; };
private:
class PageActionViewGtk : class PageActionViewGtk :
public ImageLoadingTracker::Observer, public ImageLoadingTracker::Observer,
public content::NotificationObserver, public content::NotificationObserver,
...@@ -462,7 +460,7 @@ class LocationBarViewGtk : public OmniboxEditController, ...@@ -462,7 +460,7 @@ class LocationBarViewGtk : public OmniboxEditController,
// Content setting icons. // Content setting icons.
ui::OwnedWidgetGtk content_setting_hbox_; ui::OwnedWidgetGtk content_setting_hbox_;
ScopedVector<ContentSettingImageViewGtk> content_setting_views_; ScopedVector<PageToolViewGtk> content_setting_views_;
// Extension page actions. // Extension page actions.
std::vector<ExtensionAction*> page_actions_; std::vector<ExtensionAction*> page_actions_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment