Google Drive Realtime API in a Chrome Packaged App - google-drive-realtime-api

Has anyone figured out how to use the Google Drive Realtime API in a Chrome Packaged App?
Loading gapi in a sandboxed iframe results in:
Uncaught TypeError: Cannot read property 'prototype' of undefined cb=gapi.loaded_0:6
gapi.load("auth:client,drive-realtime,drive-share", function(){...});
Please see my example repo at: https://github.com/damondouglas/sandbox-cpa-drive-rt

Damon - I took the example you posted on GitHub and changed it to use a webview which works fine. I think you are restricting yourself to not using one for artificial reasons. It may still be possible to solve this issue another way without using a webview, but after a good amount of research and trial and error I have not found a better option.
The updated code uses webview partitions to access your local app files without using an external website, so all of the app's resources are bundled with the app with no external references other than to the realtime APIs.
https://drive.google.com/file/d/0B1es-bMybSeSVWozSkJ6OFd5YTQ/edit?usp=sharing

I've spent a bit of time investigating how to make this possible. The best option I have come up with is to use a host page and a webview element as a container for an external site. I believe you may be able to use the webview to access resources that come packaged with the app using webview partitions though I haven't tried yet.
Trying to load the Google Javascript Client Library in a Chrome App page throws the DOM exception you're seeing due to it's use of window.sessionStorage which is not accessible from a chrome app.
manifest.json
{
"name": "Moo.do",
"description": "Moo.do - Organize your way",
"version": "0.1",
"manifest_version": 2,
"app": {
"background": {
"scripts": [ "chromeapp.js" ]
}
},
"permissions": [
"storage",
"webview"
]
}
chromeapp.js
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('test.html', {
'bounds': {
'width': 400,
'height': 500
}
});
});
test.html
<head>
<script src="test.js" type="text/javascript"></script>
<style>
body {
margin: 0px;
}
.view {
position: absolute;
left: 0px;
top: 0px;
}
#authView {
width: 100%;
height: 100%;
}
#mainView {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<webview id="mainView" class="view" src="http://www.moo.do"></webview>
</body>
</html>
test.js
function handleNewWindow(evNew)
{
var authView = document.createElement('webview');
authView.id = 'authView';
authView.classList.add('view');
document.body.appendChild(authView);
authView.addEventListener('exit', function (e)
{
debugger;
});
authView.addEventListener('loadredirect', function (e)
{
debugger;
});
evNew.window.attach(authView);
}
document.addEventListener('DOMContentLoaded', function ()
{
var mainView = document.getElementById('mainView');
mainView.addEventListener('newwindow', handleNewWindow);
});

Related

How to remove url protocol from Angular $http get response

