Chromium Code Reviews| Index: chrome/browser/extensions/api/app_window/app_window_api.cc |
| diff --git a/chrome/browser/extensions/api/app_window/app_window_api.cc b/chrome/browser/extensions/api/app_window/app_window_api.cc |
| index 856d82db410a3a1b52675ec816a9e37e29697376..68d6ec71bbbb4a9c02cecc2f658cdc460d4537b0 100644 |
| --- a/chrome/browser/extensions/api/app_window/app_window_api.cc |
| +++ b/chrome/browser/extensions/api/app_window/app_window_api.cc |
| @@ -11,6 +11,7 @@ |
| #include "apps/ui/native_app_window.h" |
| #include "base/command_line.h" |
| #include "base/strings/string_number_conversions.h" |
| +#include "base/strings/string_util.h" |
| #include "base/time/time.h" |
| #include "base/values.h" |
| #include "chrome/browser/app_mode/app_mode_utils.h" |
| @@ -56,6 +57,8 @@ const char kInvalidChannelForFrameOptions[] = |
| const char kFrameOptionsAndFrame[] = |
| "Only one of frame and frameOptions can be supplied."; |
| const char kColorWithFrameNone[] = "Windows with no frame cannot have a color."; |
| +const char kInvalidChannelForBounds[] = |
| + "innerBounds and outerBounds are only available in dev channel."; |
| } // namespace app_window_constants |
| const char kNoneFrameOption[] = "none"; |
| @@ -93,6 +96,48 @@ class DevToolsRestorer : public base::RefCounted<DevToolsRestorer> { |
| scoped_refptr<AppWindowCreateFunction> delayed_create_function_; |
| }; |
| +// If the same property is specified for the inner and outer bounds, raise an |
| +// error. |
| +bool CheckBoundsConflict(const scoped_ptr<int>& inner_property, |
| + const scoped_ptr<int>& outer_property, |
| + const std::string& property_name, |
| + std::string* error) { |
| + if (inner_property.get() && outer_property.get()) { |
| + std::vector<std::string> subst; |
| + subst.push_back(property_name); |
| + *error = ReplaceStringPlaceholders( |
| + "The $1 property cannot be specified for both inner and outer bounds.", |
|
benwells
2014/03/05 02:33:30
Nit: put this in kConflictingBlahBlah up with the
|
| + subst, |
| + NULL); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +// Copy over the bounds specification properties from the API to the |
| +// AppWindow::CreateParams. |
| +void CopyBoundsSpec( |
| + const extensions::api::app_window::BoundsSpecification* input_spec, |
| + apps::AppWindow::BoundsSpecification* create_spec) { |
| + if (input_spec && input_spec->left.get()) |
|
tapted
2014/03/05 03:14:03
nit:
if (!input_spec)
return;
|
| + create_spec->bounds.set_x(*input_spec->left); |
| + if (input_spec && input_spec->top.get()) |
| + create_spec->bounds.set_y(*input_spec->top); |
| + if (input_spec && input_spec->width.get()) |
| + create_spec->bounds.set_width(*input_spec->width); |
| + if (input_spec && input_spec->height.get()) |
| + create_spec->bounds.set_height(*input_spec->height); |
| + if (input_spec && input_spec->min_width.get()) |
| + create_spec->minimum_size.set_width(*input_spec->min_width); |
| + if (input_spec && input_spec->min_height.get()) |
| + create_spec->minimum_size.set_height(*input_spec->min_height); |
| + if (input_spec && input_spec->max_width.get()) |
| + create_spec->maximum_size.set_width(*input_spec->max_width); |
| + if (input_spec && input_spec->max_height.get()) |
| + create_spec->maximum_size.set_height(*input_spec->max_height); |
| +} |
| + |
| } // namespace |
| AppWindowCreateFunction::AppWindowCreateFunction() |
| @@ -173,37 +218,8 @@ bool AppWindowCreateFunction::RunImpl() { |
| } |
| } |
| - // TODO(jeremya): remove these, since they do the same thing as |
| - // left/top/width/height. |
| - if (options->default_width.get()) |
| - create_params.bounds.set_width(*options->default_width.get()); |
| - if (options->default_height.get()) |
| - create_params.bounds.set_height(*options->default_height.get()); |
| - if (options->default_left.get()) |
| - create_params.bounds.set_x(*options->default_left.get()); |
| - if (options->default_top.get()) |
| - create_params.bounds.set_y(*options->default_top.get()); |
| - |
| - if (options->width.get()) |
| - create_params.bounds.set_width(*options->width.get()); |
| - if (options->height.get()) |
| - create_params.bounds.set_height(*options->height.get()); |
| - if (options->left.get()) |
| - create_params.bounds.set_x(*options->left.get()); |
| - if (options->top.get()) |
| - create_params.bounds.set_y(*options->top.get()); |
| - |
| - if (options->bounds.get()) { |
| - app_window::ContentBounds* bounds = options->bounds.get(); |
| - if (bounds->width.get()) |
| - create_params.bounds.set_width(*bounds->width.get()); |
| - if (bounds->height.get()) |
| - create_params.bounds.set_height(*bounds->height.get()); |
| - if (bounds->left.get()) |
| - create_params.bounds.set_x(*bounds->left.get()); |
| - if (bounds->top.get()) |
| - create_params.bounds.set_y(*bounds->top.get()); |
| - } |
| + if (!ParseBoundsSpec(*options, &create_params, &error_)) |
|
benwells
2014/03/05 02:33:30
Yay for making this monster function shorter. Mayb
|
| + return false; |
| if (GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV || |
| GetExtension()->location() == extensions::Manifest::COMPONENT) { |
| @@ -222,17 +238,6 @@ bool AppWindowCreateFunction::RunImpl() { |
| create_params.transparent_background = *options->transparent_background; |
| } |
| - gfx::Size& minimum_size = create_params.minimum_size; |
| - if (options->min_width.get()) |
| - minimum_size.set_width(*options->min_width); |
| - if (options->min_height.get()) |
| - minimum_size.set_height(*options->min_height); |
| - gfx::Size& maximum_size = create_params.maximum_size; |
| - if (options->max_width.get()) |
| - maximum_size.set_width(*options->max_width); |
| - if (options->max_height.get()) |
| - maximum_size.set_height(*options->max_height); |
| - |
| if (options->hidden.get()) |
| create_params.hidden = *options->hidden.get(); |
| @@ -301,6 +306,128 @@ bool AppWindowCreateFunction::RunImpl() { |
| return true; |
| } |
| +bool AppWindowCreateFunction::ParseBoundsSpec( |
| + const extensions::api::app_window::CreateWindowOptions& options, |
| + apps::AppWindow::CreateParams* params, |
| + std::string* error) { |
| + DCHECK(params); |
| + DCHECK(error); |
| + |
| + if (options.inner_bounds.get() || options.outer_bounds.get()) { |
| + // Parse the inner and outer bounds specifications. If developers use the |
| + // new API, the deprecated fields will be ignored - do not allow them to |
| + // be mixed. |
|
tapted
2014/03/05 03:14:03
nit: I read this thinking it would be an error if
|
| + |
| + if (GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV) { |
| + *error = app_window_constants::kInvalidChannelForBounds; |
| + return false; |
| + } |
| + |
| + const extensions::api::app_window::BoundsSpecification* inner_bounds = |
| + options.inner_bounds.get(); |
| + const extensions::api::app_window::BoundsSpecification* outer_bounds = |
| + options.outer_bounds.get(); |
| + if (inner_bounds && outer_bounds && |
|
benwells
2014/03/05 02:33:30
You can put all of these conflict checks into one
|
| + !CheckBoundsConflict( |
| + inner_bounds->left, outer_bounds->left, "left", error)) { |
| + return false; |
| + } |
| + if (inner_bounds && outer_bounds && |
| + !CheckBoundsConflict( |
| + inner_bounds->top, outer_bounds->top, "top", error)) { |
| + return false; |
| + } |
| + if (inner_bounds && outer_bounds && |
| + !CheckBoundsConflict( |
| + inner_bounds->width, outer_bounds->width, "width", error)) { |
| + return false; |
| + } |
| + if (inner_bounds && outer_bounds && |
| + !CheckBoundsConflict( |
| + inner_bounds->height, outer_bounds->height, "height", error)) { |
| + return false; |
| + } |
| + if (inner_bounds && outer_bounds && |
| + !CheckBoundsConflict(inner_bounds->min_width, |
| + outer_bounds->min_width, |
| + "minWidth", |
| + error)) { |
| + return false; |
| + } |
| + if (inner_bounds && outer_bounds && |
| + !CheckBoundsConflict(inner_bounds->min_height, |
| + outer_bounds->min_height, |
| + "minHeight", |
| + error)) { |
| + return false; |
| + } |
| + if (inner_bounds && outer_bounds && |
| + !CheckBoundsConflict(inner_bounds->max_width, |
| + outer_bounds->max_width, |
| + "maxWidth", |
| + error)) { |
| + return false; |
| + } |
| + if (inner_bounds && outer_bounds && |
| + !CheckBoundsConflict(inner_bounds->max_height, |
| + outer_bounds->max_height, |
| + "maxHeight", |
| + error)) { |
| + return false; |
| + } |
| + |
| + CopyBoundsSpec(inner_bounds, &(params->content_spec)); |
| + CopyBoundsSpec(outer_bounds, &(params->window_spec)); |
| + } else { |
| + // Parse deprecated fields. |
| + |
| + // TODO(jeremya): remove these, since they do the same thing as |
|
benwells
2014/03/05 02:33:30
I don't think we have a plan or bug to remove thes
|
| + // left/top/width/height. |
| + if (options.default_width.get()) |
| + params->content_spec.bounds.set_width(*options.default_width.get()); |
| + if (options.default_height.get()) |
| + params->content_spec.bounds.set_height(*options.default_height.get()); |
| + if (options.default_left.get()) |
| + params->content_spec.bounds.set_x(*options.default_left.get()); |
|
benwells
2014/03/05 02:33:30
My understanding is that previously left / top in
tmdiep
2014/03/05 03:06:47
Ugh. bounds.left and bounds.top were actually inte
tmdiep
2014/03/06 01:06:49
I will make top/left be interpreted as top/left of
benwells
2014/03/06 22:40:16
Awesome, love it. You should add a comment briefly
|
| + if (options.default_top.get()) |
| + params->content_spec.bounds.set_y(*options.default_top.get()); |
| + |
| + if (options.width.get()) |
| + params->content_spec.bounds.set_width(*options.width.get()); |
| + if (options.height.get()) |
| + params->content_spec.bounds.set_height(*options.height.get()); |
| + if (options.left.get()) |
| + params->content_spec.bounds.set_x(*options.left.get()); |
| + if (options.top.get()) |
| + params->content_spec.bounds.set_y(*options.top.get()); |
| + |
| + if (options.bounds.get()) { |
| + app_window::ContentBounds* bounds = options.bounds.get(); |
| + if (bounds->width.get()) |
| + params->content_spec.bounds.set_width(*bounds->width.get()); |
| + if (bounds->height.get()) |
| + params->content_spec.bounds.set_height(*bounds->height.get()); |
| + if (bounds->left.get()) |
| + params->content_spec.bounds.set_x(*bounds->left.get()); |
| + if (bounds->top.get()) |
| + params->content_spec.bounds.set_y(*bounds->top.get()); |
| + } |
| + |
| + gfx::Size& minimum_size = params->content_spec.minimum_size; |
| + if (options.min_width.get()) |
| + minimum_size.set_width(*options.min_width); |
| + if (options.min_height.get()) |
| + minimum_size.set_height(*options.min_height); |
| + gfx::Size& maximum_size = params->content_spec.maximum_size; |
| + if (options.max_width.get()) |
| + maximum_size.set_width(*options.max_width); |
| + if (options.max_height.get()) |
| + maximum_size.set_height(*options.max_height); |
| + } |
| + |
| + return true; |
| +} |
| + |
| AppWindow::Frame AppWindowCreateFunction::GetFrameFromString( |
| const std::string& frame_string) { |
| if (frame_string == kHtmlFrameOption && |