Google Picker API работает в Safari, но не работает в Chrome
Я занимаюсь разработкой веб-приложения на Flask и пытаюсь использовать Google Picker API, чтобы позволить пользователю выбрать файл на своем Google Диске. Ниже приведен мой код для тестирования API выбора (код, адаптированный с https://gist.github.com/Daniel15/5994054).
Вот HTML-файл (без личных идентификаторов):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Google Drive File Picker Example</title>
</head>
<body>
<button type="button" id="pick">Pick File</button>
<script src="../static/gdrive-filepicker.js"></script>
<script>
function initPicker() {
var picker = new FilePicker({
apiKey: '<Complete with API key>',
clientId: <Complete with numerical clientId>,
buttonEl: document.getElementById('pick'),
onSelect: function(file) {
console.log(file);
alert('Selected ' + file.title);
}
});
}
</script>
</body>
</html>
<script src="https://www.google.com/jsapi?key=<completed with key>"></script>
<script src="https://apis.google.com/js/client.js?onload=initPicker"></script>
А вот и файл javascript:
(function() {
/**
* Initialise a Google Driver file picker
*/
var FilePicker = window.FilePicker = function(options) {
// Config
this.apiKey = options.apiKey;
this.clientId = options.clientId;
// Elements
this.buttonEl = options.buttonEl;
// Events
this.onSelect = options.onSelect;
this.buttonEl.addEventListener('click', this.open.bind(this));
// Disable the button until the API loads, as it won't work properly until then.
this.buttonEl.disabled = true;
// Load the drive API
gapi.client.setApiKey(this.apiKey);
gapi.client.load('drive', 'v2', this._driveApiLoaded.bind(this));
google.load('picker', '1', { callback: this._pickerApiLoaded.bind(this) });
}
FilePicker.prototype = {
/**
* Open the file picker.
*/
open: function() {
// Check if the user has already authenticated
var token = gapi.auth.getToken();
if (token) {
this._showPicker();
} else {
// The user has not yet authenticated with Google
// We need to do the authentication before displaying the Drive picker.
this._doAuth(false, function() { this._showPicker(); }.bind(this));
}
},
/**
* Show the file picker once authentication has been done.
* @private
*/
_showPicker: function() {
var accessToken = gapi.auth.getToken().access_token;
this.picker = new google.picker.PickerBuilder().
addView(google.picker.ViewId.SPREADSHEETS).
setAppId(this.clientId).
setOAuthToken(accessToken).
setCallback(this._pickerCallback.bind(this)).
//setOrigin(google.script.host.origin).
build().
setVisible(true);
},
/**
* Called when a file has been selected in the Google Drive file picker.
* @private
*/
_pickerCallback: function(data) {
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var file = data[google.picker.Response.SPREADSHEETS][0],
id = file[google.picker.Document.ID],
request = gapi.client.drive.files.get({
fileId: id
});
request.execute(this._fileGetCallback.bind(this));
}
},
/**
* Called when file details have been retrieved from Google Drive.
* @private
*/
_fileGetCallback: function(file) {
if (this.onSelect) {
this.onSelect(file);
}
},
/**
* Called when the Google Drive file picker API has finished loading.
* @private
*/
_pickerApiLoaded: function() {
this.buttonEl.disabled = false;
},
/**
* Called when the Google Drive API has finished loading.
* @private
*/
_driveApiLoaded: function() {
this._doAuth(true);
},
/**
* Authenticate with Google Drive via the Google JavaScript API.
* @private
*/
_doAuth: function(immediate, callback) {
gapi.auth.authorize({
client_id: this.clientId + '<complete with second part of client id>.apps.googleusercontent.com',
scope: 'https://www.googleapis.com/auth/drive.readonly',
immediate: immediate
}, callback);
}
};
}());
Когда я запускаю его в Safari, он работает нормально, однако в Chrome происходит сбой с перенаправлением 401. Журналы ошибок в Chrome:
Completed initPicker()
Uncaught null
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://docs.google.com') does not match the recipient window's origin ('http://localhost:8081').
Invalid 'X-Frame-Options' header encountered when loading 'https://docs.google.com/picker?protocol=gadgets&origin=http%3A%2F%2Flocalho…adsheets%22))&rpctoken=bmrqgq5vh5h&rpcService=k3a915ai4cgk&thirdParty=true': 'ALLOW-FROM http://localhost:8081' is not a recognized directive. The header will be ignored.
GET https://docs.google.com/picker?protocol=gadgets&origin=http%3A%2F%2Flocalho…adsheets%22))&rpctoken=bmrqgq5vh5h&rpcService=k3a915ai4cgk&thirdParty=true 401 ()
И логи от Safari:
[Error] Unable to post message to https://docs.google.com. Recipient has origin http://localhost:8081.
[Error] Invalid 'X-Frame-Options' header encountered when loading 'https://docs.google.com/picker?protocol=gadgets&origin=http%3A%2F%2Flocalhost%3A8081&oauth_token=ya29..vgIMhRk5EJ9sBOEppY9NbkFpujbhPBvsUoEDJB85OW6ED9Gnfx2PK8N1U1W-zPVvSSs&hostId=localhost&relayUrl=http%3A%2F%2Flocalhost%3A8081%2Ffavicon.ico&nav=((%22spreadsheets%22))&rpctoken=oox715usn81y&rpcService=m5rgot68gsh3&thirdParty=true': 'ALLOW-FROM http://localhost:8081' is not a recognized directive. The header will be ignored.
Этот ответ (не удалось выполнить 'postMessage' в 'DOMWindow': https://www.youtube.com! == http: // localhost: 9000), по-видимому, предполагает, что это из-за разницы в протоколе между https и http, но Я нахожу странным, что он будет работать на Safari, но не на Chrome. Я также пытался использовать .setOrigin(window.location.protocol + '//' + window.location.host)
безуспешно. Есть идеи? Спасибо!