תוכן חיצוני

מודל האבטחה של אפליקציות Chrome אוסרת על תוכן חיצוני במסגרות iframe ולהשתמש ברכיבי iframe מוטבעים כתיבת סקריפטים ו-eval(). אפשר לבטל את ההגבלות האלה, אבל התוכן החיצוני שלך חייב להיות הוא מבודד מהאפליקציה.

תוכן מבודד לא יכול לגשת ישירות לנתוני האפליקציה או לאף אחד מממשקי ה-API. שימוש במקורות שונים XMLHttpRequests ולאחר-העברת הודעות כדי לתקשר בין דף האירוע לבין תוכן שבארגז חול, וגם לגשת באופן עקיף לממשקי ה-API.

הפניה למשאבים חיצוניים

המדיניות בנושא אבטחת תוכן שמשמשות אפליקציות אוסרת על שימוש בסוגים רבים של כתובות URL מרוחקות, לא יכול להפנות ישירות לתמונות חיצוניות, לגיליונות של סגנונות או לגופנים מדף האפליקציה. במקום זאת, אפשר להשתמש ב-XMLHttpRequests ממקורות שונים כדי לאחזר את המשאבים האלה, ולאחר מכן להציג אותם באמצעות כתובות URL של blob:.

דרישה למניפסט

כדי שתהיה אפשרות לבצע בקשות XMLHttpRequests ממקורות שונים, צריך להוסיף הרשאה לכתובות ה-URL המרוחקות Host (מארח):

"permissions": [
    "...",
    "https://supersweetdomainbutnotcspfriendly.com/"
  ]

XMLHttpRequest חוצה-מקורות

מאחזרים את כתובת ה-URL המרוחקת לאפליקציה ומציגים את התוכן שלה ככתובת URL של blob::

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://supersweetdomainbutnotcspfriendly.com/image.png', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
  var img = document.createElement('img');
  img.src = window.URL.createObjectURL(this.response);
  document.body.appendChild(img);
};

xhr.send();

מומלץ לשמור את המשאבים האלה באופן מקומי כדי שיהיו זמינים במצב אופליין.

הטמעה של דפי אינטרנט חיצוניים

