Bug 1044736 - Part 6. Widget should only require embed-widgets permission. r=fabrice

As discussed on dev-webapi[1] the app that wants to use widgets only
need the "embed-widgets" permission to use <iframe mozbrowser mozwidget>

If the app also wants to implement a browser, it could request the
"browser" separately. A <iframe mozbrowser mozwidget> will have
restricted mozbrowser API defined on the prototype if the embedder has
the "brower" permission; they will always throw when used.

[1]: https://groups.google.com/d/msg/mozilla.dev.webapi/uQweGWtVKRA/Bj1jZq3LN-0J

--HG--
rename : dom/apps/tests/test_widget.html => dom/apps/tests/test_widget_browser.html
This commit is contained in:
Kan-Ru Chen (陳侃如) 2014-11-12 14:20:19 +08:00
parent 8b1fe2d8ed
commit 1d20d5e1bb
7 changed files with 82 additions and 14 deletions

View File

@ -1,6 +1,7 @@
var gWidgetManifestURL = 'http://test/tests/dom/apps/tests/file_app.sjs?apptype=widget&getmanifest=true';
var gInvalidWidgetManifestURL = 'http://test/tests/dom/apps/tests/file_app.sjs?apptype=invalidWidget&getmanifest=true';
var gApp;
var gHasBrowserPermission;
function onError() {
ok(false, "Error callback invoked");
@ -82,21 +83,34 @@ function testApp(isValidWidget) {
function testLimitedBrowserAPI(ifr) {
var securitySensitiveCalls = [
'sendMouseEvent',
'sendTouchEvent',
'goBack',
'goForward',
'reload',
'stop',
'download',
'purgeHistory',
'getScreenshot',
'zoom',
'getCanGoBack',
'getCanGoForward'
{ api: 'sendMouseEvent' , args: ['mousedown', 0, 0, 0, 0, 0] },
{ api: 'sendTouchEvent' , args: ['touchstart', [0], [0], [0], [1], [1], [0], [1], 1, 0] },
{ api: 'goBack' , args: [] },
{ api: 'goForward' , args: [] },
{ api: 'reload' , args: [] },
{ api: 'stop' , args: [] },
{ api: 'download' , args: ['http://example.org'] },
{ api: 'purgeHistory' , args: [] },
{ api: 'getScreenshot' , args: [0, 0] },
{ api: 'zoom' , args: [0.1] },
{ api: 'getCanGoBack' , args: [] },
{ api: 'getCanGoForward' , args: [] },
{ api: 'getContentDimensions', args: [] }
];
securitySensitiveCalls.forEach( function(call) {
is(typeof ifr[call], "undefined", call + " should be hidden for widget");
if (gHasBrowserPermission) {
isnot(typeof ifr[call.api], "undefined", call.api + " should be defined");
var didThrow;
try {
ifr[call.api].apply(ifr, call.args);
} catch (e) {
ok(e instanceof DOMException, "throw right exception type");
didThrow = e.code;
}
is(didThrow, DOMException.INVALID_NODE_TYPE_ERR, "call " + call.api + " should throw exception");
} else {
is(typeof ifr[call.api], "undefined", call.api + " should be hidden for widget");
}
});
}
@ -154,7 +168,7 @@ var tests = [
// Permissions
function() {
SpecialPowers.pushPermissions(
[{ "type": "browser", "allow": 1, "context": document },
[{ "type": "browser", "allow": gHasBrowserPermission ? 1 : 0, "context": document },
{ "type": "embed-widgets", "allow": 1, "context": document },
{ "type": "webapps-manage", "allow": 1, "context": document }], runTest);
},

View File

@ -45,3 +45,5 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_web_app_install.html]
[test_widget.html]
skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app
[test_widget_browser.html]
skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app

View File

@ -11,6 +11,7 @@
<div id="container"></div>
<script type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
gHasBrowserPermission = false;
runTest();
</script>
</body>

View File

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for DataStore - basic operation on a readonly db</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="file_test_widget.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
gHasBrowserPermission = true;
runTest();
</script>
</body>
</html>

View File

@ -111,6 +111,16 @@ nsBrowserElement::IsBrowserElementOrThrow(ErrorResult& aRv)
return false;
}
bool
nsBrowserElement::IsNotWidgetOrThrow(ErrorResult& aRv)
{
if (!mOwnerIsWidget) {
return true;
}
aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
return false;
}
void
nsBrowserElement::InitBrowserElementAPI()
{
@ -119,6 +129,8 @@ nsBrowserElement::InitBrowserElementAPI()
NS_ENSURE_TRUE_VOID(frameLoader);
nsresult rv = frameLoader->GetOwnerIsBrowserOrAppFrame(&isBrowserOrApp);
NS_ENSURE_SUCCESS_VOID(rv);
rv = frameLoader->GetOwnerIsWidget(&mOwnerIsWidget);
NS_ENSURE_SUCCESS_VOID(rv);
if (!isBrowserOrApp) {
return;
@ -131,6 +143,7 @@ nsBrowserElement::InitBrowserElementAPI()
}
nsBrowserElement::nsBrowserElement()
: mOwnerIsWidget(false)
{
mObserver = new BrowserShownObserver(this);
mObserver->AddObserver();
@ -207,6 +220,7 @@ nsBrowserElement::SendMouseEvent(const nsAString& aType,
ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
nsresult rv = mBrowserElementAPI->SendMouseEvent(aType,
aX,
@ -234,6 +248,7 @@ nsBrowserElement::SendTouchEvent(const nsAString& aType,
ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
if (aIdentifiers.Length() != aCount ||
aXs.Length() != aCount ||
@ -266,6 +281,7 @@ void
nsBrowserElement::GoBack(ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
nsresult rv = mBrowserElementAPI->GoBack();
@ -278,6 +294,7 @@ void
nsBrowserElement::GoForward(ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
nsresult rv = mBrowserElementAPI->GoForward();
@ -290,6 +307,7 @@ void
nsBrowserElement::Reload(bool aHardReload, ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
nsresult rv = mBrowserElementAPI->Reload(aHardReload);
@ -302,6 +320,7 @@ void
nsBrowserElement::Stop(ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
nsresult rv = mBrowserElementAPI->Stop();
@ -316,6 +335,7 @@ nsBrowserElement::Download(const nsAString& aUrl,
ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
nsCOMPtr<nsIDOMDOMRequest> req;
AutoJSAPI jsapi;
@ -339,6 +359,7 @@ already_AddRefed<dom::DOMRequest>
nsBrowserElement::PurgeHistory(ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = mBrowserElementAPI->PurgeHistory(getter_AddRefs(req));
@ -358,6 +379,7 @@ nsBrowserElement::GetScreenshot(uint32_t aWidth,
ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = mBrowserElementAPI->GetScreenshot(aWidth, aHeight, aMimeType,
@ -379,6 +401,8 @@ void
nsBrowserElement::Zoom(float aZoom, ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
nsresult rv = mBrowserElementAPI->Zoom(aZoom);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -390,6 +414,7 @@ already_AddRefed<dom::DOMRequest>
nsBrowserElement::GetCanGoBack(ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = mBrowserElementAPI->GetCanGoBack(getter_AddRefs(req));
@ -406,6 +431,7 @@ already_AddRefed<dom::DOMRequest>
nsBrowserElement::GetCanGoForward(ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = mBrowserElementAPI->GetCanGoForward(getter_AddRefs(req));
@ -422,6 +448,7 @@ already_AddRefed<dom::DOMRequest>
nsBrowserElement::GetContentDimensions(ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = mBrowserElementAPI->GetContentDimensions(getter_AddRefs(req));

View File

@ -96,6 +96,8 @@ protected:
private:
void InitBrowserElementAPI();
bool IsBrowserElementOrThrow(ErrorResult& aRv);
bool IsNotWidgetOrThrow(ErrorResult& aRv);
bool mOwnerIsWidget;
class BrowserShownObserver;
friend class BrowserShownObserver;

View File

@ -307,6 +307,10 @@ nsGenericHTMLFrameElement::GetReallyIsBrowserOrApp(bool *aOut)
uint32_t permission = nsIPermissionManager::DENY_ACTION;
nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission);
NS_ENSURE_SUCCESS(rv, NS_OK);
if (permission != nsIPermissionManager::ALLOW_ACTION) {
rv = permMgr->TestPermissionFromPrincipal(principal, "embed-widgets", &permission);
NS_ENSURE_SUCCESS(rv, NS_OK);
}
*aOut = permission == nsIPermissionManager::ALLOW_ACTION;
return NS_OK;
}