Commit b6682be2 authored by Thibaut Frain's avatar Thibaut Frain

Links in iframed gadgets are opened in top window (using base element)

parent f7b2f00f
......@@ -147,6 +147,14 @@
return this;
};
// Set aq_parent on gadget_instance which call acquire on parent_gadget
function setAqParent(gadget_instance, parent_gadget) {
gadget_instance.__aq_parent = function (method_name, argument_list) {
return acquire.apply(parent_gadget, [gadget_instance, method_name,
argument_list]);
};
}
/////////////////////////////////////////////////////////////////
// RenderJSEmbeddedGadget
/////////////////////////////////////////////////////////////////
......@@ -166,7 +174,7 @@
/////////////////////////////////////////////////////////////////
// privateDeclarePublicGadget
/////////////////////////////////////////////////////////////////
function privateDeclarePublicGadget(url, options) {
function privateDeclarePublicGadget(url, options, parent_gadget) {
var gadget_instance;
if (options.element === undefined) {
options.element = document.createElement("div");
......@@ -194,6 +202,7 @@
template_node_list[i].cloneNode(true)
);
}
setAqParent(gadget_instance, parent_gadget);
// Load dependencies if needed
return RSVP.all([
gadget_instance.getRequiredJSList(),
......@@ -237,12 +246,11 @@
/////////////////////////////////////////////////////////////////
// privateDeclareIframeGadget
/////////////////////////////////////////////////////////////////
function privateDeclareIframeGadget(url, options) {
function privateDeclareIframeGadget(url, options, parent_gadget) {
var gadget_instance,
iframe,
node,
iframe_loading_deferred = RSVP.defer();
if (options.element === undefined) {
throw new Error("DOM element is required to create Iframe Gadget " +
url);
......@@ -262,12 +270,12 @@
}
gadget_instance = new RenderJSIframeGadget();
setAqParent(gadget_instance, parent_gadget);
iframe = document.createElement("iframe");
// gadget_instance.element.setAttribute("seamless", "seamless");
iframe.setAttribute("src", url);
gadget_instance.__path = url;
gadget_instance.__element = options.element;
// Attach it to the DOM
options.element.appendChild(iframe);
......@@ -348,7 +356,6 @@
// transform url to absolute url if it is relative
url = renderJS.getAbsoluteURL(url, this.__path);
// Change the global variable to update the loading queue
queue = new RSVP.Queue()
// Wait for previous gadget loading to finish first
......@@ -369,16 +376,11 @@
throw new Error("Unsupported sandbox options '" +
options.sandbox + "'");
}
return method(url, options);
return method(url, options, parent_gadget);
})
// Set the HTML context
.push(function (gadget_instance) {
var i;
// Define __aq_parent to reach parent gadget
gadget_instance.__aq_parent = function (method_name, argument_list) {
return acquire.apply(parent_gadget, [gadget_instance, method_name,
argument_list]);
};
// Drop the current loading klass info used by selector
gadget_loading_klass = undefined;
// Trigger calling of all ready callback
......@@ -711,7 +713,6 @@
notifyDeclareMethod,
gadget_ready = false;
// Create the gadget class for the current url
if (gadget_model_dict.hasOwnProperty(url)) {
throw new Error("bootstrap should not be called twice");
......@@ -745,6 +746,12 @@
);
};
tmp_constructor.prototype.__acquired_method_dict = {};
// Allow acquisition of getTopURL returning the top gadget path
tmp_constructor.allowPublicAcquisition('getTopURL', function () {
return root_gadget.__path;
});
} else {
// Create the communication channel
embedded_channel = Channel.build({
......@@ -831,9 +838,8 @@
});
});
};
}
tmp_constructor.prototype.__acquired_method_dict = {};
}
gadget_loading_klass = tmp_constructor;
function init() {
......@@ -871,6 +877,19 @@
function ready_wrapper() {
return root_gadget;
}
if (window.top !== window.self) {
tmp_constructor.ready(function () {
var base = document.createElement('base');
return root_gadget.__aq_parent('getTopURL', [])
.then(function (topURL) {
base.href = topURL;
base.target = "_top";
document.head.appendChild(base);
});
});
}
queue.push(ready_wrapper);
for (i = 0; i < tmp_constructor.__ready_list.length; i += 1) {
// Put a timeout?
......
......@@ -7,6 +7,14 @@
gk.ready(function (g) {
ready_called = true;
})
.declareMethod('getBaseHref', function () {
return document.querySelector('base')
.getAttribute('href');
})
.declareMethod('getBaseTarget', function () {
return document.querySelector('base')
.getAttribute('target');
})
.declareMethod('wasReadyCalled', function () {
return ready_called;
......
......@@ -2427,11 +2427,17 @@
test('Can take a scope options', function () {
// Subclass RenderJSGadget to not pollute its namespace
var gadget = new RenderJSGadget(),
url = "./embedded.html";
url = "./embedded.html",
topURL = "http://example.org/topGadget";
gadget.__sub_gadget_dict = {};
document.getElementById("qunit-fixture").textContent = "";
gadget.__acquired_method_dict = {
getTopURL: function () {return topURL; }
};
stop();
gadget.declareGadget(url, {
sandbox: 'iframe',
......@@ -2459,11 +2465,16 @@
port: parsed.port,
path: parsed.path}).toString(),
gadget_path = "./embedded.html",
absolute_path = parent_path + "embedded.html";
absolute_path = parent_path + "embedded.html",
topURL = "http://example.org/topGadget";
document.getElementById("qunit-fixture").textContent = "";
parent_gadget.__path = parent_path;
parent_gadget.__acquired_method_dict = {
getTopURL: function () {return topURL; }
};
stop();
parent_gadget.declareGadget(gadget_path, {
sandbox: 'iframe',
......@@ -2471,7 +2482,9 @@
})
.then(function (new_gadget) {
equal(new_gadget.__path, absolute_path);
deepEqual(new_gadget.__acquired_method_dict, undefined);
equal(Object.keys(new_gadget.__acquired_method_dict).length, 1);
equal(typeof new_gadget.__acquired_method_dict.getTopURL,
'function');
ok(new_gadget instanceof RenderJSIframeGadget);
equal(
new_gadget.__element.innerHTML,
......@@ -2487,10 +2500,15 @@
test('Initialize sub_gadget_dict private property', function () {
// Check that declare gadget returns the gadget
var gadget = new RenderJSGadget(),
url = "./embedded.html";
url = "./embedded.html",
topURL = "http://example.org/topGadget";
document.getElementById("qunit-fixture").textContent = "";
gadget.__acquired_method_dict = {
getTopURL: function () {return topURL; }
};
stop();
gadget.declareGadget(url, {
sandbox: 'iframe',
......@@ -2509,7 +2527,8 @@
// Check that declare gadget returns the gadget
var gadget = new RenderJSGadget(),
acquire_called = false,
url = "./embedded.html";
url = "./embedded.html",
topURL = "http://example.org/topGadget";
gadget.__aq_parent = function (method_name, argument_list) {
acquire_called = true;
......@@ -2525,6 +2544,10 @@
throw new renderJS.AcquisitionError("Can not handle " + method_name);
};
gadget.__acquired_method_dict = {
getTopURL: function () {return topURL; }
};
stop();
gadget.declareGadget(url, {
sandbox: 'iframe',
......@@ -2605,6 +2628,18 @@
"acquireMethodRequestedWithAcquisitionError",
error
);
})
.push(function () {
return new_gadget.getBaseHref();
})
.push(function (href) {
equal(href, topURL);
})
.push(function () {
return new_gadget.getBaseTarget();
})
.push(function (target) {
equal(target, "_top");
});
})
.fail(function (error) {
......@@ -2739,7 +2774,8 @@
.then(function (root_gadget) {
// Check instance
equal(root_gadget.__path, window.location.href);
deepEqual(root_gadget.__acquired_method_dict, {});
equal(typeof root_gadget.__acquired_method_dict, 'object');
equal(Object.keys(root_gadget.__acquired_method_dict).length, 1);
equal(root_gadget.__title, document.title);
deepEqual(root_gadget.__interface_list, []);
deepEqual(root_gadget.__required_css_list,
......@@ -2788,6 +2824,8 @@
ok(root_gadget.__aq_parent !== undefined);
ok(root_gadget.hasOwnProperty("__sub_gadget_dict"));
deepEqual(root_gadget.__sub_gadget_dict, {});
equal(root_gadget.__acquired_method_dict.getTopURL(),
window.location.href);
})
.fail(function (e) {
ok(false, e);
......
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