התג webview מאפשר להטמיע באפליקציה תוכן מהאינטרנט החיצוני, למשל אתר הדף הזה. היא מחליפה מסגרות iframe שמפנות לכתובות URL מרוחקות, שמושבתות באפליקציות Chrome. ביטול הלייק iframes, התג webview פועל בתהליך נפרד. כלומר שנצליח בתוכו עדיין יהיו מבודדים ולא יוכלו לקבל הרשאות מורחבות. יתרה מכך, מאז האחסון (קובצי cookie וכו') מבודדים מהאפליקציה, אין דרך לתוכן באינטרנט לגשת לנתוני האפליקציה.

הוספת רכיב WebView

הרכיב webview חייב לכלול את כתובת ה-URL של תוכן המקור ולציין את המידות שלו.

<webview src="http://news.google.com/" width="640" height="480"></webview>

עדכון המאפיינים

כדי לשנות באופן דינמי את המאפיינים src, width ו-height של תג webview, אפשר להגדיר את המאפיינים האלה ישירות באובייקט ה-JavaScript, או להשתמש בפונקציית ה-DOM setAttribute.

document.querySelector('#mywebview').src =
    'http://blog.chromium.org/';
// or
document.querySelector('#mywebview').setAttribute(
    'src', 'http://blog.chromium.org/');

תוכן מקומי ב-Sandbox

ארגז חול מאפשר להציג דפים ספציפיים במקור ייחודי שמופעל בארגז חול (sandbox). לאחר מכן הדפים האלה פטור מהמדיניות שלהם בנושא אבטחת תוכן. דפים בארגז חול יכולים להשתמש ב-iframes, בכתיבת סקריפטים מוטבעים, eval() קוראים את תיאור שדה המניפסט של Sandbox.

אבל זה יתרון: דפים בארגז חול לא יכולים להשתמש ב-Chrome.* ממשקי API. אם צריך לבצע פעולות כמו eval(), תהיה לך אפשרות לקבל פטור מ-CSP, אבל לא תהיה לך אפשרות להשתמש בדברים המגניבים החדשים.

שימוש בסקריפטים מוטבעים ב-Sandbox

הנה דוגמה לדף ארגז חול שמשתמש בסקריפט מוטבע וב-eval():

<html>
  <body>
    <h1>Woot</h1>
    <script>
      eval('console.log(\'I am an eval-ed inline script.\')');
    </script>
  </body>
</html>

הכללת Sandbox במניפסט

עליך לכלול את השדה sandbox במניפסט ולציין את דפי האפליקציה להצגה Sandbox:

"sandbox": {
  "pages": ["sandboxed.html"]
}

פתיחת דף שנמצא בארגז חול (sandbox) בחלון

כמו בכל דף אפליקציה אחר, אפשר ליצור חלון שבו נפתח הדף שבארגז החול. הנה דוגמה שיוצרת שני חלונות, אחד לחלון הראשי של האפליקציה שלא נמצא בארגז חול, והשני דף שנמצא בארגז חול:

chrome.app.runtime.onLaunched.addListener(function() {
  chrome.app.window.create('window.html', {
    'bounds': {
      'width': 400,
      'height': 400,
      'left': 0,
      'top': 0
    }
  });

  chrome.app.window.create('sandboxed.html', {
    'bounds': {
      'width': 400,
      'height': 400,
      'left': 400,
      'top': 0
    }
  });
});

הטמעה של דף שהופעל בארגז חול (sandbox) בדף האפליקציה

ניתן להטמיע דפים שבארגז חול גם בתוך דף אפליקציה אחר באמצעות iframe:

<!DOCTYPE html>
<html>
<head>
</head>
  <body>
    <p>I am normal app window.</p>

    <iframe src="sandboxed.html" width="300" height="200"></iframe>
  </body>
</html>

שליחת הודעות לדפים בארגז חול (sandbox)

שליחת הודעה כוללת שני חלקים: עליך לפרסם הודעה מדף/חלון השולח, ולהאזין להודעות בדף/בחלון המקבל.

פרסום ההודעה

אפשר להשתמש ב-postMessage כדי לתקשר בין האפליקציה שלך לבין תוכן שארגז חול (sandbox). הנה דוגמה סקריפט רקע שמפרסם הודעה בדף שבארגז החול (sandbox) שהוא נפתח:

var myWin = null;

chrome.app.runtime.onLaunched.addListener(function() {
  chrome.app.window.create('sandboxed.html', {
    'bounds': {
      'width': 400,
      'height': 400
    }
  }, function(win) {
       myWin = win;
       myWin.contentWindow.postMessage('Just wanted to say hey.', '*');
     });
});

באופן כללי באינטרנט, כדאי לציין את המקור המדויק שממנו ההודעה נשלחת. לאפליקציות Chrome אין גישה למקור הייחודי של תוכן בארגז החול, לכן ניתן להוסיף רק את כל הפריטים לרשימת ההיתרים מקורות כמקורות קבילים ('*'). בדרך כלל, בצד המקבל כדאי לבדוק את המקור. אבל מכיוון שהתוכן של אפליקציות Chrome כלול, הוא לא נחוץ. מידע נוסף זמין במאמר הבא: window.postMessage.

האזנה להודעה ולתשובה

הנה דוגמה למקלט הודעות שמתווסף לדף שלכם בארגז החול:

var messageHandler = function(event) {
  console.log('Background script says hello.', event.data);

  // Send a reply
  event.source.postMessage(
      {'reply': 'Sandbox received: ' + event.data}, event.origin);
};

window.addEventListener('message', messageHandler);

לפרטים נוספים, אפשר לראות את הדוגמה של ארגז החול.