I'm working on a chrome extension that uses the iframe.ly API to grab the responsive iframe markup from a video on the page the user is currently on. I'm using Angular JS (v1.5.8) to communicate with the API, and to generate a preview of the iframe markup. Everything's working splendidly if the extension is being used on a YouTube page. Here's the basic flow:
content script <-- grabs current url
chrome.runtime.sendMessage({
theurl: window.location.href
});
background script <-- puts current url into url made for the API call:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse){
localStorage["theurl"] = request.theurl;
}
);
var url = "http://iframe.ly/api/iframely?url="
+ localStorage["theurl"] + "&api_key=**my api key, to be removed in production**>";
stuff.js <-- not greatly named, but the Angular bit that makes the call:
var iframeApp = angular.module('iframeApp', ['ngSanitize']);
iframeApp.controller('linkCtrl', function($scope, $http) {
$http.get(url).success(function(data) {
$scope.iframe = data;
});
});
iframeApp.filter('trusted', ['$sce', function ($sce) {
return function(url) {
return $sce.trustAsResourceUrl(url);
};
}]);
iframeApp.filter('rawHtml', ['$sce', function($sce){
return function(val) {
return $sce.trustAsHtml(val);
};
}]);
sandboxed.html <-- again, not greatly named (leftover from when I was trying a different approach for this extension), but the default popup when browser icon is clicked:
<html class="ng-scope" ng-csp ng-app="iframeApp">
<head>
<meta charset="utf-8">
<title>Angular.js JSON Fetching Example</title>
<link rel="stylesheet" href="bootstrap.min.css">
<script src="angular.min.js"></script>
<script src="angular-sanitize.min.js"></script>
<script src="backgroundscript.js"></script>
<script src="stuff.js"></script>
</head>
<body ng-controller="linkCtrl">
<h4>Responsive iFrame code is <pre>{{iframe.links.player[0].html}}</pre></h4>
<div ng-bind-html="iframe.links.player[0].html | rawHtml"></div>
</body>
</body>
</html>
Now! On a YouTube page (for example), this is what happens when the browser icon is clicked:
Wonderful! BUT! Things get a bit, um, not working at all when I attempt to make the same call when on a Vimeo page. Here's the problem: The source url on the iframe.ly API call to a YouTube page returns a URL that's appended with a https protocol. However, a Vimeo call returns a URL with a non-relative, "//" protocol appended to the source. So, this happens, because obviously this won't work unless you're doing it on an HTML file that's running on a server of some sort, because it otherwise attempts to access a local file:
Now, I'd like to fix this by calling for the source url (by replacing the iframe.links.player[0].html with iframe.links.player[0].href) and then putting that inside an iframe inside of a hardcoded responsive div element. That way, my call would return, say //player.vimeo.com/video/177375994?byline=0&badge=0&portrait=0&title=0.
So, how could I remove all the protocols from the URLs from the API calls? This would be great, because player.vimeo.com/video/177375994?byline=0&badge=0&portrait=0&title=0 automatically routes the browser to append the proper protocol, rather than making it think that I'm trying to load a local file, and it does the same when there's no protocol on a YouTube URL, and I'm assuming any other URL for a video as well.
The functionality of the extension is to allow a developer to quickly copy/paste iframe markup, instead of having to type it out, just to make things a tad easier. So, the "//" protocol would actually be fine in the long run if a site is being built, because then it's running on a server, and it doesn't matter. But, for purposes of not looking ugly, it'd be nice if the preview worked for all videos with the extension.
Thank you!
In case you're working on an extension or app with Angular, and you're communicating with public API that you don't have control over, and that API is giving you some guff with some unwanted characters its responses: Never fear!
I successfully pulled the protocol from the get request's returning URL, but after realizing that a URL without a protocol is treated like a local file, too, I added an "http://" protocol to the URL after stripping it. This way, any Vimeo source in the iframe.ly API that had a protocol of "//" would be replaced with an "http://", which ends up redirecting it to an "https://" protocol anyway (it seems safe to put "http://" on anything and have your bases covered, because, at least in Chrome, it'll be sufficient to route to anything SSL protected as well).
So, basically, the problem was that the iframe.ly API was spectacular for finding the source URLs for videos, but the protocols weren't normalized, which caused problems when trying to use those URLs inside of the chrome extension. Here's the code I'm currently using to pull the URLs from the API, and then normalize their protocols to all be "http://":
In the poorly named stuff.js, where the Angular code for the extension lives:
var iframeApp = angular.module('iframeApp', ['ngSanitize']);
iframeApp.controller('linkCtrl', function($scope, $http, $sce) {
$http.get(url).success(function(data) {
$scope.iframe = data;
var newurl = $scope.iframe.links.player[0].href;
var secondurl = newurl.split('/').slice(2).join('/');
$scope.iframe2 = $sce.trustAsResourceUrl((secondurl.indexOf('://') == -1) ? 'http://' + secondurl : secondurl) ;
var testurl = $scope.iframe.links.player[0].href;
$scope.iframe3 = testurl;
$scope.iframe3 = $sce.trustAsResourceUrl(testurl);
});
});
iframeApp.filter('trusted', ['$sce', function ($sce) {
return function(url) {
return $sce.trustAsResourceUrl(url);
};
}]);
iframeApp.filter('rawHtml', ['$sce', function($sce){
return function(val) {
return $sce.trustAsHtml(val);
};
}]);
And, in the also-poorly-named sandboxed.html, which is the extension's default popup:
<html class="ng-scope" ng-csp ng-app="iframeApp">
<head>
<meta charset="utf-8">
<title>Angular.js JSON Fetching Example</title>
<link rel="stylesheet" href="bootstrap.min.css">
<script src="angular.min.js"></script>
<script src="angular-sanitize.min.js"></script>
<script src="backgroundscript.js"></script>
<script src="stuff.js"></script>
</head>
<body ng-controller="linkCtrl">
<h4>Responsive iFrame: <pre><code><div style="left: 0px; width: 100%; height: 0px; position: relative; padding-bottom: 56.2493%;"><iframe src="{{iframe2}}" frameborder="0" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" style="top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;"></iframe></div></code></pre>
<div>Source URL is: <code>{{iframe2}}</code></div>
<div style="left: 0px; width: 100%; height: 0px; position: relative; padding-bottom: 56.2493%;"><iframe ng-src="{{iframe2}}" frameborder="0" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" style="top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;"></iframe></div>
</body>
</html>
And now, clicking the browser action icon on a Vimeo video's page will not return with the Sad Face graphic that I've come to loathe so, so very much over the past couple weeks:
And, if I copy/paste that source URL into the browser, we can see that it automatically routes the "http://" protocol to its rightful "https://" protocol:
And, just for fun, an html page that's populated with stuff copy/pasted from the Responsive iFrame Code section of the default popup:
Gives us this, when the file is opened locally:
I have a feeling that any AngularJS purist is looking at this code and shouting "NO NO NO NO NO" at their screen, because, even as a n00b, I'm pretty sure that this Angular code is ugly, and should be separated into different pieces. BUT! It is working, and I'd love to hear any suggestions on accomplishing this in a more proper, "Angular Way" :)

