Skip to content

Commit

Permalink
WebApp changes for Cordova Android -- oAuth through Twitter now works
Browse files Browse the repository at this point in the history
Added InAppBrowser support for the oAuth redirect scheme, this relies on
a PR that I made to Cordova to allow schemes
apache/cordova-plugin-inappbrowser#263
which they are likely to approve, but if not we can work off of the fork.
Moved all the iOS twitter scheme processing out of Application.js and into
TwitterSignIn.jsx, and enhanced it for Android.  Some small styling changes
to remove the iOS
  • Loading branch information
SailingSteve committed Apr 6, 2018
1 parent 0a0cfd1 commit 66ce945
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 104 deletions.
92 changes: 46 additions & 46 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"react-dom": "^15.6.2",
"react-helmet": "^3.3.0",
"react-iframe-resizer-super": "^0.2.0",
"react-player": "^0.14.1",
"react-player": "^1.3.1",
"react-router-scroll": "^0.4.4",
"react-slick": "^0.14.5",
"react-slide-out": "^0.1.4",
Expand Down
18 changes: 11 additions & 7 deletions src/js/Application.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import PropTypes from "prop-types";
import { ToastContainer } from "react-toastify";
import BookmarkActions from "./actions/BookmarkActions";
import cookies from "./utils/cookies";
import { historyPush, isCordova, cordovaOpenSafariView, isWebApp } from "./utils/cordovaUtils";
import { historyPush, cordovaOpenSafariView, isAndroid, isCordova, isIOS,
isWebApp } from "./utils/cordovaUtils";
import ElectionActions from "./actions/ElectionActions";
import FooterBarCordova from "./components/Navigation/FooterBarCordova";
import FriendActions from "./actions/FriendActions";
Expand Down Expand Up @@ -59,9 +60,10 @@ export default class Application extends Component {

initCordova () {
console.log("Application initCordova ------------ " + __filename);
console.log("------------------ device.platform = " + device.platform);
if (isCordova()) {
window.handleOpenURL = function (url) {
console.log("Application handleOpenUrl: " + url);
console.log("---------------xxxxxx-------- Application handleOpenUrl: " + url);
if (url.startsWith("wevotetwitterscheme://")) {
console.log("window.handleOpenURL received wevotetwitterscheme: " + url);
let search = url.replace(new RegExp("&", "g"), "&");
Expand Down Expand Up @@ -388,8 +390,10 @@ export default class Application extends Component {
"headroom-getting-started__margin" : isWebApp() ? "headroom-wrapper" : "headroom-wrapper__cordova";

let pageHeaderStyle = this.state.we_vote_branding_off ? "page-header__container_branding_off headroom" : "page-header__container headroom";
if (isCordova()) {
pageHeaderStyle += " page-header-cordova";
if (isIOS()) {
pageHeaderStyle = "page-header__container headroom page-header-cordova-ios"; // Note March 2018: no headroom.js for Cordova
} else if (isAndroid()) {
pageHeaderStyle = "page-header__container headroom";
}

let footerStyle = this.state.showFooter ? "footroom-wrapper" : "footroom-wrapper__hide";
Expand All @@ -412,7 +416,7 @@ export default class Application extends Component {

return <div className="app-base" id="app-base-id">
<ToastContainer closeButton={false} />
{ isCordova() && <div className={"ios7plus-spacer"} /> }
{ isCordova() && isIOS() && <div className={"ios7plus-spacer"} /> }
<div className={headRoomSize}>
<div ref="pageHeader" className={pageHeaderStyle}>
{ showBackToHeader ?
Expand Down Expand Up @@ -440,7 +444,7 @@ export default class Application extends Component {
} else if (settingsMode) {
return <div className="app-base" id="app-base-id">
<ToastContainer closeButton={false} />
{ isCordova() && <div className={"ios7plus-spacer"} /> }
{ isCordova() && isIOS() && <div className={"ios7plus-spacer"} /> }
<div className={headRoomSize}>
<div ref="pageHeader" className={pageHeaderStyle}>
{/* March 2018: One of HeaderBackToBar OR HeaderBar is displayed, AND under some circumstances HeaderGettingStartedBar is
Expand All @@ -467,7 +471,7 @@ export default class Application extends Component {
// This handles other pages, like Welcome and the Ballot display
return <div className="app-base" id="app-base-id">
<ToastContainer closeButton={false} />
{ isCordova() && <div className={"ios7plus-spacer"} /> }
{ isCordova() && isIOS() && <div className={"ios7plus-spacer"} /> }
<div className={headRoomSize}>
<div ref="pageHeader" className={pageHeaderStyle}>
{/* March 2018: One of HeaderBackToBar OR HeaderBar is displayed, AND under some circumstances HeaderGettingStartedBar is
Expand Down
78 changes: 74 additions & 4 deletions src/js/components/Twitter/TwitterSignIn.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { Button } from "react-bootstrap";
import { renderLog } from "../../utils/logging";
import { oAuthLog, renderLog } from "../../utils/logging";
import { $ajax } from "../../utils/service";
import cookies from "../../utils/cookies";
import { isWebApp, cordovaOpenSafariView } from "../../utils/cordovaUtils";
import { isWebApp, cordovaOpenSafariView, isIOS, isAndroid, historyPush } from "../../utils/cordovaUtils";
import webAppConfig from "../../config";
import TwitterActions from "../../actions/TwitterActions";

const returnURL = webAppConfig.WE_VOTE_URL_PROTOCOL + webAppConfig.WE_VOTE_HOSTNAME + "/twitter_sign_in";

Expand Down Expand Up @@ -57,8 +58,77 @@ export default class TwitterSignIn extends Component {
twitterSignInWebAppCordova () {
const requestURL = webAppConfig.WE_VOTE_SERVER_API_ROOT_URL + "twitterSignInStart" +
"?cordova=true&voter_device_id=" + cookies.getItem("voter_device_id") + "&return_url=http://nonsense.com";
console.log("twitterSignInWebAppCordova requestURL: " + requestURL);
cordovaOpenSafariView(requestURL, 50);
oAuthLog("twitterSignInWebAppCordova requestURL: " + requestURL);
if (isIOS()) {
cordovaOpenSafariView(requestURL, 50);
} else if (isAndroid()) {
// April 6, 2018: Needs Steve's PR to handle customscheme
// https://github.com/apache/cordova-plugin-inappbrowser/pull/263
let inAppBrowserRef = cordova.InAppBrowser.open(requestURL, "_blank", "toolbar=no,location=yes,hardwareback=no");
inAppBrowserRef.addEventListener("exit", function () {
oAuthLog("inAppBrowserRef on exit: ", requestURL);
});

inAppBrowserRef.addEventListener("customscheme", function (event) {
oAuthLog("customscheme: ", event.url);
TwitterSignIn.handleTwitterOpenURL(event.url);

//inAppBrowserRef.close();
});
}
}

static handleTwitterOpenURL (url) {
oAuthLog("---------------xxxxxx-------- Application handleTwitterOpenUrl: " + url);
if (url.startsWith("wevotetwitterscheme://")) {
oAuthLog("handleTwitterOpenURL received wevotetwitterscheme: " + url);
let search = url.replace(new RegExp("&amp;", "g"), "&");
let urlParams = new URLSearchParams(search);
if (urlParams.has("twitter_redirect_url")) {
let redirectURL = urlParams.get("twitter_redirect_url");
oAuthLog("twitterSignIn cordova, redirecting to: " + redirectURL);

if (isIOS()) {
// eslint-disable-next-line no-undef
SafariViewController.hide(); // Hide the previous WKWebView
cordovaOpenSafariView(redirectURL, 500);
} else {
oAuthLog("redirectURL: ", redirectURL);
let inAppBrowserRef = cordova.InAppBrowser.open(redirectURL, "_blank", "toolbar=no,location=yes,hardwareback=no");
inAppBrowserRef.addEventListener('exit', function () {
oAuthLog("inAppBrowserRef on exit: ", redirectURL);
});

inAppBrowserRef.addEventListener('customscheme', function (event) {
oAuthLog("customscheme: ", event.url);
TwitterSignIn.handleTwitterOpenURL(event.url);
inAppBrowserRef.close();
});
}
} else if (urlParams.has("access_token_and_secret_returned")) {
if (urlParams.get("success") === "True") {
oAuthLog("twitterSignIn cordova, received secret -- push /ballot");
TwitterActions.twitterSignInRetrieve();
historyPush("/ballot");
} else {
oAuthLog("twitterSignIn cordova, FAILED to receive secret -- push /twitter_sign_in");
historyPush("/twitter_sign_in");
}
} else if (urlParams.has("twitter_handle_found") && urlParams.get("twitter_handle_found") === "True") {
oAuthLog("twitterSignIn cordova, twitter_handle_found -- push /twitter_sign_in -- received handle = " + urlParams.get("twitter_handle"));

if (isIOS()) {
// eslint-disable-next-line no-undef
SafariViewController.hide(); // Hide the previous WKWebView
}

historyPush("/twitter_sign_in");
} else {
console.log("ERROR in window.handleOpenURL, NO MATCH");
}
} else {
console.log("ERROR: window.handleOpenURL received invalid url: " + url);
}
}

render () {
Expand Down
4 changes: 3 additions & 1 deletion src/js/dispatcher/Dispatcher.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { httpLog } from "../utils/logging";

var Dispatcher = require("flux/lib/Dispatcher");

Dispatcher.prototype.$ajax = require("../utils/service").$ajax;
Expand All @@ -10,7 +12,7 @@ Dispatcher.prototype.loadEndpoint = function (endpoint, data = {}) {
endpoint,
data: data,
success: (res) => {
// console.log("Ajax response to endpoint: " + endpoint);
httpLog("AJAX Response to endpoint: " + endpoint);
this.dispatch({ type: endpoint, res });
},

Expand Down
9 changes: 7 additions & 2 deletions src/js/routes/VoterGuide/OrganizationVoterGuide.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import { Link } from "react-router";
import { Button } from "react-bootstrap";
import AnalyticsActions from "../../actions/AnalyticsActions";
import { historyPush, isWebApp } from "../../utils/cordovaUtils";
import { historyPush, isIOS, isWebApp } from "../../utils/cordovaUtils";
import FollowToggle from "../../components/Widgets/FollowToggle";
import VoterGuideStore from "../../stores/VoterGuideStore";
import HeaderBar from "../../components/Navigation/HeaderBar";
Expand Down Expand Up @@ -153,7 +153,12 @@ export default class OrganizationVoterGuide extends Component {
let isVoterOwner = this.state.organization.organization_we_vote_id !== undefined &&
this.state.organization.organization_we_vote_id === this.state.voter.linked_organization_we_vote_id;

let pageHeaderStyle = isWebApp() ? "page-header__container headroom" : "page-header__container headroom page-header-cordova";
let pageHeaderStyle = "page-header__container headroom";
if (isIOS()) {
pageHeaderStyle = "page-header__container page-header-cordova-ios"; // Note March 2018: no headroom.js for Cordova
} else if (isAndroid()) {
pageHeaderStyle = "page-header__container";
}

if (!organizationId) {
let floatRight = {
Expand Down
9 changes: 9 additions & 0 deletions src/js/utils/cordovaUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,12 @@ export function deviceTypeString () {

return deviceString;
}

export function isIOS () {
return isCordova() && window.device && device.platform === "iOS";
}

export function isAndroid () {
return isCordova() && window.device && device.platform === "Android";
}

13 changes: 12 additions & 1 deletion src/js/utils/logging.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function renderLog (filePath, suffix) {

// Log http requests and cookie CHANGES
export function httpLog (text, res) {
if (webAppConfig.LOG_NATIVE_HTTP_REQUESTS) {
if (webAppConfig.LOG_HTTP_REQUESTS) {
if (res) {
console.log(text, res);
} else {
Expand All @@ -39,3 +39,14 @@ export function httpLog (text, res) {
}
}

// Log oAuth steps
export function oAuthLog (text, res) {
if (webAppConfig.LOG_SIGNIN_STEPS) {
if (res) {
console.log(">> oAuth >> ", text, res);
} else {
console.log(">> oAuth >> ", text);
}
}
}

36 changes: 2 additions & 34 deletions src/js/utils/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import assign from "object-assign";
import url from "url";
import cookies from "./cookies";
import webAppConfig from "../config";
import { httpLog } from "../utils/logging";

// import { isCordova } from "../utils/cordovaUtils";

Expand Down Expand Up @@ -40,40 +41,7 @@ export function $ajax (options) {
options.error = options.error || defaults.error;
options.url = url.resolve(defaults.baseUrl, options.endpoint) + "/";

// if (isCordova()) {
// console.log("AJAX URL: " + options.url);
// }
httpLog("AJAX URL: " + options.url);

return $.ajax(options);
}

// Commented out March 2018, feel free to delete in a few months. This seems to be abandoned.
//const DEBUG = false;
// export function get (options) {
// var opts = assign(defaults, options);
//
// opts.url = url.resolve(opts.baseUrl, opts.endpoint);
// // We add voter_device_id to all endpoint calls
// opts.query.voter_device_id = cookies.getItem("voter_device_id");
//
// return new Promise( (resolve, reject) => new request.Request("GET", opts.url)
// .accept(opts.dataType)
// .query(opts.query)
// .withCredentials()
// .end((err, res) => {
// if (err) {
// if (opts.error instanceof Function === true)
// opts.error(err || res.body);
//
// reject(err);
// } else {
// if (opts.success instanceof Function === true)
// opts.success(res.body);
// else if (DEBUG)
// console.warn(res.body);
//
// resolve(res.body);
// }
// })
// );
// }
2 changes: 1 addition & 1 deletion src/sass/components/_header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ $space-search-right: 10%;
}
}

.page-header-cordova {
.page-header-cordova-ios {
margin: $space-header-height auto $space-none;
}

Expand Down
5 changes: 2 additions & 3 deletions src/sass/components/_navigator.scss
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,7 @@ $container-margin: -15px;
}

&__text {
font-weight: 200 !important;
font-size: 13pt !important;
color: $blue !important;
font-weight: 300;
font-size: 13pt;
}
}
14 changes: 10 additions & 4 deletions www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@
* Enable inline JS: add 'unsafe-inline' to default-src
Steve 1/18/18: I was working on making all the correct policies, and decided to just make it wide open for now.
Wide open security policy for Apache Cordova. TODO: We should close this down
default-src 'self' data: http: https: localhost: wevotetwitterscheme: gap://* https://ssl.gstatic.com ;
-->
<meta http-equiv="Content-Security-Policy" content="
default-src * gap: ;
default-src * data: content: gap: https://ssl.gstatic.com;
img-src *;
style-src * 'unsafe-inline';
script-src * 'unsafe-inline';
frame-src http://*.facebook.com https://*.facebook.com https://*.twitter.com gap: ;
child-src gap://* ;
font-src *;
media-src *;
img-src * data:;
" />
<!--img-src https: data: file: android-webview-video-poster: https://api.wevoteusa.org;-->
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport"
Expand Down Expand Up @@ -67,9 +73,9 @@
font-size: 32px;
font-weight: normal;
color: #fff;
">Loading We Vote...
">Loading We Vote CORDOVA2...
</h1>
<div class="u-loading-spinner u-loading-spinner--light">Loading We Vote...</div>
<div class="u-loading-spinner u-loading-spinner--light">Loading We Vote CORDOVA...</div>
</div>
</div>
<!--<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>-->
Expand Down

0 comments on commit 66ce945

Please sign in to comment.