Commit e018a29e authored by ericzeng@chromium.org's avatar ericzeng@chromium.org

Implement autosizing for <extensionoptions>

This CL enables autosizing for extension options guests using
the built-in autosizing functionality in GuestViewBase.

BUG=386838

Review URL: https://codereview.chromium.org/431503002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287993 0039d316-1c4b-4281-b951-d872f2087c98
parent d73f88ee
......@@ -6,6 +6,15 @@
namespace extensionoptions {
// Attributes.
const char kAttributeAutoSize[] = "autosize";
const char kAttributeMaxHeight[] = "maxheight";
const char kAttributeMaxWidth[] = "maxwidth";
const char kAttributeMinHeight[] = "minheight";
const char kAttributeMinWidth[] = "minwidth";
const char kExtensionId[] = "extensionId";
const char kHeight[] = "height";
const char kWidth[] = "width";
} // namespace extensionoptions
......@@ -7,7 +7,16 @@
namespace extensionoptions {
// Attributes.
extern const char kAttributeAutoSize[];
extern const char kAttributeMaxHeight[];
extern const char kAttributeMaxWidth[];
extern const char kAttributeMinHeight[];
extern const char kAttributeMinWidth[];
extern const char kExtensionId[];
extern const char kHeight[];
extern const char kWidth[];
} // namespace extensionoptions
......
......@@ -22,6 +22,7 @@
#include "ipc/ipc_message_macros.h"
using content::WebContents;
using namespace extensions::api;
// static
const char ExtensionOptionsGuest::Type[] = "extensionoptions";
......@@ -100,6 +101,7 @@ void ExtensionOptionsGuest::CreateWebContents(
}
void ExtensionOptionsGuest::DidAttachToEmbedder() {
SetUpAutoSize();
guest_web_contents()->GetController().LoadURL(options_page_,
content::Referrer(),
content::PAGE_TRANSITION_LINK,
......@@ -138,3 +140,41 @@ void ExtensionOptionsGuest::OnRequest(
extension_function_dispatcher_->Dispatch(
params, guest_web_contents()->GetRenderViewHost());
}
void ExtensionOptionsGuest::GuestSizeChangedDueToAutoSize(
const gfx::Size& old_size,
const gfx::Size& new_size) {
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
args->SetInteger(extensionoptions::kWidth, new_size.width());
args->SetInteger(extensionoptions::kHeight, new_size.height());
DispatchEventToEmbedder(new GuestViewBase::Event(
extension_options_internal::OnSizeChanged::kEventName, args.Pass()));
}
bool ExtensionOptionsGuest::IsAutoSizeSupported() const {
return true;
}
void ExtensionOptionsGuest::SetUpAutoSize() {
// Read the autosize parameters passed in from the embedder.
bool auto_size_enabled;
extra_params()->GetBoolean(extensionoptions::kAttributeAutoSize,
&auto_size_enabled);
int max_height = 0;
int max_width = 0;
extra_params()->GetInteger(extensionoptions::kAttributeMaxHeight,
&max_height);
extra_params()->GetInteger(extensionoptions::kAttributeMaxWidth, &max_width);
int min_height = 0;
int min_width = 0;
extra_params()->GetInteger(extensionoptions::kAttributeMinHeight,
&min_height);
extra_params()->GetInteger(extensionoptions::kAttributeMinWidth, &min_width);
// Call SetAutoSize to apply all the appropriate validation and clipping of
// values.
SetAutoSize(
true, gfx::Size(min_width, min_height), gfx::Size(max_width, max_height));
}
......@@ -33,6 +33,10 @@ class ExtensionOptionsGuest
virtual void DidAttachToEmbedder() OVERRIDE;
virtual void DidInitialize() OVERRIDE;
virtual void DidStopLoading() OVERRIDE;
virtual void GuestSizeChangedDueToAutoSize(
const gfx::Size& old_size,
const gfx::Size& new_size) OVERRIDE;
virtual bool IsAutoSizeSupported() const OVERRIDE;
// ExtensionFunctionDispatcher::Delegate implementation.
virtual content::WebContents* GetAssociatedWebContents() const OVERRIDE;
......@@ -44,6 +48,7 @@ class ExtensionOptionsGuest
ExtensionOptionsGuest(content::BrowserContext* browser_context,
int guest_instance_id);
virtual ~ExtensionOptionsGuest();
void SetUpAutoSize();
void OnRequest(const ExtensionHostMsg_Request_Params& params);
scoped_ptr<extensions::ExtensionFunctionDispatcher>
......
......@@ -6,5 +6,6 @@
namespace extensionOptionsInternal {
interface Events {
static void onLoad();
static void onSizeChanged(long width, long height);
};
};
......@@ -8,6 +8,16 @@ var ExtensionOptionsEvents =
var GuestViewInternal =
require('binding').Binding.create('guestViewInternal').generate();
var IdGenerator = requireNative('id_generator');
var utils = require('utils');
// Mapping of the autosize attribute names to default values
var AUTO_SIZE_ATTRIBUTES = {
'autosize': 'on',
'maxheight': 600,
'maxwidth': 800,
'minheight': 32,
'minwidth': 80
};
function ExtensionOptionsInternal(extensionoptionsNode) {
privates(extensionoptionsNode).internal = this;
......@@ -27,7 +37,12 @@ function ExtensionOptionsInternal(extensionoptionsNode) {
ExtensionOptionsInternal.prototype.attachWindow = function(instanceId) {
this.instanceId = instanceId;
var params = {
'autosize': this.autosize,
'instanceId': this.viewInstanceId,
'maxheight': parseInt(this.maxheight || 0),
'maxwidth': parseInt(this.maxwidth || 0),
'minheight': parseInt(this.minheight || 0),
'minwidth': parseInt(this.minwidth || 0)
}
return this.browserPluginNode['-internal-attach'](instanceId, params);
};
......@@ -42,17 +57,28 @@ ExtensionOptionsInternal.prototype.createGuest = function() {
var params = {
'extensionId': this.extensionId,
};
var self = this;
GuestViewInternal.createGuest(
'extensionoptions',
params,
function(instanceId) {
if (instanceId == 0) {
self.initCalled = false;
this.initCalled = false;
} else {
self.attachWindow(instanceId);
this.attachWindow(instanceId);
GuestViewInternal.setAutoSize(this.instanceId, {
'enableAutoSize':
this.extensionoptionsNode.hasAttribute('autosize'),
'min': {
'width': parseInt(this.minwidth || 0),
'height': parseInt(this.minheight || 0)
},
'max': {
'width': parseInt(this.maxwidth || 0),
'height': parseInt(this.maxheight || 0)
}
});
}
});
}.bind(this));
};
ExtensionOptionsInternal.prototype.dispatchEvent =
......@@ -62,8 +88,6 @@ ExtensionOptionsInternal.prototype.dispatchEvent =
ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation =
function(name, oldValue, newValue) {
if (name != 'extension')
return;
// We treat null attribute (attribute removed) and the empty string as
// one case.
oldValue = oldValue || '';
......@@ -71,13 +95,33 @@ ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation =
if (oldValue === newValue)
return;
this.extensionId = newValue;
// Create new guest view if one hasn't been created for this element.
if (!this.instanceId && this.parseExtensionAttribute())
this.init();
// TODO(ericzeng): Implement navigation to another guest view if we want
// that functionality.
if (name == 'extension') {
this.extensionId = newValue;
// Create new guest view if one hasn't been created for this element.
if (!this.instanceId && this.parseExtensionAttribute())
this.init();
// TODO(ericzeng): Implement navigation to another guest view if we want
// that functionality.
} else if (AUTO_SIZE_ATTRIBUTES.hasOwnProperty(name) > -1) {
this[name] = newValue;
this.resetSizeConstraintsIfInvalid();
if (!this.instanceId)
return;
GuestViewInternal.setAutoSize(this.instanceId, {
'enableAutoSize': this.extensionoptionsNode.hasAttribute('autosize'),
'min': {
'width': parseInt(this.minwidth || 0),
'height': parseInt(this.minheight || 0)
},
'max': {
'width': parseInt(this.maxwidth || 0),
'height': parseInt(this.maxheight || 0)
}
});
}
};
ExtensionOptionsInternal.prototype.init = function() {
......@@ -91,6 +135,11 @@ ExtensionOptionsInternal.prototype.init = function() {
this.createGuest();
};
ExtensionOptionsInternal.prototype.onSizeChanged = function(width, height) {
this.browserPluginNode.style.width = width + 'px';
this.browserPluginNode.style.height = height + 'px';
};
ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() {
if (this.extensionoptionsNode.hasAttribute('extension')) {
var extensionId = this.extensionoptionsNode.getAttribute('extension');
......@@ -127,19 +176,51 @@ ExtensionOptionsInternal.prototype.setupEventProperty = function(eventName) {
};
ExtensionOptionsInternal.prototype.setupNodeProperties = function() {
var self = this;
this.extensionId = this.extensionoptionsNode.getAttribute('extension');
utils.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) {
// Get the size constraints from the <extensionoptions> tag, or use the
// defaults if not specified
if (this.extensionoptionsNode.hasAttribute(attributeName)) {
this[attributeName] =
this.extensionoptionsNode.getAttribute(attributeName);
} else {
this[attributeName] = AUTO_SIZE_ATTRIBUTES[attributeName];
}
Object.defineProperty(this.extensionoptionsNode, attributeName, {
get: function() {
return this[attributeName];
}.bind(this),
set: function(value) {
this.extensionoptionsNode.setAttribute(attributeName, value);
}.bind(this),
enumerable: true
});
}, this);
this.resetSizeConstraintsIfInvalid();
Object.defineProperty(this.extensionoptionsNode, 'extension', {
get: function() {
return self.extensionId;
},
return this.extensionId;
}.bind(this),
set: function(value) {
self.extensionoptionsNode.setAttribute('extension', value);
},
this.extensionoptionsNode.setAttribute('extension', value);
}.bind(this),
enumerable: true
});
};
ExtensionOptionsInternal.prototype.resetSizeConstraintsIfInvalid = function () {
if (this.minheight > this.maxheight || this.minheight < 0) {
this.minheight = AUTO_SIZE_ATTRIBUTES.minheight;
this.maxheight = AUTO_SIZE_ATTRIBUTES.maxheight;
}
if (this.minwidth > this.maxwidth || this.minwidth < 0) {
this.minwidth = AUTO_SIZE_ATTRIBUTES.minwidth;
this.maxwidth = AUTO_SIZE_ATTRIBUTES.maxwidth;
}
}
function registerBrowserPluginElement() {
var proto = Object.create(HTMLObjectElement.prototype);
......
......@@ -14,6 +14,13 @@ var EXTENSION_OPTIONS_EVENTS = {
evt: CreateEvent('extensionOptionsInternal.onLoad'),
fields: []
},
'sizechanged': {
evt: CreateEvent('extensionOptionsInternal.onSizeChanged'),
customHandler: function(handler, event, webViewEvent) {
handler.handleSizeChangedEvent(event, webViewEvent);
},
fields:['width', 'height']
}
}
/**
......@@ -54,5 +61,12 @@ ExtensionOptionsEvents.prototype.setupEvent = function(name, info) {
this.extensionOptionsInternal.setupEventProperty(name);
};
ExtensionOptionsEvents.prototype.handleSizeChangedEvent = function(
event, extensionOptionsEvent) {
this.extensionOptionsInternal.onSizeChanged(extensionOptionsEvent.width,
extensionOptionsEvent.height);
this.extensionOptionsInternal.dispatchEvent(extensionOptionsEvent);
}
exports.ExtensionOptionsEvents = ExtensionOptionsEvents;
exports.CreateEvent = CreateEvent;
......@@ -5,7 +5,7 @@
-->
<html>
<body>
<p>Test test test</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam neque lacus, ultricies in dui ac, consequat mattis justo. Curabitur in felis sed sapien vulputate vulputate. In mauris mi, rhoncus quis massa in, viverra molestie mauris. Vestibulum ac dui ante. Etiam rutrum tristique fermentum. Nulla ut pretium leo. Phasellus ac ligula tristique, lacinia nulla non, bibendum mauris. Vestibulum venenatis tortor leo, laoreet lobortis urna tempor eu. </p>
<script src="options.js"></script>
</body>
</html>
......@@ -109,6 +109,32 @@ chrome.test.runTests([
var extensionoptions = document.createElement('extensionoptions');
extensionoptions.setAttribute('extension', chrome.runtime.id);
document.body.appendChild(extensionoptions);
},
function autosizedGuestIsWithinSizeConstraints() {
var done = chrome.test.callbackAdded();
var extensionoptions = new ExtensionOptions();
extensionoptions.extension = chrome.runtime.id;
extensionoptions.autosize = 'on';
extensionoptions.minheight = 499;
extensionoptions.minwidth = 499;
extensionoptions.maxheight = 501;
extensionoptions.maxwidth = 501;
extensionoptions.onsizechanged = function(evt) {
try {
chrome.test.assertTrue(evt.width >= 499);
chrome.test.assertTrue(evt.height >= 499);
chrome.test.assertTrue(evt.width <= 501);
chrome.test.assertTrue(evt.height <= 501);
done();
} finally {
document.body.removeChild(extensionoptions);
}
};
document.body.appendChild(extensionoptions);
}
]);
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