cordova azure media player

How would one implement the azureMediaPLayer inside of cordova application?
I tried the tutorials/instructions from the website: http://amp.azure.net/libs/amp/latest/docs/ but I just can't make it work.
I put the
<link href="http:////amp.azure.net/libs/amp/1.5.0/skins/amp-default/azuremediaplayer.min.css" rel="stylesheet">
<script src= "http://amp.azure.net/libs/amp/1.5.0/azuremediaplayer.min.js"></script>
in my header of index.html
then i put the
<video id="vid1" class="azuremediaplayer amp-default-skin" autoplay controls width="640" height="400" poster="poster.jpg" data-setup='{"nativeControlsForTouch": false}'>
<source src="http://amssamples.streaming.mediaservices.windows.net/91492735-c523-432b-ba01-faba6c2206a2/AzureMediaServicesPromo.ism/manifest" type="application/vnd.ms-sstr+xml" />
<p class="amp-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
</p>
</video>
in the html
and it's just a black screen, no controls, no loading, and no error message from debug.
I tried the manual example running from the angular controller but that just tells me that amp is undefined.
var myPlayer = amp('vid1', { /* Options */
"nativeControlsForTouch": false,
autoplay: false,
controls: true,
width: "640",
height: "400",
poster: ""
}, function() {
console.log('Good to go!');
// add an event listener
this.addEventListener('ended', function() {
console.log('Finished!');
}
}
);
myPlayer.src([{
src: "http://amssamples.streaming.mediaservices.windows.net/91492735-c523-432b-ba01-faba6c2206a2/AzureMediaServicesPromo.ism/manifest",
type: "application/vnd.ms-sstr+xml"
}]);
Have anyone made this work? I started to look into the dash.js but I can't make that work either...
Cordova has the concept of whitelisting domains that are okay for use in the application. You will need to whitelist the domains for the AMP scripts and your domain for the streaming locators. Here is more information: https://cordova.apache.org/docs/en/latest/guide/appdev/whitelist/index.html

Insert Google Adsense code in Ionic breaks display

In this simple Codepen demo, I have a bar and a slider. Works fine, but if I add the Google Adsense code, then display is broken. How should I insert the Adsense code to display the Ad at the top of the web page.
What I mean by "display is broken": the bar overlays the start of the ion-content (hello1 hello2). I already put class="has-header" in the <ion-content>.
NB I use Ionic framework both for the mobile site, and (next step) for the hybrid app. I don't expect the ad to work in the native code. I just need to display the Adsense ad on the mobile web site.
Code of the ad is:
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- hybride_320x50 -->
<ins class="adsbygoogle"
style="display:inline-block;width:320px;height:50px"
data-ad-client="ca-pub-4134311660880303"
data-ad-slot="1861097476"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
Skeleton of the ionic page:
header / angularjs
Google ad
bar
ion-content
content
slider
content
I would recommend you to use AdMob. I've written this native plugin which supports ionic: https://github.com/appfeel/admob-google-cordova/wiki/Angular.js,-Ionic-apps. Moreover it will also let you show interstitials.
ionic plugin add cordova-admob
<script src="lib/angular-admob/angular-admob.js"></script>
<script>
var app = angular.module('myApp', ['admobModule']);
app.config(['admobSvcProvider', function (admobSvcProvider) {
// Optionally you can configure the options here:
admobSvcProvider.setOptions({
publisherId: "ca-app-pub-XXXXXXXXXXXXXXXX/BBBBBBBBBB",
interstitialAdId: "ca-app-pub-XXXXXXXXXXXXXXXX/IIIIIIIIII",
autoShowBanner: true,
autoShowInterstitial: true
});
}]);
app.run(['admobSvc', function (admobSvc) {
admobSvc.createBannerView();
admob.requestInterstitialAd();
// Handle events:
$rootScope.$on(admobSvc.events.onAdOpened, function onAdOpened(evt, e) {
console.log('adOpened: type of ad:' + e.adType);
});
}]);
</script>
one fast solution is add the following class to your style
.adsbygoogle {
position: absolute;
z-index: 10;
}

Add multiple filters to cardboard app rally

I have one cardboard application which display's number of cards for each PortfolioItem/Feature. likewise it's on Rally platform Release Planning. I want to implement filter box like that.
Attached the screenshot of filters, which I want to implement.
You can sometimes get hints/code for your apps via the open source repo for the Rally App Catalog. For your example, there is available source code for the Release Planning App. Reviewing the source code, you can see that the Filter Picker is defined by the following requirement defined in the source:
Rally.ui.gridboard.plugin.GridBoardCustomFilterControl
And this is incorporated into the board by adding its plugin to the board configuration.
It's tempting to add this to a Simple Grid example, exactly as the Release planning board does, which I tried doing as follows:
<!DOCTYPE html>
<html>
<head>
<title>Rally Example: Simple Board</title>
<script type="text/javascript" src="/apps/2.0rc3/sdk.js"></script>
<script type="text/javascript">
Rally.onReady(function () {
Ext.define('Rally.example.SimpleBoard', {
extend: 'Rally.app.App',
requires: [
'Rally.ui.gridboard.plugin.GridBoardCustomFilterControl'
],
launch: function() {
this.add({
xtype: 'rallycardboard',
types: ['User Story'],
attribute: 'ScheduleState',
context: this.getContext(),
readOnly: true,
cardConfig: {
showIconsAndHighlightBorder: false,
editable: false
},
plugins: [
{
ptype: 'rallygridboardcustomfiltercontrol',
filterChildren: false,
filterControlConfig: {
margin: '3 9 3 30',
blackListFields: ['PortfolioItemType', 'Release'],
whiteListFields: [this._milestonesAreEnabled() ? 'Milestones' : ''],
modelNames: ['HierarchicalRequirement']
}
}
]
});
}
});
Rally.launchApp('Rally.example.SimpleBoard', {
name:"Rally Example: Simple Board",
parentRepos:""
});
});
</script>
<style type="text/css">
.app {
/* Add app styles here */
}
</style>
</head>
<body>
</body>
</html>
However, if you try to load the app in this way, you'll get a 404 when it looks for the Rally.ui.gridboard.plugin.GridBoardCustomFilterControl class.
Looking at the AppSDK2.0rc3 docs, this plugin does not appear to be available under the Rally.ui.cardboard.plugins.* tree that's bundled into the SDK. See screenshot here:
AppSDK2.0rc3 screenshot excerpt:
Nor does it appear that the Rally.ui.gridboard.plugin.* tree is bundled into the AppSDK. It is likely that the class is however, available to the Rally UI via a different javascript bundle (non-public) that the Rally developers use.
Perhaps it would be feasible for Rally Engineering to bundle this plugin into the AppSDK so that customer developers could use it - perhaps file a Feature Request on Rally Ideas or something like that to see if this is achievable.

How do i open Angularjs app in jQuery dialog?

I have written an AngularJS app which works just fine when launching it from browser. But when i try to launch the same app within jQuery dialog from one of my app, it never runs. I see the app loading all the scripts in Chrome developer toolbar but it never hits the debugger; statement in the app.run method. Am i missing something here?
Following is how i am trying to launch my app using jQuery dialog:
var windowWidth = $(window).width()-40;
var windowHeight = $(window).height()-40;
$("#div").load('<link to my angular app>').dialog({ modal: true, height: windowHeight, width: windowWidth, title: "Angular App" });

Resources