Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

285
Views
Accessing a Google Doc's content from a Chrome extension after July 2021

I wrote a Chrome extension that counts words in a Google Doc, and compares them to suggested word counts from a data source (CSV, table, or database).

My method was to parse each span.kix-lineview-text-block on the page, which stopped working when Google switched to an SVG canvas display. Here's a screenshot showing all word counts at 0.

The recommended alternative to parsing the page is authentication. That is, using Oauth 2.0 to authorize requests and edit content through the well-documented Google Docs API.

GDocs' API Overview makes sense. But I'm new to authentication, and too much of a noob to make sense of this answer. Google offers a quickstart tutorial, but I haven't been able to get it working as an extension.

Clearly there's a gap in my knowledge, and I'm at a loss for what to search for ("Google Docs chrome extension authentication" lead me here...) Most of Google's examples use Java/PHP/Python, which makes me wonder if I'm barking up the wrong tree.

Could someone smarter than me point out what I'm looking for and/or where to learn it?

TL;DR - I have a mostly-working Chrome extension that needs data from a Google Doc. How do I draw the rest of the owl?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

It seems wasteful to fetch data from a remote API when it's all present locally so here's a workaround that extracts the text from the doc's internals. Since content scripts run in an isolated environment, we'll have to put the extractor code into the page context and use DOM messaging to communicate with the content script.

Content script (ManifestV2):

// Adds the extractor into the page context (aka "main world")
const script = document.createElement('script');
const eventId = `${Math.random()}${performance.now()}`;
script.textContent = `(${eventId => {
  window.addEventListener(eventId, () => {
    const doc = document.querySelector('.docs-texteventtarget-iframe').contentDocument;
    const key = Object.keys(doc).find(k => k.startsWith('closure_'));
    const res = dig(key ? doc[key] : doc.defaultView, new Set());
    window.dispatchEvent(new CustomEvent(`${eventId}res`, { detail: res || '' }));
  });
  function dig(src, seen) {
    seen.add(src);
    if (!Array.isArray(src)) src = Object.values(src);
    for (let v, len = src.length, i = 0; i < len; i++) {
      try {
        if (!(v = src[i]) ||
            Object.prototype.toString.call(v) === '[object Window]' ||
            seen.has(v)) {
          continue;
        }
      } catch (e) {}
      seen.add(v)
      if (typeof v === 'string' && v[0] === '\x03' && v.endsWith('\n') ||
          typeof v === 'object' && (v = dig(v, seen))) {
        return v;
      }
    }
  }
}})(${JSON.stringify(eventId)})`;
document.documentElement.appendChild(script);
script.remove();

// Listens for messages from the extension
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg === 'getDocText') {
    sendResponse(getDocText());
  }
});

// Calls the extractor via synchronous DOM messaging
function getDocText() {
  let res;
  window.addEventListener(`${eventId}res`, e => { res = e.detail }, {once: true});
  window.dispatchEvent(new CustomEvent(eventId));
  return res;
}

In ManifestV3 the only difference is that instead of script.textContent you will use script.src + a separate script file exposed in web_accessible_resources as shown in method 1 here. In the future ManifestV3 will allow registering code in the main world directly.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!