[Extensions] Include frameId in the result list for the scripting API
Add a new property to the injection result, frameId, for use in the
scripting.executeScript() API. This allows extensions to determine
which frame the result came from, even though the results may not be
in order.
To facilitate this, also create a more detailed struct for the result
from ScriptExecutor, which includes the per-frame error and URL. In
the future, these could be used to pass more information to the
extension (as well as making testing more thorough today).
Add tests for both ScriptExecutor and the end-to-end executeScript
API.
Bug: 1152910
Change-Id: Icd57251205e513ae8a632c5e02520c3c003634a9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2538164
Commit-Queue: Devlin <[email protected]>
Reviewed-by: Karan Bhatia <[email protected]>
Cr-Commit-Position: refs/heads/master@{#847469}
diff --git a/extensions/browser/script_executor.h b/extensions/browser/script_executor.h
index fbe3776..d9cd807 100644
--- a/extensions/browser/script_executor.h
+++ b/extensions/browser/script_executor.h
@@ -18,10 +18,6 @@
class GURL;
struct ExtensionMsg_ExecuteCode_Params;
-namespace base {
-class ListValue;
-} // namespace base
-
namespace content {
class WebContents;
}
@@ -72,10 +68,30 @@
JSON_SERIALIZED_RESULT,
};
- // Callback from ExecuteScript. The arguments are (error, on_url, result).
- // Success is implied by an empty error.
- using ScriptFinishedCallback = base::OnceCallback<
- void(const std::string&, const GURL&, const base::ListValue&)>;
+ struct FrameResult {
+ FrameResult();
+ FrameResult(FrameResult&&);
+ FrameResult& operator=(FrameResult&&);
+
+ // The ID of the frame of the injection.
+ int frame_id = -1;
+ // The error associated with the injection, if any. Empty if the injection
+ // succeeded.
+ std::string error;
+ // The URL of the frame from the injection. Only set if the frame exists.
+ GURL url;
+ // The result value from the injection, or null if the injection failed (or
+ // had no result).
+ base::Value value;
+ // Whether the frame responded to the attempted injection (which can fail if
+ // the frame was removed or never existed). Note this doesn't necessarily
+ // mean the injection succeeded, since it could fail due to other reasons
+ // (like permissions).
+ bool frame_responded = false;
+ };
+
+ using ScriptFinishedCallback =
+ base::OnceCallback<void(std::vector<FrameResult> frame_results)>;
// Executes a script. The arguments match ExtensionMsg_ExecuteCode_Params in
// extension_messages.h (request_id is populated automatically).
@@ -88,6 +104,7 @@
// |callback| will always be called even if the IPC'd renderer is destroyed
// before a response is received (in this case the callback will be with a
// failure and appropriate error message).
+ // TODO(devlin): Make |frame_ids| a std::set<> (since they must be unique).
void ExecuteScript(const HostID& host_id,
UserScript::ActionType action_type,
const std::string& code,